diff mbox

[V6,2/7] nios2: Add architecture emulation support

Message ID 62733dfe-5ccc-4d84-cc6e-92c100a1447e@roeck-us.net (mailing list archive)
State New, archived
Headers show

Commit Message

Guenter Roeck Nov. 12, 2016, 11:25 p.m. UTC
Hi Marek,

On 11/12/2016 01:50 PM, Marek Vasut wrote:
> On 11/07/2016 08:54 PM, Guenter Roeck wrote:
>> Hi Marek,
>>
>> On 11/07/2016 10:14 AM, Marek Vasut wrote:
>>> On 11/07/2016 04:58 AM, Guenter Roeck wrote:
>>>> On Tue, Oct 25, 2016 at 09:57:43PM +0200, Marek Vasut wrote:
>>>>> From: Chris Wulff <crwulff@gmail.com>
>>>>>
>>>>> Add support for emulating Altera NiosII R1 architecture into qemu.
>>>>> This patch is based on previous work by Chris Wulff from 2012 and
>>>>> updated to latest mainline QEMU.
>>>>>
>>>>> Signed-off-by: Marek Vasut <marex@denx.de>
>>>>> Cc: Chris Wulff <crwulff@gmail.com>
>>>>> Cc: Jeff Da Silva <jdasilva@altera.com>
>>>>> Cc: Ley Foon Tan <lftan@altera.com>
>>>>> Cc: Sandra Loosemore <sandra@codesourcery.com>
>>>>> Cc: Yves Vandervennet <yvanderv@altera.com>
>>>>> ---
>>>>> V3: Thorough cleanup, deal with the review comments all over the place
>>>>> V4: - Use extract32()
>>>>>     - Fix gen_goto_tb() , suppress tcg_gen_goto_tb()
>>>>>     - Clean up gen_check_supervisor() helper
>>>>>     - Use TCGMemOp type for flags
>>>>>     - Drop jump labels from wrctl/rdctl
>>>>>     - More TCG cleanup
>>>>> V5: - Simplify load/store handling
>>>>>     - Handle loads into R_ZERO from protected page, add comment
>>>>> V6: - Fix division opcode handling
>>>>>     - Add missing disas handling
>>>>>     - V5 review comments cleanup
>>>>> ---
>>>> [ ... ]
>>>>
>>>>> diff --git a/target-nios2/cpu.h b/target-nios2/cpu.h
>>>>> new file mode 100644
>>>>> index 0000000..17c9a0f
>>>> [ ... ]
>>>>
>>>>> +static inline void cpu_get_tb_cpu_state(CPUNios2State *env,
>>>>> target_ulong *pc,
>>>>> +                                        target_ulong *cs_base,
>>>>> uint32_t *flags)
>>>>> +{
>>>>> +    *pc = env->regs[R_PC];
>>>>> +    *cs_base = 0;
>>>>> +    *flags = (env->regs[CR_STATUS] & (CR_STATUS_EH | CR_STATUS_U));
>>>>> +}
>>>>> +
>>>>> +#endif /* CPU_NIOS2_H */
>>>>> +
>>>>
>>>> The empty line at the end results in a whitespace message from git.
>>>
>>> Dropped, thanks. Is there anything else or is this patchset starting to
>>> become acceptable ?
>>>
>>
>> Hard for me to say. I tried to build and run the series with the latest
>> linux
>> kernel (v4.9-rc4), but it is stuck in early boot. I tried with
>> 10m50_defconfig
>> and 10m50_devboard.dtb. gcc is 6.1.0 built with buildroot, though I also
>> tried
>> with toolchains from CodeSourcery. Obviously I have no idea if there is a
>> kernel bug or a qemu bug or a problem with the command line I used.
>>
>> Here is my command line:
>>
>> qemu-system-nios2 -M 10m50-ghrd -kernel vmlinux -dtb 10m50_devboard.dtb \
>>     -append "earlycon=uart8250,mmio32,0x18001600,115200n8 console=ttyS0"
>>
>> This may be wrong, but the boot is stuck in an endless loop in
>> mark_bootmem(),
>> which seems early and odd. I tried with both vmlinux and
>> arch/nios2/boot/vmImage,
>> with the same results.
>>
>> Can you provide a working command line and kernel version, and/or
>> directions how
>> to create a working image if I need to run the image, for example, from
>> u-boot ?
>> Sorry if that is posted somewhere and I missed it.
>
> I guess Romain gave you something since I see you made some progress.
> I'll have to look into that fdt loader issue.
>

Yes, WFM after

This is my command line, running your patch series plus the above fixup on top of
the qemu master branch:

qemu-system-nios2 -M 10m50-ghrd \
	-kernel vmlinux -no-reboot \
	-dtb 10m50_devboard.dtb \
	--append "rdinit=/sbin/init" \
	-initrd busybox-nios2.cpio \
	-nographic -monitor none

