Message ID | 20200625230740.549114-1-keithp@keithp.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | hw/arm: Add 'virtm' hardware | expand |
On Fri, 26 Jun 2020 at 00:07, Keith Packard <keithp@keithp.com> wrote: > > 'virtm' is a hardware target that is designed to be used for compiler > and library testing on Cortex-M processors. It supports all cortex-m > processors and includes sufficient memory to run even large test > cases. > > Signed-off-by: Keith Packard <keithp@keithp.com> So, I'm really dubious about adding more "virtual" not-real-hardware boards. We have "virt" because we absolutely have to have it for KVM purposes; but otherwise "emulate real hardware" gives us a concrete specification of what we're trying to do and tends to lead us into fewer messy swamps than making up virtual platforms does. For instance, this board model claims to handle the M33 but makes no attempt to set up any of the TrustZone related components like the IDAU, so it isn't really a useful platform for that CPU. You also enable bitband, which is maybe plausible for Cortex-M3/M4 but not for the others. This is the kind of area where having a real hardware system to check against means we make the right choices about what does or doesn't need to be present. thanks -- PMM
Peter Maydell <peter.maydell@linaro.org> writes: > So, I'm really dubious about adding more "virtual" > not-real-hardware boards. We have "virt" because we > absolutely have to have it for KVM purposes; but otherwise > "emulate real hardware" gives us a concrete specification > of what we're trying to do and tends to lead us into fewer > messy swamps than making up virtual platforms does. It depends on what you're using qemu for. I'm using it for C library tests, where I need memory and a processor, plus the ability to make semihosting calls and that's it. It seems like it should be possible to construct a virtual platform that is limited to just these elements without getting too far into the weeds? > For instance, this board model claims to handle the M33 > but makes no attempt to set up any of the TrustZone > related components like the IDAU, so it isn't really > a useful platform for that CPU. It's sufficient for my purposes, if adding those things would make it suitable for more people, that'd be awesome. > You also enable bitband, which is maybe plausible for Cortex-M3/M4 but > not for the others. Thanks for the bug report; bits of this code came from the stellaris code, including that part. I'll review the code in more detail to make sure it doesn't expose any features which aren't supposed to be. That will catch toolchain bugs which attempt to use features not present in the hardware, which is critical to successful validation. > This is the kind of area where having a real hardware system to check > against means we make the right choices about what does or doesn't > need to be present. I have tried every single 32-bit ARM emulation provided by qemu and none of them offer enough memory along with the ability to select an arbitrary processor. The stellaris code is the closest as it allows overriding the CPU type, and I've been able to run most of the C library tests using that. However, both boards supported by that code have a small fixed memory size, which isn't large enough to run the full test suite (the math tests require over 1M of ROM and RAM). Instead of creating another virtual platform, should I be working on the existing virt code to add cortex-m support? Ideally, I'd be able to emulate the full set of configurations that the embedded ARM GCC port does. I'm currently using the 2019-q3 release, which offers 18 configurations. Before I included 'virtm', I was able to test only one of them using the mps2-an385 emulator. With virtm, I'm covering 11 of them. The 'virt' emulator should cover the cortex-a7 cases, leaving only four cases untested (I haven't figured out the right configuration to run bare metal code on that yet). I can't find any ARM processors which implement v8-m with DP support, and the only QEMU module with v5te support appears to be digic, which I haven't experimented with at all. Architecture FPU QEMU -cpu Picolibc tests ---- ----- ------ --------- -------------- arm v5te softfp arm946 arm v5te hard arm946 thumb v7 nofp cortex-a7 thumb v7+fp softfp cortex-a7 thumb v7+fp hard cortex-a7 thumb v6-m nofp cortex-m0 yes thumb v7-m nofp cortex-m3 yes thumb v7e-m nofp cortex-m4 yes thumb v7e-m+fp softfp cortex-m4 yes thumb v7e-m+fp hard cortex-m4 yes thumb v7e-m+dp softfp cortex-m7 yes thumb v7e-m+dp hard cortex-m7 yes thumb v8-m.base nofp cortex-m33 yes thumb v8-m.main nofp cortex-m33 yes thumb v8-m.main+fp softfp cortex-m33 yes thumb v8-m.main+fp hard cortex-m33 yes thumb v8-m.main+dp softfp thumb v8-m.main+dp hard
On Fri, 26 Jun 2020 at 17:40, Keith Packard <keithp@keithp.com> wrote: > > Peter Maydell <peter.maydell@linaro.org> writes: > > > So, I'm really dubious about adding more "virtual" > > not-real-hardware boards. We have "virt" because we > > absolutely have to have it for KVM purposes; but otherwise > > "emulate real hardware" gives us a concrete specification > > of what we're trying to do and tends to lead us into fewer > > messy swamps than making up virtual platforms does. > > It depends on what you're using qemu for. I'm using it for C library > tests, where I need memory and a processor, plus the ability to make > semihosting calls and that's it. You might find the user-mode qemu-arm sufficient for that kind of thing. I know some gcc tests run that way. You get a processor, semihosting, and whatever memory your ELF file's data segment says you have (plus anything you care to mmap()). > > For instance, this board model claims to handle the M33 > > but makes no attempt to set up any of the TrustZone > > related components like the IDAU, so it isn't really > > a useful platform for that CPU. > > It's sufficient for my purposes, if adding those things would make it > suitable for more people, that'd be awesome. Sure, but "machine-that-works-for-keith-packard" isn't really a very clearly-defined concept :-) > > This is the kind of area where having a real hardware system to check > > against means we make the right choices about what does or doesn't > > need to be present. > > I have tried every single 32-bit ARM emulation provided by qemu and none > of them offer enough memory along with the ability to select an > arbitrary processor. The stellaris code is the closest as it allows > overriding the CPU type, and I've been able to run most of the C library > tests using that. However, both boards supported by that code have a > small fixed memory size, which isn't large enough to run the full test > suite (the math tests require over 1M of ROM and RAM). > Instead of creating another virtual platform, should I be working on the > existing virt code to add cortex-m support? I think that trying to weld M-profile into the A-profile virt board is likely to be more confusing than having a separate board. But I remain unhappy about defining a virtual board at all if I can avoid it. thanks -- PMM
On Fri, Jun 26, 2020 at 10:32 AM Peter Maydell <peter.maydell@linaro.org> wrote: > You might find the user-mode qemu-arm sufficient for that > kind of thing. I know some gcc tests run that way. You > get a processor, semihosting, and whatever memory your > ELF file's data segment says you have (plus anything > you care to mmap()). I routinely run xtensa gcc testsuite in user-mode qemu, the results are the same as when I run it on a remote board emulated by system-mode QEMU. OTOH for the glibc testsuite the results in user-mode and system-mode emulation used to differ significantly. Here's my account of differences: http://wiki.osll.ru/doku.php/etc:users:jcmvbkbc:glibc-xtensa Most of them are due to unsupported/differently implemented syscalls.
Peter Maydell <peter.maydell@linaro.org> writes: > You might find the user-mode qemu-arm sufficient for that > kind of thing. I know some gcc tests run that way. You > get a processor, semihosting, and whatever memory your > ELF file's data segment says you have (plus anything > you care to mmap()). Thanks for the pointer; I've spent a bit of time checking out whether that might work, and it looks like I could get some testing done there, but I couldn't get the chip startup code tested (things like enabling the FPU, setting up the stack, data and bss segments). I had always assumed that qemu-arm was designed to run user-mode Linux applications on top of another Linux system (given that it's called 'arm-linux-user' in the qemu configuration code). That's why I hadn't even tried using it for this work. > Sure, but "machine-that-works-for-keith-packard" isn't really > a very clearly-defined concept :-) It seems well defined to me at least? An ARM core plus memory. That's sufficient to run tests with semihosting to validate compilers, libraries and the like. It would also serve as a model for people developing new QEMU boards to start from; here's a processor and memory, now you add peripherals and you've got a complete system. This is all in service of a pretty easily explained goal -- a free software C library designed for embedded systems that gets tested on the target processors. With QEMU, I'm able to incorporate all of the code necessary right in the library to execute tests on simulated hardware that starts from the reset vector. That same code can run on native hardware, allowing developers to get past the usual embedded development startup hurdle of creating a linker script, writing NVIC interrupt vector table and initializing RAM. I'd like to make the memory parameters configurable so that a developer could set qemu to match their particular SoC. Then they'd be able to run their application under QEMU and at least ensure that it gets to main() before flashing it on the target hardware. > I think that trying to weld M-profile into the A-profile virt > board is likely to be more confusing than having a separate board. > But I remain unhappy about defining a virtual board at all > if I can avoid it. Ok, that was my thinking for doing this as a separate board; the existing virt board seems complex enough without attempting to wedge something very different into it. I'll experiment with the arm-linux-user mode of QEMU a bit more to see how much testing that would enable; it should at least allow testing of the libc and libm functions, although not the crt0 implementation and sample linker scripts. I'd love help in creating a better definition of what the 'virtm' board should be, and figure out a way to explain it so that you appreciate the value it brings to the ARM ecosystem.
Max Filippov <jcmvbkbc@gmail.com> writes: > Most of them are due to unsupported/differently implemented > syscalls. Yeah, I think that was the basis of my confusion -- qemu-arm is not a bare metal environment, and my work is focused on enabling application development in that environment.
On Fri, 26 Jun 2020 at 21:14, Keith Packard <keithp@keithp.com> wrote: > > Max Filippov <jcmvbkbc@gmail.com> writes: > > > Most of them are due to unsupported/differently implemented > > syscalls. > > Yeah, I think that was the basis of my confusion -- qemu-arm is not a > bare metal environment, and my work is focused on enabling application > development in that environment. Yes, but for certain cases of bare-metal code that doesn't need to touch devices or use any privileged-only instructions it may be a usable environment. (This is more side-effect than intentional: as you say the primary use case is Linux userspace binaries.) thanks -- PMM
diff --git a/MAINTAINERS b/MAINTAINERS index 1b40446c73..4c7e394dd6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -850,9 +850,16 @@ Virt M: Peter Maydell <peter.maydell@linaro.org> L: qemu-arm@nongnu.org S: Maintained -F: hw/arm/virt* +F: hw/arm/virt.c +F: hw/arm/virt-acpi-build.c F: include/hw/arm/virt.h +Virt M +M: Keith Packard <keithp@keithp.com> +L: qemu-arm@nongnu.org +S: Maintained +F: hw/arm/virtm.c + Xilinx Zynq M: Edgar E. Iglesias <edgar.iglesias@gmail.com> M: Alistair Francis <alistair@alistair23.me> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 534a6a119e..54be15b40a 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -1,6 +1,6 @@ obj-y += boot.o obj-$(CONFIG_PLATFORM_BUS) += sysbus-fdt.o -obj-$(CONFIG_ARM_VIRT) += virt.o +obj-$(CONFIG_ARM_VIRT) += virt.o virtm.o obj-$(CONFIG_ACPI) += virt-acpi-build.o obj-$(CONFIG_DIGIC) += digic_boards.o obj-$(CONFIG_EXYNOS4) += exynos4_boards.o diff --git a/hw/arm/virtm.c b/hw/arm/virtm.c new file mode 100644 index 0000000000..beda3644f5 --- /dev/null +++ b/hw/arm/virtm.c @@ -0,0 +1,112 @@ +/* + * Virtual ARM Cortex M + * + * Copyright © 2020, Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/arm/boot.h" +#include "hw/boards.h" +#include "exec/address-spaces.h" +#include "hw/arm/armv7m.h" +#include "hw/misc/unimp.h" +#include "cpu.h" + +#define NUM_IRQ_LINES 32 +#define ROM_BASE 0x00000000 +#define ROM_SIZE 0x20000000 +#define RAM_BASE 0x20000000 +#define RAM_SIZE 0x20000000 + +static const char *valid_cpus[] = { + ARM_CPU_TYPE_NAME("cortex-m0"), + ARM_CPU_TYPE_NAME("cortex-m3"), + ARM_CPU_TYPE_NAME("cortex-m33"), + ARM_CPU_TYPE_NAME("cortex-m4"), + ARM_CPU_TYPE_NAME("cortex-m7"), +}; + +static bool cpu_type_valid(const char *cpu) +{ + int i; + + return true; + for (i = 0; i < ARRAY_SIZE(valid_cpus); i++) { + if (strcmp(cpu, valid_cpus[i]) == 0) { + return true; + } + } + return false; +} + +static void machvirtm_init(MachineState *ms) +{ + DeviceState *nvic; + + if (!cpu_type_valid(ms->cpu_type)) { + error_report("virtm: CPU type %s not supported", ms->cpu_type); + exit(1); + } + + MemoryRegion *ram = g_new(MemoryRegion, 1); + MemoryRegion *rom = g_new(MemoryRegion, 1); + MemoryRegion *system_memory = get_system_memory(); + + /* Flash programming is done via the SCU, so pretend it is ROM. */ + memory_region_init_rom(rom, NULL, "virtm.rom", ROM_SIZE, + &error_fatal); + memory_region_add_subregion(system_memory, ROM_BASE, rom); + + memory_region_init_ram(ram, NULL, "virtm.ram", RAM_SIZE, + &error_fatal); + memory_region_add_subregion(system_memory, RAM_BASE, ram); + + nvic = qdev_new(TYPE_ARMV7M); + qdev_prop_set_uint32(nvic, "num-irq", NUM_IRQ_LINES); + qdev_prop_set_string(nvic, "cpu-type", ms->cpu_type); + qdev_prop_set_bit(nvic, "enable-bitband", true); + object_property_set_link(OBJECT(nvic), OBJECT(get_system_memory()), + "memory", &error_abort); + /* This will exit with an error if the user passed us a bad cpu_type */ + sysbus_realize_and_unref(SYS_BUS_DEVICE(nvic), &error_fatal); + + armv7m_load_kernel(ARM_CPU(first_cpu), ms->kernel_filename, ROM_SIZE); +} + +static void virtm_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "Virtual Cortex-M"; + mc->init = machvirtm_init; + mc->ignore_memory_transaction_failures = true; + mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m3"); +} + +static const TypeInfo virtm_type = { + .name = MACHINE_TYPE_NAME("virtm"), + .parent = TYPE_MACHINE, + .class_init = virtm_class_init, +}; + +static void virtm_machine_init(void) +{ + type_register_static(&virtm_type); +} + +type_init(virtm_machine_init)
'virtm' is a hardware target that is designed to be used for compiler and library testing on Cortex-M processors. It supports all cortex-m processors and includes sufficient memory to run even large test cases. Signed-off-by: Keith Packard <keithp@keithp.com> --- MAINTAINERS | 9 +++- hw/arm/Makefile.objs | 2 +- hw/arm/virtm.c | 112 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 hw/arm/virtm.c