I use 10m50_defconfig with CONFIG_NIOS2_PASS_CMDLINE=y and CONFIG_BLK_DEV_INITRD=y.

One boot error I get is:

cpu cpu0: Error -2 creating of_node link

but that doesn't seem to have an impact. Also, I see

altera_tse 400.ethernet (unnamed net_device) (uninitialized): MDIO bus altera_tse-0: created
altera_tse 400.ethernet: Altera TSE MAC version 0.0 at 0x00000400 irq 3/4
altera_tse 400.ethernet eth0: Bad PHY UID 0x00000000
altera_tse 400.ethernet eth0: Cannot attach to PHY (error: -19)
altera_tse 400.ethernet eth0 (unregistered): MDIO bus altera_tse-0: removed

As far as I can see the ethernet controller isn't supported in qemu, so I guess that
is as expected.

Also, it still gives me

qemu-system-nios2: Trying to execute code outside RAM or ROM at 0xd4000000

on reboot, suggesting something like "rom_add_blob_fixed()" might be useful, if I knew
what to put there. If there is a means to get a clean reset, please let me know.

Thanks,
Guenter

Comments

Marek Vasut Nov. 13, 2016, 12:01 p.m. UTC | #1
On 11/13/2016 12:25 AM, Guenter Roeck wrote:
> Hi Marek,

Hi!

> On 11/12/2016 01:50 PM, Marek Vasut wrote:
>> On 11/07/2016 08:54 PM, Guenter Roeck wrote:
>>> Hi Marek,
>>>
>>> On 11/07/2016 10:14 AM, Marek Vasut wrote:
>>>> On 11/07/2016 04:58 AM, Guenter Roeck wrote:
>>>>> On Tue, Oct 25, 2016 at 09:57:43PM +0200, Marek Vasut wrote:
>>>>>> From: Chris Wulff <crwulff@gmail.com>
>>>>>>
>>>>>> Add support for emulating Altera NiosII R1 architecture into qemu.
>>>>>> This patch is based on previous work by Chris Wulff from 2012 and
>>>>>> updated to latest mainline QEMU.
>>>>>>
>>>>>> Signed-off-by: Marek Vasut <marex@denx.de>
>>>>>> Cc: Chris Wulff <crwulff@gmail.com>
>>>>>> Cc: Jeff Da Silva <jdasilva@altera.com>
>>>>>> Cc: Ley Foon Tan <lftan@altera.com>
>>>>>> Cc: Sandra Loosemore <sandra@codesourcery.com>
>>>>>> Cc: Yves Vandervennet <yvanderv@altera.com>
>>>>>> ---
>>>>>> V3: Thorough cleanup, deal with the review comments all over the
>>>>>> place
>>>>>> V4: - Use extract32()
>>>>>>     - Fix gen_goto_tb() , suppress tcg_gen_goto_tb()
>>>>>>     - Clean up gen_check_supervisor() helper
>>>>>>     - Use TCGMemOp type for flags
>>>>>>     - Drop jump labels from wrctl/rdctl
>>>>>>     - More TCG cleanup
>>>>>> V5: - Simplify load/store handling
>>>>>>     - Handle loads into R_ZERO from protected page, add comment
>>>>>> V6: - Fix division opcode handling
>>>>>>     - Add missing disas handling
>>>>>>     - V5 review comments cleanup
>>>>>> ---
>>>>> [ ... ]
>>>>>
>>>>>> diff --git a/target-nios2/cpu.h b/target-nios2/cpu.h
>>>>>> new file mode 100644
>>>>>> index 0000000..17c9a0f
>>>>> [ ... ]
>>>>>
>>>>>> +static inline void cpu_get_tb_cpu_state(CPUNios2State *env,
>>>>>> target_ulong *pc,
>>>>>> +                                        target_ulong *cs_base,
>>>>>> uint32_t *flags)
>>>>>> +{
>>>>>> +    *pc = env->regs[R_PC];
>>>>>> +    *cs_base = 0;
>>>>>> +    *flags = (env->regs[CR_STATUS] & (CR_STATUS_EH | CR_STATUS_U));
>>>>>> +}
>>>>>> +
>>>>>> +#endif /* CPU_NIOS2_H */
>>>>>> +
>>>>>
>>>>> The empty line at the end results in a whitespace message from git.
>>>>
>>>> Dropped, thanks. Is there anything else or is this patchset starting to
>>>> become acceptable ?
>>>>
>>>
>>> Hard for me to say. I tried to build and run the series with the latest
>>> linux
>>> kernel (v4.9-rc4), but it is stuck in early boot. I tried with
>>> 10m50_defconfig
>>> and 10m50_devboard.dtb. gcc is 6.1.0 built with buildroot, though I also
>>> tried
>>> with toolchains from CodeSourcery. Obviously I have no idea if there
>>> is a
>>> kernel bug or a qemu bug or a problem with the command line I used.
>>>
>>> Here is my command line:
>>>
>>> qemu-system-nios2 -M 10m50-ghrd -kernel vmlinux -dtb
>>> 10m50_devboard.dtb \
>>>     -append "earlycon=uart8250,mmio32,0x18001600,115200n8 console=ttyS0"
>>>
>>> This may be wrong, but the boot is stuck in an endless loop in
>>> mark_bootmem(),
>>> which seems early and odd. I tried with both vmlinux and
>>> arch/nios2/boot/vmImage,
>>> with the same results.
>>>
>>> Can you provide a working command line and kernel version, and/or
>>> directions how
>>> to create a working image if I need to run the image, for example, from
>>> u-boot ?
>>> Sorry if that is posted somewhere and I missed it.
>>
>> I guess Romain gave you something since I see you made some progress.
>> I'll have to look into that fdt loader issue.
>>
> 
> Yes, WFM after
> 
> diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c
> index 564dbae..e0a9aff 100644
> --- a/hw/nios2/boot.c
> +++ b/hw/nios2/boot.c
> @@ -73,6 +73,11 @@ static void main_cpu_reset(void *opaque)
>      }
>  }
> 
> +static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
> +{
> +    return addr - 0xc0000000LL;
> +}
> +
>  static int nios2_load_dtb(struct nios2_boot_info bi, const uint32_t
> ramsize,
>                            const char *kernel_cmdline, const char
> *dtb_filename)
>  {
> @@ -97,21 +102,16 @@ static int nios2_load_dtb(struct nios2_boot_info
> bi, const uint32_t ramsize,
> 
>      if (bi.initrd_start) {
>          qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
> -                              bi.initrd_start);
> +                              translate_kernel_address(NULL,
> bi.initrd_start));
> 
>          qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
> -                              bi.initrd_end);
> +                              translate_kernel_address(NULL,
> bi.initrd_end));
>      }
> 
>      cpu_physical_memory_write(bi.fdt, fdt, fdt_size);
>      return fdt_size;
>  }
> 
> -static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
> -{
> -    return addr - 0xc0000000LL;
> -}
> -
>  void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
> 
> 
> This is my command line, running your patch series plus the above fixup
> on top of
> the qemu master branch:

Uhm, how could that patch fix the DT passing for you ? I am still
looking into the DT passing, that's quite odd.

> qemu-system-nios2 -M 10m50-ghrd \
>     -kernel vmlinux -no-reboot \
>     -dtb 10m50_devboard.dtb \
>     --append "rdinit=/sbin/init" \
>     -initrd busybox-nios2.cpio \
>     -nographic -monitor none
> 
> I use 10m50_defconfig with CONFIG_NIOS2_PASS_CMDLINE=y and
> CONFIG_BLK_DEV_INITRD=y.
> 
> One boot error I get is:
> 
> cpu cpu0: Error -2 creating of_node link

This happens on real HW too, I have it on my list.

> but that doesn't seem to have an impact. Also, I see
> 
> altera_tse 400.ethernet (unnamed net_device) (uninitialized): MDIO bus
> altera_tse-0: created
> altera_tse 400.ethernet: Altera TSE MAC version 0.0 at 0x00000400 irq 3/4
> altera_tse 400.ethernet eth0: Bad PHY UID 0x00000000
> altera_tse 400.ethernet eth0: Cannot attach to PHY (error: -19)
> altera_tse 400.ethernet eth0 (unregistered): MDIO bus altera_tse-0: removed
> 
> As far as I can see the ethernet controller isn't supported in qemu, so
> I guess that
> is as expected.

Yes, ethernet is not yet supported but it looks like the hardware should
be easy enough to model.

> Also, it still gives me
> 
> qemu-system-nios2: Trying to execute code outside RAM or ROM at 0xd4000000
> 
> on reboot, suggesting something like "rom_add_blob_fixed()" might be
> useful, if I knew
> what to put there. If there is a means to get a clean reset, please let
> me know.

Will check, thanks!
Guenter Roeck Nov. 13, 2016, 4:09 p.m. UTC | #2
Hi Marek,

On 11/13/2016 04:01 AM, Marek Vasut wrote:
>>
>> diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c
>> index 564dbae..e0a9aff 100644
>> --- a/hw/nios2/boot.c
>> +++ b/hw/nios2/boot.c
>> @@ -73,6 +73,11 @@ static void main_cpu_reset(void *opaque)
>>      }
>>  }
>>
>> +static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
>> +{
>> +    return addr - 0xc0000000LL;
>> +}
>> +
>>  static int nios2_load_dtb(struct nios2_boot_info bi, const uint32_t
>> ramsize,
>>                            const char *kernel_cmdline, const char
>> *dtb_filename)
>>  {
>> @@ -97,21 +102,16 @@ static int nios2_load_dtb(struct nios2_boot_info
>> bi, const uint32_t ramsize,
>>
>>      if (bi.initrd_start) {
>>          qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
>> -                              bi.initrd_start);
>> +                              translate_kernel_address(NULL,
>> bi.initrd_start));
>>
>>          qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
>> -                              bi.initrd_end);
>> +                              translate_kernel_address(NULL,
>> bi.initrd_end));
>>      }
>>
>>      cpu_physical_memory_write(bi.fdt, fdt, fdt_size);
>>      return fdt_size;
>>  }
>>
>> -static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
>> -{
>> -    return addr - 0xc0000000LL;
>> -}
>> -
>>  void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
>>
>>
>> This is my command line, running your patch series plus the above fixup
>> on top of
>> the qemu master branch:
>
> Uhm, how could that patch fix the DT passing for you ? I am still
> looking into the DT passing, that's quite odd.
>

The problem isn't that much that dtb passing fails without the above fix,
the problem is that memory initialization fails if wrong addresses are
passed in the initrd properties (probably because the kernel tries to
access or free memory that does not exist). This results in a kernel hang
(endless loop) in memory initialization code.

Guenter
Marek Vasut Nov. 13, 2016, 10:58 p.m. UTC | #3
On 11/13/2016 05:09 PM, Guenter Roeck wrote:
> Hi Marek,
> 
> On 11/13/2016 04:01 AM, Marek Vasut wrote:
>>>
>>> diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c
>>> index 564dbae..e0a9aff 100644
>>> --- a/hw/nios2/boot.c
>>> +++ b/hw/nios2/boot.c
>>> @@ -73,6 +73,11 @@ static void main_cpu_reset(void *opaque)
>>>      }
>>>  }
>>>
>>> +static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
>>> +{
>>> +    return addr - 0xc0000000LL;
>>> +}
>>> +
>>>  static int nios2_load_dtb(struct nios2_boot_info bi, const uint32_t
>>> ramsize,
>>>                            const char *kernel_cmdline, const char
>>> *dtb_filename)
>>>  {
>>> @@ -97,21 +102,16 @@ static int nios2_load_dtb(struct nios2_boot_info
>>> bi, const uint32_t ramsize,
>>>
>>>      if (bi.initrd_start) {
>>>          qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
>>> -                              bi.initrd_start);
>>> +                              translate_kernel_address(NULL,
>>> bi.initrd_start));
>>>
>>>          qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
>>> -                              bi.initrd_end);
>>> +                              translate_kernel_address(NULL,
>>> bi.initrd_end));
>>>      }
>>>
>>>      cpu_physical_memory_write(bi.fdt, fdt, fdt_size);
>>>      return fdt_size;
>>>  }
>>>
>>> -static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
>>> -{
>>> -    return addr - 0xc0000000LL;
>>> -}
>>> -
>>>  void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
>>>
>>>
>>> This is my command line, running your patch series plus the above fixup
>>> on top of
>>> the qemu master branch:
>>
>> Uhm, how could that patch fix the DT passing for you ? I am still
>> looking into the DT passing, that's quite odd.
>>
> 
> The problem isn't that much that dtb passing fails without the above fix,
> the problem is that memory initialization fails if wrong addresses are
> passed in the initrd properties (probably because the kernel tries to
> access or free memory that does not exist). This results in a kernel hang
> (endless loop) in memory initialization code.

I was looking through that initcode today and through the Nios2 DTS, it
looks like quite an inconsistent mess of User and Kernel addresses used
there.
diff mbox

Patch

diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c
index 564dbae..e0a9aff 100644
--- a/hw/nios2/boot.c
+++ b/hw/nios2/boot.c
@@ -73,6 +73,11 @@  static void main_cpu_reset(void *opaque)
      }
  }

+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+    return addr - 0xc0000000LL;
+}
+
  static int nios2_load_dtb(struct nios2_boot_info bi, const uint32_t ramsize,
                            const char *kernel_cmdline, const char *dtb_filename)
  {
@@ -97,21 +102,16 @@  static int nios2_load_dtb(struct nios2_boot_info bi, const uint32_t ramsize,

      if (bi.initrd_start) {
          qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start",
-                              bi.initrd_start);
+                              translate_kernel_address(NULL, bi.initrd_start));

          qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
-                              bi.initrd_end);
+                              translate_kernel_address(NULL, bi.initrd_end));
      }

      cpu_physical_memory_write(bi.fdt, fdt, fdt_size);
      return fdt_size;
  }

-static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
-{
-    return addr - 0xc0000000LL;
-}
-
  void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,