Re: [PATCH] target/arm: allow setting SCR_EL3.EnTP2 when FEAT_SME is implemented
On Tue, 4 Oct 2022 09:23:54 +0200 Jerome Forissier wrote: Hi, > Updates write_scr() to allow setting SCR_EL3.EnTP2 when FEAT_SME is > implemented. SCR_EL3 being a 64-bit register, valid_mask is changed > to uint64_t and the SCR_* constants in target/arm/cpu.h are extended > to 64-bit so that masking and bitwise not (~) behave as expected. > > This enables booting Linux with Trusted Firmware-A at EL3 with > "-M virt,secure=on -cpu max". > > Cc: qemu-sta...@nongnu.org > Fixes: 78cb9776662a ("target/arm: Enable SME for -cpu max") > Signed-off-by: Jerome Forissier Good catch! So I can confirm that this fixes the issue, given a TF-A patch to actually enable SME (and SVE). Checked against the ARM ARM, also verified that the defines don't accidentally changed their values. Reviewed-by: Andre Przywara > --- > target/arm/cpu.h| 54 ++--- > target/arm/helper.c | 5 - > 2 files changed, 31 insertions(+), 28 deletions(-) > > diff --git a/target/arm/cpu.h b/target/arm/cpu.h > index 5168e3d837..d5e9949eb6 100644 > --- a/target/arm/cpu.h > +++ b/target/arm/cpu.h > @@ -1653,33 +1653,33 @@ static inline void xpsr_write(CPUARMState *env, > uint32_t val, uint32_t mask) > > #define HPFAR_NS (1ULL << 63) > > -#define SCR_NS(1U << 0) > -#define SCR_IRQ (1U << 1) > -#define SCR_FIQ (1U << 2) > -#define SCR_EA(1U << 3) > -#define SCR_FW(1U << 4) > -#define SCR_AW(1U << 5) > -#define SCR_NET (1U << 6) > -#define SCR_SMD (1U << 7) > -#define SCR_HCE (1U << 8) > -#define SCR_SIF (1U << 9) > -#define SCR_RW(1U << 10) > -#define SCR_ST(1U << 11) > -#define SCR_TWI (1U << 12) > -#define SCR_TWE (1U << 13) > -#define SCR_TLOR (1U << 14) > -#define SCR_TERR (1U << 15) > -#define SCR_APK (1U << 16) > -#define SCR_API (1U << 17) > -#define SCR_EEL2 (1U << 18) > -#define SCR_EASE (1U << 19) > -#define SCR_NMEA (1U << 20) > -#define SCR_FIEN (1U << 21) > -#define SCR_ENSCXT(1U << 25) > -#define SCR_ATA (1U << 26) > -#define SCR_FGTEN (1U << 27) > -#define SCR_ECVEN (1U << 28) > -#define SCR_TWEDEN(1U << 29) > +#define SCR_NS(1ULL << 0) > +#define SCR_IRQ (1ULL << 1) > +#define SCR_FIQ (1ULL << 2) > +#define SCR_EA(1ULL << 3) > +#define SCR_FW(1ULL << 4) > +#define SCR_AW(1ULL << 5) > +#define SCR_NET (1ULL << 6) > +#define SCR_SMD (1ULL << 7) > +#define SCR_HCE (1ULL << 8) > +#define SCR_SIF (1ULL << 9) > +#define SCR_RW(1ULL << 10) > +#define SCR_ST(1ULL << 11) > +#define SCR_TWI (1ULL << 12) > +#define SCR_TWE (1ULL << 13) > +#define SCR_TLOR (1ULL << 14) > +#define SCR_TERR (1ULL << 15) > +#define SCR_APK (1ULL << 16) > +#define SCR_API (1ULL << 17) > +#define SCR_EEL2 (1ULL << 18) > +#define SCR_EASE (1ULL << 19) > +#define SCR_NMEA (1ULL << 20) > +#define SCR_FIEN (1ULL << 21) > +#define SCR_ENSCXT(1ULL << 25) > +#define SCR_ATA (1ULL << 26) > +#define SCR_FGTEN (1ULL << 27) > +#define SCR_ECVEN (1ULL << 28) > +#define SCR_TWEDEN(1ULL << 29) > #define SCR_TWEDELMAKE_64BIT_MASK(30, 4) > #define SCR_TME (1ULL << 34) > #define SCR_AMVOFFEN (1ULL << 35) > diff --git a/target/arm/helper.c b/target/arm/helper.c > index d7bc467a2a..5cde8a0425 100644 > --- a/target/arm/helper.c > +++ b/target/arm/helper.c > @@ -1669,7 +1669,7 @@ static void vbar_write(CPUARMState *env, const > ARMCPRegInfo *ri, > static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t > value) > { > /* Begin with base v8.0 state. */ > -uint32_t valid_mask = 0x3fff; > +uint64_t valid_mask = 0x3fff; > ARMCPU *cpu = env_archcpu(env); > > /* > @@ -1706,6 +1706,9 @@ static void scr_write(CPUARMState *env, const > ARMCPRegInfo *ri, uint64_t value) > if (cpu_isar_feature(aa64_doublefault, cpu)) { > valid_mask |= SCR_EASE | SCR_NMEA; > } > +if (cpu_isar_feature(aa64_sme, cpu)) { > +valid_mask |= SCR_ENTP2; > +} > } else { > valid_mask &= ~(SCR_RW | SCR_ST); > if (cpu_isar_feature(aa32_ras, cpu)) {
Re: [PATCH 05/16] hw/arm: allwinner: Don't enable PSCI conduit when booting guest in EL3
On Sun, 30 Jan 2022 23:35:37 +0100 Niek Linnenbank wrote: Hi, (CC:ing Samuel for his intimate Allwinner BootROM knowledge) > Hi Peter, > > > > On Thu, Jan 27, 2022 at 4:46 PM Peter Maydell > wrote: > > > Change the allwinner-h3 based board to use the new boot.c > > functionality to allow us to enable psci-conduit only if the guest is > > being booted in EL1 or EL2, so that if the user runs guest EL3 > > firmware code our PSCI emulation doesn't get in its way. > > > > To do this we stop setting the psci-conduit property on the CPU > > objects in the SoC code, and instead set the psci_conduit field in > > the arm_boot_info struct to tell the common boot loader code that > > we'd like PSCI if the guest is starting at an EL that it makes sense > > with. > > > > This affects the orangepi-pc board. > > > > This commit leaves the secondary CPUs in the powered-down state if > > the guest is booting at EL3, which is the same behaviour as before > > this commit. The secondaries can no longer be started by that EL3 > > code making a PSCI call but can still be started via the CPU > > Configuration Module registers (which we model in > > hw/misc/allwinner-cpucfg.c). > > > > Signed-off-by: Peter Maydell > > > > While testing your patches on the orangepi-pc machine, I've found that two > acceptance tests BootLinuxConsole.test_arm_orangepi_bionic_20_08 and > BootLinuxConsole.test_arm_orangepi_uboot_netbsd9 of the orangepi-pc board > are no longer passing on current master: > > ARMBIAN_ARTIFACTS_CACHED=yes AVOCADO_ALLOW_LARGE_STORAGE=yes avocado > --show=app,console run -t machine:orangepi-pc > tests/avocado/boot_linux_console.py > ... > (4/5) > tests/avocado/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi_bionic_20_08: > -console: U-Boot SPL 2020.04-armbian (Sep 02 2020 - 10:16:13 +0200) > \console: DRAM: > INTERRUPTED: Test interrupted by SIGTERM\nRunner error occurred: Timeout > reached\nOriginal status: ERROR\n{'name': > '4-tests/avocado/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi_bionic_20_08', > 'logdi> > (5/5) > tests/avocado/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi_uboot_netbsd9: > /console: U-Boot SPL 2020.01+dfsg-1 (Jan 08 2020 - 08:19:44 +) > console: DRAM: > INTERRUPTED: Test interrupted by SIGTERM\nRunner error occurred: Timeout > reached\nOriginal status: ERROR\n{'name': > '5-tests/avocado/boot_linux_console.py:BootLinuxConsole.test_arm_orangepi_uboot_netbsd9', > 'logd> > RESULTS: PASS 3 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 2 | > CANCEL 0 > JOB TIME : 221.25 s > > Bisecting the error I was able to trace it back to commit 5ead62185d > ("memory: Make memory_region_is_mapped() succeed when mapped via an alias"). > I'll try to find the original thread and respond to that with this > information. > > However, with commit 5ead62185d reverted, all tested passed fine: > > ARMBIAN_ARTIFACTS_CACHED=yes AVOCADO_ALLOW_LARGE_STORAGE=yes avocado > --show=app,console run -t machine:orangepi-pc > tests/avocado/boot_linux_console.py > ... > PASS (16.48 s) > RESULTS: PASS 5 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | > CANCEL 0 > JOB TIME : 116.63 s > > So for the orangepi-pc and allwinner-h3: > > Reviewed-by: Niek Linnenbank > Tested-by: Niek Linnenbank > > > > --- > > If anybody knows for definite that the secondaries should be > > powered-down at startup for guest firmware, we can delete the TODO. > > > > Looking at the Allwinner H3 datasheet in 4.4.3.7 page 146, it says that > for the CPU1 Status Register the default value indicates at least that its > not in a > wait for interrupt standby mode. And if I look in U-Boot's > arm/arm/cpu/armv7/sunxi/psci.c code > in the psci_cpu_on implementation, there is an explicit 'power on' part > there, suggesting the secondary CPUs > are by default off. So while I don't have any hard proof, these findings > suggest we are modeling the correct behavior > with secondary CPUs by default off. So when it comes to firmware, indeed the secondaries seem to be off when the first user provided code (boot0/SPL) is entered. However there is an MPIDR read in the BROM, with the corresponding "branch if not primary core". I think this is because the BROM is mapped at the reset vector, so upon SMP firmware releasing the reset line it always starts in ROM, then gets diverted to the actual entry point. Maybe Samuel can confirm that the secondary cores are power gated when the SoCs comes out of reset? Cheers, Andre > > The allwinner-cpucfg.c code makes the reset value for the > > REG_CPU*_RST_CTRL registers "CPUX_RESET_RELEASED", which might > > suggest otherwise, but that could easily just be a QEMU error. > > --- > > hw/arm/allwinner-h3.c | 9 - > > hw/arm/orangepi.c | 1 + > > 2 files changed, 5 insertions(+), 5 deletions(-) > > > > diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c > > index f9b7ed18711..f54aff6d2d2 100644 > > --- a/hw/arm/allwinner-h3.c > > +++
Re: [PATCH v2 00/13] arm gicv3 ITS: Various bug fixes and refactorings
On Wed, 19 Jan 2022 10:15:52 + Peter Maydell wrote: Hi Peter, > On Tue, 18 Jan 2022 at 23:30, Andre Przywara wrote: > > Looking at k-u-t's arm/gic.c and QEMU's hw/intc/arm_gic.c I see two > > problems here: QEMU implements word accesses as four successive calls to > > gic_dist_readb() - which is probably fine if that helps code design, > > but it won't allow it to actually spot access size issues. I just > > remember that we spent some brain cells and CPP macros on getting the > > access size right in KVM - hence those tests in kvm-unit-tests. > > Thanks for looking at this. I should have read the code rather > than dashing off a reply last thing in the evening based just > on the test case output! I think I was confusing how our GICv3 > emulation handles register accesses (with separate functions for > byte/halfword/word/quad accesses) with the GICv2 emulation > (which as you say calls down into the byte emulation code > wherever it can). No worries! > > But more importantly it looks like GICD_IIDR is actually not > > implemented: There is a dubious "if (offset < 0x08) return 0;" line, > > but IIDR (offset 0x8) would actually fall through, and hit the bad_reg > > label, which would return 0 (and cause the message, if enabled). > > Mmm. I actually have a patch in target-arm.next from Petr Pavlu > which implements GICC_IIDR, but we do indeed not implement the > distributor equivalent. Well, returning 0 is actually not the worst idea. Using proper ID values might not even be feasible for QEMU, or would create some hassle with versioning. With 0 all a user can assume is spec compliance. > > If that helps: from a GIC MMIO perspective 8-bit accesses are actually > > the exception rather than the norm (ARM IHI 0048B.b 4.1.4 GIC register > > access). > > Yes. We got this right in the GICv3 emulation design, where almost > all the logic is in the 32-bit accessor functions and the 8/16-bit > functions deal only with the very few registers that have to > permit non-word accesses. Indeed. I dusted off my old GICv3 MMIO patches for kvm-unit-tests, and QEMU passed with flying colours. With the debug switch I see it reporting exactly the violating accesses we except to see. Will send those patches ASAP. > The GICv2 code is a lot older (and to > be fair to it, started out as 11MPcore interrupt controller > emulation, and I bet the docs of that were not very specific about > what registers could or could not be accessed byte at a time). > Unless we want to rewrite all that logic in the GICv2 emulation > (which I at least do not :-)) ... and I can't ... > I think we'll have to live with > the warnings about bad-offsets reporting for each byte rather > than just once for the word access. Yeah, if those warnings appear only with that debug switch, there is probably little reason to change that code just because of this. At least it seemed to work quite well over the years. Cheers, Andre P.S. I changed k-u-t to special case the UP case, so that TCG passes. But now KVM fails, of course. So I will have to make a patch for the kernel ...
Re: [PATCH v2 00/13] arm gicv3 ITS: Various bug fixes and refactorings
On Tue, 18 Jan 2022 19:41:56 + Peter Maydell wrote: Hi Peter, Alex, thanks for the heads up! > On Tue, 18 Jan 2022 at 17:42, Alex Bennée wrote: > > > > > > Peter Maydell writes: > > > > > I've been working on the ITS to add support for the GICv4 functionality. > > > In the course of that I found a handful of bugs in it and also some > > > places where the code benefited from refactoring to make it a better > > > base to put in the GICv4 parts. This patchset is just the bugfixes > > > and cleanups, because there are enough patches here that I figured it > > > made sense to send them out now rather than holding on to them. > > > > > > Most of these patches were in v1 and have been reviewed already. > > > > I've reviewed the patches and they look good to me. kvm-unit-tests is > > still failing some tests but the ones it fails hasn't changed from > > before this patch: > > > > ✗ env QEMU=$HOME/lsrc/qemu.git/builds/arm.all/qemu-system-aarch64 > > ./run_tests.sh -g gic > > PASS gicv2-ipi (3 tests) > > PASS gicv2-mmio (17 tests, 1 skipped) > > FAIL gicv2-mmio-up (17 tests, 2 unexpected failures) > > FAIL gicv2-mmio-3p (17 tests, 3 unexpected failures) > > PASS gicv3-ipi (3 tests) > > PASS gicv2-active (1 tests) > > PASS gicv3-active (1 tests) > > > > That said running with -d unimp,guest_errors there are some things that > > should probably be double checked, e.g.: > > Almost all of the logging seems to be where the test code is > doing stuff that the GIC spec says isn't valid. That sounds like a plausible explanation for a unit test suite, but does not seem to be actually true in this case, see below. > Also, this > test is gicv2, which is unrelated to either the gicv3 code > or to the ITS... This is true. > > > /home/alex/lsrc/qemu.git/builds/arm.all/qemu-system-aarch64 -nodefaults > > -machine virt -accel tcg -cpu cortex-a57 -device virtio-serial-device > > -device virtconsole,chardev= > > ctd -chardev testdev,id=ctd -device pci-testdev -display none -serial > > stdio -kernel arm/gic.flat -machine gic-version=2 -smp 1 -append "mmio" -d > > unimp,guest_errors > > PASS: gicv2: mmio: all CPUs have interrupts > > gic_dist_readb: Bad offset 8 > > gic_dist_readb: Bad offset 9 > > gic_dist_readb: Bad offset a > > gic_dist_readb: Bad offset b > > This is GICD_IIDR, which is a 32-bit register. The test looks like it's > trying to read it as 4 separate bytes, which is out of spec, and > is why our implementation is warning about it. Looking at k-u-t's arm/gic.c and QEMU's hw/intc/arm_gic.c I see two problems here: QEMU implements word accesses as four successive calls to gic_dist_readb() - which is probably fine if that helps code design, but it won't allow it to actually spot access size issues. I just remember that we spent some brain cells and CPP macros on getting the access size right in KVM - hence those tests in kvm-unit-tests. But more importantly it looks like GICD_IIDR is actually not implemented: There is a dubious "if (offset < 0x08) return 0;" line, but IIDR (offset 0x8) would actually fall through, and hit the bad_reg label, which would return 0 (and cause the message, if enabled). Also the name and how it's called suggests that this deals with bytes only, but returns uint32_t, and for instance deals with bit 10 in TYPER. I see how this eventually falls into place magically (the upper three bytes return 0, and get ORed into the >8 bit result of offset 8), but those messages are definitely false alarm then. If that helps: from a GIC MMIO perspective 8-bit accesses are actually the exception rather than the norm (ARM IHI 0048B.b 4.1.4 GIC register access). > > INFO: gicv2: mmio: IIDR: 0x > > gic_dist_writeb: Bad offset 4 > > gic_dist_writeb: Bad offset 5 > > gic_dist_writeb: Bad offset 6 > > gic_dist_writeb: Bad offset 7 > > gic_dist_writeb: Bad offset 4 > > gic_dist_writeb: Bad offset 5 > > gic_dist_writeb: Bad offset 6 > > gic_dist_writeb: Bad offset 7 > > gic_dist_writeb: Bad offset 4 > > gic_dist_writeb: Bad offset 5 > > gic_dist_writeb: Bad offset 6 > > gic_dist_writeb: Bad offset 7 > > These complaints are because the test is trying to write > to GICD_TYPER, which is not permitted. Writes are not permitted, yes, but k-u-t emits a proper str, so there should be only three lines, not twelve. > > PASS: gicv2: mmio: GICD_TYPER is read-only > > gic_dist_readb: Bad offset 8 > > gic_dist_readb: Bad offset 9 > > gic_dist_readb: Bad offset a > > gic_dist_readb: Bad offset b > > More attempts to do byte accesses to a word-only register. The messages come actually again because IIDR is not handled at all, and there are only four of them because of the design of gic_dist_read(). k-u-t issues a proper ldr here. I think we refrained from actually testing illegal access sizes, because that could trigger external aborts/SErrors on real hardware. > > gic_dist_writeb: Bad offset 8 > >
Re: [PATCH 00/16] fdt: Make OF_BOARD a boolean option
On Thu, 14 Oct 2021 09:17:52 -0600 Simon Glass wrote: > Hi Tom, > > On Thu, 14 Oct 2021 at 08:56, Tom Rini wrote: > > > > On Wed, Oct 13, 2021 at 12:06:02PM -0600, Simon Glass wrote: > > > Hi François, > > > > > > On Wed, 13 Oct 2021 at 11:35, François Ozog > > > wrote: > > > > > > > > Hi Simon > > > > > > > > Le mer. 13 oct. 2021 à 16:49, Simon Glass a écrit : > > > > > > > >> > > > >> Hi Tom, Bin,François, > > > >> > > > >> On Tue, 12 Oct 2021 at 19:34, Tom Rini wrote: > > > >> > > > > >> > On Wed, Oct 13, 2021 at 09:29:14AM +0800, Bin Meng wrote: > > > >> > > Hi Simon, > > > >> > > > > > >> > > On Wed, Oct 13, 2021 at 9:01 AM Simon Glass > > > >> > > wrote: > > > >> > > > > > > >> > > > With Ilias' efforts we have dropped OF_PRIOR_STAGE and > > > >> > > > OF_HOSTFILE so > > > >> > > > there are only three ways to obtain a devicetree: > > > >> > > > > > > >> > > >- OF_SEPARATE - the normal way, where the devicetree is built > > > >> > > > and > > > >> > > > appended to U-Boot > > > >> > > >- OF_EMBED - for development purposes, the devicetree is > > > >> > > > embedded in > > > >> > > > the ELF file (also used for EFI) > > > >> > > >- OF_BOARD - the board figures it out on its own > > > >> > > > > > > >> > > > The last one is currently set up so that no devicetree is needed > > > >> > > > at all > > > >> > > > in the U-Boot tree. Most boards do provide one, but some don't. > > > >> > > > Some > > > >> > > > don't even provide instructions on how to boot on the board. > > > >> > > > > > > >> > > > The problems with this approach are documented at [1]. > > > >> > > > > > > >> > > > In practice, OF_BOARD is not really distinct from OF_SEPARATE. > > > >> > > > Any board > > > >> > > > can obtain its devicetree at runtime, even it is has a > > > >> > > > devicetree built > > > >> > > > in U-Boot. This is because U-Boot may be a second-stage > > > >> > > > bootloader and its > > > >> > > > caller may have a better idea about the hardware available in > > > >> > > > the machine. > > > >> > > > This is the case with a few QEMU boards, for example. > > > >> > > > > > > >> > > > So it makes no sense to have OF_BOARD as a 'choice'. It should > > > >> > > > be an > > > >> > > > option, available with either OF_SEPARATE or OF_EMBED. > > > >> > > > > > > >> > > > This series makes this change, adding various missing devicetree > > > >> > > > files > > > >> > > > (and placeholders) to make the build work. > > > >> > > > > > >> > > Adding device trees that are never used sounds like a hack to me. > > > >> > > > > > >> > > For QEMU, device tree is dynamically generated on the fly based on > > > >> > > command line parameters, and the device tree you put in this series > > > >> > > has various hardcoded values which normally do not show > > > >> > > up > > > >> > > in hand-written dts files. > > > >> > > > > > >> > > I am not sure I understand the whole point of this. > > > >> > > > > >> > I am also confused and do not like the idea of adding device trees > > > >> > for > > > >> > platforms that are capable of and can / do have a device tree to > > > >> > give us > > > >> > at run time. > > > >> > > > >> (I'll just reply to this one email, since the same points applies to > > > >> all replies I think) > > > >> > > > >> I have been thinking about this and discussing it with people for a > > > >> few months now. I've been signalling a change like this for over a > > > >> month now, on U-Boot contributor calls and in discussions with Linaro > > > >> people. I sent a patch (below) to try to explain things. I hope it is > > > >> not a surprise! > > > >> > > > >> The issue here is that we need a devicetree in-tree in U-Boot, to > > > >> avoid the mess that has been created by OF_PRIOR_STAGE, OF_BOARD, > > > >> BINMAN_STANDALONE_FDT and to a lesser extent, OF_HOSTFILE. Between > > > >> Ilias' series and this one we can get ourselves on a stronger footing. > > > >> There is just OF_SEPARATE, with OF_EMBED for debugging/ELF use. > > > >> For more context: > > > >> > > > >> http://patchwork.ozlabs.org/project/uboot/patch/20210919215111.3830278-3-...@chromium.org/ > > > >> > > > >> BTW I did suggest to QEMU ARM that they support a way of adding the > > > >> u-boot.dtsi but there was not much interest there (in fact the > > > >> maintainer would prefer there was no special support even for booting > > > >> Linux directly!) > > > > > > > > i understand their point of view and agree with it. > > > >> > > > >> But in any case it doesn't really help U-Boot. I > > > >> think the path forward might be to run QEMU twice, once to get its > > > >> generated tree and once to give the 'merged' tree with the U-Boot > > > >> properties in it, if people want to use U-Boot features. > > > >> > > > >> I do strongly believe that OF_BOARD must be a run-time option, not a > > > >> build-time one. It creates all sorts of problems and obscurity which > > > >> have taken months to
Re: [PATCH 00/16] fdt: Make OF_BOARD a boolean option
On Tue, 12 Oct 2021 19:01:04 -0600 Simon Glass wrote: Hi, > With Ilias' efforts we have dropped OF_PRIOR_STAGE and OF_HOSTFILE so > there are only three ways to obtain a devicetree: > >- OF_SEPARATE - the normal way, where the devicetree is built and > appended to U-Boot >- OF_EMBED - for development purposes, the devicetree is embedded in > the ELF file (also used for EFI) >- OF_BOARD - the board figures it out on its own > > The last one is currently set up so that no devicetree is needed at all > in the U-Boot tree. Most boards do provide one, but some don't. Some > don't even provide instructions on how to boot on the board. > > The problems with this approach are documented at [1]. > > In practice, OF_BOARD is not really distinct from OF_SEPARATE. Any board > can obtain its devicetree at runtime, even it is has a devicetree built > in U-Boot. This is because U-Boot may be a second-stage bootloader and its > caller may have a better idea about the hardware available in the machine. > This is the case with a few QEMU boards, for example. > > So it makes no sense to have OF_BOARD as a 'choice'. It should be an > option, available with either OF_SEPARATE or OF_EMBED. So I am possibly fine with that, but: > This series makes this change, adding various missing devicetree files > (and placeholders) to make the build work. If we just need it to make the build work, we not just have pure stub DTs, as you do for highbank, everywhere? Adding *some* DT files for those platforms that actually do the right thing seems like the wrong direction to me. Providing DTs in the source repositories of the actual consumers is more of a bad habit that dragged on since Linux started this around 10 years ago (for practical reasons). For *some* platforms U-Boot is the firmware component that is in the best situation to provide the DTB (because it's more than a mere bootloader), but for other it's just not. And this is not even looking at really dynamic platforms like QEMU, where providing some kind of fixed DT is just not working. I don't get the argument that people would need to see the DT in the tree to develop code. The DT spec and binding documentation (currently living in the Linux kernel source tree) provide the specification to code against, and the platform specific selection of drivers in Kconfig and _defconfig select the drivers for the devices that people are expected to see. Why does one need actual DT files in the tree? I totally agree on adding more documentation, possibly *pointing* to example DTs or giving commands on how to obtain the actual copy (-dumpdtb, /sys/firmware/devicetree), but don't think that adding some .dts files for platforms that don't need them is the right way. Cheers, Andre. > > It also provides a few qemu clean-ups discovered along the way. > > This series is based on Ilias' two series for OF_HOSTFILE and > OF_PRIOR_STAGE removal. > > It is available at u-boot-dm/ofb-working > > [1] > https://patchwork.ozlabs.org/project/uboot/patch/20210919215111.3830278-3-...@chromium.org/ > > > Simon Glass (16): > arm: qemu: Mention -nographic in the docs > arm: qemu: Explain how to extract the generate devicetree > riscv: qemu: Explain how to extract the generate devicetree > arm: qemu: Add a devicetree file for qemu_arm > arm: qemu: Add a devicetree file for qemu_arm64 > riscv: qemu: Add devicetree files for qemu_riscv32/64 > arm: rpi: Add a devicetree file for rpi_4 > arm: vexpress: Add a devicetree file for juno > arm: xenguest_arm64: Add a fake devicetree file > arm: octeontx: Add a fake devicetree file > arm: xilinx_versal_virt: Add a devicetree file > arm: bcm7xxx: Add a devicetree file > arm: qemu-ppce500: Add a devicetree file > arm: highbank: Add a fake devicetree file > fdt: Make OF_BOARD a bool option > Drop CONFIG_BINMAN_STANDALONE_FDT > > Makefile |3 +- > arch/arm/dts/Makefile | 20 +- > arch/arm/dts/bcm2711-rpi-4-b.dts | 1958 > arch/arm/dts/bcm7xxx.dts | 15 + > arch/arm/dts/highbank.dts | 14 + > arch/arm/dts/juno-r2.dts | 1038 + > arch/arm/dts/octeontx.dts | 14 + > arch/arm/dts/qemu-arm.dts | 402 + > arch/arm/dts/qemu-arm64.dts| 381 + > arch/arm/dts/xenguest-arm64.dts| 15 + > arch/arm/dts/xilinx-versal-virt.dts| 307 > arch/powerpc/dts/Makefile |1 + > arch/powerpc/dts/qemu-ppce500.dts | 264 > arch/riscv/dts/Makefile|2 +- > arch/riscv/dts/qemu-virt.dts |8 - > arch/riscv/dts/qemu-virt32.dts | 217 +++ > arch/riscv/dts/qemu-virt64.dts | 217 +++ > configs/bcm7260_defconfig |1 + > configs/bcm7445_defconfig |1 + > configs/highbank_defconfig |2 +- >
Re: arm: Launching EFI-enabled arm32 Linux
On Wed, 8 Sep 2021 01:25:04 +0200 Adam Lackorzynski wrote: Hi Adam, > On Mon Sep 06, 2021 at 16:34:03 +0100, Andre Przywara wrote: > > On Sat, 4 Sep 2021 21:26:45 +0200 > > Adam Lackorzynski wrote: > > > > Hi Adam, > > > > > while trying to launch an EFI-enabled arm32 Linux binary (zImage) I > > > noticed I get an undefined instruction exception on the first > > > instruction. Now this is a bit special because Linux uses a nop > > > instruction there that also is a PE file signature ('MZ') such that the > > > CPU runs over it and the file is still recognized as a PE binary. Linux > > > uses 0x13105a4d (tstne r0, #0x4d000) as the instruction (see also > > > arch/arm/boot/compressed/head.S and efi-header.S in Linux). > > > However, QEMU's instruction decoder will only recognize TST with bits > > > 12-15 being 0, which this instruction is not fullfilling, and thus the > > > undef exception. I guess other CPU implementations will allow this > > > encoding. So while investigating I was doing the following to make Linux > > > proceed. I also believe this was working in a previous version of QEMU. > > > > > > diff --git a/target/arm/a32.decode b/target/arm/a32.decode > > > index fcd8cd4f7d..222553750e 100644 > > > --- a/target/arm/a32.decode > > > +++ b/target/arm/a32.decode > > > @@ -127,7 +127,7 @@ ADD_rri 001 0100 . > > > @s_rri_rot > > > ADC_rri 001 0101 . @s_rri_rot > > > SBC_rri 001 0110 . @s_rri_rot > > > RSC_rri 001 0111 . @s_rri_rot > > > -TST_xri 001 1000 1 @S_xri_rot > > > +TST_xri 001 1000 1 @S_xri_rot > > > TEQ_xri 001 1001 1 @S_xri_rot > > > CMP_xri 001 1010 1 @S_xri_rot > > > CMN_xri 001 1011 1 @S_xri_rot > > > > > > > > > Any thoughts on this? > > > > thanks for the report, I was looking at this and have a kernel patch > > to fix this properly as Peter suggested. And while I agree on the > > problem, I was struggling to reproduce this in reality: both with > > -kernel and when booting through U-Boot the "Z" bit is set, which lets > > QEMU not even bother about the rest of the encoding - the condition > > flags don't match, so it proceeds. If I change the __nop to use "tsteq", > > I see it hanging due to the missing exception handler, but not with > > "tstne". > > So can you say how you spotted this issue? This would be needed as a > > justification for patching the guts of the ARM Linux kernel port. > > Good point with the condition flags. I'm doing this with our own vmm > where I'm loading the binary directly as the payload (as mandated by the > header), and where psr is set to a defined value with all flags cleared. Right, I was thinking something like this. > If I set the Z bit than it also works (of course). > Looking a bit around in QEMU as well as u-boot I it looks like this is > rather by luck how flags are set. Yes, the kernel boot protocol doesn't say anything about the condition flags, so any combination would be valid and we were just lucky before. I did also test on an Cortex-A7 and A53, both ignore bits [15:12] (so execute the instruction as if they were 0), which explains why it works on real hardware. > Thanks for doing the Linux patch, I'll scrap mine, and also thanks to > Peter for the idea! Oh, didn't want to cut you off, if you want to have the commit: be my guest! Otherwise I will send something tomorrow, with a Reported-by: to you. Grüße an die Elbe! Cheers, Andre
Re: arm: Launching EFI-enabled arm32 Linux
On Sat, 4 Sep 2021 21:26:45 +0200 Adam Lackorzynski wrote: Hi Adam, > while trying to launch an EFI-enabled arm32 Linux binary (zImage) I > noticed I get an undefined instruction exception on the first > instruction. Now this is a bit special because Linux uses a nop > instruction there that also is a PE file signature ('MZ') such that the > CPU runs over it and the file is still recognized as a PE binary. Linux > uses 0x13105a4d (tstne r0, #0x4d000) as the instruction (see also > arch/arm/boot/compressed/head.S and efi-header.S in Linux). > However, QEMU's instruction decoder will only recognize TST with bits > 12-15 being 0, which this instruction is not fullfilling, and thus the > undef exception. I guess other CPU implementations will allow this > encoding. So while investigating I was doing the following to make Linux > proceed. I also believe this was working in a previous version of QEMU. > > diff --git a/target/arm/a32.decode b/target/arm/a32.decode > index fcd8cd4f7d..222553750e 100644 > --- a/target/arm/a32.decode > +++ b/target/arm/a32.decode > @@ -127,7 +127,7 @@ ADD_rri 001 0100 . > @s_rri_rot > ADC_rri 001 0101 . @s_rri_rot > SBC_rri 001 0110 . @s_rri_rot > RSC_rri 001 0111 . @s_rri_rot > -TST_xri 001 1000 1 @S_xri_rot > +TST_xri 001 1000 1 @S_xri_rot > TEQ_xri 001 1001 1 @S_xri_rot > CMP_xri 001 1010 1 @S_xri_rot > CMN_xri 001 1011 1 @S_xri_rot > > > Any thoughts on this? thanks for the report, I was looking at this and have a kernel patch to fix this properly as Peter suggested. And while I agree on the problem, I was struggling to reproduce this in reality: both with -kernel and when booting through U-Boot the "Z" bit is set, which lets QEMU not even bother about the rest of the encoding - the condition flags don't match, so it proceeds. If I change the __nop to use "tsteq", I see it hanging due to the missing exception handler, but not with "tstne". So can you say how you spotted this issue? This would be needed as a justification for patching the guts of the ARM Linux kernel port. Cheers, Andre
Re: [kvm-unit-tests PATCH v2 5/9] arm: pmu: Basic event counter Tests
On Thu, 30 Jan 2020 12:25:06 +0100 Eric Auger wrote: > Adds the following tests: > - event-counter-config: test event counter configuration > - basic-event-count: > - programs counters #0 and #1 to count 2 required events > (resp. CPU_CYCLES and INST_RETIRED). Counter #0 is preset > to a value close enough to the 32b > overflow limit so that we check the overflow bit is set > after the execution of the asm loop. > - mem-access: counts MEM_ACCESS event on counters #0 and #1 > with and without 32-bit overflow. > > Signed-off-by: Eric Auger > > --- > > v1 -> v2: > - fix PMCNTENSET_EL0 and PMCNTENCLR_EL0 op0 > - print PMEVTYPER SH > - properly clobber used regs and add "cc" > - simplify mem_access_loop > --- > arm/pmu.c | 269 ++ > arm/unittests.cfg | 18 > 2 files changed, 287 insertions(+) > > diff --git a/arm/pmu.c b/arm/pmu.c > index 4a26a76..1b0101f 100644 > --- a/arm/pmu.c > +++ b/arm/pmu.c > @@ -18,9 +18,15 @@ > #include "asm/barrier.h" > #include "asm/sysreg.h" > #include "asm/processor.h" > +#include > +#include > > #define PMU_PMCR_E (1 << 0) > +#define PMU_PMCR_P (1 << 1) > #define PMU_PMCR_C (1 << 2) > +#define PMU_PMCR_D (1 << 3) > +#define PMU_PMCR_X (1 << 4) > +#define PMU_PMCR_DP(1 << 5) > #define PMU_PMCR_LC(1 << 6) > #define PMU_PMCR_N_SHIFT 11 > #define PMU_PMCR_N_MASK0x1f > @@ -104,6 +110,9 @@ static inline void precise_instrs_loop(int loop, uint32_t > pmcr) > > /* event counter tests only implemented for aarch64 */ > static void test_event_introspection(void) {} > +static void test_event_counter_config(void) {} > +static void test_basic_event_count(void) {} > +static void test_mem_access(void) {} > > #elif defined(__aarch64__) > #define ID_AA64DFR0_PERFMON_SHIFT 8 > @@ -145,6 +154,33 @@ static inline void precise_instrs_loop(int loop, > uint32_t pmcr) > } > > #define PMCEID1_EL0 sys_reg(3, 3, 9, 12, 7) > +#define PMCNTENSET_EL0 sys_reg(3, 3, 9, 12, 1) > +#define PMCNTENCLR_EL0 sys_reg(3, 3, 9, 12, 2) > + > +#define PMEVTYPER_EXCLUDE_EL1 (1 << 31) > +#define PMEVTYPER_EXCLUDE_EL0 (1 << 30) Please use 1U << or BIT() ;-) Rest looks OK now: Reviewed-by: Andre Przywara > + > +#define regn_el0(__reg, __n) __reg ## __n ## _el0 > +#define write_regn(__reg, __n, __val) \ > + write_sysreg((__val), __reg ## __n ## _el0) > + > +#define read_regn(__reg, __n) \ > + read_sysreg(__reg ## __n ## _el0) > + > +#define print_pmevtyper(__s, __n) do { \ > + uint32_t val; \ > + val = read_regn(pmevtyper, __n);\ > + report_info("%s pmevtyper%d=0x%x, eventcount=0x%x (p=%ld, u=%ld > nsk=%ld, nsu=%ld, nsh=%ld m=%ld, mt=%ld, sh=%ld)", \ > + (__s), (__n), val, val & 0x,\ > + (BIT_MASK(31) & val) >> 31, \ > + (BIT_MASK(30) & val) >> 30, \ > + (BIT_MASK(29) & val) >> 29, \ > + (BIT_MASK(28) & val) >> 28, \ > + (BIT_MASK(27) & val) >> 27, \ > + (BIT_MASK(26) & val) >> 26, \ > + (BIT_MASK(25) & val) >> 25);\ > + (BIT_MASK(24) & val) >> 24);\ > + } while (0) > > static bool is_event_supported(uint32_t n, bool warn) > { > @@ -198,6 +234,230 @@ static void test_event_introspection(void) > report(required_events, "Check required events are implemented"); > } > > +/* > + * Extra instructions inserted by the compiler would be difficult to > compensate > + * for, so hand assemble everything between, and including, the PMCR accesses > + * to start and stop counting. isb instructions are inserted to make sure > + * pmccntr read after this function returns the exact instructions executed > + * in the controlled block. Loads @loop times the data at @address into x9. > + */ > +static void mem_access_loop(void *addr, int loop, uint32_t pmcr) > +{ > +asm volatile( > + " msr pmcr_el0, %[pmcr]\n" > + " isb\n" > + " mov x10, %[loop]\n" > + "1: sub x10, x10, #1\n" > + " ldr x9, [%[addr]]\n" > + " cmp x10, #0x0\n" > + " b.gt1b\n" > + "
Re: [kvm-unit-tests PATCH v2 4/9] arm: pmu: Check Required Event Support
On Thu, 30 Jan 2020 12:25:05 +0100 Eric Auger wrote: Hi, > If event counters are implemented check the common events > required by the PMUv3 are implemented. > > Some are unconditionally required (SW_INCR, CPU_CYCLES, > either INST_RETIRED or INST_SPEC). Some others only are > required if the implementation implements some other features. > > Check those wich are unconditionally required. > > This test currently fails on TCG as neither INST_RETIRED > or INST_SPEC are supported. > > Signed-off-by: Eric Auger > > --- > > v1 -> v2: > - fix is_event_supported() > - fix boolean condition for PMU v4 > - fix PMCEID0 definition > > RFC ->v1: > - add a comment to explain the PMCEID0/1 splits > --- > arm/pmu.c | 62 +++ > arm/unittests.cfg | 6 + > 2 files changed, 68 insertions(+) > > diff --git a/arm/pmu.c b/arm/pmu.c > index d24857e..4a26a76 100644 > --- a/arm/pmu.c > +++ b/arm/pmu.c > @@ -101,6 +101,10 @@ static inline void precise_instrs_loop(int loop, > uint32_t pmcr) > : [pmcr] "r" (pmcr), [z] "r" (0) > : "cc"); > } > + > +/* event counter tests only implemented for aarch64 */ > +static void test_event_introspection(void) {} > + > #elif defined(__aarch64__) > #define ID_AA64DFR0_PERFMON_SHIFT 8 > #define ID_AA64DFR0_PERFMON_MASK 0xf > @@ -139,6 +143,61 @@ static inline void precise_instrs_loop(int loop, > uint32_t pmcr) > : [pmcr] "r" (pmcr) > : "cc"); > } > + > +#define PMCEID1_EL0 sys_reg(3, 3, 9, 12, 7) > + > +static bool is_event_supported(uint32_t n, bool warn) > +{ > + uint64_t pmceid0 = read_sysreg(pmceid0_el0); > + uint64_t pmceid1 = read_sysreg_s(PMCEID1_EL0); > + bool supported; > + uint64_t reg; > + > + /* > + * The low 32-bits of PMCEID0/1 respectly describe > + * event support for events 0-31/32-63. Their High > + * 32-bits describe support for extended events > + * starting at 0x4000, using the same split. > + */ > + if (n >= 0x0 && n <= 0x3F) > + reg = (pmceid0 & 0x) | ((pmceid1 & 0x) << 32); > + else if (n >= 0x4000 && n <= 0x403F) > + reg = (pmceid0 >> 32) | ((pmceid1 >> 32) << 32); > + else > + abort(); > + > + supported = reg & (1UL << (n & 0x3F)); > + > + if (!supported && warn) > + report_info("event %d is not supported", n); > + return supported; > +} > + > +static void test_event_introspection(void) > +{ > + bool required_events; > + > + if (!pmu.nb_implemented_counters) { > + report_skip("No event counter, skip ..."); > + return; > + } > + > + /* PMUv3 requires an implementation includes some common events */ > + required_events = is_event_supported(0x0, true) /* SW_INCR */ && > + is_event_supported(0x11, true) /* CPU_CYCLES */ && > + (is_event_supported(0x8, true) /* INST_RETIRED */ || > +is_event_supported(0x1B, true) /* INST_PREC */); > + > + if (pmu.version == 0x4) { I think this should read >= 0x4, since those requirements are stacked on top of the prevision revision's requirements. Even better with some symbolic name. With that fixed: Reviewed-by: Andre Przywara Cheers, Andre > + /* ARMv8.1 PMU: STALL_FRONTEND and STALL_BACKEND are required */ > + required_events = required_events && > + is_event_supported(0x23, true) && > + is_event_supported(0x24, true); > + } > + > + report(required_events, "Check required events are implemented"); > +} > + > #endif > > /* > @@ -326,6 +385,9 @@ int main(int argc, char *argv[]) > "Monotonically increasing cycle count"); > report(check_cpi(cpi), "Cycle/instruction ratio"); > pmccntr64_test(); > + } else if (strcmp(argv[1], "event-introspection") == 0) { > + report_prefix_push(argv[1]); > + test_event_introspection(); > } else { > report_abort("Unknown sub-test '%s'", argv[1]); > } > diff --git a/arm/unittests.cfg b/arm/unittests.cfg > index 79f0d7a..4433ef3 100644 > --- a/arm/unittests.cfg > +++ b/arm/unittests.cfg > @@ -66,6 +66,12 @@ file = pmu.flat > groups = pmu > extra_params = -append 'cycle-counter 0' > > +[pmu-event-introspection] > +file = pmu.flat > +groups = pmu > +arch = arm64 > +extra_params = -append 'event-introspection' > + > # Test PMU support (TCG) with -icount IPC=1 > #[pmu-tcg-icount-1] > #file = pmu.flat
Re: [kvm-unit-tests PATCH v2 2/9] arm: pmu: Let pmu tests take a sub-test parameter
On Thu, 30 Jan 2020 12:25:03 +0100 Eric Auger wrote: > As we intend to introduce more PMU tests, let's add > a sub-test parameter that will allow to categorize > them. Existing tests are in the cycle-counter category. > > Signed-off-by: Eric Auger Did you change anything? Or just forgot to add my previous R-b? Anyway, Reviewed-by: Andre Przywara Cheers, Andre > --- > arm/pmu.c | 24 +++- > arm/unittests.cfg | 7 --- > 2 files changed, 19 insertions(+), 12 deletions(-) > > diff --git a/arm/pmu.c b/arm/pmu.c > index d5a03a6..e5e012d 100644 > --- a/arm/pmu.c > +++ b/arm/pmu.c > @@ -287,22 +287,28 @@ int main(int argc, char *argv[]) > { > int cpi = 0; > > - if (argc > 1) > - cpi = atol(argv[1]); > - > if (!pmu_probe()) { > printf("No PMU found, test skipped...\n"); > return report_summary(); > } > > + if (argc < 2) > + report_abort("no test specified"); > + > report_prefix_push("pmu"); > > - report(check_pmcr(), "Control register"); > - report(check_cycles_increase(), > -"Monotonically increasing cycle count"); > - report(check_cpi(cpi), "Cycle/instruction ratio"); > - > - pmccntr64_test(); > + if (strcmp(argv[1], "cycle-counter") == 0) { > + report_prefix_push(argv[1]); > + if (argc > 2) > + cpi = atol(argv[2]); > + report(check_pmcr(), "Control register"); > + report(check_cycles_increase(), > +"Monotonically increasing cycle count"); > + report(check_cpi(cpi), "Cycle/instruction ratio"); > + pmccntr64_test(); > + } else { > + report_abort("Unknown sub-test '%s'", argv[1]); > + } > > return report_summary(); > } > diff --git a/arm/unittests.cfg b/arm/unittests.cfg > index daeb5a0..79f0d7a 100644 > --- a/arm/unittests.cfg > +++ b/arm/unittests.cfg > @@ -61,21 +61,22 @@ file = pci-test.flat > groups = pci > > # Test PMU support > -[pmu] > +[pmu-cycle-counter] > file = pmu.flat > groups = pmu > +extra_params = -append 'cycle-counter 0' > > # Test PMU support (TCG) with -icount IPC=1 > #[pmu-tcg-icount-1] > #file = pmu.flat > -#extra_params = -icount 0 -append '1' > +#extra_params = -icount 0 -append 'cycle-counter 1' > #groups = pmu > #accel = tcg > > # Test PMU support (TCG) with -icount IPC=256 > #[pmu-tcg-icount-256] > #file = pmu.flat > -#extra_params = -icount 8 -append '256' > +#extra_params = -icount 8 -append 'cycle-counter 256' > #groups = pmu > #accel = tcg >
Re: [kvm-unit-tests PATCH v2 3/9] arm: pmu: Add a pmu struct
On Thu, 30 Jan 2020 12:25:04 +0100 Eric Auger wrote: > This struct aims at storing information potentially used by > all tests such as the pmu version, the read-only part of the > PMCR, the number of implemented event counters, ... > > Signed-off-by: Eric Auger As I stated already in v1: Reviewed-by: Andre Przywara Cheers, Andre > --- > arm/pmu.c | 30 +- > 1 file changed, 25 insertions(+), 5 deletions(-) > > diff --git a/arm/pmu.c b/arm/pmu.c > index e5e012d..d24857e 100644 > --- a/arm/pmu.c > +++ b/arm/pmu.c > @@ -33,7 +33,14 @@ > > #define NR_SAMPLES 10 > > -static unsigned int pmu_version; > +struct pmu { > + unsigned int version; > + unsigned int nb_implemented_counters; > + uint32_t pmcr_ro; > +}; > + > +static struct pmu pmu; > + > #if defined(__arm__) > #define ID_DFR0_PERFMON_SHIFT 24 > #define ID_DFR0_PERFMON_MASK 0xf > @@ -265,7 +272,7 @@ static bool check_cpi(int cpi) > static void pmccntr64_test(void) > { > #ifdef __arm__ > - if (pmu_version == 0x3) { > + if (pmu.version == 0x3) { > if (ERRATA(9e3f7a296940)) { > write_sysreg(0xdead, PMCCNTR64); > report(read_sysreg(PMCCNTR64) == 0xdead, "pmccntr64"); > @@ -278,9 +285,22 @@ static void pmccntr64_test(void) > /* Return FALSE if no PMU found, otherwise return TRUE */ > static bool pmu_probe(void) > { > - pmu_version = get_pmu_version(); > - report_info("PMU version: %d", pmu_version); > - return pmu_version != 0 && pmu_version != 0xf; > + uint32_t pmcr; > + > + pmu.version = get_pmu_version(); > + report_info("PMU version: %d", pmu.version); > + > + if (pmu.version == 0 || pmu.version == 0xF) > + return false; > + > + pmcr = get_pmcr(); > + pmu.pmcr_ro = pmcr & 0xFF80; > + pmu.nb_implemented_counters = > + (pmcr >> PMU_PMCR_N_SHIFT) & PMU_PMCR_N_MASK; > + report_info("Implements %d event counters", > + pmu.nb_implemented_counters); > + > + return true; > } > > int main(int argc, char *argv[])
Re: [kvm-unit-tests PATCH 05/10] arm: pmu: Basic event counter Tests
On Mon, 16 Dec 2019 21:47:52 +0100 Eric Auger wrote: Hi Eric, thanks a lot for your work on these elaborate tests! I have some PMU test extensions as well, but they are nowhere as sophisticated as yours! Just ran this on my ThunderX2 desktop (4.15.0-65-generic #74-Ubuntu kernel, QEMU emulator version 2.11.1(Debian 1:2.11+dfsg-1ubuntu7.21)), and it reported the following fails: INFO: pmu: basic-event-count: counter #0 is 0x207e (CPU_CYCLES) INFO: pmu: basic-event-count: counter #1 is 0xc89 (INST_RETIRED) INFO: pmu: basic-event-count: overflow reg = 0x0 FAIL: pmu: basic-event-count: check overflow happened on #0 only INFO: PMU version: 4 INFO: Implements 6 event counters INFO: pmu: mem-access: counter #0 is 1297 (MEM_ACCESS) INFO: pmu: mem-access: counter #1 is 1287 (MEM_ACCESS) FAIL: pmu: mem-access: Ran 20 mem accesses FAIL: pmu: mem-access: Ran 20 mem accesses with expected overflows on both counters INFO: pmu: mem-access: cnt#0 = 1353 cnt#1=1259 overflow=0x0 Do you know about this? Is this due to kernel bugs? Because Ubuntu cleverly chose an EOL kernel for their stable distro :-P Will try to have a look and repeat on a Juno. Comments inline > Adds the following tests: > - event-counter-config: test event counter configuration > - basic-event-count: > - programs counters #0 and #1 to count 2 required events > (resp. CPU_CYCLES and INST_RETIRED). Counter #0 is preset > to a value close enough to the 32b > overflow limit so that we check the overflow bit is set > after the execution of the asm loop. > - mem-access: counts MEM_ACCESS event on counters #0 and #1 > with and without 32-bit overflow. > > Signed-off-by: Eric Auger > --- > arm/pmu.c | 261 ++ > arm/unittests.cfg | 18 > 2 files changed, 279 insertions(+) > > diff --git a/arm/pmu.c b/arm/pmu.c > index d88ef22..139dae3 100644 > --- a/arm/pmu.c > +++ b/arm/pmu.c > @@ -18,9 +18,15 @@ > #include "asm/barrier.h" > #include "asm/sysreg.h" > #include "asm/processor.h" > +#include > +#include > > #define PMU_PMCR_E (1 << 0) > +#define PMU_PMCR_P (1 << 1) > #define PMU_PMCR_C (1 << 2) > +#define PMU_PMCR_D (1 << 3) > +#define PMU_PMCR_X (1 << 4) > +#define PMU_PMCR_DP(1 << 5) > #define PMU_PMCR_LC(1 << 6) > #define PMU_PMCR_N_SHIFT 11 > #define PMU_PMCR_N_MASK0x1f > @@ -104,6 +110,9 @@ static inline void precise_instrs_loop(int loop, uint32_t > pmcr) > > /* event counter tests only implemented for aarch64 */ > static void test_event_introspection(void) {} > +static void test_event_counter_config(void) {} > +static void test_basic_event_count(void) {} > +static void test_mem_access(void) {} > > #elif defined(__aarch64__) > #define ID_AA64DFR0_PERFMON_SHIFT 8 > @@ -145,6 +154,32 @@ static inline void precise_instrs_loop(int loop, > uint32_t pmcr) > } > > #define PMCEID1_EL0 sys_reg(11, 3, 9, 12, 7) > +#define PMCNTENSET_EL0 sys_reg(11, 3, 9, 12, 1) > +#define PMCNTENCLR_EL0 sys_reg(11, 3, 9, 12, 2) op0 (the first argument) is only two bits, so it should read "3" instead of "11" here. That's already a bug in the existing PMCEID1_EL0 definition. We get away with it because the macro masks with 3, but it should be still written correctly here. Not sure where the "11" actually comes from. > + > +#define PMEVTYPER_EXCLUDE_EL1 (1 << 31) > +#define PMEVTYPER_EXCLUDE_EL0 (1 << 30) > + > +#define regn_el0(__reg, __n) __reg ## __n ## _el0 > +#define write_regn(__reg, __n, __val) \ > + write_sysreg((__val), __reg ## __n ## _el0) > + > +#define read_regn(__reg, __n) \ > + read_sysreg(__reg ## __n ## _el0) > + > +#define print_pmevtyper(__s, __n) do { \ > + uint32_t val; \ > + val = read_regn(pmevtyper, __n);\ > + report_info("%s pmevtyper%d=0x%x, eventcount=0x%x (p=%ld, u=%ld > nsk=%ld, nsu=%ld, nsh=%ld m=%ld, mt=%ld)", \ > + (__s), (__n), val, val & 0x, \ > + (BIT_MASK(31) & val) >> 31, \ > + (BIT_MASK(30) & val) >> 30, \ > + (BIT_MASK(29) & val) >> 29, \ > + (BIT_MASK(28) & val) >> 28, \ > + (BIT_MASK(27) & val) >> 27, \ > + (BIT_MASK(26) & val) >> 26, \ > + (BIT_MASK(25) & val) >> 25); \ Just a nit, but later versions of the ARMv8 ARM list bit 24 as "SH", for filtering Secure EL2 events. For the sake of completeness you could add this as well, since we list the EL3 filter bit as well. > + } while (0) > > static bool is_event_supported(uint32_t n, bool warn) > { > @@ -207,6 +242,223 @@ static void test_event_introspection(void) > report(required_events, "Check required events are implemented"); > } > > +static inline void mem_access_loop(void *addr, int loop, uint32_t pmcr) Do we really need the "inline" here? If you rely on this being inlined, we need something stronger, I
Re: [kvm-unit-tests PATCH 04/10] arm: pmu: Check Required Event Support
On Mon, 16 Dec 2019 21:47:51 +0100 Eric Auger wrote: Hi Eric, > If event counters are implemented check the common events > required by the PMUv3 are implemented. > > Some are unconditionally required (SW_INCR, CPU_CYCLES, > either INST_RETIRED or INST_SPEC). Some others only are > required if the implementation implements some other features. > > Check those wich are unconditionally required. > > This test currently fails on TCG as neither INST_RETIRED > or INST_SPEC are supported. > > Signed-off-by: Eric Auger > > --- > > v1 ->v2: > - add a comment to explain the PMCEID0/1 splits > --- > arm/pmu.c | 71 +++ > arm/unittests.cfg | 6 > 2 files changed, 77 insertions(+) > > diff --git a/arm/pmu.c b/arm/pmu.c > index d24857e..d88ef22 100644 > --- a/arm/pmu.c > +++ b/arm/pmu.c > @@ -101,6 +101,10 @@ static inline void precise_instrs_loop(int loop, > uint32_t pmcr) > : [pmcr] "r" (pmcr), [z] "r" (0) > : "cc"); > } > + > +/* event counter tests only implemented for aarch64 */ > +static void test_event_introspection(void) {} > + > #elif defined(__aarch64__) > #define ID_AA64DFR0_PERFMON_SHIFT 8 > #define ID_AA64DFR0_PERFMON_MASK 0xf > @@ -139,6 +143,70 @@ static inline void precise_instrs_loop(int loop, > uint32_t pmcr) > : [pmcr] "r" (pmcr) > : "cc"); > } > + > +#define PMCEID1_EL0 sys_reg(11, 3, 9, 12, 7) > + > +static bool is_event_supported(uint32_t n, bool warn) > +{ > + uint64_t pmceid0 = read_sysreg(pmceid0_el0); > + uint64_t pmceid1 = read_sysreg_s(PMCEID1_EL0); > + bool supported; > + uint32_t reg; > + > + /* > + * The low 32-bits of PMCEID0/1 respectly describe > + * event support for events 0-31/32-63. Their High > + * 32-bits describe support for extended events > + * starting at 0x4000, using the same split. > + */ > + if (n >= 0x0 && n <= 0x1F) > + reg = pmceid0 & 0x; > + else if (n >= 0x4000 && n <= 0x401F) > + reg = pmceid0 >> 32; > + else if (n >= 0x20 && n <= 0x3F) > + reg = pmceid1 & 0x; > + else if (n >= 0x4020 && n <= 0x403F) > + reg = pmceid1 >> 32; > + else > + abort(); > + > + supported = reg & (1 << n); Don't we need to mask off everything but the lowest 5 bits of "n"? Probably also using "1U" is better. > + if (!supported && warn) > + report_info("event %d is not supported", n); > + return supported; > +} > + > +static void test_event_introspection(void) "introspection" sounds quite sophisticated. Are you planning to extend this? If not, could we maybe rename it to "test_available_events"? > +{ > + bool required_events; > + > + if (!pmu.nb_implemented_counters) { > + report_skip("No event counter, skip ..."); > + return; > + } > + > + /* PMUv3 requires an implementation includes some common events */ > + required_events = is_event_supported(0x0, true) /* SW_INCR */ && > + is_event_supported(0x11, true) /* CPU_CYCLES */ && > + (is_event_supported(0x8, true) /* INST_RETIRED */ || > +is_event_supported(0x1B, true) /* INST_PREC */); > + > + if (pmu.version == 0x4) { > + /* ARMv8.1 PMU: STALL_FRONTEND and STALL_BACKEND are required */ > + required_events = required_events || > + is_event_supported(0x23, true) || Shouldn't those two operators be '&&' instead? > + is_event_supported(0x24, true); > + } > + > + /* > + * L1D_CACHE_REFILL(0x3) and L1D_CACHE(0x4) are only required if > + * L1 data / unified cache. BR_MIS_PRED(0x10), BR_PRED(0x12) are only > + * required if program-flow prediction is implemented. > + */ Is this a TODO? Cheers, Andre > + > + report(required_events, "Check required events are implemented"); > +} > + > #endif > > /* > @@ -326,6 +394,9 @@ int main(int argc, char *argv[]) > "Monotonically increasing cycle count"); > report(check_cpi(cpi), "Cycle/instruction ratio"); > pmccntr64_test(); > + } else if (strcmp(argv[1], "event-introspection") == 0) { > + report_prefix_push(argv[1]); > + test_event_introspection(); > } else { > report_abort("Unknown sub-test '%s'", argv[1]); > } > diff --git a/arm/unittests.cfg b/arm/unittests.cfg > index 79f0d7a..4433ef3 100644 > --- a/arm/unittests.cfg > +++ b/arm/unittests.cfg > @@ -66,6 +66,12 @@ file = pmu.flat > groups = pmu > extra_params = -append 'cycle-counter 0' > > +[pmu-event-introspection] > +file = pmu.flat > +groups = pmu > +arch = arm64 > +extra_params = -append 'event-introspection' > + > # Test PMU support (TCG) with -icount IPC=1 > #[pmu-tcg-icount-1] > #file = pmu.flat
Re: [kvm-unit-tests PATCH 03/10] arm: pmu: Add a pmu struct
On Mon, 16 Dec 2019 21:47:50 +0100 Eric Auger wrote: > This struct aims at storing information potentially used by > all tests such as the pmu version, the read-only part of the > PMCR, the number of implemented event counters, ... > > Signed-off-by: Eric Auger Reviewed-by: Andre Przywara Cheers, Andre > --- > arm/pmu.c | 30 +- > 1 file changed, 25 insertions(+), 5 deletions(-) > > diff --git a/arm/pmu.c b/arm/pmu.c > index e5e012d..d24857e 100644 > --- a/arm/pmu.c > +++ b/arm/pmu.c > @@ -33,7 +33,14 @@ > > #define NR_SAMPLES 10 > > -static unsigned int pmu_version; > +struct pmu { > + unsigned int version; > + unsigned int nb_implemented_counters; > + uint32_t pmcr_ro; > +}; > + > +static struct pmu pmu; > + > #if defined(__arm__) > #define ID_DFR0_PERFMON_SHIFT 24 > #define ID_DFR0_PERFMON_MASK 0xf > @@ -265,7 +272,7 @@ static bool check_cpi(int cpi) > static void pmccntr64_test(void) > { > #ifdef __arm__ > - if (pmu_version == 0x3) { > + if (pmu.version == 0x3) { > if (ERRATA(9e3f7a296940)) { > write_sysreg(0xdead, PMCCNTR64); > report(read_sysreg(PMCCNTR64) == 0xdead, "pmccntr64"); > @@ -278,9 +285,22 @@ static void pmccntr64_test(void) > /* Return FALSE if no PMU found, otherwise return TRUE */ > static bool pmu_probe(void) > { > - pmu_version = get_pmu_version(); > - report_info("PMU version: %d", pmu_version); > - return pmu_version != 0 && pmu_version != 0xf; > + uint32_t pmcr; > + > + pmu.version = get_pmu_version(); > + report_info("PMU version: %d", pmu.version); > + > + if (pmu.version == 0 || pmu.version == 0xF) > + return false; > + > + pmcr = get_pmcr(); > + pmu.pmcr_ro = pmcr & 0xFF80; > + pmu.nb_implemented_counters = > + (pmcr >> PMU_PMCR_N_SHIFT) & PMU_PMCR_N_MASK; > + report_info("Implements %d event counters", > + pmu.nb_implemented_counters); > + > + return true; > } > > int main(int argc, char *argv[])
Re: [kvm-unit-tests PATCH 02/10] arm: pmu: Let pmu tests take a sub-test parameter
On Mon, 16 Dec 2019 21:47:49 +0100 Eric Auger wrote: > As we intend to introduce more PMU tests, let's add > a sub-test parameter that will allow to categorize > them. Existing tests are in the cycle-counter category. > > Signed-off-by: Eric Auger Reviewed-by: Andre Przywara Cheers, Andre > --- > arm/pmu.c | 24 +++- > arm/unittests.cfg | 7 --- > 2 files changed, 19 insertions(+), 12 deletions(-) > > diff --git a/arm/pmu.c b/arm/pmu.c > index d5a03a6..e5e012d 100644 > --- a/arm/pmu.c > +++ b/arm/pmu.c > @@ -287,22 +287,28 @@ int main(int argc, char *argv[]) > { > int cpi = 0; > > - if (argc > 1) > - cpi = atol(argv[1]); > - > if (!pmu_probe()) { > printf("No PMU found, test skipped...\n"); > return report_summary(); > } > > + if (argc < 2) > + report_abort("no test specified"); > + > report_prefix_push("pmu"); > > - report(check_pmcr(), "Control register"); > - report(check_cycles_increase(), > -"Monotonically increasing cycle count"); > - report(check_cpi(cpi), "Cycle/instruction ratio"); > - > - pmccntr64_test(); > + if (strcmp(argv[1], "cycle-counter") == 0) { > + report_prefix_push(argv[1]); > + if (argc > 2) > + cpi = atol(argv[2]); > + report(check_pmcr(), "Control register"); > + report(check_cycles_increase(), > +"Monotonically increasing cycle count"); > + report(check_cpi(cpi), "Cycle/instruction ratio"); > + pmccntr64_test(); > + } else { > + report_abort("Unknown sub-test '%s'", argv[1]); > + } > > return report_summary(); > } > diff --git a/arm/unittests.cfg b/arm/unittests.cfg > index daeb5a0..79f0d7a 100644 > --- a/arm/unittests.cfg > +++ b/arm/unittests.cfg > @@ -61,21 +61,22 @@ file = pci-test.flat > groups = pci > > # Test PMU support > -[pmu] > +[pmu-cycle-counter] > file = pmu.flat > groups = pmu > +extra_params = -append 'cycle-counter 0' > > # Test PMU support (TCG) with -icount IPC=1 > #[pmu-tcg-icount-1] > #file = pmu.flat > -#extra_params = -icount 0 -append '1' > +#extra_params = -icount 0 -append 'cycle-counter 1' > #groups = pmu > #accel = tcg > > # Test PMU support (TCG) with -icount IPC=256 > #[pmu-tcg-icount-256] > #file = pmu.flat > -#extra_params = -icount 8 -append '256' > +#extra_params = -icount 8 -append 'cycle-counter 256' > #groups = pmu > #accel = tcg >
Re: [Qemu-devel] [PATCH v2] hw/arm/boot: Increase compliance with kernel arm64 boot protocol
On Tue, 16 Oct 2018 15:06:29 + Stewart Hildebrand wrote: Hi, > "The Image must be placed text_offset bytes from a 2MB aligned base > address anywhere in usable system RAM and called there." > > For the virt board, we write our startup bootloader at the very > bottom of RAM, so that bit can't be used for the image. To avoid > overlap in case the image requests to be loaded at an offset > smaller than our bootloader, we increment the load offset to the > next 2MB. > > This fixes a boot failure for Xen AArch64. Thanks for that, works for me. > Signed-off-by: Stewart Hildebrand Tested-by: Andre Przywara Cheers, Andre.
Re: [Qemu-devel] [PATCH] hw/arm/boot: Increase compliance with kernel arm64 boot protocol.
On Tue, 16 Oct 2018 01:19:35 + Stewart Hildebrand wrote: Hi, Stewart, thanks a lot for picking this up! > On Monday, October 15, 2018 6:05 PM, Philippe Mathieu-Daudé wrote: > > Hi Stewart, > > > > On 15/10/2018 23:26, Stewart Hildebrand wrote: > > > +/* For the virt board, we write our startup > > > "bootloader" at the very > > > + * bottom of RAM, so that bit can't be used for the > > > image. To avoid > > > + * overlap in case the image requests to be loaded > > > at an offset > > > + * smaller than our bootloader, we increment the > > > load offset to the > > > + * next 2MB. > > > + */ > > > +if (kernel_load_offset < FIXUP_MAX) { > > > > I don't understand how this is related to FIXUP_MAX... > > You're right, my apologies, it's not directly related. > write_bootloader() calculates the size of the bootloader like so: > len = 0; > while (insns[len].fixup != FIXUP_TERMINATOR) { > len++; > } > > The size of the bootloader then would be len * sizeof(uint32_t) > > It would be nice not to have to repeat that logic in > load_aarch64_image(). I'll send out a v2 after I take some time to > wrap my head around it... I wonder if this could be done much easier, since TEXT_OFFSET must actually be page aligned. So all we would need is an *upper bound* for the bootloader size, as long as that is below 4K we wouldn't even loose anything. Cheers, Andre. > > > > > +kernel_load_offset += 2 << 20; > > > > You can use += 2 * MiB; which is easier to review. > > OK, I will include this in v2.
[Qemu-devel] [kvm-unit-tests PATCH v2 3/4] arm/arm64: GICv2: add GICD_IPRIORITYR testing
Some tests for the IPRIORITY registers. The significant number of bits is IMPLEMENTATION DEFINED, but should be the same for every IRQ. Also these registers must be byte-accessible. Check that accesses beyond the implemented IRQ limit are actually read-as-zero/write-ignore. Signed-off-by: Andre Przywara --- arm/gic.c | 79 +++ 1 file changed, 79 insertions(+) diff --git a/arm/gic.c b/arm/gic.c index 23cb9a4..57a2995 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -354,6 +354,83 @@ static void test_typer_v2(uint32_t reg) nr_gic_cpus); } +#define BYTE(reg32, byte) (((reg32) >> ((byte) * 8)) & 0xff) +#define REPLACE_BYTE(reg32, byte, new) (((reg32) & ~(0xff << ((byte) * 8))) |\ + ((new) << ((byte) * 8))) + +/* + * Some registers are byte accessible, do a byte-wide read and write of known + * content to check for this. + * Apply a @mask to cater for special register properties. + * @pattern contains the value already in the register. + */ +static void test_byte_access(void *base_addr, u32 pattern, u32 mask) +{ + u32 reg = readb(base_addr + 1); + + report("byte reads successful (0x%08x => 0x%02x)", + reg == (BYTE(pattern, 1) & (mask >> 8)), + pattern & mask, reg); + + pattern = REPLACE_BYTE(pattern, 2, 0x1f); + writeb(BYTE(pattern, 2), base_addr + 2); + reg = readl(base_addr); + report("byte writes successful (0x%02x => 0x%08x)", + reg == (pattern & mask), BYTE(pattern, 2), reg); +} + +static void test_priorities(int nr_irqs, void *priptr) +{ + u32 orig_prio, reg, pri_bits; + u32 pri_mask, pattern; + void *first_spi = priptr + GIC_FIRST_SPI; + + orig_prio = readl(first_spi); + report_prefix_push("IPRIORITYR"); + + /* +* Determine implemented number of priority bits by writing all 1's +* and checking the number of cleared bits in the value read back. +*/ + writel(0x, first_spi); + pri_mask = readl(first_spi); + + reg = ~pri_mask; + report("consistent priority masking (0x%08x)", + (((reg >> 16) == (reg & 0x)) && + ((reg & 0xff) == ((reg >> 8) & 0xff))), pri_mask); + + reg = reg & 0xff; + for (pri_bits = 8; reg & 1; reg >>= 1, pri_bits--) + ; + report("implements at least 4 priority bits (%d)", + pri_bits >= 4, pri_bits); + + pattern = 0; + writel(pattern, first_spi); + report("clearing priorities", readl(first_spi) == pattern); + + /* setting all priorities to their max valus was tested above */ + + report("accesses beyond limit RAZ/WI", + test_readonly_32(priptr + nr_irqs, true)); + + writel(pattern, priptr + nr_irqs - 4); + report("accessing last SPIs", + readl(priptr + nr_irqs - 4) == (pattern & pri_mask)); + + pattern = 0xff7fbf3f; + writel(pattern, first_spi); + report("priorities are preserved", + readl(first_spi) == (pattern & pri_mask)); + + /* The PRIORITY registers are byte accessible. */ + test_byte_access(first_spi, pattern, pri_mask); + + report_prefix_pop(); + writel(orig_prio, first_spi); +} + static void gic_test_mmio(void) { u32 reg; @@ -388,6 +465,8 @@ static void gic_test_mmio(void) report("ICPIDR2 is read-only (0x%08x)", test_readonly_32(idreg, false), reg); + + test_priorities(nr_irqs, gic_dist_base + GICD_IPRIORITYR); } int main(int argc, char **argv) -- 2.14.4
[Qemu-devel] [kvm-unit-tests PATCH v2 4/4] arm/arm64: GICv2: add GICD_ITARGETSR testing
Some tests for the ITARGETS registers. Bits corresponding to non-existent CPUs must be RAZ/WI. These registers must be byte-accessible, also check that accesses beyond the implemented IRQ limit are actually read-as-zero/write-ignore. Signed-off-by: Andre Przywara --- arm/gic.c | 43 +++ lib/arm/asm/gic.h | 1 + 2 files changed, 44 insertions(+) diff --git a/arm/gic.c b/arm/gic.c index 57a2995..ed5642e 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -431,6 +431,46 @@ static void test_priorities(int nr_irqs, void *priptr) writel(orig_prio, first_spi); } +/* GICD_ITARGETSR is only used by GICv2. */ +static void test_targets(int nr_irqs) +{ + void *targetsptr = gicv2_dist_base() + GICD_ITARGETSR; + u32 orig_targets; + u32 cpu_mask; + u32 pattern, reg; + + orig_targets = readl(targetsptr + GIC_FIRST_SPI); + report_prefix_push("ITARGETSR"); + + cpu_mask = (1 << nr_cpus) - 1; + cpu_mask |= cpu_mask << 8; + cpu_mask |= cpu_mask << 16; + + /* Check that bits for non implemented CPUs are RAZ/WI. */ + if (nr_cpus < 8) { + writel(0x, targetsptr + GIC_FIRST_SPI); + report("bits for %d non-existent CPUs masked", + !(readl(targetsptr + GIC_FIRST_SPI) & ~cpu_mask), + 8 - nr_cpus); + } else { + report_skip("CPU masking (all CPUs implemented)"); + } + + report("accesses beyond limit RAZ/WI", + test_readonly_32(targetsptr + nr_irqs, true)); + + pattern = 0x0103020f; + writel(pattern, targetsptr + GIC_FIRST_SPI); + reg = readl(targetsptr + GIC_FIRST_SPI); + report("register content preserved (%08x => %08x)", + reg == (pattern & cpu_mask), pattern & cpu_mask, reg); + + /* The TARGETS registers are byte accessible. */ + test_byte_access(targetsptr + GIC_FIRST_SPI, pattern, cpu_mask); + + writel(orig_targets, targetsptr + GIC_FIRST_SPI); +} + static void gic_test_mmio(void) { u32 reg; @@ -467,6 +507,9 @@ static void gic_test_mmio(void) reg); test_priorities(nr_irqs, gic_dist_base + GICD_IPRIORITYR); + + if (gic_version() == 2) + test_targets(nr_irqs); } int main(int argc, char **argv) diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h index a469645..f6dfb90 100644 --- a/lib/arm/asm/gic.h +++ b/lib/arm/asm/gic.h @@ -20,6 +20,7 @@ #define GICD_ISACTIVER 0x0300 #define GICD_ICACTIVER 0x0380 #define GICD_IPRIORITYR0x0400 +#define GICD_ITARGETSR 0x0800 #define GICD_SGIR 0x0f00 #define GICD_ICPIDR2 0x0fe8 -- 2.14.4
[Qemu-devel] [kvm-unit-tests PATCH v2 1/4] mark exit() and abort() as non-returning functions
exit() and abort() are functions that never return, and (at least) GCC has an attribute to flag those functions accordingly. This allows the compiler to do further optimizations and to omit various warnings about uninitialized variables, for instance. Since the actual "play-dead" function is in (inline) assembly, the compiler does not recognize its fatal nature, so help it with the __builtin_unreachable() hint. Flag the prototypes of our fatal functions accordingly. Signed-off-by: Andre Przywara --- lib/arm/io.c | 1 + lib/libcflat.h | 7 --- lib/powerpc/io.c | 1 + lib/x86/io.c | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/arm/io.c b/lib/arm/io.c index 603456f..d2c1a07 100644 --- a/lib/arm/io.c +++ b/lib/arm/io.c @@ -83,4 +83,5 @@ void exit(int code) { chr_testdev_exit(code); halt(code); + __builtin_unreachable(); } diff --git a/lib/libcflat.h b/lib/libcflat.h index cc56553..7529958 100644 --- a/lib/libcflat.h +++ b/lib/libcflat.h @@ -84,8 +84,8 @@ typedef u64 phys_addr_t; extern void puts(const char *s); extern int __getchar(void); extern int getchar(void); -extern void exit(int code); -extern void abort(void); +extern void exit(int code) __attribute__((noreturn)); +extern void abort(void) __attribute__((noreturn)); extern long atol(const char *ptr); extern char *getenv(const char *name); @@ -107,7 +107,8 @@ extern void report(const char *msg_fmt, bool pass, ...) extern void report_xfail(const char *msg_fmt, bool xfail, bool pass, ...) __attribute__((format(printf, 1, 4))); extern void report_abort(const char *msg_fmt, ...) - __attribute__((format(printf, 1, 2))); + __attribute__((format(printf, 1, 2))) + __attribute__((noreturn)); extern void report_skip(const char *msg_fmt, ...) __attribute__((format(printf, 1, 2))); extern void report_info(const char *msg_fmt, ...) diff --git a/lib/powerpc/io.c b/lib/powerpc/io.c index 915e12e..217eb07 100644 --- a/lib/powerpc/io.c +++ b/lib/powerpc/io.c @@ -35,4 +35,5 @@ void exit(int code) printf("\nEXIT: STATUS=%d\n", ((code) << 1) | 1); rtas_power_off(); halt(code); + __builtin_unreachable(); } diff --git a/lib/x86/io.c b/lib/x86/io.c index 7e1c16d..057f579 100644 --- a/lib/x86/io.c +++ b/lib/x86/io.c @@ -82,6 +82,7 @@ void exit(int code) #else asm volatile("out %0, %1" : : "a"(code), "d"((short)0xf4)); #endif + __builtin_unreachable(); } void __iomem *ioremap(phys_addr_t phys_addr, size_t size) -- 2.14.4
[Qemu-devel] [kvm-unit-tests PATCH v2 0/4] arm: add GICv2 MMIO tests
I found this in one my branches: this is an updated version of what I sent end of 2016 [1]. I tried to address all comments that Drew and Eric had at the time. Please have a look whether this makes sense. Changelog v1..v2: - made many functions void - use symbolic name for first SPI being number 32 - add test runs with one and three vCPUs - use gic_version() directly - factor out test_byte_access() - drop redundant "filling priorities" test - dropped GICv3 test [1] https://lists.cs.columbia.edu/pipermail/kvmarm/2016-November/022352.html Original cover letter: == The GIC spec mandates certain constraints on how to acccess the MMIO mapped registers, both in terms of which registers are available and also in terms of which bits within a register should be masked, for instance. Since we went through some lengths in the KVM emulation to implement this, it's about time to give this actually a test beyond what the kernel as a GIC user actually implements - for instance we ignore priorities in Linux. This series tries to attack some constraints, on a low-hanging-fruit base. It focusses on some generic registers and the PRIORITY and TARGETS registers of GICv2. GICv3 is not covered yet. This actually revealed genuine bugs in the KVM emulation in the past. KVM passes these tests now, but QEMU fails some UP and 3-way-SMP tests. Cheers, Andre. Andre Przywara (4): mark exit() and abort() as non-returning functions arm/arm64: GIC: basic GICv2 MMIO tests arm/arm64: GICv2: add GICD_IPRIORITYR testing arm/arm64: GICv2: add GICD_ITARGETSR testing arm/gic.c | 213 ++ arm/unittests.cfg | 18 + lib/arm/asm/gic.h | 5 ++ lib/arm/io.c | 1 + lib/libcflat.h| 7 +- lib/powerpc/io.c | 1 + lib/x86/io.c | 1 + 7 files changed, 243 insertions(+), 3 deletions(-) -- 2.14.4
[Qemu-devel] [kvm-unit-tests PATCH v2 2/4] arm/arm64: GIC: basic GICv2 MMIO tests
This adds an MMIO subtest to the GIC test. It accesses some generic GICv2 registers and does some sanity tests, like checking for some of them being read-only. Signed-off-by: Andre Przywara --- arm/gic.c | 91 +++ arm/unittests.cfg | 18 +++ lib/arm/asm/gic.h | 4 +++ 3 files changed, 113 insertions(+) diff --git a/arm/gic.c b/arm/gic.c index 5dd958e..23cb9a4 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -3,6 +3,7 @@ * * GICv2 * + test sending/receiving IPIs + * + MMIO access tests * GICv3 * + test sending/receiving IPIs * @@ -303,6 +304,92 @@ static void run_active_clear_test(void) report_prefix_pop(); } +static bool test_ro_pattern_32(void *address, u32 pattern, u32 orig) +{ + u32 reg; + + writel(pattern, address); + reg = readl(address); + + if (reg != orig) + writel(orig, address); + + return reg == orig; +} + +static bool test_readonly_32(void *address, bool razwi) +{ + u32 orig, pattern; + + orig = readl(address); + if (razwi && orig) + return false; + + pattern = 0x; + if (orig != pattern) { + if (!test_ro_pattern_32(address, pattern, orig)) + return false; + } + + pattern = 0xa5a55a5a; + if (orig != pattern) { + if (!test_ro_pattern_32(address, pattern, orig)) + return false; + } + + pattern = 0; + if (orig != pattern) { + if (!test_ro_pattern_32(address, pattern, orig)) + return false; + } + + return true; +} + +static void test_typer_v2(uint32_t reg) +{ + int nr_gic_cpus = ((reg >> 5) & 0x7) + 1; + + report("all %d CPUs have interrupts", nr_cpus == nr_gic_cpus, + nr_gic_cpus); +} + +static void gic_test_mmio(void) +{ + u32 reg; + int nr_irqs; + void *gic_dist_base, *idreg; + + switch(gic_version()) { + case 0x2: + gic_dist_base = gicv2_dist_base(); + idreg = gic_dist_base + GICD_ICPIDR2; + break; + case 0x3: + report_abort("GICv3 MMIO tests NYI"); + default: + report_abort("GIC version %d not supported", gic_version()); + } + + reg = readl(gic_dist_base + GICD_TYPER); + nr_irqs = GICD_TYPER_IRQS(reg); + report_info("number of implemented SPIs: %d", nr_irqs - GIC_FIRST_SPI); + + test_typer_v2(reg); + + report_info("IIDR: 0x%08x", readl(gic_dist_base + GICD_IIDR)); + + report("GICD_TYPER is read-only", + test_readonly_32(gic_dist_base + GICD_TYPER, false)); + report("GICD_IIDR is read-only", + test_readonly_32(gic_dist_base + GICD_IIDR, false)); + + reg = readl(idreg); + report("ICPIDR2 is read-only (0x%08x)", + test_readonly_32(idreg, false), + reg); +} + int main(int argc, char **argv) { if (!gic_init()) { @@ -330,6 +417,10 @@ int main(int argc, char **argv) on_cpus(ipi_test, NULL); } else if (strcmp(argv[1], "active") == 0) { run_active_clear_test(); + } else if (strcmp(argv[1], "mmio") == 0) { + report_prefix_push(argv[1]); + gic_test_mmio(); + report_prefix_pop(); } else { report_abort("Unknown subtest '%s'", argv[1]); } diff --git a/arm/unittests.cfg b/arm/unittests.cfg index 44b98cf..7f3a321 100644 --- a/arm/unittests.cfg +++ b/arm/unittests.cfg @@ -86,6 +86,24 @@ smp = $((($MAX_SMP < 8)?$MAX_SMP:8)) extra_params = -machine gic-version=2 -append 'ipi' groups = gic +[gicv2-mmio] +file = gic.flat +smp = $((($MAX_SMP < 8)?$MAX_SMP:8)) +extra_params = -machine gic-version=2 -append 'mmio' +groups = gic + +[gicv2-mmio-up] +file = gic.flat +smp = 1 +extra_params = -machine gic-version=2 -append 'mmio' +groups = gic + +[gicv2-mmio-3p] +file = gic.flat +smp = $((($MAX_SMP < 3)?$MAX_SMP:3)) +extra_params = -machine gic-version=2 -append 'mmio' +groups = gic + [gicv3-ipi] file = gic.flat smp = $MAX_SMP diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h index 2eb4af8..a469645 100644 --- a/lib/arm/asm/gic.h +++ b/lib/arm/asm/gic.h @@ -6,10 +6,13 @@ #ifndef _ASMARM_GIC_H_ #define _ASMARM_GIC_H_ +#define GIC_NR_PRIVATE_IRQS32 +#define GIC_FIRST_SPI GIC_NR_PRIVATE_IRQS /* Distributor registers */ #define GICD_CTLR 0x #define GICD_TYPER 0x0004 +#define GICD_IIDR 0x0008 #define GICD_IGROUPR 0x0080 #define GICD_ISENABLER 0x0100 #define GICD_ISPENDR 0x0200 @@ -18,6 +21,7 @@ #define GICD_ICACTI
[Qemu-devel] [kvm-unit-tests PATCH 0/2] arm64: extend arch timer tests
While debugging some timer emulation IRQ problem, I realised that the failure pattern I was looking at is not covered by kvm-unit-tests. Add a test for the TVAL register, also check that KVM correctly injects the timer interrupt for the emulated physical timer when the guest is in WFI (hint: it does not, starting with 4.15-rc, I am on it). Cheers, Andre. Andre Przywara (2): arm64: timer: add TVAL accessors arm64: timer: Add TVAL timeout test and test IRQ trigger arm/timer.c | 36 1 file changed, 36 insertions(+) -- 2.14.4
[Qemu-devel] [kvm-unit-tests PATCH 1/2] arm64: timer: add TVAL accessors
The ARM arch timer features the CVAL register, which holds an absolute value that is compared against the counter value. But there is also the TVAL register, which is defined as (CVAL - counter), and can be used to program or read relative timeouts. Add accessors for the TVAL register, to be able to read and write them easily later. Signed-off-by: Andre Przywara --- arm/timer.c | 26 ++ 1 file changed, 26 insertions(+) diff --git a/arm/timer.c b/arm/timer.c index 5f3135f..1c9ef44 100644 --- a/arm/timer.c +++ b/arm/timer.c @@ -40,6 +40,16 @@ static void write_vtimer_cval(u64 val) write_sysreg(val, cntv_cval_el0); } +static s32 read_vtimer_tval(void) +{ + return read_sysreg(cntv_tval_el0); +} + +static void write_vtimer_tval(s32 val) +{ + write_sysreg(val, cntv_tval_el0); +} + static u64 read_vtimer_ctl(void) { return read_sysreg(cntv_ctl_el0); @@ -65,6 +75,16 @@ static void write_ptimer_cval(u64 val) write_sysreg(val, cntp_cval_el0); } +static s32 read_ptimer_tval(void) +{ + return read_sysreg(cntp_tval_el0); +} + +static void write_ptimer_tval(s32 val) +{ + write_sysreg(val, cntp_tval_el0); +} + static u64 read_ptimer_ctl(void) { return read_sysreg(cntp_ctl_el0); @@ -82,6 +102,8 @@ struct timer_info { u64 (*read_counter)(void); u64 (*read_cval)(void); void (*write_cval)(u64); + s32 (*read_tval)(void); + void (*write_tval)(s32); u64 (*read_ctl)(void); void (*write_ctl)(u64); }; @@ -91,6 +113,8 @@ static struct timer_info vtimer_info = { .read_counter = read_vtimer_counter, .read_cval = read_vtimer_cval, .write_cval = write_vtimer_cval, + .read_tval = read_vtimer_tval, + .write_tval = write_vtimer_tval, .read_ctl = read_vtimer_ctl, .write_ctl = write_vtimer_ctl, }; @@ -100,6 +124,8 @@ static struct timer_info ptimer_info = { .read_counter = read_ptimer_counter, .read_cval = read_ptimer_cval, .write_cval = write_ptimer_cval, + .read_tval = read_ptimer_tval, + .write_tval = write_ptimer_tval, .read_ctl = read_ptimer_ctl, .write_ctl = write_ptimer_ctl, }; -- 2.14.4
[Qemu-devel] [kvm-unit-tests PATCH 2/2] arm64: timer: Add TVAL timeout IRQ trigger test
So far we were only testing the CVAL register. Add a test which programs a (relative) TVAL value to check this functionality as well. Also we go into WFI and wait for the interrupt to release us from it. The timer tests are run with a 2 second timeout on the host side, so that any failure in coming back would be covered. Signed-off-by: Andre Przywara --- arm/timer.c | 10 ++ 1 file changed, 10 insertions(+) diff --git a/arm/timer.c b/arm/timer.c index 1c9ef44..275d049 100644 --- a/arm/timer.c +++ b/arm/timer.c @@ -211,6 +211,7 @@ static void test_timer(struct timer_info *info) u64 now = info->read_counter(); u64 time_10s = read_sysreg(cntfrq_el0) * 10; u64 later = now + time_10s; + s32 left; /* We don't want the irq handler to fire because that will change the * timer state and we want to test the timer output signal. We can @@ -236,6 +237,15 @@ static void test_timer(struct timer_info *info) /* Disable the timer again */ info->write_ctl(0); + + /* Test TVAL and IRQ trigger */ + info->irq_received = false; + info->write_tval(read_sysreg(cntfrq_el0) / 100);/* 10 ms */ + info->write_ctl(ARCH_TIMER_CTL_ENABLE); + wfi(); + left = info->read_tval(); + report("interrupt received after TVAL/WFI", info->irq_received); + report("timer has expired (%d)", left < 0, left); } static void test_vtimer(void) -- 2.14.4
Re: [Qemu-devel] [PATCH kvm-unit-tests v8 09/10] arm/arm64: gicv3: add an IPI test
pu >= nr_cpus) > + break; > + > + mpidr = cpus[cpu]; > + > + if (cluster_id != (mpidr & ~0xffUL)) { > + /* > + * The next cpu isn't in our cluster. Roll > + * back the cpu index allowing the outer > + * for_each_cpu to find it again with > + * cpumask_next > + */ > + --cpu; > + break; > + } > + } > + > + /* Send the IPIs for the target list of this cluster */ > + sgi1r = (MPIDR_TO_SGI_AFFINITY(cluster_id, 3) | > + MPIDR_TO_SGI_AFFINITY(cluster_id, 2) | > + irq << 24 | > + MPIDR_TO_SGI_AFFINITY(cluster_id, 1) | > + tlist); > + > + gicv3_write_sgi1r(sgi1r); > + } > + > + /* Force the above writes to ICC_SGI1R_EL1 to be executed */ > + isb(); > +} Wow, this is really heavy stuff, especially for a Friday afternoon ;-) But I convinced myself that it's correct. The only issue is that it's sub-optimal if the MPIDRs of the VCPUs are not in order, say: 0x000, 0x100, 0x001. In this case we do three register writes instead of the minimal two. But it's still correct, so it's actually a minor nit just to prove that I checked the algorithm ;-) So apart from the minor comment above: Reviewed-by: Andre Przywara <andre.przyw...@arm.com> Cheers, Andre. > + > +void gicv3_ipi_send_single(int irq, int cpu) > +{ > + cpumask_t dest; > + > + cpumask_clear(); > + cpumask_set_cpu(cpu, ); > + gicv3_ipi_send_mask(irq, ); > +} > diff --git a/lib/arm/gic.c b/lib/arm/gic.c > index 4d3ddd9722b1..3ed539727f8c 100644 > --- a/lib/arm/gic.c > +++ b/lib/arm/gic.c > @@ -10,6 +10,38 @@ > struct gicv2_data gicv2_data; > struct gicv3_data gicv3_data; > > +struct gic_common_ops { > + int gic_version; > + void (*enable_defaults)(void); > + u32 (*read_iar)(void); > + u32 (*iar_irqnr)(u32 iar); > + void (*write_eoir)(u32 irqstat); > + void (*ipi_send_single)(int irq, int cpu); > + void (*ipi_send_mask)(int irq, const cpumask_t *dest); > +}; > + > +static const struct gic_common_ops *gic_common_ops; > + > +static const struct gic_common_ops gicv2_common_ops = { > + .gic_version = 2, > + .enable_defaults = gicv2_enable_defaults, > + .read_iar = gicv2_read_iar, > + .iar_irqnr = gicv2_iar_irqnr, > + .write_eoir = gicv2_write_eoir, > + .ipi_send_single = gicv2_ipi_send_single, > + .ipi_send_mask = gicv2_ipi_send_mask, > +}; > + > +static const struct gic_common_ops gicv3_common_ops = { > + .gic_version = 3, > + .enable_defaults = gicv3_enable_defaults, > + .read_iar = gicv3_read_iar, > + .iar_irqnr = gicv3_iar_irqnr, > + .write_eoir = gicv3_write_eoir, > + .ipi_send_single = gicv3_ipi_send_single, > + .ipi_send_mask = gicv3_ipi_send_mask, > +}; > + > /* > * Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt > * Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt > @@ -58,9 +90,58 @@ int gicv3_init(void) > > int gic_init(void) > { > - if (gicv2_init()) > + if (gicv2_init()) { > + gic_common_ops = _common_ops; > return 2; > - else if (gicv3_init()) > + } else if (gicv3_init()) { > + gic_common_ops = _common_ops; > return 3; > + } > return 0; > } > + > +void gic_enable_defaults(void) > +{ > + if (!gic_common_ops) { > + int ret = gic_init(); > + assert(ret != 0); > + } else > + assert(gic_common_ops->enable_defaults); > + gic_common_ops->enable_defaults(); > +} > + > +int gic_version(void) > +{ > + assert(gic_common_ops); > + return gic_common_ops->gic_version; > +} > + > +u32 gic_read_iar(void) > +{ > + assert(gic_common_ops && gic_common_ops->read_iar); > + return gic_common_ops->read_iar(); > +} > + > +u32 gic_iar_irqnr(u32 iar) > +{ > + assert(gic_common_ops && gic_common_ops->iar_irqnr); > + return gic_common_ops->iar_irqnr(iar); > +} > + > +void gic_write_eoir(u32 irqstat) > +{ > + assert(gic_common_ops && gic_common_ops->write_eoir); > + gic_common_ops->write_eoir(irqstat); > +} > + > +void gic_ipi_send_single(int irq, int cpu) > +{ > + assert(gic_common_ops && gic_common_ops->ipi_send_single); > + gic_common_ops->ipi_send_single(irq, cpu); > +} > + > +void gic_ipi_send_mask(int irq, const cpumask_t *dest) > +{ > + assert(gic_common_ops && gic_common_ops->ipi_send_mask); > + gic_common_ops->ipi_send_mask(irq, dest); > +} >
Re: [Qemu-devel] [PATCH kvm-unit-tests v8 03/10] arm/arm64: add some delay routines
Hi, On 08/12/16 17:50, Andrew Jones wrote: > Allow a thread to wait some specified amount of time. Can > specify in cycles, usecs, and msecs. > > Signed-off-by: Andrew Jones <drjo...@redhat.com> > > --- > v8: rewrote basing on new sysreg framework. Also decided delay > functions warrant their own files (delay.[ch]) > --- > arm/Makefile.common | 1 + > lib/arm/asm/delay.h | 14 ++ > lib/arm/asm/processor.h | 15 +++ > lib/arm64/asm/delay.h | 1 + > lib/arm64/asm/processor.h | 12 > lib/arm/delay.c | 29 + > 6 files changed, 72 insertions(+) > create mode 100644 lib/arm/asm/delay.h > create mode 100644 lib/arm64/asm/delay.h > create mode 100644 lib/arm/delay.c > > diff --git a/arm/Makefile.common b/arm/Makefile.common > index b2c0fc8a2fdc..89fe3f69eb44 100644 > --- a/arm/Makefile.common > +++ b/arm/Makefile.common > @@ -48,6 +48,7 @@ cflatobjs += lib/arm/mmu.o > cflatobjs += lib/arm/bitops.o > cflatobjs += lib/arm/psci.o > cflatobjs += lib/arm/smp.o > +cflatobjs += lib/arm/delay.o > > libeabi = lib/arm/libeabi.a > eabiobjs = lib/arm/eabi_compat.o > diff --git a/lib/arm/asm/delay.h b/lib/arm/asm/delay.h > new file mode 100644 > index ..2436b28c77ae > --- /dev/null > +++ b/lib/arm/asm/delay.h > @@ -0,0 +1,14 @@ > +#ifndef _ASMARM_DELAY_H_ > +#define _ASMARM_DELAY_H_ > +/* > + * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjo...@redhat.com> > + * > + * This work is licensed under the terms of the GNU LGPL, version 2. > + */ > +#include > + > +extern void delay(u64 cycles); Nit: Shouldn't this parameter be called "ticks"? Cycles might be a bit misleading, especially since this prototype is the only documentation on this. You might just want to fix this when applying the patches. That notwithstanding: Reviewed-by: Andre Przywara <andre.przyw...@arm.com> Cheers, Andre. > +extern void udelay(unsigned long usecs); > +extern void mdelay(unsigned long msecs); > + > +#endif /* _ASMARM_DELAY_H_ */ > diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h > index 6b0d36b87817..857bdd96a3cc 100644 > --- a/lib/arm/asm/processor.h > +++ b/lib/arm/asm/processor.h > @@ -7,6 +7,7 @@ > */ > #include > #include > +#include > > enum vector { > EXCPTN_RST, > @@ -51,4 +52,18 @@ extern int mpidr_to_cpu(uint64_t mpidr); > extern void start_usr(void (*func)(void *arg), void *arg, unsigned long > sp_usr); > extern bool is_user(void); > > +#define CNTVCT __ACCESS_CP15_64(1, c14) > +#define CNTFRQ __ACCESS_CP15(c14, 0, c0, 0) > + > +static inline u64 get_cntvct(void) > +{ > + isb(); > + return read_sysreg(CNTVCT); > +} > + > +static inline u32 get_cntfrq(void) > +{ > + return read_sysreg(CNTFRQ); > +} > + > #endif /* _ASMARM_PROCESSOR_H_ */ > diff --git a/lib/arm64/asm/delay.h b/lib/arm64/asm/delay.h > new file mode 100644 > index ..288e4b3fe610 > --- /dev/null > +++ b/lib/arm64/asm/delay.h > @@ -0,0 +1 @@ > +#include "../../arm/asm/delay.h" > diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h > index 48abf2c9e358..0898d89f9761 100644 > --- a/lib/arm64/asm/processor.h > +++ b/lib/arm64/asm/processor.h > @@ -20,6 +20,7 @@ > #include > #include > #include > +#include > > enum vector { > EL1T_SYNC, > @@ -83,5 +84,16 @@ extern int mpidr_to_cpu(uint64_t mpidr); > extern void start_usr(void (*func)(void *arg), void *arg, unsigned long > sp_usr); > extern bool is_user(void); > > +static inline u64 get_cntvct(void) > +{ > + isb(); > + return read_sysreg(cntvct_el0); > +} > + > +static inline u32 get_cntfrq(void) > +{ > + return read_sysreg(cntfrq_el0); > +} > + > #endif /* !__ASSEMBLY__ */ > #endif /* _ASMARM64_PROCESSOR_H_ */ > diff --git a/lib/arm/delay.c b/lib/arm/delay.c > new file mode 100644 > index ..fa65e2dc9e35 > --- /dev/null > +++ b/lib/arm/delay.c > @@ -0,0 +1,29 @@ > +/* > + * Delay loops > + * > + * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjo...@redhat.com> > + * > + * This work is licensed under the terms of the GNU LGPL, version 2. > + */ > +#include > +#include > +#include > + > +void delay(u64 cycles) > +{ > + u64 start = get_cntvct(); > + > + while ((get_cntvct() - start) < cycles) > + cpu_relax(); > +} > + > +void udelay(unsigned long usec) > +{ > + delay((u64)usec * get_cntfrq() / 100); > +} > + > +void mdelay(unsigned long msecs) > +{ > + while (msecs--) > + udelay(1000); > +} >
Re: [Qemu-devel] [kvm-unit-tests RFC 00/15] arm/arm64: add ITS framework
Hi, On 06/12/16 09:48, Andrew Jones wrote: > On Mon, Dec 05, 2016 at 10:46:31PM +0100, Eric Auger wrote: >> This series proposes a framework to test the virtual ITS. >> This is based on Drew's v7 series [1]. The last patch tests >> several ITS commands (collection/device mapping, interrupt >> translation service entry creation and LPI trigger through INT >> command). At this point we don't use any external PCIe device >> to write into the GITS_TRANSLATER register. >> >> The bulk of the code derives from the ITS driver code so all >> the credit is due to Marc. >> >> Many other ITS commands could be tested. Also existing MMIO >> accesses could be enhanced into standalone tests. Current focus >> was to make it functional. >> >> The code deserves more cleanup with respect to cacheability >> attributes in general. >> >> Tested on Cavium ThunderX [2]. >> >> Best Regards >> >> Eric >> >> [1] [kvm-unit-tests PATCH v7 00/11] arm/arm64: add gic framework >> >> [2] sample command line: >> >> $QEMU -machine virt,accel=kvm -cpu host \ >> -device virtio-serial-device \ >> -device virtconsole,chardev=ctd -chardev testdev,id=ctd \ >> -display none -serial stdio \ >> -kernel arm/gic.flat \ >> -smp 8 -machine gic-version=3 -append 'its' >> >> Eric Auger (15): >> libcflat: Add other size defines >> arm/arm64: gicv3: Add some re-distributor defines >> arm/arm64: ITS skeleton >> arm/arm64: ITS: BASER parsing and setup >> arm/arm64: GICv3: add cpu count >> arm/arm64: ITS: Set the LPI config and pending tables >> arm/arm64: ITS: Init the command queue >> arm/arm64: ITS: enable LPIs at re-distributor level >> arm/arm64: ITS: Parse the typer register >> arm/arm64: ITS: its_enable_defaults >> arm/arm64: ITS: create device >> arm/arm64: ITS: create collection >> arm/arm64: ITS: commands >> arm/arm64: gic: Generalize ipi_enable() >> arm/arm64: ITS test >> >> arm/Makefile.common| 1 + >> arm/gic.c | 101 +++- >> lib/arm/asm/gic-v3-its.h | 238 +++ >> lib/arm/asm/gic-v3.h | 84 ++ >> lib/arm/asm/gic.h | 1 + >> lib/arm/gic-v3-its-cmd.c | 399 >> + >> lib/arm/gic-v3-its.c | 305 ++ >> lib/arm/gic-v3.c | 2 + >> lib/arm/gic.c | 30 +++- >> lib/arm64/asm/gic-v3-its.h | 1 + >> lib/libcflat.h | 3 + >> 11 files changed, 1154 insertions(+), 11 deletions(-) >> create mode 100644 lib/arm/asm/gic-v3-its.h >> create mode 100644 lib/arm/gic-v3-its-cmd.c >> create mode 100644 lib/arm/gic-v3-its.c >> create mode 100644 lib/arm64/asm/gic-v3-its.h >> >> -- >> 2.5.5 >> >> > > Thanks for this Eric! I'm glad to see we're getting more GIC test > coverage written, even before v8 of the gic series is posted :-) > v8 will be rebased on some sysreg stuff Wei is doing for the PMU > series, Are you planning on a v8 post any time soon? > that's why it's held up. I'll need to set plenty of time > aside to learn enough in order to review all the 'ITS:' patches > in this series. Are you sure you want to really taint yourself with this stuff? You wouldn't be the first who risks his mental health by understanding the ITS ;-) That being said, I will take a look, I am in ITS land anyway for Xen ... Cheers, Andre. > Apologies if I can't get to it right away. > > Thanks again, > drew >
Re: [Qemu-devel] [kvm-unit-tests RFC 05/15] arm/arm64: GICv3: add cpu count
Hi, On 06/12/16 09:29, Andrew Jones wrote: > On Mon, Dec 05, 2016 at 10:46:36PM +0100, Eric Auger wrote: >> Add a new cpu_count field in gicv3_data indicating the >> number of redistributors. This will be useful for enumeration >> of their resources such as LPI pending tables. > > I'm fine with the additional state, but just curious, will it > ever be possible for gicv3.cpu_count != nr_cpus? If not you are in trouble, so that should in fact be one test. Which brings me to my comment ... >> >> Signed-off-by: Eric Auger>> --- >> lib/arm/asm/gic-v3.h | 1 + >> lib/arm/gic-v3.c | 2 ++ >> 2 files changed, 3 insertions(+) >> >> diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h >> index ed330af..039b7c2 100644 >> --- a/lib/arm/asm/gic-v3.h >> +++ b/lib/arm/asm/gic-v3.h >> @@ -58,6 +58,7 @@ struct gicv3_data { >> void *dist_base; >> void *redist_base[NR_CPUS]; >> unsigned int irq_nr; >> +unsigned int cpu_count; Should that be called "nr_redists" or the like? Since this is what it counts in the code below. Later we can then compare this with nr_cpus to check for a match. Cheers, Andre. >> }; >> extern struct gicv3_data gicv3_data; >> >> diff --git a/lib/arm/gic-v3.c b/lib/arm/gic-v3.c >> index 6246221..9921f4d 100644 >> --- a/lib/arm/gic-v3.c >> +++ b/lib/arm/gic-v3.c >> @@ -12,12 +12,14 @@ void gicv3_set_redist_base(size_t stride) >> void *ptr = gicv3_data.redist_base[0]; >> u64 typer; >> >> +gicv3_data.cpu_count = 0; >> do { >> typer = gicv3_read_typer(ptr + GICR_TYPER); >> if ((typer >> 32) == aff) { >> gicv3_redist_base() = ptr; >> return; >> } >> +gicv3_data.cpu_count++; >> ptr += stride; /* skip RD_base, SGI_base, etc. */ >> } while (!(typer & GICR_TYPER_LAST)); >> >> -- >> 2.5.5 >> >>
Re: [Qemu-devel] [kvm-unit-tests PATCH v13 4/4] arm: pmu: Add CPI checking
Hi, On 01/12/16 05:16, Wei Huang wrote: > From: Christopher Covington> > Calculate the numbers of cycles per instruction (CPI) implied by ARM > PMU cycle counter values. The code includes a strict checking facility > intended for the -icount option in TCG mode in the configuration file. > > Signed-off-by: Christopher Covington > Signed-off-by: Wei Huang > Reviewed-by: Andrew Jones > --- > arm/pmu.c | 123 > +- > arm/unittests.cfg | 14 +++ > 2 files changed, 136 insertions(+), 1 deletion(-) > > diff --git a/arm/pmu.c b/arm/pmu.c > index 3566a27..29d7c2c 100644 > --- a/arm/pmu.c > +++ b/arm/pmu.c > @@ -69,6 +69,27 @@ static inline void set_pmccfiltr(uint32_t value) > set_pmxevtyper(value); > isb(); > } > + > +/* > + * Extra instructions inserted by the compiler would be difficult to > compensate > + * for, so hand assemble everything between, and including, the PMCR accesses > + * to start and stop counting. isb instructions were inserted to make sure > + * pmccntr read after this function returns the exact instructions executed > in > + * the controlled block. Total instrs = isb + mcr + 2*loop = 2 + 2*loop. > + */ > +static inline void precise_instrs_loop(int loop, uint32_t pmcr) > +{ > + asm volatile( > + " mcr p15, 0, %[pmcr], c9, c12, 0\n" > + " isb\n" > + "1: subs%[loop], %[loop], #1\n" > + " bgt 1b\n" > + " mcr p15, 0, %[z], c9, c12, 0\n" > + " isb\n" > + : [loop] "+r" (loop) > + : [pmcr] "r" (pmcr), [z] "r" (0) > + : "cc"); > +} > #elif defined(__aarch64__) > DEFINE_GET_SYSREG32(pmcr, el0) > DEFINE_SET_SYSREG32(pmcr, el0) > @@ -77,6 +98,27 @@ DEFINE_GET_SYSREG64(pmccntr, el0); > DEFINE_SET_SYSREG64(pmccntr, el0); > DEFINE_SET_SYSREG32(pmcntenset, el0); > DEFINE_SET_SYSREG32(pmccfiltr, el0); > + > +/* > + * Extra instructions inserted by the compiler would be difficult to > compensate > + * for, so hand assemble everything between, and including, the PMCR accesses > + * to start and stop counting. isb instructions are inserted to make sure > + * pmccntr read after this function returns the exact instructions executed > + * in the controlled block. Total instrs = isb + msr + 2*loop = 2 + 2*loop. > + */ > +static inline void precise_instrs_loop(int loop, uint32_t pmcr) > +{ > + asm volatile( > + " msr pmcr_el0, %[pmcr]\n" > + " isb\n" > + "1: subs%[loop], %[loop], #1\n" > + " b.gt1b\n" > + " msr pmcr_el0, xzr\n" > + " isb\n" > + : [loop] "+r" (loop) > + : [pmcr] "r" (pmcr) > + : "cc"); > +} > #endif > > /* > @@ -134,6 +176,79 @@ static bool check_cycles_increase(void) > return success; > } > > +/* > + * Execute a known number of guest instructions. Only even instruction counts > + * greater than or equal to 4 are supported by the in-line assembly code. The > + * control register (PMCR_EL0) is initialized with the provided value > (allowing > + * for example for the cycle counter or event counters to be reset). At the > end > + * of the exact instruction loop, zero is written to PMCR_EL0 to disable > + * counting, allowing the cycle counter or event counters to be read at the > + * leisure of the calling code. > + */ > +static void measure_instrs(int num, uint32_t pmcr) > +{ > + int loop = (num - 2) / 2; > + > + assert(num >= 4 && ((num - 2) % 2 == 0)); > + precise_instrs_loop(loop, pmcr); > +} > + > +/* > + * Measure cycle counts for various known instruction counts. Ensure that the > + * cycle counter progresses (similar to check_cycles_increase() but with more > + * instructions and using reset and stop controls). If supplied a positive, > + * nonzero CPI parameter, also strictly check that every measurement matches > + * it. Strict CPI checking is used to test -icount mode. > + */ > +static bool check_cpi(int cpi) > +{ > + uint32_t pmcr = get_pmcr() | PMU_PMCR_LC | PMU_PMCR_C | PMU_PMCR_E; > + > + /* init before event access, this test only cares about cycle count */ > + set_pmcntenset(1 << PMU_CYCLE_IDX); > + set_pmccfiltr(0); /* count cycles in EL0, EL1, but not EL2 */ > + > + if (cpi > 0) > + printf("Checking for CPI=%d.\n", cpi); > + printf("instrs : cycles0 cycles1 ...\n"); Do we really need this line? In general I find the output quite confusing, actually distracting from the other, actual tests. To make it more readable, I tweaked it a bit to look like: 4: 9996 173 222 122 118 119 120 212 240 233 avg=1155: 288 cpi 36: 773 282 291 314 291 335 315 264 162 308 avg= 333: 9 cpi 68: 229 356 400 339 203 201 335 233 201 372 avg= 286: 4 cpi with some padding hints and limiting the line to at most 80 characters, by: > + > + for (unsigned int
Re: [Qemu-devel] [kvm-unit-tests PATCH v13 2/4] arm: Add PMU test
Hi, On 01/12/16 12:02, Peter Maydell wrote: > On 1 December 2016 at 11:28, Andre Przywara <andre.przyw...@arm.com> wrote: >> I don't think so. At least here as a _variable_ type uint32_t is >> probably the right one, as the ARMv8 ARM explicitly says that PMCR is a >> 32-bit register, for both bitnesses. > > For 64-bit ARM this is strictly speaking just shorthand for "64-bit > register with the top 32-bit being RES0". It is in theory possible that > a future architecture extension might define uses for those RES0 > bits. I trade: "in theory possible that a future architecture extension might" (that's four speculative terms, right?) against: ARMv8 ARM, D7.4.7 PMCR_EL0, Performance Monitors Control Register: Attributes PMCR_EL0 is a 32-bit register. If this ever gets extended, we would need extra code to deal with the new bits, so we would need to touch the code anyway. And again, it's just a local variable, not an interface. Cheers, Andre. P.S. We really should save this discussion for a Friday afternoon ;-)
Re: [Qemu-devel] [kvm-unit-tests PATCH v13 2/4] arm: Add PMU test
Hi, On 01/12/16 09:03, Andrew Jones wrote: > On Wed, Nov 30, 2016 at 11:16:40PM -0600, Wei Huang wrote: >> From: Christopher Covington>> >> Beginning with a simple sanity check of the control register, add >> a unit test for the ARM Performance Monitors Unit (PMU). PMU register >> was read using the newly defined macros. >> >> Signed-off-by: Christopher Covington >> Signed-off-by: Wei Huang >> Reviewed-by: Andrew Jones >> --- >> arm/Makefile.common | 3 ++- >> arm/pmu.c | 62 >> + >> arm/unittests.cfg | 5 + >> 3 files changed, 69 insertions(+), 1 deletion(-) >> create mode 100644 arm/pmu.c >> >> diff --git a/arm/Makefile.common b/arm/Makefile.common >> index f37b5c2..5da2fdd 100644 >> --- a/arm/Makefile.common >> +++ b/arm/Makefile.common >> @@ -12,7 +12,8 @@ endif >> tests-common = \ >> $(TEST_DIR)/selftest.flat \ >> $(TEST_DIR)/spinlock-test.flat \ >> -$(TEST_DIR)/pci-test.flat >> +$(TEST_DIR)/pci-test.flat \ >> +$(TEST_DIR)/pmu.flat >> >> all: test_cases >> >> diff --git a/arm/pmu.c b/arm/pmu.c >> new file mode 100644 >> index 000..1fe2b1a >> --- /dev/null >> +++ b/arm/pmu.c >> @@ -0,0 +1,62 @@ >> +/* >> + * Test the ARM Performance Monitors Unit (PMU). >> + * >> + * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. >> + * >> + * This program is free software; you can redistribute it and/or modify it >> + * under the terms of the GNU Lesser General Public License version 2.1 and >> + * only version 2.1 as published by the Free Software Foundation. >> + * >> + * 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 Lesser General Public >> License >> + * for more details. >> + */ >> +#include "libcflat.h" >> +#include "asm/barrier.h" >> +#include "asm/processor.h" >> + >> +#define PMU_PMCR_N_SHIFT 11 >> +#define PMU_PMCR_N_MASK0x1f >> +#define PMU_PMCR_ID_SHIFT 16 >> +#define PMU_PMCR_ID_MASK 0xff >> +#define PMU_PMCR_IMP_SHIFT 24 >> +#define PMU_PMCR_IMP_MASK 0xff >> + >> +#if defined(__arm__) >> +DEFINE_GET_SYSREG32(pmcr, 0, c9, c12, 0) >> +#elif defined(__aarch64__) >> +DEFINE_GET_SYSREG32(pmcr, el0) >> +#endif >> + >> +/* >> + * As a simple sanity check on the PMCR_EL0, ensure the implementer field >> isn't >> + * null. Also print out a couple other interesting fields for diagnostic >> + * purposes. For example, as of fall 2016, QEMU TCG mode doesn't implement >> + * event counters and therefore reports zero event counters, but hopefully >> + * support for at least the instructions event will be added in the future >> and >> + * the reported number of event counters will become nonzero. >> + */ >> +static bool check_pmcr(void) >> +{ >> +uint32_t pmcr; > > So based on my comments from the previous patch, pmcr should be > 'unsigned int' I don't think so. At least here as a _variable_ type uint32_t is probably the right one, as the ARMv8 ARM explicitly says that PMCR is a 32-bit register, for both bitnesses. I find it only natural to express it here accordingly. I believe this is a different (though related) discussion from the return type of the accessor functions. Cheers, Andre. >> + >> +pmcr = get_pmcr(); >> + >> +report_info("PMU implementer/ID code/counters: 0x%x(\"%c\")/0x%x/%d", >> +(pmcr >> PMU_PMCR_IMP_SHIFT) & PMU_PMCR_IMP_MASK, >> +((pmcr >> PMU_PMCR_IMP_SHIFT) & PMU_PMCR_IMP_MASK) ? : ' ', >> +(pmcr >> PMU_PMCR_ID_SHIFT) & PMU_PMCR_ID_MASK, >> +(pmcr >> PMU_PMCR_N_SHIFT) & PMU_PMCR_N_MASK); >> + >> +return ((pmcr >> PMU_PMCR_IMP_SHIFT) & PMU_PMCR_IMP_MASK) != 0; >> +} >> + >> +int main(void) >> +{ >> +report_prefix_push("pmu"); >> + >> +report("Control register", check_pmcr()); >> + >> +return report_summary(); >> +} >> diff --git a/arm/unittests.cfg b/arm/unittests.cfg >> index ae32a42..816f494 100644 >> --- a/arm/unittests.cfg >> +++ b/arm/unittests.cfg >> @@ -58,3 +58,8 @@ groups = selftest >> [pci-test] >> file = pci-test.flat >> groups = pci >> + >> +# Test PMU support >> +[pmu] >> +file = pmu.flat >> +groups = pmu >> -- >> 1.8.3.1 >> >> > > drew >
Re: [Qemu-devel] [kvm-unit-tests PATCH v13 3/4] arm: pmu: Check cycle count increases
Hi, On 01/12/16 05:16, Wei Huang wrote: > From: Christopher Covington> > Ensure that reads of the PMCCNTR_EL0 are monotonically increasing, > even for the smallest delta of two subsequent reads. > > Signed-off-by: Christopher Covington > Signed-off-by: Wei Huang > Reviewed-by: Andrew Jones > --- > arm/pmu.c | 94 > +++ > 1 file changed, 94 insertions(+) > > diff --git a/arm/pmu.c b/arm/pmu.c > index 1fe2b1a..3566a27 100644 > --- a/arm/pmu.c > +++ b/arm/pmu.c > @@ -16,6 +16,9 @@ > #include "asm/barrier.h" > #include "asm/processor.h" > > +#define PMU_PMCR_E (1 << 0) > +#define PMU_PMCR_C (1 << 2) > +#define PMU_PMCR_LC(1 << 6) > #define PMU_PMCR_N_SHIFT 11 > #define PMU_PMCR_N_MASK0x1f > #define PMU_PMCR_ID_SHIFT 16 > @@ -23,10 +26,57 @@ > #define PMU_PMCR_IMP_SHIFT 24 > #define PMU_PMCR_IMP_MASK 0xff > > +#define ID_DFR0_PERFMON_SHIFT 24 > +#define ID_DFR0_PERFMON_MASK 0xf > + > +#define PMU_CYCLE_IDX 31 > + > +#define NR_SAMPLES 10 > + > +static unsigned int pmu_version; > #if defined(__arm__) > DEFINE_GET_SYSREG32(pmcr, 0, c9, c12, 0) > +DEFINE_SET_SYSREG32(pmcr, 0, c9, c12, 0) > +DEFINE_GET_SYSREG32(id_dfr0, 0, c0, c1, 2) > +DEFINE_SET_SYSREG32(pmselr, 0, c9, c12, 5) > +DEFINE_SET_SYSREG32(pmxevtyper, 0, c9, c13, 1) > +DEFINE_GET_SYSREG32(pmccntr32, 0, c9, c13, 0) > +DEFINE_SET_SYSREG32(pmccntr32, 0, c9, c13, 0) > +DEFINE_GET_SYSREG64(pmccntr64, 0, c9) > +DEFINE_SET_SYSREG64(pmccntr64, 0, c9) > +DEFINE_SET_SYSREG32(pmcntenset, 0, c9, c12, 1) > + > +static inline uint64_t get_pmccntr(void) > +{ > + if (pmu_version == 0x3) > + return get_pmccntr64(); > + else > + return get_pmccntr32(); > +} > + > +static inline void set_pmccntr(uint64_t value) > +{ > + if (pmu_version == 0x3) > + set_pmccntr64(value); > + else > + set_pmccntr32(value & 0x); > +} > + > +/* PMCCFILTR is an obsolete name for PMXEVTYPER31 in ARMv7 */ > +static inline void set_pmccfiltr(uint32_t value) > +{ > + set_pmselr(PMU_CYCLE_IDX); > + set_pmxevtyper(value); > + isb(); > +} > #elif defined(__aarch64__) > DEFINE_GET_SYSREG32(pmcr, el0) > +DEFINE_SET_SYSREG32(pmcr, el0) > +DEFINE_GET_SYSREG32(id_dfr0, el1) > +DEFINE_GET_SYSREG64(pmccntr, el0); > +DEFINE_SET_SYSREG64(pmccntr, el0); > +DEFINE_SET_SYSREG32(pmcntenset, el0); > +DEFINE_SET_SYSREG32(pmccfiltr, el0); > #endif > > /* > @@ -52,11 +102,55 @@ static bool check_pmcr(void) > return ((pmcr >> PMU_PMCR_IMP_SHIFT) & PMU_PMCR_IMP_MASK) != 0; > } > > +/* > + * Ensure that the cycle counter progresses between back-to-back reads. > + */ > +static bool check_cycles_increase(void) > +{ > + bool success = true; > + > + /* init before event access, this test only cares about cycle count */ > + set_pmcntenset(1 << PMU_CYCLE_IDX); > + set_pmccfiltr(0); /* count cycles in EL0, EL1, but not EL2 */ > + set_pmccntr(0); Why do we need this? Shouldn't PMU_PMCR_C below take care of that? > + > + set_pmcr(get_pmcr() | PMU_PMCR_LC | PMU_PMCR_C | PMU_PMCR_E); > + > + for (int i = 0; i < NR_SAMPLES; i++) { > + uint64_t a, b; > + > + a = get_pmccntr(); > + b = get_pmccntr(); > + > + if (a >= b) { > + printf("Read %"PRId64" then %"PRId64".\n", a, b); > + success = false; > + break; > + } > + } > + > + set_pmcr(get_pmcr() & ~PMU_PMCR_E); > + > + return success; > +} > + > +void pmu_init(void) Mmh, this function doesn't really initialize anything, does it? Should it be named pmu_available() or pmu_version() or the like? And should we bail out early here (or rather at the caller) if this register reports that no PMU is available? For instance by making it return a boolean? > +{ > + uint32_t dfr0; > + > + /* probe pmu version */ > + dfr0 = get_id_dfr0(); > + pmu_version = (dfr0 >> ID_DFR0_PERFMON_SHIFT) & ID_DFR0_PERFMON_MASK; > + report_info("PMU version: %d", pmu_version); > +} > + > int main(void) > { > report_prefix_push("pmu"); > > + pmu_init(); > report("Control register", check_pmcr()); > + report("Monotonically increasing cycle count", check_cycles_increase()); I wonder if we should skip this test if check_pmcr() has returned false before? We let it return a boolean, so it seems quite natural to use this information here. This would avoid a lot of false FAILs due to the PMU not being available (because QEMU is too old, for instance). Cheers, Andre.
Re: [Qemu-devel] [kvm-unit-tests PATCH v13 1/4] arm: Define macros for accessing system registers
Hi, On 01/12/16 08:59, Andrew Jones wrote: > > Should this be From: Andre? No need from my side, this way all the bug reports are send to Wei ;-) > On Wed, Nov 30, 2016 at 11:16:39PM -0600, Wei Huang wrote: >> This patch defines four macros to assist creating system register >> accessors under both ARMv7 and AArch64: >>* DEFINE_GET_SYSREG32(name, ...) >>* DEFINE_SET_SYSREG32(name, ...) >>* DEFINE_GET_SYSREG64(name, ...) >>* DEFINE_SET_SYSREG64(name, ...) >> These macros are translated to inline functions with consistent naming, >> get_##name() and set_##name(), which can be used by C code directly. >> >> Signed-off-by: Andre Przywara <andre.przyw...@arm.com> >> Signed-off-by: Wei Huang <w...@redhat.com> >> --- >> lib/arm/asm/processor.h | 37 - >> lib/arm64/asm/processor.h | 35 --- >> 2 files changed, 60 insertions(+), 12 deletions(-) >> >> diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h >> index f25e7ee..3ca6b42 100644 >> --- a/lib/arm/asm/processor.h >> +++ b/lib/arm/asm/processor.h >> @@ -33,13 +33,40 @@ static inline unsigned long current_cpsr(void) >> >> #define current_mode() (current_cpsr() & MODE_MASK) >> >> -static inline unsigned int get_mpidr(void) >> -{ >> -unsigned int mpidr; >> -asm volatile("mrc p15, 0, %0, c0, c0, 5" : "=r" (mpidr)); >> -return mpidr; >> +#define DEFINE_GET_SYSREG32(name, opc1, crn, crm, opc2) >> \ >> +static inline uint32_t get_##name(void) >> \ >> +{ \ >> +uint32_t reg; \ >> +asm volatile("mrc p15, " #opc1 ", %0, " #crn ", " #crm ", " \ >> + #opc2 : "=r" (reg)); \ >> +return reg; \ >> +} >> + >> +#define DEFINE_SET_SYSREG32(name, opc1, crn, crm, opc2) >> \ >> +static inline void set_##name(uint32_t value) >> \ >> +{ \ >> +asm volatile("mcr p15, " #opc1 ", %0, " #crn ", " #crm ", " \ >> + #opc2 :: "r" (value)); \ >^ nit: no space here, checkpatch would complain >> +} >> + >> +#define DEFINE_GET_SYSREG64(name, opc, crm) \ >> +static inline uint64_t get_##name(void) >> \ >> +{ \ >> +uint32_t lo, hi;\ >> +asm volatile("mrrc p15, " #opc ", %0, %1, " #crm\ >> + : "=r" (lo), "=r" (hi)); \ >> +return (uint64_t)hi << 32 | lo; \ >> +} >> + >> +#define DEFINE_SET_SYSREG64(name, opc, crm) \ >> +static inline void set_##name(uint64_t value) >> \ >> +{ \ >> +asm volatile("mcrr p15, " #opc ", %0, %1, " #crm\ >> + :: "r" (value & 0x), "r" (value >> 32)); \ >> } >> >> +DEFINE_GET_SYSREG32(mpidr, 0, c0, c0, 5) >> + >> /* Only support Aff0 for now, up to 4 cpus */ >> #define mpidr_to_cpu(mpidr) ((int)((mpidr) & 0xff)) >> >> diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h >> index 84d5c7c..dfa75eb 100644 >> --- a/lib/arm64/asm/processor.h >> +++ b/lib/arm64/asm/processor.h >> @@ -66,14 +66,35 @@ static inline unsigned long current_level(void) >> return el & 0xc; >> } >> >> -#define DEFINE_GET_SYSREG32(reg)\ >> -static inline unsigned int get_##reg(void) \ >> -{ \ >> -unsigned int reg; \ >> -asm volatile("mrs %0, " #reg "_el1" : "=r" (reg)); \ >> -return reg;
Re: [Qemu-devel] [kvm-unit-tests PATCH v13 4/4] arm: pmu: Add CPI checking
Hi Drew, actually unrelated to this actual patch, but since you mentioned it: > As we work out how best to handle tcg-only tests in order to get Alex > Bennee's MTTCG tests merged, we'll probably revisit this file, So when I was experimenting with kvmtool, I realized that some tests would need to be QEMU only. Also I was tempted to try some tests either on bare metal machines or in a Fast Model. So I wonder if we should have some constraints or tags on the tests, so that a certain backend can filter on this and skip if it's not capable? Just wanted to mention this so that we can use this refactoring opportunity to come up with something more generic than just a boolean TGC vs. KVM. Maybe we should introduce the notion of a "test backend"? That could be QEMU/KVM and TCG for now, but later extended to cover kvmtool and probably other hypervisors like Xen as well. Cheers, Andre.
Re: [Qemu-devel] [kvm-unit-tests PATCH v11 1/3] arm: Add PMU test
Hi, On 25/11/16 14:26, Andrew Jones wrote: > On Fri, Nov 25, 2016 at 12:32:24PM +0000, Andre Przywara wrote: >> Hi Drew, >> >> >> >> On 23/11/16 17:15, Andrew Jones wrote: >>>>> + >>>>> +#if defined(__arm__) >>>> >>>> I guess you should use the arch specific header files we have in place >>>> for that (lib/arm{.64}/asm/processor.h). Also there are sysreg read >>>> wrappers (at least for arm64) in there already, can't we base this >>>> function on them: DEFINE_GET_SYSREG32(pmcr, el0)? >>>> (Requires a small change to get rid of the forced "_el1" suffix) >>>> >>>> We should wait for the GIC series to be merged, as this contains some >>>> changes in this area. >>> >>> As this unit test is the only consumer of PMC registers so far, then >>> I'd prefer the defines and accessors stay here for now. Once we see >>> a use in other unit tests then we can move some of it out. >> >> Well, I was more thinking of something like below. >> I am fine with keeping the PMU sysregs private to pmu.c, but we can still >> use the sysreg wrappers, can't we? >> This is on top of Wei's series, so doesn't have your SYSREG32/64 >> unification, but I leave this as an exercise to the reader. >> There is some churn in pmu.c below due to the change of _write to >> set_, but the rest looks like simplification to me. >> >> Does that make sense? > > Ah, now I see what you mean, and I think I like that. The question is > whether or not I like my SYSREG macros :-) I see value in having the > asm's easy to read (open-coded), Mmh, where is this easy to read? Especially the v7 syntax is really error prone and hard to grasp with all these c9s, c12s and friends, in addition to the weird ordering and mixing in of register names in the (inline) assembly syntax. Blame the company that came up with this architecture ;-) Compare: mrc p15, 0, %0, c9, c12, 0 with: DEFINE_GET_SYSREG32(pmcr, 0, c9, c12, 0) The "0, %0" in there always kills me when reading this. On top of this a list of one-line-per-sysreg declarations is much easier to compare with the manual than the open coded versions. Another benefit is that we don't need to encode versions for both bitnesses in each test. For shared sysregs we could put the definitions in processor.h, the code then just uses one architecture agnostic version. But I leave it up to you guys to decide on this, you don't break my heart if you stick with inline assembly ;-) Cheers, Andre. as well as value in making sure we > only have to review sysreg functions once. Let's ask for Wei's and > Cov's votes. If they like the SYSREG direction, then they can vote > with another version of this series :-) > > Thanks, > drew > >> >> Cheers, >> Andre. >> >> --- >> arm/pmu.c | 159 >> +- >> lib/arm/asm/processor.h | 34 -- >> lib/arm64/asm/processor.h | 23 ++- >> 3 files changed, 92 insertions(+), 124 deletions(-) >> >> diff --git a/arm/pmu.c b/arm/pmu.c >> index f667676..f0ad02a 100644 >> --- a/arm/pmu.c >> +++ b/arm/pmu.c >> @@ -14,6 +14,7 @@ >> */ >> #include "libcflat.h" >> #include "asm/barrier.h" >> +#include "asm/processor.h" >> >> #define PMU_PMCR_E (1 << 0) >> #define PMU_PMCR_C (1 << 2) >> @@ -33,78 +34,42 @@ >> #define NR_SAMPLES 10 >> >> static unsigned int pmu_version; >> -#if defined(__arm__) >> -static inline uint32_t pmcr_read(void) >> -{ >> -uint32_t ret; >> - >> -asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (ret)); >> -return ret; >> -} >> - >> -static inline void pmcr_write(uint32_t value) >> -{ >> -asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r" (value)); >> -isb(); >> -} >> >> -static inline void pmselr_write(uint32_t value) >> -{ >> -asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (value)); >> -isb(); >> -} >> - >> -static inline void pmxevtyper_write(uint32_t value) >> -{ >> -asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (value)); >> -} >> - >> -static inline uint64_t pmccntr_read(void) >> +#if defined(__arm__) >> +DEFINE_GET_SYSREG32(pmcr, 0, c9, c12, 0) >> +DEFINE_SET_SYSREG32(pmcr, 0, c9, c12, 0) >> +DEFINE_GET_SYSREG32(id_dfr0, 0, c0, c1, 2) >> +DEFINE_SE
Re: [Qemu-devel] [kvm-unit-tests PATCH v11 1/3] arm: Add PMU test
Hi Drew, On 23/11/16 17:15, Andrew Jones wrote: >>> + >>> +#if defined(__arm__) >> >> I guess you should use the arch specific header files we have in place >> for that (lib/arm{.64}/asm/processor.h). Also there are sysreg read >> wrappers (at least for arm64) in there already, can't we base this >> function on them: DEFINE_GET_SYSREG32(pmcr, el0)? >> (Requires a small change to get rid of the forced "_el1" suffix) >> >> We should wait for the GIC series to be merged, as this contains some >> changes in this area. > > As this unit test is the only consumer of PMC registers so far, then > I'd prefer the defines and accessors stay here for now. Once we see > a use in other unit tests then we can move some of it out. Well, I was more thinking of something like below. I am fine with keeping the PMU sysregs private to pmu.c, but we can still use the sysreg wrappers, can't we? This is on top of Wei's series, so doesn't have your SYSREG32/64 unification, but I leave this as an exercise to the reader. There is some churn in pmu.c below due to the change of _write to set_, but the rest looks like simplification to me. Does that make sense? Cheers, Andre. --- arm/pmu.c | 159 +- lib/arm/asm/processor.h | 34 -- lib/arm64/asm/processor.h | 23 ++- 3 files changed, 92 insertions(+), 124 deletions(-) diff --git a/arm/pmu.c b/arm/pmu.c index f667676..f0ad02a 100644 --- a/arm/pmu.c +++ b/arm/pmu.c @@ -14,6 +14,7 @@ */ #include "libcflat.h" #include "asm/barrier.h" +#include "asm/processor.h" #define PMU_PMCR_E (1 << 0) #define PMU_PMCR_C (1 << 2) @@ -33,78 +34,42 @@ #define NR_SAMPLES 10 static unsigned int pmu_version; -#if defined(__arm__) -static inline uint32_t pmcr_read(void) -{ - uint32_t ret; - - asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (ret)); - return ret; -} - -static inline void pmcr_write(uint32_t value) -{ - asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r" (value)); - isb(); -} -static inline void pmselr_write(uint32_t value) -{ - asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (value)); - isb(); -} - -static inline void pmxevtyper_write(uint32_t value) -{ - asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (value)); -} - -static inline uint64_t pmccntr_read(void) +#if defined(__arm__) +DEFINE_GET_SYSREG32(pmcr, 0, c9, c12, 0) +DEFINE_SET_SYSREG32(pmcr, 0, c9, c12, 0) +DEFINE_GET_SYSREG32(id_dfr0, 0, c0, c1, 2) +DEFINE_SET_SYSREG32(pmselr, 0, c9, c12, 5) +DEFINE_SET_SYSREG32(pmxevtyper, 0, c9, c13, 1) +DEFINE_GET_SYSREG32(pmccntr32, 0, c9, c13, 0) +DEFINE_SET_SYSREG32(pmccntr32, 0, c9, c13, 0) +DEFINE_GET_SYSREG64(pmccntr64, 0, c9) +DEFINE_SET_SYSREG64(pmccntr64, 0, c9) +DEFINE_SET_SYSREG32(pmcntenset, 0, c9, c12, 1) + +static inline uint64_t get_pmccntr(void) { - uint32_t lo, hi = 0; - if (pmu_version == 0x3) - asm volatile("mrrc p15, 0, %0, %1, c9" : "=r" (lo), "=r" (hi)); + return get_pmccntr32(); else - asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (lo)); - - return ((uint64_t)hi << 32) | lo; + return get_pmccntr64(); } -static inline void pmccntr_write(uint64_t value) +static inline void set_pmccntr(uint64_t value) { - uint32_t lo, hi; - - lo = value & 0x; - hi = (value >> 32) & 0x; - if (pmu_version == 0x3) - asm volatile("mcrr p15, 0, %0, %1, c9" : : "r" (lo), "r" (hi)); + set_pmccntr64(value); else - asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (lo)); + set_pmccntr64(value & 0x); } - -static inline void pmcntenset_write(uint32_t value) -{ - asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (value)); -} - /* PMCCFILTR is an obsolete name for PMXEVTYPER31 in ARMv7 */ -static inline void pmccfiltr_write(uint32_t value) +static inline void set_pmccfiltr(uint32_t value) { - pmselr_write(PMU_CYCLE_IDX); - pmxevtyper_write(value); + set_pmselr(PMU_CYCLE_IDX); + set_pmxevtyper(value); isb(); } -static inline uint32_t id_dfr0_read(void) -{ - uint32_t val; - - asm volatile("mrc p15, 0, %0, c0, c1, 2" : "=r" (val)); - return val; -} - /* * Extra instructions inserted by the compiler would be difficult to compensate * for, so hand assemble everything between, and including, the PMCR accesses @@ -126,51 +91,13 @@ static inline void precise_instrs_loop(int loop, uint32_t pmcr) : "cc"); } #elif defined(__aarch64__) -static inline uint32_t pmcr_read(void) -{ - uint32_t ret; - - asm volatile("mrs %0, pmcr_el0" : "=r" (ret)); - return ret; -} - -static inline void pmcr_write(uint32_t value) -{ - asm volatile("msr pmcr_el0, %0" : : "r" (value)); - isb(); -} - -static inline uint64_t pmccntr_read(void) -{ - uint64_t cycles; -
Re: [Qemu-devel] [kvm-unit-tests PATCH v11 1/3] arm: Add PMU test
Hi, On 22/11/16 18:29, Wei Huang wrote: > From: Christopher Covington> > Beginning with a simple sanity check of the control register, add > a unit test for the ARM Performance Monitors Unit (PMU). Mmh, the output of this is a bit confusing. How about to join some information? I changed it to give me: INFO: pmu: PMU implementer/ID code: "A"(0x41)/0x0 INFO: pmu: Event counters: 0 PASS: pmu: Control register ... by using the newly introduced report_info() to make it look nicer. > > Signed-off-by: Christopher Covington > Signed-off-by: Wei Huang > Reviewed-by: Andrew Jones > --- > arm/Makefile.common | 3 ++- > arm/pmu.c | 74 > + > arm/unittests.cfg | 5 > 3 files changed, 81 insertions(+), 1 deletion(-) > create mode 100644 arm/pmu.c > > diff --git a/arm/Makefile.common b/arm/Makefile.common > index f37b5c2..5da2fdd 100644 > --- a/arm/Makefile.common > +++ b/arm/Makefile.common > @@ -12,7 +12,8 @@ endif > tests-common = \ > $(TEST_DIR)/selftest.flat \ > $(TEST_DIR)/spinlock-test.flat \ > - $(TEST_DIR)/pci-test.flat > + $(TEST_DIR)/pci-test.flat \ > + $(TEST_DIR)/pmu.flat > > all: test_cases > > diff --git a/arm/pmu.c b/arm/pmu.c > new file mode 100644 > index 000..9d9c53b > --- /dev/null > +++ b/arm/pmu.c > @@ -0,0 +1,74 @@ > +/* > + * Test the ARM Performance Monitors Unit (PMU). > + * > + * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of the GNU Lesser General Public License version 2.1 and > + * only version 2.1 as published by the Free Software Foundation. > + * > + * 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 Lesser General Public > License > + * for more details. > + */ > +#include "libcflat.h" > +#include "asm/barrier.h" > + > +#define PMU_PMCR_N_SHIFT 11 > +#define PMU_PMCR_N_MASK0x1f > +#define PMU_PMCR_ID_SHIFT 16 > +#define PMU_PMCR_ID_MASK 0xff > +#define PMU_PMCR_IMP_SHIFT 24 > +#define PMU_PMCR_IMP_MASK 0xff > + > +#if defined(__arm__) I guess you should use the arch specific header files we have in place for that (lib/arm{.64}/asm/processor.h). Also there are sysreg read wrappers (at least for arm64) in there already, can't we base this function on them: DEFINE_GET_SYSREG32(pmcr, el0)? (Requires a small change to get rid of the forced "_el1" suffix) We should wait for the GIC series to be merged, as this contains some changes in this area. > +static inline uint32_t pmcr_read(void) > +{ > + uint32_t ret; > + > + asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (ret)); > + return ret; > +} > +#elif defined(__aarch64__) > +static inline uint32_t pmcr_read(void) > +{ > + uint32_t ret; > + > + asm volatile("mrs %0, pmcr_el0" : "=r" (ret)); > + return ret; > +} > +#endif > + > +/* > + * As a simple sanity check on the PMCR_EL0, ensure the implementer field > isn't > + * null. Also print out a couple other interesting fields for diagnostic > + * purposes. For example, as of fall 2016, QEMU TCG mode doesn't implement > + * event counters and therefore reports zero event counters, but hopefully > + * support for at least the instructions event will be added in the future > and > + * the reported number of event counters will become nonzero. > + */ > +static bool check_pmcr(void) > +{ > + uint32_t pmcr; > + > + pmcr = pmcr_read(); > + > + printf("PMU implementer: %c\n", > +(pmcr >> PMU_PMCR_IMP_SHIFT) & PMU_PMCR_IMP_MASK); If this register reads as zero, the output is mangled (since it cuts off the string before the newline): = PMU implementer: Identification code: 0x0 = I guess you need something like: (pmcr >> PMU_PMCR_IMP_SHIFT) & PMU_PMCR_IMP_MASK ?: ' ' > + printf("Identification code: 0x%x\n", > +(pmcr >> PMU_PMCR_ID_SHIFT) & PMU_PMCR_ID_MASK); As mentioned above this should use report_info() now, also it would be nice to merge this with the message above into one line of output. Cheers, Andre > + printf("Event counters: %d\n", > +(pmcr >> PMU_PMCR_N_SHIFT) & PMU_PMCR_N_MASK); > + > + return ((pmcr >> PMU_PMCR_IMP_SHIFT) & PMU_PMCR_IMP_MASK) != 0; > +} > + > +int main(void) > +{ > + report_prefix_push("pmu"); > + > + report("Control register", check_pmcr()); > + > + return report_summary(); > +} > diff --git a/arm/unittests.cfg b/arm/unittests.cfg > index ae32a42..816f494 100644 > --- a/arm/unittests.cfg > +++ b/arm/unittests.cfg > @@ -58,3 +58,8 @@ groups = selftest > [pci-test] > file = pci-test.flat > groups = pci > + > +# Test PMU support > +[pmu] > +file =
Re: [Qemu-devel] [kvm-unit-tests PATCH 3/4] arm/arm64: GICv2: add GICD_ITARGETSR testing
Hi Eric, thanks for having such a close look (as always!). On 23/11/16 13:51, Auger Eric wrote: > Hi Andre, > > On 23/11/2016 14:24, Auger Eric wrote: >> Hi, >> >> On 18/11/2016 15:20, Andrew Jones wrote: >>> On Thu, Nov 17, 2016 at 05:57:51PM +, Andre Przywara wrote: >>>> Some tests for the ITARGETS registers. >>>> Bits corresponding to non-existent CPUs must be RAZ/WI. >>>> These registers must be byte-accessible, also check that accesses beyond >>>> the implemented IRQ limit are actually read-as-zero/write-ignore. >>>> >>>> Signed-off-by: Andre Przywara <andre.przyw...@arm.com> >>>> --- >>>> arm/gic.c | 54 >>>> ++ >>>> lib/arm/asm/gic.h | 1 + >>>> 2 files changed, 55 insertions(+) >>>> >>>> diff --git a/arm/gic.c b/arm/gic.c >>>> index a27da2c..02b1be1 100644 >>>> --- a/arm/gic.c >>>> +++ b/arm/gic.c >>>> @@ -397,6 +397,57 @@ static bool test_priorities(int nr_irqs, void *priptr) >>>>return true; >>>> } >>>> >>>> +static bool test_targets(int nr_irqs) >>>> +{ >>>> + void *targetsptr = gicv2_dist_base() + GICD_ITARGETSR; >>>> + u32 orig_targets; >>>> + u32 cpu_mask; >>>> + u32 pattern, reg; >>>> + >>>> + orig_targets = readl(targetsptr + 32); >>>> + report_prefix_push("ITARGETSR"); >>>> + >>>> + cpu_mask = (1 << nr_cpus) - 1; >>> >>> Shouldn't this be 1 << (nr_cpus - 1) ? >> original looks correct to me. >>> >>> Is this test always going to be gicv2-only? We should probably comment it, >>> if so. We don't want to risk this being run when nr_cpus can be larger >>> than 8. >>> >>>> + cpu_mask |= cpu_mask << 8; So this instruction is supposed to copy bits[7:0] into bits[15:8] (not caring about the other bits, which are zero anyway). >>>> + cpu_mask |= cpu_mask << 16; And this one copies bits[15:0] into bits[31:16]. >> Don't we miss the 4th byte mask? I don't think so, the idea is just to copy the lowest byte into all the other three bytes of that word and thus to propagate the byte mask for one IRQ into a word covering four interrupts. Does that make sense? I take it this deserves a comment then ... >>>> + >>>> + /* Check that bits for non implemented CPUs are RAZ/WI. */ >>>> + if (nr_cpus < 8) { >>>> + writel(0x, targetsptr + 32); >>>> + report("bits for %d non-existent CPUs masked", >>>> + !(readl(targetsptr + 32) & ~cpu_mask), 8 - nr_cpus); > > yep on AMD overdrive with smp=4 I get: > > FAIL: gicv2: mmio: ITARGETSR: bits for 4 non-existent CPUs masked I guess because you don't have http://lists.infradead.org/pipermail/linux-arm-kernel/2016-November/468296.html in your host kernel? This was one of the two genuine bugs I spotted with this. Cheers, Andre. >>>> + } else { >>>> + report_skip("CPU masking (all CPUs implemented)"); >>>> + } >>>> + >>>> + report("accesses beyond limit RAZ/WI", >>>> + test_readonly_32(targetsptr + nr_irqs, true)); >>>> + >>>> + pattern = 0x0103020f; >>>> + writel(pattern, targetsptr + 32); >>>> + reg = readl(targetsptr + 32); >>>> + report("register content preserved (%08x => %08x)", >>>> + reg == (pattern & cpu_mask), pattern & cpu_mask, reg); >>>> + >>>> + /* >>>> + * The TARGETS registers are byte accessible, do a byte-wide >>>> + * read and write of known content to check for this. >>>> + */ >>>> + reg = readb(targetsptr + 33); >>>> + report("byte reads successful (0x%08x => 0x%02x)", >>>> + reg == (BYTE(pattern, 1) & cpu_mask), >>>> + pattern & cpu_mask, reg); >>>> + >>>> + pattern = REPLACE_BYTE(pattern, 2, 0x04); >>>> + writeb(BYTE(pattern, 2), targetsptr + 34); >>>> + reg = readl(targetsptr + 32); >>>> + report("byte writes successful (0x%02x => 0x%08x)", >>>> + reg == (pattern & cpu_mask), BYTE(pattern, 2), reg); >>> >>> Last patch also had a byte addressability test. Maybe we should make >>> a helper function? >>> >>>> + >>>> + writel(orig_targets, targetsptr + 32); >>>> + return true; >>> >>> Function can/should be void. >>> >>>> +} >>>> + >>>> static int gic_test_mmio(int gic_version) >>>> { >>>>u32 reg; >>>> @@ -436,6 +487,9 @@ static int gic_test_mmio(int gic_version) >>>> >>>>test_priorities(nr_irqs, gic_dist_base + GICD_IPRIORITYR); >>>> >>>> + if (gic_version == 2) >>>> + test_targets(nr_irqs); >>>> + >>>>return 0; >>>> } >>>> >>>> diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h >>>> index cef748d..6f170cb 100644 >>>> --- a/lib/arm/asm/gic.h >>>> +++ b/lib/arm/asm/gic.h >>>> @@ -14,6 +14,7 @@ >>>> #define GICD_IGROUPR 0x0080 >>>> #define GICD_ISENABLER0x0100 >>>> #define GICD_IPRIORITYR 0x0400 >>>> +#define GICD_ITARGETSR0x0800 >>>> #define GICD_SGIR 0x0f00 >>>> #define GICD_ICPIDR2 0x0fe8 >>>> >>>> -- >>>> 2.9.0 >>>> >>>> >>> >>> Thanks, >>> drew >>>
Re: [Qemu-devel] [kvm-unit-tests PATCH v6 00/11] arm/arm64: add gic framework
Hi, On 22/11/16 18:45, Andrew Jones wrote: > > Andre, Alex, Eric, anybody, > > Any more comments on this? If not, I'll send a pull request > to Radim and Paolo to finally get this merged. I didn't manage to look in detail at the IPI test, but I am OK with the rest of the GIC framework. So I'd say: go ahead. Cheers, Andre. > On Mon, Nov 14, 2016 at 10:08:28PM +0100, Andrew Jones wrote: >> v6: >> - rebased to latest master >> - several other changes thanks to Andre and Alex, changes in >>individual patch change logs >> - some code cleanups >> >> v5: >> - fix arm32/gicv3 compile [drew] >> - use modern register names [Andre] >> - one Andre r-b >> >> v4: >> - Eric's r-b's >> - Andre's suggestion to only take defines we need >> - several other changes listed in individual patches >> >> v3: >> - Rebased on latest master >> - Added Alex's r-b's >> >> v2: >> Rebased on latest master + my "populate argv[0]" series (will >> send a REPOST for that shortly. Additionally a few patches got >> fixes/features; >> 07/10 got same fix as kernel 7c9b973061 "irqchip/gic-v3: Configure >>all interrupts as non-secure Group-1" in order to continue >>working over TCG, as the gicv3 code for TCG removed a hack >>it had there to make Linux happy. >> 08/10 added more output for when things fail (if they fail) >> 09/10 switched gicv3 broadcast implementation to using IRM. This >>found a bug in a recent (but not tip) kernel, which I was >>about to fix, but then I saw MarcZ beat me to it. >> 10/10 actually check that the input irq is the received irq >> >> >> Import defines, and steal enough helper functions, from Linux to >> enable programming of the gic (v2 and v3). Then use the framework >> to add an initial test (an ipi test; self, target-list, broadcast). >> >> It's my hope that this framework will be a suitable base on which >> more tests may be easily added, particularly because we have >> vgic-new and tcg gicv3 emulation getting close to merge. (v3 UPDATE: >> vgic-new and tcg gicv3 are merged now) >> >> To run it, along with other tests, just do >> >> ./configure [ --arch=[arm|arm64] --cross-prefix=$PREFIX ] >> make >> export QEMU=$PATH_TO_QEMU >> ./run_tests.sh >> >> To run it separately do, e.g. >> >> $QEMU -machine virt,accel=tcg -cpu cortex-a57 \ >> -device virtio-serial-device \ >> -device virtconsole,chardev=ctd -chardev testdev,id=ctd \ >> -display none -serial stdio \ >> -kernel arm/gic.flat \ >> -smp 123 -machine gic-version=3 -append ipi >> ^^ note, we can go nuts with nr-cpus on TCG :-) >> >> Or, a KVM example using a different "sender" cpu and irq (other than zero) >> >> $QEMU -machine virt,accel=kvm -cpu host \ >> -device virtio-serial-device \ >> -device virtconsole,chardev=ctd -chardev testdev,id=ctd \ >> -display none -serial stdio \ >> -kernel arm/gic.flat \ >> -smp 48 -machine gic-version=3 -append 'ipi sender=42 irq=1' >> >> >> Patches: >> 01-05: fixes and functionality needed by the later gic patches >> 06-07: enable gicv2 and gicv2 IPI test >> 08-10: enable gicv3 and gicv3 IPI test >>11: extend the IPI tests to take variable sender and irq >> >> Available here: >> https://github.com/rhdrjones/kvm-unit-tests/commits/arm/gic-v6 >> >> >> Andrew Jones (10): >> lib: xstr: allow multiple args >> arm64: fix get_"sysreg32" and make MPIDR 64bit >> arm/arm64: smp: support more than 8 cpus >> arm/arm64: add some delay routines >> arm/arm64: irq enable/disable >> arm/arm64: add initial gicv2 support >> arm/arm64: gicv2: add an IPI test >> arm/arm64: add initial gicv3 support >> arm/arm64: gicv3: add an IPI test >> arm/arm64: gic: don't just use zero >> >> Peter Xu (1): >> libcflat: add IS_ALIGNED() macro, and page sizes >> >> arm/Makefile.common| 9 +- >> arm/gic.c | 340 >> + >> arm/run| 19 ++- >> arm/selftest.c | 5 +- >> arm/unittests.cfg | 14 ++ >> lib/arm/asm/arch_gicv3.h | 70 ++ >> lib/arm/asm/gic-v2.h | 36 + >> lib/arm/asm/gic-v3.h | 112 +++ >> lib/arm/asm/gic.h | 106 ++ >> lib/arm/asm/processor.h| 42 +- >> lib/arm/asm/setup.h| 4 +- >> lib/arm/gic.c | 267 +++ >> lib/arm/processor.c| 15 ++ >> lib/arm/setup.c| 10 ++ >> lib/arm64/asm/arch_gicv3.h | 66 + >> lib/arm64/asm/gic-v2.h | 1 + >> lib/arm64/asm/gic-v3.h | 1 + >> lib/arm64/asm/gic.h| 1 + >> lib/arm64/asm/processor.h | 53 +-- >> lib/arm64/asm/sysreg.h | 44 ++ >> lib/arm64/processor.c | 15 ++ >> lib/libcflat.h | 10 +- >> 22 files changed, 1212 insertions(+), 28 deletions(-) >> create mode 100644 arm/gic.c >> create mode 100644 lib/arm/asm/arch_gicv3.h >> create mode 100644 lib/arm/asm/gic-v2.h >> create
[Qemu-devel] [kvm-unit-tests PATCH] configure: honour $ARCH and $CROSS_COMPILE
Both environment variables seem to be standard in cross-compilation environments, especially with Linux. Let the configure script take those into account when setting the default values for --arch and --cross-prefix. Explicitly specifying the latter on the configure command line still works as expected. Signed-off-by: Andre Przywara <andre.przyw...@arm.com> --- Hi, this maybe a personal itch to scratch here, since I set these two variables in my environment via a (sourced) script here and never have to care about the particular cross-compiler prefix, for instance. It looks rather generic, though, so I was wondering if this is useful upstream as well. Cheers, Andre. configure | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 995c8fa..9bb38ba 100755 --- a/configure +++ b/configure @@ -8,8 +8,9 @@ objdump=objdump ar=ar addr2line=addr2line arch=`uname -m | sed -e 's/i.86/i386/;s/arm.*/arm/;s/ppc64.*/ppc64/'` +[ -n "$ARCH" ] && arch="$ARCH" host=$arch -cross_prefix= +cross_prefix=${CROSS_COMPILE} endian="" pretty_print_stacks=yes -- 2.9.0
Re: [Qemu-devel] [kvm-unit-tests PATCH 1/4] arm/arm64: GIC: basic GICv2 MMIO tests
Hi Drew, On 18/11/16 13:06, Andrew Jones wrote: > Hi Andre, > > I'm so pleased to see this series. Thank you! > > On Thu, Nov 17, 2016 at 05:57:49PM +, Andre Przywara wrote: >> This adds an MMIO subtest to the GIC test. >> It accesses some generic GICv2 registers and does some sanity tests, >> like checking for some of them being read-only. >> >> Signed-off-by: Andre Przywara <andre.przyw...@arm.com> >> --- >> arm/gic.c | 99 >> +++ >> arm/unittests.cfg | 6 >> lib/arm/asm/gic.h | 2 ++ >> 3 files changed, 107 insertions(+) >> >> diff --git a/arm/gic.c b/arm/gic.c >> index 638b8b1..ba2585b 100644 >> --- a/arm/gic.c >> +++ b/arm/gic.c >> @@ -3,6 +3,7 @@ >> * >> * GICv2 >> * + test sending/receiving IPIs >> + * + MMIO access tests >> * GICv3 >> * + test sending/receiving IPIs >> * >> @@ -274,6 +275,98 @@ static struct gic gicv3 = { >> }, >> }; >> >> +static bool test_ro_pattern_32(void *address, u32 pattern, u32 orig) >> +{ >> +u32 reg; >> + >> +writel(pattern, address); >> +reg = readl(address); >> + >> +if (reg != orig) >> +writel(orig, address); >> + >> +return reg == orig; >> +} >> + >> +static bool test_readonly_32(void *address, bool razwi) >> +{ >> +u32 orig, pattern; >> + >> +orig = readl(address); >> +if (razwi && orig) >> +return false; >> + >> +pattern = 0x; >> +if (orig != pattern) { >> +if (!test_ro_pattern_32(address, pattern, orig)) >> +return false; >> +} >> + >> +pattern = 0xa5a55a5a; >> +if (orig != pattern) { >> +if (!test_ro_pattern_32(address, pattern, orig)) >> +return false; >> +} >> + >> +pattern = 0; >> +if (orig != pattern) { >> +if (!test_ro_pattern_32(address, pattern, orig)) >> +return false; >> +} >> + >> +return true; >> +} >> + >> +static bool test_typer_v2(uint32_t reg) >> +{ >> +int nr_gic_cpus = ((reg >> 5) & 0x7) + 1; >> + >> +report("all %d CPUs have interrupts", nr_cpus == nr_gic_cpus, >> + nr_gic_cpus); >> + >> +return true; > > This test function can be a void. > >> +} >> + >> +static int gic_test_mmio(int gic_version) >> +{ >> +u32 reg; >> +int nr_irqs; >> +void *gic_dist_base, *idreg; >> + >> +switch(gic_version) { >> +case 0x2: >> +gic_dist_base = gicv2_dist_base(); >> +idreg = gic_dist_base + 0xfe8; > > I see below you introduce GICD_ICPIDR2, so I guess you can use it here. > >> +break; >> +case 0x3: >> +report_abort("GICv3 MMIO tests NYI"); >> +return -1; > > can't reach this return But we need to tell GCC about this, because otherwise we get all kind of warnings (including bogus "maybe unused" warnings). __attribute__ ((noreturn)) seems the way to go here, but this is currently giving me a hard time ... >> +default: >> +report_abort("GIC version %d not supported", gic_version); >> +return 0; > > can't reach this return > >> +} >> + >> +reg = readl(gic_dist_base + GICD_TYPER); >> +nr_irqs = 32 * ((reg & 0x1f) + 1); > > Any reason to avoid using GICD_TYPER_IRQS() here? On the first write I wasn't aware of it, on a second thought then I wanted to avoid using the macro copied from Linux. But you are right, I will use it here. > >> +report("number of implemented SPIs: %d", 1, nr_irqs - 32); > > We usually just use printf for informational output (but we should > probably add a 'report_info' in order to keep the prefixes. I can > do that now.) Anyway, please s/1/true I saw your patch, will use that. >> + >> +test_typer_v2(reg); >> + >> +report("IIDR: 0x%x", 1, readl(gic_dist_base + GICD_IIDR)); >> + >> +report("GICD_TYPER is read-only", >> + test_readonly_32(gic_dist_base + GICD_TYPER, false)); >> +report("GICD_IIDR is read-only", >> + test_readonly_32(gic_dist_base + GICD_IIDR, false)); >> + >> +reg = readl(idreg); >> +
[Qemu-devel] [kvm-unit-tests PATCH 0/4] kvm-unit-tests: add first GIC MMIO tests
The GIC spec mandates certain constraints on how to acccess the MMIO mapped registers, both in terms of which registers are available and also in terms of which bits within a register should be masked, for instance. Since we went through some lengths in the KVM emulation to implement this, it's about time to give this actually a test beyond what the kernel as a GIC user actually implements - for instance we ignore priorities in Linux. This series tries to attack some constraints, on a low-hanging-fruit base. It focusses on some generic registers and the PRIORITY and TARGETS registers of GICv2. GICv3 is only covered to the point where the GICv2 tests overlap with GICv3. This actually revealed genuine bugs in the KVM emulation, for which I sent fixes in the last days. With those fixes the kernel passes all tests. Please have a look whether this makes sense and should eventually be extended on that base. Applies on top of master + Drew's v6 series. Cheers, Andre. Andre Przywara (4): arm/arm64: GIC: basic GICv2 MMIO tests arm/arm64: GICv2: add GICD_IPRIORITYR testing arm/arm64: GICv2: add GICD_ITARGETSR testing arm/arm64: GICv3: add TYPER test arm/gic.c | 253 ++ arm/unittests.cfg | 12 +++ lib/arm/asm/gic.h | 3 + 3 files changed, 268 insertions(+) -- 2.9.0
[Qemu-devel] [kvm-unit-tests PATCH 3/4] arm/arm64: GICv2: add GICD_ITARGETSR testing
Some tests for the ITARGETS registers. Bits corresponding to non-existent CPUs must be RAZ/WI. These registers must be byte-accessible, also check that accesses beyond the implemented IRQ limit are actually read-as-zero/write-ignore. Signed-off-by: Andre Przywara <andre.przyw...@arm.com> --- arm/gic.c | 54 ++ lib/arm/asm/gic.h | 1 + 2 files changed, 55 insertions(+) diff --git a/arm/gic.c b/arm/gic.c index a27da2c..02b1be1 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -397,6 +397,57 @@ static bool test_priorities(int nr_irqs, void *priptr) return true; } +static bool test_targets(int nr_irqs) +{ + void *targetsptr = gicv2_dist_base() + GICD_ITARGETSR; + u32 orig_targets; + u32 cpu_mask; + u32 pattern, reg; + + orig_targets = readl(targetsptr + 32); + report_prefix_push("ITARGETSR"); + + cpu_mask = (1 << nr_cpus) - 1; + cpu_mask |= cpu_mask << 8; + cpu_mask |= cpu_mask << 16; + + /* Check that bits for non implemented CPUs are RAZ/WI. */ + if (nr_cpus < 8) { + writel(0x, targetsptr + 32); + report("bits for %d non-existent CPUs masked", + !(readl(targetsptr + 32) & ~cpu_mask), 8 - nr_cpus); + } else { + report_skip("CPU masking (all CPUs implemented)"); + } + + report("accesses beyond limit RAZ/WI", + test_readonly_32(targetsptr + nr_irqs, true)); + + pattern = 0x0103020f; + writel(pattern, targetsptr + 32); + reg = readl(targetsptr + 32); + report("register content preserved (%08x => %08x)", + reg == (pattern & cpu_mask), pattern & cpu_mask, reg); + + /* +* The TARGETS registers are byte accessible, do a byte-wide +* read and write of known content to check for this. +*/ + reg = readb(targetsptr + 33); + report("byte reads successful (0x%08x => 0x%02x)", + reg == (BYTE(pattern, 1) & cpu_mask), + pattern & cpu_mask, reg); + + pattern = REPLACE_BYTE(pattern, 2, 0x04); + writeb(BYTE(pattern, 2), targetsptr + 34); + reg = readl(targetsptr + 32); + report("byte writes successful (0x%02x => 0x%08x)", + reg == (pattern & cpu_mask), BYTE(pattern, 2), reg); + + writel(orig_targets, targetsptr + 32); + return true; +} + static int gic_test_mmio(int gic_version) { u32 reg; @@ -436,6 +487,9 @@ static int gic_test_mmio(int gic_version) test_priorities(nr_irqs, gic_dist_base + GICD_IPRIORITYR); + if (gic_version == 2) + test_targets(nr_irqs); + return 0; } diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h index cef748d..6f170cb 100644 --- a/lib/arm/asm/gic.h +++ b/lib/arm/asm/gic.h @@ -14,6 +14,7 @@ #define GICD_IGROUPR 0x0080 #define GICD_ISENABLER 0x0100 #define GICD_IPRIORITYR0x0400 +#define GICD_ITARGETSR 0x0800 #define GICD_SGIR 0x0f00 #define GICD_ICPIDR2 0x0fe8 -- 2.9.0
[Qemu-devel] [kvm-unit-tests PATCH 2/4] arm/arm64: GICv2: add GICD_IPRIORITYR testing
Some tests for the IPRIORITY registers. The significant number of bits is IMPLEMENTATION DEFINED, but should be the same for every IRQ. Also these registers must be byte-accessible. Check that accesses beyond the implemented IRQ limit are actually read-as-zero/write-ignore. Signed-off-by: Andre Przywara <andre.przyw...@arm.com> --- arm/gic.c | 72 +++ 1 file changed, 72 insertions(+) diff --git a/arm/gic.c b/arm/gic.c index ba2585b..a27da2c 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -327,6 +327,76 @@ static bool test_typer_v2(uint32_t reg) return true; } +#define BYTE(reg32, byte) (((reg32) >> ((byte) * 8)) & 0xff) +#define REPLACE_BYTE(reg32, byte, new) (((reg32) & ~(0xff << ((byte) * 8))) |\ + ((new) << ((byte) * 8))) + +static bool test_priorities(int nr_irqs, void *priptr) +{ + u32 orig_prio, reg, pri_bits; + u32 pri_mask, pattern; + + orig_prio = readl(priptr + 32); + report_prefix_push("IPRIORITYR"); + + /* +* Determine implemented number of priority bits by writing all 1's +* and checking the number of cleared bits in the value read back. +*/ + writel(0x, priptr + 32); + pri_mask = readl(priptr + 32); + + reg = ~pri_mask; + report("consistent priority masking (0x%08x)", + (((reg >> 16) == (reg & 0x)) && + ((reg & 0xff) == ((reg >> 8) & 0xff))), pri_mask); + + reg = reg & 0xff; + for (pri_bits = 8; reg & 1; reg >>= 1, pri_bits--) + ; + report("implements at least 4 priority bits (%d)", + pri_bits >= 4, pri_bits); + + pattern = 0; + writel(pattern, priptr + 32); + report("clearing priorities", readl(priptr + 32) == pattern); + + pattern = 0x; + writel(pattern, priptr + 32); + report("filling priorities", + readl(priptr + 32) == (pattern & pri_mask)); + + report("accesses beyond limit RAZ/WI", + test_readonly_32(priptr + nr_irqs, true)); + + writel(pattern, priptr + nr_irqs - 4); + report("accessing last SPIs", + readl(priptr + nr_irqs - 4) == (pattern & pri_mask)); + + pattern = 0xff7fbf3f; + writel(pattern, priptr + 32); + report("priorities are preserved", + readl(priptr + 32) == (pattern & pri_mask)); + + /* +* The PRIORITY registers are byte accessible, do a byte-wide +* read and write of known content to check for this. +*/ + reg = readb(priptr + 33); + report("byte reads successful (0x%08x => 0x%02x)", + reg == (BYTE(pattern, 1) & pri_mask), pattern & pri_mask, reg); + + pattern = REPLACE_BYTE(pattern, 2, 0x1f); + writeb(BYTE(pattern, 2), priptr + 34); + reg = readl(priptr + 32); + report("byte writes successful (0x%02x => 0x%08x)", + reg == (pattern & pri_mask), BYTE(pattern, 2) & pri_mask, reg); + + report_prefix_pop(); + writel(orig_prio, priptr + 32); + return true; +} + static int gic_test_mmio(int gic_version) { u32 reg; @@ -364,6 +434,8 @@ static int gic_test_mmio(int gic_version) test_readonly_32(idreg, false), reg); + test_priorities(nr_irqs, gic_dist_base + GICD_IPRIORITYR); + return 0; } -- 2.9.0
[Qemu-devel] [kvm-unit-tests PATCH 4/4] arm/arm64: GICv3: add TYPER test
Add a simple test for the GICv3 TYPER test, which does only one basic check to ensure we have actually enough interrupt IDs if we support LPIs. Allow a GICv3 guest to do the common MMIO checks as well, where the register semantics are shared with a GICv2. Signed-off-by: Andre Przywara <andre.przyw...@arm.com> --- arm/gic.c | 34 +++--- arm/unittests.cfg | 6 ++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/arm/gic.c b/arm/gic.c index 02b1be1..7de0e47 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -327,6 +327,30 @@ static bool test_typer_v2(uint32_t reg) return true; } +static bool test_typer_v3(uint32_t reg) +{ + int nr_intids; + + report("GIC emulation %ssupport%s MBIs", 1, + reg & BIT(16) ? "" : "does not ", + reg & BIT(16) ? "s" : ""); + report("GIC emulation %ssupport%s LPIs", 1, + reg & BIT(17) ? "" : "does not ", + reg & BIT(17) ? "s" : ""); + report("GIC emulation %ssupport%s Aff3", 1, + reg & BIT(24) ? "" : "does not ", + reg & BIT(24) ? "s" : ""); + + nr_intids = BIT(((reg >> 19) & 0x1f) + 1); + report("%d interrupt IDs implemented", 1, nr_intids); + + if (reg & BIT(17)) + report("%d LPIs supported", nr_intids > 8192, + nr_intids > 8192 ? nr_intids - 8192 : 0); + + return true; +} + #define BYTE(reg32, byte) (((reg32) >> ((byte) * 8)) & 0xff) #define REPLACE_BYTE(reg32, byte, new) (((reg32) & ~(0xff << ((byte) * 8))) |\ ((new) << ((byte) * 8))) @@ -460,8 +484,9 @@ static int gic_test_mmio(int gic_version) idreg = gic_dist_base + 0xfe8; break; case 0x3: - report_abort("GICv3 MMIO tests NYI"); - return -1; + gic_dist_base = gicv3_dist_base(); + idreg = gic_dist_base + 0xffe8; + break; default: report_abort("GIC version %d not supported", gic_version); return 0; @@ -471,7 +496,10 @@ static int gic_test_mmio(int gic_version) nr_irqs = 32 * ((reg & 0x1f) + 1); report("number of implemented SPIs: %d", 1, nr_irqs - 32); - test_typer_v2(reg); + if (gic_version == 2) + test_typer_v2(reg); + else + test_typer_v3(reg); report("IIDR: 0x%x", 1, readl(gic_dist_base + GICD_IIDR)); diff --git a/arm/unittests.cfg b/arm/unittests.cfg index 0162e5a..b432346 100644 --- a/arm/unittests.cfg +++ b/arm/unittests.cfg @@ -78,3 +78,9 @@ file = gic.flat smp = $MAX_SMP extra_params = -machine gic-version=3 -append 'ipi' groups = gic + +[gicv3-mmio] +file = gic.flat +smp = $MAX_SMP +extra_params = -machine gic-version=3 -append 'mmio' +groups = gic -- 2.9.0
[Qemu-devel] [kvm-unit-tests PATCH 1/4] arm/arm64: GIC: basic GICv2 MMIO tests
This adds an MMIO subtest to the GIC test. It accesses some generic GICv2 registers and does some sanity tests, like checking for some of them being read-only. Signed-off-by: Andre Przywara <andre.przyw...@arm.com> --- arm/gic.c | 99 +++ arm/unittests.cfg | 6 lib/arm/asm/gic.h | 2 ++ 3 files changed, 107 insertions(+) diff --git a/arm/gic.c b/arm/gic.c index 638b8b1..ba2585b 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -3,6 +3,7 @@ * * GICv2 * + test sending/receiving IPIs + * + MMIO access tests * GICv3 * + test sending/receiving IPIs * @@ -274,6 +275,98 @@ static struct gic gicv3 = { }, }; +static bool test_ro_pattern_32(void *address, u32 pattern, u32 orig) +{ + u32 reg; + + writel(pattern, address); + reg = readl(address); + + if (reg != orig) + writel(orig, address); + + return reg == orig; +} + +static bool test_readonly_32(void *address, bool razwi) +{ + u32 orig, pattern; + + orig = readl(address); + if (razwi && orig) + return false; + + pattern = 0x; + if (orig != pattern) { + if (!test_ro_pattern_32(address, pattern, orig)) + return false; + } + + pattern = 0xa5a55a5a; + if (orig != pattern) { + if (!test_ro_pattern_32(address, pattern, orig)) + return false; + } + + pattern = 0; + if (orig != pattern) { + if (!test_ro_pattern_32(address, pattern, orig)) + return false; + } + + return true; +} + +static bool test_typer_v2(uint32_t reg) +{ + int nr_gic_cpus = ((reg >> 5) & 0x7) + 1; + + report("all %d CPUs have interrupts", nr_cpus == nr_gic_cpus, + nr_gic_cpus); + + return true; +} + +static int gic_test_mmio(int gic_version) +{ + u32 reg; + int nr_irqs; + void *gic_dist_base, *idreg; + + switch(gic_version) { + case 0x2: + gic_dist_base = gicv2_dist_base(); + idreg = gic_dist_base + 0xfe8; + break; + case 0x3: + report_abort("GICv3 MMIO tests NYI"); + return -1; + default: + report_abort("GIC version %d not supported", gic_version); + return 0; + } + + reg = readl(gic_dist_base + GICD_TYPER); + nr_irqs = 32 * ((reg & 0x1f) + 1); + report("number of implemented SPIs: %d", 1, nr_irqs - 32); + + test_typer_v2(reg); + + report("IIDR: 0x%x", 1, readl(gic_dist_base + GICD_IIDR)); + + report("GICD_TYPER is read-only", + test_readonly_32(gic_dist_base + GICD_TYPER, false)); + report("GICD_IIDR is read-only", + test_readonly_32(gic_dist_base + GICD_IIDR, false)); + + reg = readl(idreg); + report("ICPIDR2 is read-only (0x%x)", + test_readonly_32(idreg, false), + reg); + + return 0; +} + int main(int argc, char **argv) { char pfx[8]; @@ -332,6 +425,12 @@ int main(int argc, char **argv) } ipi_test(); + } else if (!strcmp(argv[1], "mmio")) { + report_prefix_push(argv[1]); + + gic_test_mmio(gic_version()); + + report_prefix_pop(); } else { report_abort("Unknown subtest '%s'", argv[1]); } diff --git a/arm/unittests.cfg b/arm/unittests.cfg index c7392c7..0162e5a 100644 --- a/arm/unittests.cfg +++ b/arm/unittests.cfg @@ -67,6 +67,12 @@ smp = $((($MAX_SMP < 8)?$MAX_SMP:8)) extra_params = -machine gic-version=2 -append 'ipi' groups = gic +[gicv2-mmio] +file = gic.flat +smp = $((($MAX_SMP < 8)?$MAX_SMP:8)) +extra_params = -machine gic-version=2 -append 'mmio' +groups = gic + [gicv3-ipi] file = gic.flat smp = $MAX_SMP diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h index c2267b6..cef748d 100644 --- a/lib/arm/asm/gic.h +++ b/lib/arm/asm/gic.h @@ -10,10 +10,12 @@ /* Distributor registers */ #define GICD_CTLR 0x #define GICD_TYPER 0x0004 +#define GICD_IIDR 0x0008 #define GICD_IGROUPR 0x0080 #define GICD_ISENABLER 0x0100 #define GICD_IPRIORITYR0x0400 #define GICD_SGIR 0x0f00 +#define GICD_ICPIDR2 0x0fe8 #define GICD_TYPER_IRQS(typer) typer) & 0x1f) + 1) * 32) #define GICD_INT_EN_SET_SGI0x -- 2.9.0
Re: [Qemu-devel] [kvm-unit-tests PATCH v5 09/11] arm/arm64: add initial gicv3 support
Hi, On 10/11/16 17:21, Andrew Jones wrote: > Signed-off-by: Andrew Jones> > --- > v5: use modern register names [Andre] > v4: > - only take defines from kernel we need now [Andre] > - simplify enable by not caring if we reinit the distributor [drew] > v2: > - configure irqs as NS GRP1 > --- > lib/arm/asm/arch_gicv3.h | 42 + > lib/arm/asm/gic-v3.h | 94 > ++ > lib/arm/asm/gic.h | 6 ++- > lib/arm/gic.c | 65 > lib/arm64/asm/arch_gicv3.h | 44 ++ > lib/arm64/asm/gic-v3.h | 1 + > lib/arm64/asm/sysreg.h | 44 ++ > 7 files changed, 294 insertions(+), 2 deletions(-) > create mode 100644 lib/arm/asm/arch_gicv3.h > create mode 100644 lib/arm/asm/gic-v3.h > create mode 100644 lib/arm64/asm/arch_gicv3.h > create mode 100644 lib/arm64/asm/gic-v3.h > create mode 100644 lib/arm64/asm/sysreg.h > > diff --git a/lib/arm/asm/arch_gicv3.h b/lib/arm/asm/arch_gicv3.h > new file mode 100644 > index ..81a1e5f6c29c > --- /dev/null > +++ b/lib/arm/asm/arch_gicv3.h > @@ -0,0 +1,42 @@ > +/* > + * All ripped off from arch/arm/include/asm/arch_gicv3.h > + * > + * Copyright (C) 2016, Red Hat Inc, Andrew Jones > + * > + * This work is licensed under the terms of the GNU LGPL, version 2. > + */ > +#ifndef _ASMARM_ARCH_GICV3_H_ > +#define _ASMARM_ARCH_GICV3_H_ > + > +#ifndef __ASSEMBLY__ > +#include > +#include > +#include > + > +#define __stringify xstr > + > +#define __ACCESS_CP15(CRn, Op1, CRm, Op2)p15, Op1, %0, CRn, CRm, Op2 > + > +#define ICC_PMR __ACCESS_CP15(c4, 0, c6, 0) > +#define ICC_IGRPEN1 __ACCESS_CP15(c12, 0, c12, 7) > + > +static inline void gicv3_write_pmr(u32 val) > +{ > + asm volatile("mcr " __stringify(ICC_PMR) : : "r" (val)); > +} > + > +static inline void gicv3_write_grpen1(u32 val) > +{ > + asm volatile("mcr " __stringify(ICC_IGRPEN1) : : "r" (val)); > + isb(); > +} > + > +static inline u64 gicv3_read_typer(const volatile void __iomem *addr) It may be worth to add that this is for GICR_TYPER (or GITS_TYPER), because GICD_TYPER is 32-bit only. Or to make the naming generic (because the code actually is), along the lines of read_64bit_reg or the like? > +{ > + u64 val = readl(addr); > + val |= (u64)readl(addr + 4) << 32; > + return val; > +} > + > +#endif /* !__ASSEMBLY__ */ > +#endif /* _ASMARM_ARCH_GICV3_H_ */ > diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h > new file mode 100644 > index ..e0f303d82508 > --- /dev/null > +++ b/lib/arm/asm/gic-v3.h > @@ -0,0 +1,94 @@ > +/* > + * All GIC* defines are lifted from include/linux/irqchip/arm-gic-v3.h > + * > + * Copyright (C) 2016, Red Hat Inc, Andrew Jones > + * > + * This work is licensed under the terms of the GNU LGPL, version 2. > + */ > +#ifndef _ASMARM_GIC_V3_H_ > +#define _ASMARM_GIC_V3_H_ > + > +#ifndef _ASMARM_GIC_H_ > +#error Do not directly include . Include > +#endif > + > +#define GICD_CTLR_RWP(1U << 31) > +#define GICD_CTLR_ARE_NS (1U << 4) > +#define GICD_CTLR_ENABLE_G1A (1U << 1) > +#define GICD_CTLR_ENABLE_G1 (1U << 0) +1 to Alex for adding a comment noting the non-secure view here. > + > +/* Re-Distributor registers, offsets from RD_base */ > +#define GICR_TYPER 0x0008 > + > +#define GICR_TYPER_LAST (1U << 4) > + > +/* Re-Distributor registers, offsets from SGI_base */ > +#define GICR_IGROUPR0GICD_IGROUPR > +#define GICR_ISENABLER0 GICD_ISENABLER > +#define GICR_IPRIORITYR0 GICD_IPRIORITYR > + > +#include > + > +#ifndef __ASSEMBLY__ > +#include > +#include > +#include > +#include > + > +struct gicv3_data { > + void *dist_base; > + void *redist_base[NR_CPUS]; > + unsigned int irq_nr; > +}; > +extern struct gicv3_data gicv3_data; > + > +#define gicv3_dist_base()(gicv3_data.dist_base) > +#define gicv3_redist_base() > (gicv3_data.redist_base[smp_processor_id()]) > +#define gicv3_sgi_base() > (gicv3_data.redist_base[smp_processor_id()] + SZ_64K) > + > +extern int gicv3_init(void); > +extern void gicv3_enable_defaults(void); > +extern void gicv3_set_redist_base(void); > + > +static inline void gicv3_do_wait_for_rwp(void *base) > +{ > + int count = 10; /* 1s */ > + > + while (readl(base + GICD_CTLR) & GICD_CTLR_RWP) { > + if (!--count) { > + printf("GICv3: RWP timeout!\n"); > + abort(); > + } > + cpu_relax(); > + udelay(10); > + }; > +} > + > +static inline void gicv3_dist_wait_for_rwp(void) > +{ > + gicv3_do_wait_for_rwp(gicv3_dist_base()); > +} > + > +static inline void
Re: [Qemu-devel] [kvm-unit-tests PATCH v5 06/11] arm/arm64: add initial gicv2 support
Hi, On 10/11/16 17:21, Andrew Jones wrote: > Add some gicv2 support. This just adds init and enable > functions, allowing unit tests to start messing with it. > > Signed-off-by: Andrew Jones <drjo...@redhat.com> > > --- > v5: share/use only the modern register names [Andre] Thanks! That looks much better now. Reviewed-by: Andre Przywara <andre.przyw...@arm.com> > v4: > - only take defines from kernel we need now [Andre] > - moved defines to asm/gic.h so they'll be shared with v3 [drew] > - simplify enable by not caring if we reinit the distributor [drew] > - init all GICD_INT_DEF_PRI_X4 registers [Eric] > --- > arm/Makefile.common| 1 + > lib/arm/asm/gic-v2.h | 34 ++ > lib/arm/asm/gic.h | 37 > lib/arm/gic.c | 76 > ++ > lib/arm64/asm/gic-v2.h | 1 + > lib/arm64/asm/gic.h| 1 + > 6 files changed, 150 insertions(+) > create mode 100644 lib/arm/asm/gic-v2.h > create mode 100644 lib/arm/asm/gic.h > create mode 100644 lib/arm/gic.c > create mode 100644 lib/arm64/asm/gic-v2.h > create mode 100644 lib/arm64/asm/gic.h > > diff --git a/arm/Makefile.common b/arm/Makefile.common > index ccb554d9251a..41239c37e092 100644 > --- a/arm/Makefile.common > +++ b/arm/Makefile.common > @@ -42,6 +42,7 @@ cflatobjs += lib/arm/mmu.o > cflatobjs += lib/arm/bitops.o > cflatobjs += lib/arm/psci.o > cflatobjs += lib/arm/smp.o > +cflatobjs += lib/arm/gic.o > > libeabi = lib/arm/libeabi.a > eabiobjs = lib/arm/eabi_compat.o > diff --git a/lib/arm/asm/gic-v2.h b/lib/arm/asm/gic-v2.h > new file mode 100644 > index ..c2d5fecd4886 > --- /dev/null > +++ b/lib/arm/asm/gic-v2.h > @@ -0,0 +1,34 @@ > +/* > + * All GIC* defines are lifted from include/linux/irqchip/arm-gic.h > + * > + * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjo...@redhat.com> > + * > + * This work is licensed under the terms of the GNU LGPL, version 2. > + */ > +#ifndef _ASMARM_GIC_V2_H_ > +#define _ASMARM_GIC_V2_H_ > + > +#ifndef _ASMARM_GIC_H_ > +#error Do not directly include . Include > +#endif > + > +#define GICD_ENABLE 0x1 > +#define GICC_ENABLE 0x1 > + > +#ifndef __ASSEMBLY__ > + > +struct gicv2_data { > + void *dist_base; > + void *cpu_base; > + unsigned int irq_nr; > +}; > +extern struct gicv2_data gicv2_data; > + > +#define gicv2_dist_base()(gicv2_data.dist_base) > +#define gicv2_cpu_base() (gicv2_data.cpu_base) > + > +extern int gicv2_init(void); > +extern void gicv2_enable_defaults(void); > + > +#endif /* !__ASSEMBLY__ */ > +#endif /* _ASMARM_GIC_V2_H_ */ > diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h > new file mode 100644 > index ..d44e47bcf404 > --- /dev/null > +++ b/lib/arm/asm/gic.h > @@ -0,0 +1,37 @@ > +/* > + * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjo...@redhat.com> > + * > + * This work is licensed under the terms of the GNU LGPL, version 2. > + */ > +#ifndef _ASMARM_GIC_H_ > +#define _ASMARM_GIC_H_ > + > +#include > + > +#define GICD_CTLR0x > +#define GICD_TYPER 0x0004 > +#define GICD_ISENABLER 0x0100 > +#define GICD_IPRIORITYR 0x0400 > + > +#define GICD_TYPER_IRQS(typer) typer) & 0x1f) + 1) * 32) > +#define GICD_INT_EN_SET_SGI 0x > +#define GICD_INT_DEF_PRI_X4 0xa0a0a0a0 > + > +#define GICC_CTLR0x > +#define GICC_PMR 0x0004 > + > +#define GICC_INT_PRI_THRESHOLD 0xf0 > + > +#ifndef __ASSEMBLY__ > + > +/* > + * gic_init will try to find all known gics, and then > + * initialize the gic data for the one found. > + * returns > + * 0 : no gic was found > + * > 0 : the gic version of the gic found > + */ > +extern int gic_init(void); > + > +#endif /* !__ASSEMBLY__ */ > +#endif /* _ASMARM_GIC_H_ */ > diff --git a/lib/arm/gic.c b/lib/arm/gic.c > new file mode 100644 > index ..d655105e058b > --- /dev/null > +++ b/lib/arm/gic.c > @@ -0,0 +1,76 @@ > +/* > + * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjo...@redhat.com> > + * > + * This work is licensed under the terms of the GNU LGPL, version 2. > + */ > +#include > +#include > +#include > + > +struct gicv2_data gicv2_data; > + > +/* > + * Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt > + */ > +static bool > +gic_get_dt_bases(const char *compatible, void **base
Re: [Qemu-devel] [kvm-unit-tests PATCH v5 03/11] arm/arm64: smp: support more than 8 cpus
Hi, On 10/11/16 17:21, Andrew Jones wrote: > By adding support for launching with gicv3 we can break the 8 vcpu > limit. This patch adds support to smp code and also selects the > vgic model corresponding to the host. The vgic model may also be > manually selected by adding e.g. -machine gic-version=3 to > extra_params. > > Reviewed-by: Alex Bennée <alex.ben...@linaro.org> > Signed-off-by: Andrew Jones <drjo...@redhat.com> > > --- > v5: left cpus a u32 for now. Changing to u64 requires a change to > devicetree. Will do it later. [Andre] Given that we address this in the future: Reviewed-by: Andre Przywara <andre.przyw...@arm.com>
Re: [Qemu-devel] [kvm-unit-tests PATCH v5 10/11] arm/arm64: gicv3: add an IPI test
Hi, On 11/11/16 14:53, Alex Bennée wrote: > > Andrew Joneswrites: > >> On Fri, Nov 11, 2016 at 10:02:59AM +, Alex Bennée wrote: >>> >>> Andrew Jones writes: >>> On Thu, Nov 10, 2016 at 07:53:58PM +, Alex Bennée wrote: [...] >> +struct gic gicv2 = { >> +.ipi = { >> +.enable = gicv2_enable_defaults, >> +.send_self = gicv2_ipi_send_self, >> +.send_tlist = gicv2_ipi_send_tlist, >> +.send_broadcast = gicv2_ipi_send_broadcast, >> +}, >> +.read_iar = gicv2_read_iar, >> +.irqnr = gicv2_irqnr, >> +.write_eoi = gicv2_write_eoi, >> +}; >> + >> +struct gic gicv3 = { >> +.ipi = { >> +.enable = gicv3_enable_defaults, >> +.send_self = gicv3_ipi_send_self, >> +.send_tlist = gicv3_ipi_send_tlist, >> +.send_broadcast = gicv3_ipi_send_broadcast, >> +}, >> +.read_iar = gicv3_read_iar, >> +.irqnr = gicv3_irqnr, >> +.write_eoi = gicv3_write_eoir, >> +}; >> + > > So I was re-basing my kvm-unit-tests against your GIC rework and found > myself copy and pasting a bunch of this into my tests that fire IRQs. > That makes me think the abstraction should be in the library code so > other tests can fiddle with sending IRQs. > > What do you think? > I guess you mean moving the above two structs and their corresponding functions (all which aren't already common) to lib/arm/ ? Or do you just mean the one non-trivial function gicv3_ipi_send_tlist? I think agree with gicv3_ipi_send_tlist getting shared, but the others are mostly one-liners, so I'm not sure. I guess I'd have to see how you're using them first. >>> >>> So it looked like there were some functions in the common code for one >>> GIC which had local test defined functions for the other. They should at >>> least be consistent. >> >> gicv3_read_iar and gicv3_write_eoir being common already is a product of >> being sysreg wrappers, allowing for both arm32 and arm64 to use functions >> of the same names, not because I wanted gicv3 to be inconsistent with >> gicv2 (which uses MMIO and thus doesn't need wrappers) >> >>> >>> For my use case I could do with a common: >>> >>> gic_enable >> >> OK, I can extend gic_init() to initialize a 'struct gic_common_ops' that >> includes an enable -> *_enable_defaults(void), ipi_send(int cpu), >> read_iar(void), iar_irqnr(u32 iar), and write_eoi(u32 irqstat). And also >> provide the wrappers gic_enable, gic_ipi_send(cpu), ... >> >>> gic_send_spi(cpu, irq) >> >> I'll let you add this one to the new common ops struct :-) >> >>> gic_irq_ack() which returns the iar. >> >> This one will be called read_iar. >> >> Would that work for you, Alex? > > Sounds good to me :-) > >> >> Andre, >> >> Would this also satisfy your needs for more common code? TBH I haven't look deeply enough to give an educated answer. I just wanted to +1 Alex for the general direction. So I guess it's OK. ;-) I guess we may need some refactoring later anyway, so any missing pieces can be added/refactored later once we exactly know what we need. Cheers, Andre.
Re: [Qemu-devel] [kvm-unit-tests PATCH v5 06/11] arm/arm64: add initial gicv2 support
Hi, On 11/11/16 14:52, Alex Bennée wrote: > > Andrew Joneswrites: > >> Add some gicv2 support. This just adds init and enable >> functions, allowing unit tests to start messing with it. >> >> Signed-off-by: Andrew Jones >> >> --- >> v5: share/use only the modern register names [Andre] >> v4: >> - only take defines from kernel we need now [Andre] >> - moved defines to asm/gic.h so they'll be shared with v3 [drew] >> - simplify enable by not caring if we reinit the distributor [drew] >> - init all GICD_INT_DEF_PRI_X4 registers [Eric] >> --- >> arm/Makefile.common| 1 + >> lib/arm/asm/gic-v2.h | 34 ++ >> lib/arm/asm/gic.h | 37 >> lib/arm/gic.c | 76 >> ++ >> lib/arm64/asm/gic-v2.h | 1 + >> lib/arm64/asm/gic.h| 1 + >> 6 files changed, 150 insertions(+) >> create mode 100644 lib/arm/asm/gic-v2.h >> create mode 100644 lib/arm/asm/gic.h >> create mode 100644 lib/arm/gic.c >> create mode 100644 lib/arm64/asm/gic-v2.h >> create mode 100644 lib/arm64/asm/gic.h >> >> diff --git a/arm/Makefile.common b/arm/Makefile.common >> index ccb554d9251a..41239c37e092 100644 >> --- a/arm/Makefile.common >> +++ b/arm/Makefile.common >> @@ -42,6 +42,7 @@ cflatobjs += lib/arm/mmu.o >> cflatobjs += lib/arm/bitops.o >> cflatobjs += lib/arm/psci.o >> cflatobjs += lib/arm/smp.o >> +cflatobjs += lib/arm/gic.o >> >> libeabi = lib/arm/libeabi.a >> eabiobjs = lib/arm/eabi_compat.o >> diff --git a/lib/arm/asm/gic-v2.h b/lib/arm/asm/gic-v2.h >> new file mode 100644 >> index ..c2d5fecd4886 >> --- /dev/null >> +++ b/lib/arm/asm/gic-v2.h >> @@ -0,0 +1,34 @@ >> +/* >> + * All GIC* defines are lifted from include/linux/irqchip/arm-gic.h >> + * >> + * Copyright (C) 2016, Red Hat Inc, Andrew Jones >> + * >> + * This work is licensed under the terms of the GNU LGPL, version 2. >> + */ >> +#ifndef _ASMARM_GIC_V2_H_ >> +#define _ASMARM_GIC_V2_H_ >> + >> +#ifndef _ASMARM_GIC_H_ >> +#error Do not directly include . Include >> +#endif >> + >> +#define GICD_ENABLE 0x1 >> +#define GICC_ENABLE 0x1 >> + >> +#ifndef __ASSEMBLY__ >> + >> +struct gicv2_data { >> +void *dist_base; >> +void *cpu_base; >> +unsigned int irq_nr; >> +}; >> +extern struct gicv2_data gicv2_data; >> + >> +#define gicv2_dist_base() (gicv2_data.dist_base) >> +#define gicv2_cpu_base()(gicv2_data.cpu_base) >> + >> +extern int gicv2_init(void); >> +extern void gicv2_enable_defaults(void); >> + >> +#endif /* !__ASSEMBLY__ */ >> +#endif /* _ASMARM_GIC_V2_H_ */ >> diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h >> new file mode 100644 >> index ..d44e47bcf404 >> --- /dev/null >> +++ b/lib/arm/asm/gic.h >> @@ -0,0 +1,37 @@ >> +/* >> + * Copyright (C) 2016, Red Hat Inc, Andrew Jones >> + * >> + * This work is licensed under the terms of the GNU LGPL, version 2. >> + */ >> +#ifndef _ASMARM_GIC_H_ >> +#define _ASMARM_GIC_H_ >> + >> +#include >> + >> +#define GICD_CTLR 0x >> +#define GICD_TYPER 0x0004 >> +#define GICD_ISENABLER 0x0100 >> +#define GICD_IPRIORITYR 0x0400 > > Maybe GICD_ISENABLER_BASE and GICD_IPRIORITYR_BASE as they are the start > of a series of registers? We should keep the naming consistent to both the spec and the Linux headers. > Also what happened to the formatting? Isn't that the usual diff artifact caused by prepending a single character? Which moves the tab stops, also the mailer adding quotation characters? >> + >> +#define GICD_TYPER_IRQS(typer) typer) & 0x1f) + 1) >> * 32) >> +#define GICD_INT_EN_SET_SGI 0x >> +#define GICD_INT_DEF_PRI_X4 0xa0a0a0a0 > > This doesn't seem to be used and I'm not sure what GICD_TYPER_IRQS it is > trying to achieve. The idea is to calculate the number of implemented SPIs. But I am not a big fan of copying a macro from the emulation code base to the test code. Cheers, Andre. > A comment above and here to make it clear we are talking about offsets > in the distributor and cpu register maps would aid confusion. > >> + >> +#define GICC_CTLR 0x >> +#define GICC_PMR0x0004 >> + >> +#define GICC_INT_PRI_THRESHOLD 0xf0 >> + >> +#ifndef __ASSEMBLY__ >> + >> +/* >> + * gic_init will try to find all known gics, and then >> + * initialize the gic data for the one found. >> + * returns >> + * 0 : no gic was found >> + * > 0 : the gic version of the gic found >> + */ >> +extern int gic_init(void); > > If we are going to make the library API agnostic I guess returning NULL > or an ops structure would be best here? > >> + >> +#endif /* !__ASSEMBLY__ */ >> +#endif /* _ASMARM_GIC_H_ */ >> diff --git a/lib/arm/gic.c b/lib/arm/gic.c >> new file mode 100644 >>
Re: [Qemu-devel] [kvm-unit-tests PATCH v5 07/11] arm/arm64: gicv2: add an IPI test
Hi, more a comment loosely related to this patch ... > diff --git a/arm/unittests.cfg b/arm/unittests.cfg > index 3f6fa45c587e..68bf5cd6008f 100644 > --- a/arm/unittests.cfg > +++ b/arm/unittests.cfg > @@ -54,3 +54,10 @@ file = selftest.flat > smp = $MAX_SMP > extra_params = -append 'smp' > groups = selftest > + > +# Test GIC emulation > +[gicv2-ipi] > +file = gic.flat > +smp = $((($MAX_SMP < 8)?$MAX_SMP:8)) So here we always go with the maximum number of VCPUs in the guest. However (as you also noted in your cover-letter) running with a different number of CPUs might be interesting, for instance with less than 8 CPUs on a GICv2 (the ITARGETSR register must be masked) or in general with an odd number (both literally and in the broader sense). I have a test case with passes with 8 VCPUs but fails with less. Is there any good way to run some tests multiple times with different numbers of VCPUS? Shall we add some "set" functionality to the smp parameter, so that we can specify a list of desired test points? Cheers, Andre.
Re: [Qemu-devel] [kvm-unit-tests PATCH v5 10/11] arm/arm64: gicv3: add an IPI test
Hi, On 10/11/16 19:53, Alex Bennée wrote: > So I was re-basing my kvm-unit-tests against your GIC rework and found > myself copy and pasting a bunch of this into my tests that fire IRQs. So I take it you are working on (or already have) code to test SPIs, probably via GICD_ISPENDR? Just asking because I was thinking about going there and thus could save my time if you are on it already... > That makes me think the abstraction should be in the library code so > other tests can fiddle with sending IRQs. ...because I was wondering the same. Cheers, Andre.
Re: [Qemu-devel] [kvm-unit-tests PATCH v4 00/11] arm/arm64: add gic framework
Hi, so is this actually v4 just resent? Or is this is a new version with s/5/4/? I can't spot any of the key changes quickly ... Cheers, Andre. On 10/11/16 16:07, Andrew Jones wrote: > v4: > - Eric's r-b's > - Andre's suggestion to only take defines we need > - several other changes listed in individual patches > > v3: > - Rebased on latest master > - Added Alex's r-b's > > v2: > Rebased on latest master + my "populate argv[0]" series (will > send a REPOST for that shortly. Additionally a few patches got > fixes/features; > 07/10 got same fix as kernel 7c9b973061 "irqchip/gic-v3: Configure >all interrupts as non-secure Group-1" in order to continue >working over TCG, as the gicv3 code for TCG removed a hack >it had there to make Linux happy. > 08/10 added more output for when things fail (if they fail) > 09/10 switched gicv3 broadcast implementation to using IRM. This >found a bug in a recent (but not tip) kernel, which I was >about to fix, but then I saw MarcZ beat me to it. > 10/10 actually check that the input irq is the received irq > > > Import defines, and steal enough helper functions, from Linux to > enable programming of the gic (v2 and v3). Then use the framework > to add an initial test (an ipi test; self, target-list, broadcast). > > It's my hope that this framework will be a suitable base on which > more tests may be easily added, particularly because we have > vgic-new and tcg gicv3 emulation getting close to merge. (v3 UPDATE: > vgic-new and tcg gicv3 are merged now) > > To run it, along with other tests, just do > > ./configure [ --arch=[arm|arm64] --cross-prefix=$PREFIX ] > make > export QEMU=$PATH_TO_QEMU > ./run_tests.sh > > To run it separately do, e.g. > > $QEMU -machine virt,accel=tcg -cpu cortex-a57 \ > -device virtio-serial-device \ > -device virtconsole,chardev=ctd -chardev testdev,id=ctd \ > -display none -serial stdio \ > -kernel arm/gic.flat \ > -smp 123 -machine gic-version=3 -append ipi > ^^ note, we can go nuts with nr-cpus on TCG :-) > > Or, a KVM example using a different "sender" cpu and irq (other than zero) > > $QEMU -machine virt,accel=kvm -cpu host \ > -device virtio-serial-device \ > -device virtconsole,chardev=ctd -chardev testdev,id=ctd \ > -display none -serial stdio \ > -kernel arm/gic.flat \ > -smp 48 -machine gic-version=3 -append 'ipi sender=42 irq=1' > > > Patches: > 01-05: fixes and functionality needed by the later gic patches > 06-07: enable gicv2 and gicv2 IPI test > 08-10: enable gicv3 and gicv3 IPI test >11: extend the IPI tests to take variable sender and irq > > Available here: https://github.com/rhdrjones/kvm-unit-tests/commits/arm/gic-v4 > > > Andrew Jones (10): > lib: xstr: allow multiple args > arm64: fix get_"sysreg32" and make MPIDR 64bit > arm/arm64: smp: support more than 8 cpus > arm/arm64: add some delay routines > arm/arm64: irq enable/disable > arm/arm64: add initial gicv2 support > arm/arm64: gicv2: add an IPI test > arm/arm64: add initial gicv3 support > arm/arm64: gicv3: add an IPI test > arm/arm64: gic: don't just use zero > > Peter Xu (1): > libcflat: add IS_ALIGNED() macro, and page sizes > > arm/Makefile.common| 7 +- > arm/gic.c | 417 > + > arm/run| 19 ++- > arm/selftest.c | 5 +- > arm/unittests.cfg | 13 ++ > lib/arm/asm/arch_gicv3.h | 65 +++ > lib/arm/asm/gic-v2.h | 28 +++ > lib/arm/asm/gic-v3.h | 92 ++ > lib/arm/asm/gic.h | 51 ++ > lib/arm/asm/processor.h| 38 - > lib/arm/asm/setup.h| 4 +- > lib/arm/gic.c | 131 ++ > lib/arm/processor.c| 15 ++ > lib/arm/setup.c| 12 +- > lib/arm64/asm/arch_gicv3.h | 66 +++ > lib/arm64/asm/gic-v2.h | 1 + > lib/arm64/asm/gic-v3.h | 1 + > lib/arm64/asm/gic.h| 1 + > lib/arm64/asm/processor.h | 53 +- > lib/arm64/asm/sysreg.h | 44 + > lib/arm64/processor.c | 15 ++ > lib/libcflat.h | 10 +- > 22 files changed, 1062 insertions(+), 26 deletions(-) > create mode 100644 arm/gic.c > create mode 100644 lib/arm/asm/arch_gicv3.h > create mode 100644 lib/arm/asm/gic-v2.h > create mode 100644 lib/arm/asm/gic-v3.h > create mode 100644 lib/arm/asm/gic.h > create mode 100644 lib/arm/gic.c > create mode 100644 lib/arm64/asm/arch_gicv3.h > create mode 100644 lib/arm64/asm/gic-v2.h > create mode 100644 lib/arm64/asm/gic-v3.h > create mode 100644 lib/arm64/asm/gic.h > create mode 100644 lib/arm64/asm/sysreg.h >
Re: [Qemu-devel] [kvm-unit-tests PATCH v4 08/11] libcflat: add IS_ALIGNED() macro, and page sizes
Hi, On 08/11/16 20:21, Andrew Jones wrote: > From: Peter Xu <pet...@redhat.com> > > These macros will be useful to do page alignment checks. Reviewed-by: Andre Przywara <andre.przyw...@arm.com> Cheers, Andre. > Signed-off-by: Peter Xu <pet...@redhat.com> > [drew: also added SZ_64K] > Signed-off-by: Andrew Jones <drjo...@redhat.com> > --- > lib/libcflat.h | 6 ++ > 1 file changed, 6 insertions(+) > > diff --git a/lib/libcflat.h b/lib/libcflat.h > index 82005f5d014f..143fc53061fe 100644 > --- a/lib/libcflat.h > +++ b/lib/libcflat.h > @@ -33,6 +33,12 @@ > #define __ALIGN_MASK(x, mask)(((x) + (mask)) & ~(mask)) > #define __ALIGN(x, a)__ALIGN_MASK(x, (typeof(x))(a) - 1) > #define ALIGN(x, a) __ALIGN((x), (a)) > +#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) > + > +#define SZ_4K(0x1000) > +#define SZ_64K (0x1) > +#define SZ_2M(0x20) > +#define SZ_1G(0x4000) > > typedef uint8_t u8; > typedef int8_t s8; >
Re: [Qemu-devel] [kvm-unit-tests PATCH v4 09/11] arm/arm64: add initial gicv3 support
Hi, On 09/11/16 13:08, Andrew Jones wrote: > On Wed, Nov 09, 2016 at 12:35:48PM +0000, Andre Przywara wrote: > [...] >>> diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h >>> new file mode 100644 >>> index ..03321f8c860f >>> --- /dev/null >>> +++ b/lib/arm/asm/gic-v3.h >>> @@ -0,0 +1,92 @@ >>> +/* >>> + * All GIC* defines are lifted from include/linux/irqchip/arm-gic-v3.h >>> + * >>> + * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjo...@redhat.com> >>> + * >>> + * This work is licensed under the terms of the GNU LGPL, version 2. >>> + */ >>> +#ifndef _ASMARM_GIC_V3_H_ >>> +#define _ASMARM_GIC_V3_H_ >>> + >>> +#ifndef _ASMARM_GIC_H_ >>> +#error Do not directly include . Include >>> +#endif >>> + >>> +#define GICD_CTLR 0x >>> +#define GICD_TYPER 0x0004 >> >> So if we share the distributor register definition with GICv2, these >> shouldn't be here, but in gic.h. >> But this is the right naming scheme we should use (instead of GIC_DIST_xxx). >> >> Now this gets interesting with your wish to both share the definitions >> for the GICv2 and GICv3 distributors, but also stick to the names the >> kernel uses (because they differ between the two) ;-) >> So now you loose the greppability for either GIC_DIST_CTR or GICD_TYPER, >> for instance. > > Well, we just have the same offset with two names (giving us two > symbols to grep). I put them here, vs. asm/gic.h, because the kernel > only uses theses symbols for gicv3. Now, nothing stops a unit test > from using them with gicv2 tests, though, because unit tests include > gic.h, which includes both gic-v2.h and gic-v3.h, and thus it gets > both. I know, it's sounding messy... Shouldn't we post some churn to > the kernel? :-) Well, on top of that the distributor registers are slightly different (check CTLR and TYPER, for instance). So it's churn plus a stretch, I guess Marc won't like that. So if greppability is important, should we revert to separate definitions in separate header files then, like in v3? I don't think we actually share _code_ between the two GIC revisions, do we? > Note, I tried to only add defines to asm/gic.h that are actually > shared in the kernel between v2 and v3, e.g. GIC_DIST_ENABLE_SET. Huh? GICv3 uses GICD_ISENABLER for that register. > Actually, GIC_DIST_CTRL and GIC_DIST_CTR may be the only exceptions > we have so far. Note that it's GIC_DIST_CTLR (L and R swapped), one reason more to dump _CTR ;-) >> >>> +#define GICD_IGROUPR 0x0080 >>> + >>> +#define GICD_CTLR_RWP (1U << 31) >>> +#define GICD_CTLR_ARE_NS (1U << 4) >>> +#define GICD_CTLR_ENABLE_G1A (1U << 1) >>> +#define GICD_CTLR_ENABLE_G1(1U << 0) >>> + >>> +#define GICR_TYPER 0x0008 >>> +#define GICR_IGROUPR0 GICD_IGROUPR >>> +#define GICR_TYPER_LAST(1U << 4) >>> + >>> + >>> +#include >>> + >>> +#ifndef __ASSEMBLY__ >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +struct gicv3_data { >>> + void *dist_base; >>> + void *redist_base[NR_CPUS]; >>> + unsigned int irq_nr; >>> +}; >>> +extern struct gicv3_data gicv3_data; >>> + >>> +#define gicv3_dist_base() (gicv3_data.dist_base) >>> +#define gicv3_redist_base() >>> (gicv3_data.redist_base[smp_processor_id()]) >>> +#define gicv3_sgi_base() >>> (gicv3_data.redist_base[smp_processor_id()] + SZ_64K) >>> + >>> +extern int gicv3_init(void); >>> +extern void gicv3_enable_defaults(void); >>> + >>> +static inline void gicv3_do_wait_for_rwp(void *base) >>> +{ >>> + int count = 10; /* 1s */ >>> + >>> + while (readl(base + GICD_CTLR) & GICD_CTLR_RWP) { >>> + if (!--count) { >>> + printf("GICv3: RWP timeout!\n"); >>> + abort(); >>> + } >>> + cpu_relax(); >>> + udelay(10); >>> + }; >>> +} >>> + >>> +static inline void gicv3_dist_wait_for_rwp(void) >>> +{ >>> + gicv3_do_wait_for_rwp(gicv3_dist_base()); >>> +} >>> + >>> +static inline void gicv3_redist_
Re: [Qemu-devel] [kvm-unit-tests PATCH v4 09/11] arm/arm64: add initial gicv3 support
Hi, On 08/11/16 20:21, Andrew Jones wrote: > Signed-off-by: Andrew Jones> > --- > v4: > - only take defines from kernel we need now [Andre] > - simplify enable by not caring if we reinit the distributor [drew] > v2: > - configure irqs as NS GRP1 > --- > lib/arm/asm/arch_gicv3.h | 42 + > lib/arm/asm/gic-v3.h | 92 > ++ > lib/arm/asm/gic.h | 1 + > lib/arm/gic.c | 56 > lib/arm64/asm/arch_gicv3.h | 44 ++ > lib/arm64/asm/gic-v3.h | 1 + > lib/arm64/asm/sysreg.h | 44 ++ > 7 files changed, 280 insertions(+) > create mode 100644 lib/arm/asm/arch_gicv3.h > create mode 100644 lib/arm/asm/gic-v3.h > create mode 100644 lib/arm64/asm/arch_gicv3.h > create mode 100644 lib/arm64/asm/gic-v3.h > create mode 100644 lib/arm64/asm/sysreg.h > > diff --git a/lib/arm/asm/arch_gicv3.h b/lib/arm/asm/arch_gicv3.h > new file mode 100644 > index ..81a1e5f6c29c > --- /dev/null > +++ b/lib/arm/asm/arch_gicv3.h > @@ -0,0 +1,42 @@ > +/* > + * All ripped off from arch/arm/include/asm/arch_gicv3.h > + * > + * Copyright (C) 2016, Red Hat Inc, Andrew Jones > + * > + * This work is licensed under the terms of the GNU LGPL, version 2. > + */ > +#ifndef _ASMARM_ARCH_GICV3_H_ > +#define _ASMARM_ARCH_GICV3_H_ > + > +#ifndef __ASSEMBLY__ > +#include > +#include > +#include > + > +#define __stringify xstr > + > +#define __ACCESS_CP15(CRn, Op1, CRm, Op2)p15, Op1, %0, CRn, CRm, Op2 > + > +#define ICC_PMR __ACCESS_CP15(c4, 0, c6, 0) > +#define ICC_IGRPEN1 __ACCESS_CP15(c12, 0, c12, 7) > + > +static inline void gicv3_write_pmr(u32 val) > +{ > + asm volatile("mcr " __stringify(ICC_PMR) : : "r" (val)); > +} > + > +static inline void gicv3_write_grpen1(u32 val) > +{ > + asm volatile("mcr " __stringify(ICC_IGRPEN1) : : "r" (val)); > + isb(); > +} > + > +static inline u64 gicv3_read_typer(const volatile void __iomem *addr) > +{ > + u64 val = readl(addr); > + val |= (u64)readl(addr + 4) << 32; > + return val; > +} > + > +#endif /* !__ASSEMBLY__ */ > +#endif /* _ASMARM_ARCH_GICV3_H_ */ > diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h > new file mode 100644 > index ..03321f8c860f > --- /dev/null > +++ b/lib/arm/asm/gic-v3.h > @@ -0,0 +1,92 @@ > +/* > + * All GIC* defines are lifted from include/linux/irqchip/arm-gic-v3.h > + * > + * Copyright (C) 2016, Red Hat Inc, Andrew Jones > + * > + * This work is licensed under the terms of the GNU LGPL, version 2. > + */ > +#ifndef _ASMARM_GIC_V3_H_ > +#define _ASMARM_GIC_V3_H_ > + > +#ifndef _ASMARM_GIC_H_ > +#error Do not directly include . Include > +#endif > + > +#define GICD_CTLR0x > +#define GICD_TYPER 0x0004 So if we share the distributor register definition with GICv2, these shouldn't be here, but in gic.h. But this is the right naming scheme we should use (instead of GIC_DIST_xxx). Now this gets interesting with your wish to both share the definitions for the GICv2 and GICv3 distributors, but also stick to the names the kernel uses (because they differ between the two) ;-) So now you loose the greppability for either GIC_DIST_CTR or GICD_TYPER, for instance. > +#define GICD_IGROUPR 0x0080 > + > +#define GICD_CTLR_RWP(1U << 31) > +#define GICD_CTLR_ARE_NS (1U << 4) > +#define GICD_CTLR_ENABLE_G1A (1U << 1) > +#define GICD_CTLR_ENABLE_G1 (1U << 0) > + > +#define GICR_TYPER 0x0008 > +#define GICR_IGROUPR0GICD_IGROUPR > +#define GICR_TYPER_LAST (1U << 4) > + > + > +#include > + > +#ifndef __ASSEMBLY__ > +#include > +#include > +#include > +#include > + > +struct gicv3_data { > + void *dist_base; > + void *redist_base[NR_CPUS]; > + unsigned int irq_nr; > +}; > +extern struct gicv3_data gicv3_data; > + > +#define gicv3_dist_base()(gicv3_data.dist_base) > +#define gicv3_redist_base() > (gicv3_data.redist_base[smp_processor_id()]) > +#define gicv3_sgi_base() > (gicv3_data.redist_base[smp_processor_id()] + SZ_64K) > + > +extern int gicv3_init(void); > +extern void gicv3_enable_defaults(void); > + > +static inline void gicv3_do_wait_for_rwp(void *base) > +{ > + int count = 10; /* 1s */ > + > + while (readl(base + GICD_CTLR) & GICD_CTLR_RWP) { > + if (!--count) { > + printf("GICv3: RWP timeout!\n"); > + abort(); > + } > + cpu_relax(); > + udelay(10); > + }; > +} > + > +static inline void gicv3_dist_wait_for_rwp(void) > +{ > + gicv3_do_wait_for_rwp(gicv3_dist_base()); > +} > + > +static inline void
Re: [Qemu-devel] [kvm-unit-tests PATCH v4 03/11] arm/arm64: smp: support more than 8 cpus
Hi, On 09/11/16 11:57, Andrew Jones wrote: > On Wed, Nov 09, 2016 at 11:12:03AM +0000, Andre Przywara wrote: > [...] >>> diff --git a/lib/arm/setup.c b/lib/arm/setup.c >>> index 7e7b39f11dde..b6e2d5815e72 100644 >>> --- a/lib/arm/setup.c >>> +++ b/lib/arm/setup.c >>> @@ -24,12 +24,22 @@ extern unsigned long stacktop; >>> extern void io_init(void); >>> extern void setup_args_progname(const char *args); >>> >>> -u32 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0U) }; >>> +u64 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0U) }; >> >> This should be ~0UL. > > Indeed. Thanks. > >> Also I think the type should be unsigned long to match the types used >> everywhere else. > > I'll change mpidr_to_cpu to return u64 instead of unsigned long. I am not sure this is the right direction. unsigned long is really the natural type for MPIDR, since this is a system register with exactly the native register size. I think we use it this way in the kernel. Cheers, Andre > Actually I think Alex suggested that. I'm not sure why I haven't > done it... > >> >>> int nr_cpus; >>> >>> struct mem_region mem_regions[NR_MEM_REGIONS]; >>> phys_addr_t __phys_offset, __phys_end; >>> >>> +int mpidr_to_cpu(unsigned long mpidr) >>> +{ >>> + int i; >>> + >>> + for (i = 0; i < nr_cpus; ++i) >>> + if (cpus[i] == (mpidr & MPIDR_HWID_BITMASK)) >>> + return i; >>> + return -1; >>> +} >>> + >>> static void cpu_set(int fdtnode __unused, u32 regval, void *info __unused) >> >> I guess this needs to be extended as well, including >> dt_for_each_cpu_node() to cope with 64-bit reg properties in the CPU >> node (where the upper word is not 0). >> But this is not really crucial atm, so can be fixed in a follow-up patch. > > Yeah, I'll do it as a followup series, because it'll affect powerpc too. > > drew >
Re: [Qemu-devel] [kvm-unit-tests PATCH v4 06/11] arm/arm64: add initial gicv2 support
Hi, On 08/11/16 20:21, Andrew Jones wrote: > Add some gicv2 support. This just adds init and enable > functions, allowing unit tests to start messing with it. > > Signed-off-by: Andrew Jones> > --- > v4: > - only take defines from kernel we need now [Andre] > - moved defines to asm/gic.h so they'll be shared with v3 [drew] > - simplify enable by not caring if we reinit the distributor [drew] > - init all GICD_INT_DEF_PRI_X4 registers [Eric] > --- > arm/Makefile.common| 1 + > lib/arm/asm/gic-v2.h | 28 +++ > lib/arm/asm/gic.h | 44 + > lib/arm/gic.c | 75 > ++ > lib/arm64/asm/gic-v2.h | 1 + > lib/arm64/asm/gic.h| 1 + > 6 files changed, 150 insertions(+) > create mode 100644 lib/arm/asm/gic-v2.h > create mode 100644 lib/arm/asm/gic.h > create mode 100644 lib/arm/gic.c > create mode 100644 lib/arm64/asm/gic-v2.h > create mode 100644 lib/arm64/asm/gic.h > > diff --git a/arm/Makefile.common b/arm/Makefile.common > index ccb554d9251a..41239c37e092 100644 > --- a/arm/Makefile.common > +++ b/arm/Makefile.common > @@ -42,6 +42,7 @@ cflatobjs += lib/arm/mmu.o > cflatobjs += lib/arm/bitops.o > cflatobjs += lib/arm/psci.o > cflatobjs += lib/arm/smp.o > +cflatobjs += lib/arm/gic.o > > libeabi = lib/arm/libeabi.a > eabiobjs = lib/arm/eabi_compat.o > diff --git a/lib/arm/asm/gic-v2.h b/lib/arm/asm/gic-v2.h > new file mode 100644 > index ..f91530f88355 > --- /dev/null > +++ b/lib/arm/asm/gic-v2.h > @@ -0,0 +1,28 @@ > +/* > + * All GIC* defines are lifted from include/linux/irqchip/arm-gic.h > + * > + * Copyright (C) 2016, Red Hat Inc, Andrew Jones > + * > + * This work is licensed under the terms of the GNU LGPL, version 2. > + */ > +#ifndef _ASMARM_GIC_V2_H_ > +#define _ASMARM_GIC_V2_H_ > + > +#ifndef _ASMARM_GIC_H_ > +#error Do not directly include . Include > +#endif > + > +struct gicv2_data { > + void *dist_base; > + void *cpu_base; > + unsigned int irq_nr; > +}; > +extern struct gicv2_data gicv2_data; > + > +#define gicv2_dist_base()(gicv2_data.dist_base) > +#define gicv2_cpu_base() (gicv2_data.cpu_base) > + > +extern int gicv2_init(void); > +extern void gicv2_enable_defaults(void); > + > +#endif /* _ASMARM_GIC_V2_H_ */ > diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h > new file mode 100644 > index ..ec92f1064dc0 > --- /dev/null > +++ b/lib/arm/asm/gic.h > @@ -0,0 +1,44 @@ > +/* > + * Copyright (C) 2016, Red Hat Inc, Andrew Jones > + * > + * This work is licensed under the terms of the GNU LGPL, version 2. > + */ > +#ifndef _ASMARM_GIC_H_ > +#define _ASMARM_GIC_H_ > + > +#include > + > +#define GIC_CPU_CTRL 0x00 > +#define GIC_CPU_PRIMASK 0x04 > + > +#define GICC_ENABLE 0x1 > +#define GICC_INT_PRI_THRESHOLD 0xf0 > + > +#define GIC_DIST_CTRL0x000 > +#define GIC_DIST_CTR 0x004 I think we shouldn't copy this old name here, which stems from pre-GICv2 times (PL390?), IIUC. Both GIC specs talk of TYPER here. Also if we now use the same defines for both the GICv2 and GICv3 distributor, we should really stick with the (modern) spec naming, which is GICD_CTRL, GICD_TYPER and so on. Same for the CPU interface (GICC_CTRL). In the kernel these names are used for GICv3, but we didn't bother to adjust the existing GICv2 names to avoid pointless churn. Also that would line up with the bit field defines below. Cheers, Andre. > +#define GIC_DIST_ENABLE_SET 0x100 > +#define GIC_DIST_PRI 0x400 > + > +#define GICD_ENABLE 0x1 > +#define GICD_INT_EN_SET_SGI 0x > +#define GICD_INT_DEF_PRI 0xa0 > +#define GICD_INT_DEF_PRI_X4 ((GICD_INT_DEF_PRI << 24) |\ > + (GICD_INT_DEF_PRI << 16) |\ > + (GICD_INT_DEF_PRI << 8) |\ > + GICD_INT_DEF_PRI) > + > +#define GICD_TYPER_IRQS(typer) typer) & 0x1f) + 1) * 32) > + > +#ifndef __ASSEMBLY__ > + > +/* > + * gic_init will try to find all known gics, and then > + * initialize the gic data for the one found. > + * returns > + * 0 : no gic was found > + * > 0 : the gic version of the gic found > + */ > +extern int gic_init(void); > + > +#endif /* !__ASSEMBLY__ */ > +#endif /* _ASMARM_GIC_H_ */ > diff --git a/lib/arm/gic.c b/lib/arm/gic.c > new file mode 100644 > index ..91d78c9a0cc2 > --- /dev/null > +++ b/lib/arm/gic.c > @@ -0,0 +1,75 @@ > +/* > + * Copyright (C) 2016, Red Hat Inc, Andrew Jones > + * > + * This work is licensed under the terms of the GNU LGPL, version 2. > + */ > +#include > +#include > +#include > + > +struct gicv2_data gicv2_data; > + > +/* > + *
Re: [Qemu-devel] [kvm-unit-tests PATCH v4 03/11] arm/arm64: smp: support more than 8 cpus
Hi, On 08/11/16 20:21, Andrew Jones wrote: > By adding support for launching with gicv3 we can break the 8 vcpu > limit. This patch adds support to smp code and also selects the > vgic model corresponding to the host. The vgic model may also be > manually selected by adding e.g. -machine gic-version=3 to > extra_params. > > Reviewed-by: Alex Bennée> Signed-off-by: Andrew Jones > > --- > v4: improved commit message > --- > arm/run | 19 --- > arm/selftest.c| 5 - > lib/arm/asm/processor.h | 9 +++-- > lib/arm/asm/setup.h | 4 ++-- > lib/arm/setup.c | 12 +++- > lib/arm64/asm/processor.h | 9 +++-- > 6 files changed, 43 insertions(+), 15 deletions(-) > > diff --git a/arm/run b/arm/run > index a2f35ef6a7e6..2d0698619606 100755 > --- a/arm/run > +++ b/arm/run > @@ -31,13 +31,6 @@ if [ -z "$ACCEL" ]; then > fi > fi > > -if [ "$HOST" = "aarch64" ] && [ "$ACCEL" = "kvm" ]; then > - processor="host" > - if [ "$ARCH" = "arm" ]; then > - processor+=",aarch64=off" > - fi > -fi > - > qemu="${QEMU:-qemu-system-$ARCH_NAME}" > qpath=$(which $qemu 2>/dev/null) > > @@ -53,6 +46,18 @@ fi > > M='-machine virt' > > +if [ "$ACCEL" = "kvm" ]; then > + if $qemu $M,\? 2>&1 | grep gic-version > /dev/null; then > + M+=',gic-version=host' > + fi > + if [ "$HOST" = "aarch64" ]; then > + processor="host" > + if [ "$ARCH" = "arm" ]; then > + processor+=",aarch64=off" > + fi > + fi > +fi > + > if ! $qemu $M -device '?' 2>&1 | grep virtconsole > /dev/null; then > echo "$qpath doesn't support virtio-console for chr-testdev. Exiting." > exit 2 > diff --git a/arm/selftest.c b/arm/selftest.c > index 196164f5313d..2f117f795d2d 100644 > --- a/arm/selftest.c > +++ b/arm/selftest.c > @@ -312,9 +312,10 @@ static bool psci_check(void) > static cpumask_t smp_reported; > static void cpu_report(void) > { > + unsigned long mpidr = get_mpidr(); > int cpu = smp_processor_id(); > > - report("CPU%d online", true, cpu); > + report("CPU(%3d) mpidr=%lx", mpidr_to_cpu(mpidr) == cpu, cpu, mpidr); > cpumask_set_cpu(cpu, _reported); > halt(); > } > @@ -343,6 +344,7 @@ int main(int argc, char **argv) > > } else if (strcmp(argv[1], "smp") == 0) { > > + unsigned long mpidr = get_mpidr(); > int cpu; > > report("PSCI version", psci_check()); > @@ -353,6 +355,7 @@ int main(int argc, char **argv) > smp_boot_secondary(cpu, cpu_report); > } > > + report("CPU(%3d) mpidr=%lx", mpidr_to_cpu(mpidr) == 0, 0, > mpidr); > cpumask_set_cpu(0, _reported); > while (!cpumask_full(_reported)) > cpu_relax(); > diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h > index f25e7eee3666..d2048f5f5f7e 100644 > --- a/lib/arm/asm/processor.h > +++ b/lib/arm/asm/processor.h > @@ -40,8 +40,13 @@ static inline unsigned int get_mpidr(void) > return mpidr; > } > > -/* Only support Aff0 for now, up to 4 cpus */ > -#define mpidr_to_cpu(mpidr) ((int)((mpidr) & 0xff)) > +#define MPIDR_HWID_BITMASK 0xff > +extern int mpidr_to_cpu(unsigned long mpidr); > + > +#define MPIDR_LEVEL_SHIFT(level) \ > + (((1 << level) >> 1) << 3) > +#define MPIDR_AFFINITY_LEVEL(mpidr, level) \ > + ((mpidr >> MPIDR_LEVEL_SHIFT(level)) & 0xff) > > extern void start_usr(void (*func)(void *arg), void *arg, unsigned long > sp_usr); > extern bool is_user(void); > diff --git a/lib/arm/asm/setup.h b/lib/arm/asm/setup.h > index cb8fdbd38dd5..b0d51f5f0721 100644 > --- a/lib/arm/asm/setup.h > +++ b/lib/arm/asm/setup.h > @@ -10,8 +10,8 @@ > #include > #include > > -#define NR_CPUS 8 > -extern u32 cpus[NR_CPUS]; > +#define NR_CPUS 255 > +extern u64 cpus[NR_CPUS];/* per-cpu IDs (MPIDRs) */ > extern int nr_cpus; > > #define NR_MEM_REGIONS 8 > diff --git a/lib/arm/setup.c b/lib/arm/setup.c > index 7e7b39f11dde..b6e2d5815e72 100644 > --- a/lib/arm/setup.c > +++ b/lib/arm/setup.c > @@ -24,12 +24,22 @@ extern unsigned long stacktop; > extern void io_init(void); > extern void setup_args_progname(const char *args); > > -u32 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0U) }; > +u64 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0U) }; This should be ~0UL. Also I think the type should be unsigned long to match the types used everywhere else. > int nr_cpus; > > struct mem_region mem_regions[NR_MEM_REGIONS]; > phys_addr_t __phys_offset, __phys_end; > > +int mpidr_to_cpu(unsigned long mpidr) > +{ > + int i; > + > + for (i = 0; i < nr_cpus; ++i) > + if (cpus[i] == (mpidr & MPIDR_HWID_BITMASK)) > + return i; > + return -1; > +} > + > static
[Qemu-devel] [RFC PATCH] kvm-unit-tests: arm/arm64: strip GIC headers
Hi, this is an illustrative patch which shows what can be removed from the kvm-unit-tests GIC headers. If this patch finds mercy, it should be squashed into the in-flight GIC patches, eventually. The rationale for this patch is that while it seems like a good idea to copy the header files with the GIC definitions from Linux, we should avoid the danger of copying bugs on the way. This is especially true for those definitions that are used by the very emulation code that we are about to test. Beside this the headers contain much more definitions than we actually need. So strip those header files, by first removing all definitions that are actually only useful for hypervisors. Also we remove definitions for registers that are not needed yet. The idea is to add them one by one as soon as we start to test functionality, so that review can be much easier and safer. Applies on top of Drew's v3 GIC series (as in his github branch). Signed-off-by: Andre Przywara <andre.przyw...@arm.com> --- lib/arm/asm/arch_gicv3.h | 62 - lib/arm/asm/gic-v2.h | 22 - lib/arm/asm/gic-v3.h | 227 - lib/arm64/asm/arch_gicv3.h | 43 - 4 files changed, 354 deletions(-) diff --git a/lib/arm/asm/arch_gicv3.h b/lib/arm/asm/arch_gicv3.h index d529a7e..333bf49 100644 --- a/lib/arm/asm/arch_gicv3.h +++ b/lib/arm/asm/arch_gicv3.h @@ -16,7 +16,6 @@ #define __stringify xstr - #define __ACCESS_CP15(CRn, Op1, CRm, Op2) p15, Op1, %0, CRn, CRm, Op2 #define __ACCESS_CP15_64(Op1, CRm) p15, Op1, %Q0, %R0, CRm @@ -31,67 +30,6 @@ #define ICC_HSRE __ACCESS_CP15(c12, 4, c9, 5) -#define ICH_VSEIR __ACCESS_CP15(c12, 4, c9, 4) -#define ICH_HCR__ACCESS_CP15(c12, 4, c11, 0) -#define ICH_VTR__ACCESS_CP15(c12, 4, c11, 1) -#define ICH_MISR __ACCESS_CP15(c12, 4, c11, 2) -#define ICH_EISR __ACCESS_CP15(c12, 4, c11, 3) -#define ICH_ELSR __ACCESS_CP15(c12, 4, c11, 5) -#define ICH_VMCR __ACCESS_CP15(c12, 4, c11, 7) - -#define __LR0(x) __ACCESS_CP15(c12, 4, c12, x) -#define __LR8(x) __ACCESS_CP15(c12, 4, c13, x) - -#define ICH_LR0__LR0(0) -#define ICH_LR1__LR0(1) -#define ICH_LR2__LR0(2) -#define ICH_LR3__LR0(3) -#define ICH_LR4__LR0(4) -#define ICH_LR5__LR0(5) -#define ICH_LR6__LR0(6) -#define ICH_LR7__LR0(7) -#define ICH_LR8__LR8(0) -#define ICH_LR9__LR8(1) -#define ICH_LR10 __LR8(2) -#define ICH_LR11 __LR8(3) -#define ICH_LR12 __LR8(4) -#define ICH_LR13 __LR8(5) -#define ICH_LR14 __LR8(6) -#define ICH_LR15 __LR8(7) - -/* LR top half */ -#define __LRC0(x) __ACCESS_CP15(c12, 4, c14, x) -#define __LRC8(x) __ACCESS_CP15(c12, 4, c15, x) - -#define ICH_LRC0 __LRC0(0) -#define ICH_LRC1 __LRC0(1) -#define ICH_LRC2 __LRC0(2) -#define ICH_LRC3 __LRC0(3) -#define ICH_LRC4 __LRC0(4) -#define ICH_LRC5 __LRC0(5) -#define ICH_LRC6 __LRC0(6) -#define ICH_LRC7 __LRC0(7) -#define ICH_LRC8 __LRC8(0) -#define ICH_LRC9 __LRC8(1) -#define ICH_LRC10 __LRC8(2) -#define ICH_LRC11 __LRC8(3) -#define ICH_LRC12 __LRC8(4) -#define ICH_LRC13 __LRC8(5) -#define ICH_LRC14 __LRC8(6) -#define ICH_LRC15 __LRC8(7) - -#define __AP0Rx(x) __ACCESS_CP15(c12, 4, c8, x) -#define ICH_AP0R0 __AP0Rx(0) -#define ICH_AP0R1 __AP0Rx(1) -#define ICH_AP0R2 __AP0Rx(2) -#define ICH_AP0R3 __AP0Rx(3) - -#define __AP1Rx(x) __ACCESS_CP15(c12, 4, c9, x) -#define ICH_AP1R0 __AP1Rx(0) -#define ICH_AP1R1 __AP1Rx(1) -#define ICH_AP1R2 __AP1Rx(2) -#define ICH_AP1R3 __AP1Rx(3) - /* Low-level accessors */ static inline void gicv3_write_eoir(u32 irq) diff --git a/lib/arm/asm/gic-v2.h b/lib/arm/asm/gic-v2.h index 973c2bf..019d553 100644 --- a/lib/arm/asm/gic-v2.h +++ b/lib/arm/asm/gic-v2.h @@ -10,44 +10,22 @@ #define GIC_CP
Re: [Qemu-devel] [kvm-unit-tests PATCH v3 07/10] arm/arm64: add initial gicv3 support
Hi Drew, On 15/07/16 14:00, Andrew Jones wrote: > Signed-off-by: Andrew Jones> > --- > v2: configure irqs as NS GRP1 > --- > lib/arm/asm/arch_gicv3.h | 184 ++ > lib/arm/asm/gic-v3.h | 321 > + > lib/arm/asm/gic.h | 1 + > lib/arm/gic.c | 73 +++ > lib/arm64/asm/arch_gicv3.h | 169 > lib/arm64/asm/gic-v3.h | 1 + > lib/arm64/asm/sysreg.h | 44 +++ > 7 files changed, 793 insertions(+) > create mode 100644 lib/arm/asm/arch_gicv3.h > create mode 100644 lib/arm/asm/gic-v3.h > create mode 100644 lib/arm64/asm/arch_gicv3.h > create mode 100644 lib/arm64/asm/gic-v3.h > create mode 100644 lib/arm64/asm/sysreg.h > > diff --git a/lib/arm/asm/arch_gicv3.h b/lib/arm/asm/arch_gicv3.h > new file mode 100644 > index 0..d529a7eb62807 > --- /dev/null > +++ b/lib/arm/asm/arch_gicv3.h > @@ -0,0 +1,184 @@ > +/* > + * All ripped off from arch/arm/include/asm/arch_gicv3.h So I was wondering if - from a test suite's perspective - it's really clever to pull in copies of Linux headers here. First it's really a lot of text we pull in while not using most of it (at least now). Also they keep changing (4.9-rc1 saw so me changes, for instance). So do we update them? But more importantly those headers are also used in the emulation code, so we would just copy any bugs or typos and would probably not detect them here. IIRC there was a fix for a bitmask lately. It's probably fine to copy the register offsets, but anything that defines Linux specific things like default priorities or more complex macros should be avoided, I think. This just makes kvm-unit-test copying Linux behaviour. Maybe we stick to the Linux naming, but pull in only the fields as we need them? This would both limit the amount of lines being merged, as would simplify the review effort (and quality), as people would just need to look at a very limited number of defines, allowing them to actually check it against the specification? I gave this a try and could reduce the header files significantly. Please let me know if you need any bits from this effort to be shared. > + * > + * Copyright (C) 2016, Red Hat Inc, Andrew Jones > + * > + * This work is licensed under the terms of the GNU LGPL, version 2. > + */ > +#ifndef _ASMARM_ARCH_GICV3_H_ > +#define _ASMARM_ARCH_GICV3_H_ > + > +#ifndef __ASSEMBLY__ > + > +#include > +#include > +#include > + > +#define __stringify xstr > + > + > +#define __ACCESS_CP15(CRn, Op1, CRm, Op2)p15, Op1, %0, CRn, CRm, Op2 > +#define __ACCESS_CP15_64(Op1, CRm) p15, Op1, %Q0, %R0, CRm > + > +#define ICC_EOIR1__ACCESS_CP15(c12, 0, c12, 1) > +#define ICC_DIR __ACCESS_CP15(c12, 0, c11, 1) > +#define ICC_IAR1 __ACCESS_CP15(c12, 0, c12, 0) > +#define ICC_SGI1R__ACCESS_CP15_64(0, c12) > +#define ICC_PMR __ACCESS_CP15(c4, 0, c6, 0) > +#define ICC_CTLR __ACCESS_CP15(c12, 0, c12, 4) > +#define ICC_SRE __ACCESS_CP15(c12, 0, c12, 5) > +#define ICC_IGRPEN1 __ACCESS_CP15(c12, 0, c12, 7) > + > +#define ICC_HSRE __ACCESS_CP15(c12, 4, c9, 5) > + > +#define ICH_VSEIR__ACCESS_CP15(c12, 4, c9, 4) > +#define ICH_HCR __ACCESS_CP15(c12, 4, c11, 0) > +#define ICH_VTR __ACCESS_CP15(c12, 4, c11, 1) > +#define ICH_MISR __ACCESS_CP15(c12, 4, c11, 2) > +#define ICH_EISR __ACCESS_CP15(c12, 4, c11, 3) > +#define ICH_ELSR __ACCESS_CP15(c12, 4, c11, 5) > +#define ICH_VMCR __ACCESS_CP15(c12, 4, c11, 7) > + > +#define __LR0(x) __ACCESS_CP15(c12, 4, c12, x) > +#define __LR8(x) __ACCESS_CP15(c12, 4, c13, x) So for instance we clearly don't need those defines (the list registers being hypervisor only). > + > +#define ICH_LR0 __LR0(0) > +#define ICH_LR1 __LR0(1) > +#define ICH_LR2 __LR0(2) > +#define ICH_LR3 __LR0(3) > +#define ICH_LR4 __LR0(4) > +#define ICH_LR5 __LR0(5) > +#define ICH_LR6 __LR0(6) > +#define ICH_LR7 __LR0(7) > +#define ICH_LR8 __LR8(0) > +#define ICH_LR9 __LR8(1) > +#define ICH_LR10 __LR8(2) > +#define ICH_LR11 __LR8(3) > +#define ICH_LR12 __LR8(4) > +#define ICH_LR13 __LR8(5) > +#define ICH_LR14 __LR8(6) > +#define ICH_LR15 __LR8(7)
Re: [Qemu-devel] [PATCH arm-devs v2 8/8] arm/highbank.c: Fix MPCore periphbase name
On 11/28/2013 08:41 PM, Peter Maydell wrote: (CCing Rob) On 28 November 2013 03:31, Peter Crosthwaite peter.crosthwa...@xilinx.com wrote: GIC_BASE_ADDR is not the base address of the GIC. Its clear from the code that this is the base address of the MPCore. Rename to MPCORE_PERIPHBASE accordingly. MPCore is one of those terms I dislike because it doesn't actually match up with the documentation's terminology... Signed-off-by: Peter Crosthwaite peter.crosthwa...@xilinx.com --- hw/arm/highbank.c | 15 --- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index cb32325..be2cc20 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -28,11 +28,11 @@ #include exec/address-spaces.h #include qemu/error-report.h -#define SMP_BOOT_ADDR 0x100 -#define SMP_BOOT_REG 0x40 -#define GIC_BASE_ADDR 0xfff1 +#define SMP_BOOT_ADDR 0x100 +#define SMP_BOOT_REG0x40 +#define MPCORE_PERIPHBASE 0xfff1 -#define NIRQ_GIC 160 +#define NIRQ_GIC160 /* Board init. */ @@ -55,7 +55,7 @@ static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info) 0xe1110001, /* tst r1, r1 */ 0x0afb, /* beq wfi */ 0xe12fff11, /* bx r1 */ -GIC_BASE_ADDR /* privbase: gic address. */ +MPCORE_PERIPHBASE /* privbase: gic address. */ Comment no longer matches code. More seriously, this secondary-boot code has a bunch of hardcoded offsets for GIC registers which are correct for the A9 but wrong for A15. Andre, did you test Midway with an SMP boot config? Obviously not ;-) In the moment I cannot care about this, but it looks like we need different SMP stubs for Highbank and Midway. Thanks for the hint, Andre. The generic hw/arm/boot code dealt with this problem by feeding the boot code the GIC CPU interface base address rather than the generic peripheral base address; the offsets within the CPU i/f are the same for both cores. }; for (n = 0; n ARRAY_SIZE(smpboot); n++) { smpboot[n] = tswap32(smpboot[n]); @@ -236,7 +236,8 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine) cpu = ARM_CPU(object_new(object_class_get_name(oc))); -object_property_set_int(OBJECT(cpu), GIC_BASE_ADDR, reset-cbar, err); +object_property_set_int(OBJECT(cpu), MPCORE_PERIPHBASE, reset-cbar, +err); if (err) { error_report(%s, error_get_pretty(err)); exit(1); @@ -287,7 +288,7 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine) qdev_prop_set_uint32(dev, num-irq, NIRQ_GIC); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); -sysbus_mmio_map(busdev, 0, GIC_BASE_ADDR); +sysbus_mmio_map(busdev, 0, MPCORE_PERIPHBASE); for (n = 0; n smp_cpus; n++) { sysbus_connect_irq(busdev, n, cpu_irq[n]); } -- 1.8.4.4 thanks -- PMM
[Qemu-devel] [Bug 1243287] Re: [KVM/QEMU][ARM][SAUCY] fails to boot cloud-image due to host kvm fail
Peter, the config option is called: CONFIG_STRICT_DEVMEM And /dev/mem behaves differently between doing read() and doing mmap(). As Peter already hinted, the memory layout is different on native Midway (which has DRAM starting at 0) and mach-virt/vexpress (which start at 128MB / 2GB respectively). So accessing 0xf reads memory on native, but faults in stage 2 mapping in the host kernel. But the actual problem is that the host kernel passes this abort on to userspace, where QEMU just does abort(), thus crashing the whole virtual machine. Actually I think we should change the host kernel to inject the data abort into the guest. I tested this with a simple patch, it now makes dmidecode crash (due to a signal), but keeps the guest alive. This approach needs some discussion on the ML, I guess. But near term we should not call dmidecode on ARM, since AFAIK it does not give any information. There once was a discussion on patching dmidecode to output hardcoded or elsewhere gathered information to make scripts happy, but I don't know where this ended. -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1243287 Title: [KVM/QEMU][ARM][SAUCY] fails to boot cloud-image due to host kvm fail Status in QEMU: Confirmed Bug description: On booting the cloud image using qemu/kvm fails with the following error: Cloud-init v. 0.7.3 running 'init' at Thu, 03 Oct 2013 16:45:21 +. Up 360.78 seconds. ci-info: +Net device info+ ci-info: ++--+---+---+---+ ci-info: | Device | Up | Address | Mask | Hw-Address | ci-info: ++--+---+---+---+ ci-info: | lo | True | 127.0.0.1 | 255.0.0.0 | . | ci-info: | eth0 | True | 10.0.2.15 | 255.255.255.0 | 52:54:00:12:34:56 | ci-info: ++--+---+---+---+ ci-info: ++Route info++ ci-info: +---+-+--+---+---+---+ ci-info: | Route | Destination | Gateway | Genmask | Interface | Flags | ci-info: +---+-+--+---+---+---+ ci-info: | 0 | 0.0.0.0 | 10.0.2.2 | 0.0.0.0 | eth0 | UG | ci-info: | 1 | 10.0.2.0 | 0.0.0.0 | 255.255.255.0 | eth0 | U | ci-info: +---+-+--+---+---+---+ error: kvm run failed Function not implemented /usr/lib/python2.7/dist- packages/cloudinit/sources/DataSourceAltCloud.py assumes that dmidecode command is availabe (ie it assumes that system is x86) on arm systems there is no dmidecode command so host kvm fails with the message error: kvm run failed Function not implemented The patch makes get_cloud_type() function return with UNKNOWN for ARM systems. I was able to boot the cloud-image on ARM after applying this change. To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1243287/+subscriptions
[Qemu-devel] [PATCH v2 0/2] add initial Calxeda Midway A15 support
While the Calxeda Midway part is actually a bit more than a Highbank with A15s, for QEMU's purposes this view is sufficient. So refactor the Highbank initialization to allow a very similar machine and add the necessary changes to support the new machine called midway. This is based on work by Rob Herring rob.herr...@calxeda.com. Signed-off-by: Andre Przywara andre.przyw...@calxeda.com Andre Przywara (2): ARM/highbank: prepare for adding similar machines ARM/highbank: add support for Calxeda ECX-2000 / Midway hw/arm/highbank.c | 61 +-- 1 file changed, 50 insertions(+), 11 deletions(-) -- 1.7.12.1
[Qemu-devel] [PATCH v2 1/2] ARM/highbank: prepare for adding similar machines
To allow the modelling of machines similar to Calxeda Highbank, introduce a parameter to the init function and call it from a wrapper. This allows to tweak the definition for individual machines later on. Signed-off-by: Andre Przywara andre.przyw...@calxeda.com --- hw/arm/highbank.c | 29 +++-- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index 4405dbd..2c32a2b 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -183,20 +183,24 @@ type_init(highbank_regs_register_types) static struct arm_boot_info highbank_binfo; +enum cxmachines { +CALXEDA_HIGHBANK, +}; + /* ram_size must be set to match the upper bound of memory in the * device tree (linux/arch/arm/boot/dts/highbank.dts), which is * normally 0xff90 or -m 4089. When running this board on a * 32-bit host, set the reg value of memory to 0xf7ff0 in the * device tree and pass -m 2047 to QEMU. */ -static void highbank_init(QEMUMachineInitArgs *args) +static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine) { ram_addr_t ram_size = args-ram_size; const char *cpu_model = args-cpu_model; const char *kernel_filename = args-kernel_filename; const char *kernel_cmdline = args-kernel_cmdline; const char *initrd_filename = args-initrd_filename; -DeviceState *dev; +DeviceState *dev = NULL; SysBusDevice *busdev; qemu_irq *irqp; qemu_irq pic[128]; @@ -208,7 +212,11 @@ static void highbank_init(QEMUMachineInitArgs *args) char *sysboot_filename; if (!cpu_model) { -cpu_model = cortex-a9; +switch (machine) { +case CALXEDA_HIGHBANK: +cpu_model = cortex-a9; +break; +} } for (n = 0; n smp_cpus; n++) { @@ -246,7 +254,11 @@ static void highbank_init(QEMUMachineInitArgs *args) } } -dev = qdev_create(NULL, a9mpcore_priv); +switch (machine) { +case CALXEDA_HIGHBANK: +dev = qdev_create(NULL, a9mpcore_priv); +break; +} qdev_prop_set_uint32(dev, num-cpu, smp_cpus); qdev_prop_set_uint32(dev, num-irq, NIRQ_GIC); qdev_init_nofail(dev); @@ -324,6 +336,11 @@ static void highbank_init(QEMUMachineInitArgs *args) arm_load_kernel(arm_env_get_cpu(first_cpu), highbank_binfo); } +static void highbank_init(QEMUMachineInitArgs *args) +{ +calxeda_init(args, CALXEDA_HIGHBANK); +} + static QEMUMachine highbank_machine = { .name = highbank, .desc = Calxeda Highbank (ECX-1000), @@ -333,9 +350,9 @@ static QEMUMachine highbank_machine = { DEFAULT_MACHINE_OPTIONS, }; -static void highbank_machine_init(void) +static void calxeda_machines_init(void) { qemu_register_machine(highbank_machine); } -machine_init(highbank_machine_init); +machine_init(calxeda_machines_init); -- 1.7.12.1
[Qemu-devel] [PATCH v2 2/2] ARM/highbank: add support for Calxeda ECX-2000 / Midway
The Calxeda ECX-2000 chip (aka. Midway) is model-wise quite similar to the Highbank. The most prominent difference is the Cortex-A15 CPU core in it, together with the associated core peripherals. Add a new ARM machine type called midway. Move the L2 cache controller device into the Highbank specific part, since Midway does not have (and need) it. Signed-off-by: Andre Przywara andre.przyw...@calxeda.com --- hw/arm/highbank.c | 32 +++- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index 2c32a2b..3c99a81 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -185,6 +185,7 @@ static struct arm_boot_info highbank_binfo; enum cxmachines { CALXEDA_HIGHBANK, +CALXEDA_MIDWAY, }; /* ram_size must be set to match the upper bound of memory in the @@ -216,6 +217,9 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine) case CALXEDA_HIGHBANK: cpu_model = cortex-a9; break; +case CALXEDA_MIDWAY: +cpu_model = cortex-a15; +break; } } @@ -256,8 +260,16 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine) switch (machine) { case CALXEDA_HIGHBANK: +dev = qdev_create(NULL, l2x0); +qdev_init_nofail(dev); +busdev = SYS_BUS_DEVICE(dev); +sysbus_mmio_map(busdev, 0, 0xfff12000); + dev = qdev_create(NULL, a9mpcore_priv); break; +case CALXEDA_MIDWAY: +dev = qdev_create(NULL, a15mpcore_priv); +break; } qdev_prop_set_uint32(dev, num-cpu, smp_cpus); qdev_prop_set_uint32(dev, num-irq, NIRQ_GIC); @@ -272,11 +284,6 @@ static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine) pic[n] = qdev_get_gpio_in(dev, n); } -dev = qdev_create(NULL, l2x0); -qdev_init_nofail(dev); -busdev = SYS_BUS_DEVICE(dev); -sysbus_mmio_map(busdev, 0, 0xfff12000); - dev = qdev_create(NULL, sp804); qdev_prop_set_uint32(dev, freq0, 15000); qdev_prop_set_uint32(dev, freq1, 15000); @@ -341,6 +348,11 @@ static void highbank_init(QEMUMachineInitArgs *args) calxeda_init(args, CALXEDA_HIGHBANK); } +static void midway_init(QEMUMachineInitArgs *args) +{ +calxeda_init(args, CALXEDA_MIDWAY); +} + static QEMUMachine highbank_machine = { .name = highbank, .desc = Calxeda Highbank (ECX-1000), @@ -350,9 +362,19 @@ static QEMUMachine highbank_machine = { DEFAULT_MACHINE_OPTIONS, }; +static QEMUMachine midway_machine = { +.name = midway, +.desc = Calxeda Midway (ECX-2000), +.init = midway_init, +.block_default_type = IF_SCSI, +.max_cpus = 4, +DEFAULT_MACHINE_OPTIONS, +}; + static void calxeda_machines_init(void) { qemu_register_machine(highbank_machine); +qemu_register_machine(midway_machine); } machine_init(calxeda_machines_init); -- 1.7.12.1
[Qemu-devel] [PATCH] highbank: add initial Calxeda Midway A15 support
From: Rob Herring rob.herr...@calxeda.com While the Calxeda Midway part is actually a bit more than a Highbank with A15s, for QEMU's purposes this view is sufficient. So to allow both emulation with that chip as well as KVM guests using that model add an A15 CPU and it's peripherals as an option. The use of: -M highbank -cpu cortex-a15 simply gives the new chip without the need for a new model. Signed-off-by: Rob Herring rob.herr...@calxeda.com Signed-off-by: Andre Przywara andre.przyw...@calxeda.com --- hw/arm/highbank.c | 19 +-- 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index 4405dbd..ed864c6 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -196,6 +196,7 @@ static void highbank_init(QEMUMachineInitArgs *args) const char *kernel_filename = args-kernel_filename; const char *kernel_cmdline = args-kernel_cmdline; const char *initrd_filename = args-initrd_filename; +CPUARMState *env = NULL; DeviceState *dev; SysBusDevice *busdev; qemu_irq *irqp; @@ -223,6 +224,8 @@ static void highbank_init(QEMUMachineInitArgs *args) cpu-reset_cbar = GIC_BASE_ADDR; irqp = arm_pic_init_cpu(cpu); cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ]; + +env = cpu-env; } sysmem = get_system_memory(); @@ -246,7 +249,16 @@ static void highbank_init(QEMUMachineInitArgs *args) } } -dev = qdev_create(NULL, a9mpcore_priv); +if (arm_feature(env, ARM_FEATURE_LPAE)) { +dev = qdev_create(NULL, a15mpcore_priv); +} else { +dev = qdev_create(NULL, l2x0); +qdev_init_nofail(dev); +busdev = SYS_BUS_DEVICE(dev); +sysbus_mmio_map(busdev, 0, 0xfff12000); + +dev = qdev_create(NULL, a9mpcore_priv); +} qdev_prop_set_uint32(dev, num-cpu, smp_cpus); qdev_prop_set_uint32(dev, num-irq, NIRQ_GIC); qdev_init_nofail(dev); @@ -260,11 +272,6 @@ static void highbank_init(QEMUMachineInitArgs *args) pic[n] = qdev_get_gpio_in(dev, n); } -dev = qdev_create(NULL, l2x0); -qdev_init_nofail(dev); -busdev = SYS_BUS_DEVICE(dev); -sysbus_mmio_map(busdev, 0, 0xfff12000); - dev = qdev_create(NULL, sp804); qdev_prop_set_uint32(dev, freq0, 15000); qdev_prop_set_uint32(dev, freq1, 15000); -- 1.7.12.1
[Qemu-devel] [PATCH] fdt: update embedded header file from upstream to fix compilation
Upstream dtc.git introduced a change in libfdt_env.h, which breaks compilation with QEMU's version of it: CC arm-softmmu/device_tree.o In file included from /usr/include/libfdt.h:55:0, from /src/qemu.git/device_tree.c:28: /usr/include/fdt.h:7:2: error: unknown type name 'fdt32_t' ... The culprit is: commit feafcd972cb744750a65728440c99526e6199a6d Author: Kim Phillips kim.phill...@freescale.com Date: Wed Nov 28 17:33:01 2012 -0600 dtc/libfdt: introduce fdt types for annotation by endian checkers ... Pull the new definitions into QEMU's version of the file. This change also works with older installed versions of dtc. The upstream version got a GPL or BSD dual license header meanwhile. I retained the original GPL license header from QEMU, only added the original copyrights. Signed-off-by: Andre Przywara andre.przyw...@linaro.org --- include/libfdt_env.h | 25 - 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/include/libfdt_env.h b/include/libfdt_env.h index 3667d4c..aad54bb 100644 --- a/include/libfdt_env.h +++ b/include/libfdt_env.h @@ -1,4 +1,12 @@ +#ifndef _LIBFDT_ENV_H +#define _LIBFDT_ENV_H /* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright 2012 Kim Phillips, Freescale Semiconductor. + * Adaptation to QEMU: Copyright IBM Corp. 2008 + * by Hollis Blanchard holl...@us.ibm.com + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, as * published by the Free Software Foundation. @@ -11,16 +19,23 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see http://www.gnu.org/licenses/. * - * Copyright IBM Corp. 2008 - * Authors: Hollis Blanchard holl...@us.ibm.com * */ -#ifndef _LIBFDT_ENV_H -#define _LIBFDT_ENV_H - #include qemu/bswap.h +#ifdef __CHECKER__ +#define __force __attribute__((force)) +#define __bitwise __attribute__((bitwise)) +#else +#define __force +#define __bitwise +#endif + +typedef uint16_t __bitwise fdt16_t; +typedef uint32_t __bitwise fdt32_t; +typedef uint64_t __bitwise fdt64_t; + #ifdef HOST_WORDS_BIGENDIAN #define fdt32_to_cpu(x) (x) #define cpu_to_fdt32(x) (x) -- 1.7.12.1
Re: [Qemu-devel] [PATCH] fdt: update embedded header file from upstream to fix compilation
On 05/07/2013 02:44 PM, Peter Maydell wrote: On 7 May 2013 13:36, Andre Przywara andre.przyw...@linaro.org wrote: Upstream dtc.git introduced a change in libfdt_env.h, which breaks compilation with QEMU's version of it: CC arm-softmmu/device_tree.o In file included from /usr/include/libfdt.h:55:0, from /src/qemu.git/device_tree.c:28: /usr/include/fdt.h:7:2: error: unknown type name 'fdt32_t' ... I'm not entirely sure I understand why we need change. Have upstream really introduced a breaking change for everybody who uses libfdt, or are we using it wrongly? Everybody who copies and changes a header from the original distribution and uses this now instead of the installed version ;-) libfdt (or better: dtc) seems to be quite out of date in the official distribution packages. I just happened to have git HEAD installed manually. Regards, Andre.
Re: [Qemu-devel] [PATCH] fdt: update embedded header file from upstream to fix compilation
On 05/07/2013 03:24 PM, Peter Maydell wrote: On 7 May 2013 13:52, Andre Przywara andre.przyw...@linaro.org wrote: On 05/07/2013 02:44 PM, Peter Maydell wrote: I'm not entirely sure I understand why we need change. Have upstream really introduced a breaking change for everybody who uses libfdt, or are we using it wrongly? Everybody who copies and changes a header from the original distribution and uses this now instead of the installed version ;-) Right, but the distro libfdt-dev package doesn't ship with libfdt_env.h, so presumably the expectation is that users of libfdt copy and adjust it, and so the set of things it has to provide is part of the public interface? Seems to be true for the CentOS package for instance, but not for Wheezy: http://packages.debian.org/wheezy/amd64/libfdt-dev/filelist Also make install on the source distribution copies the file to /usr/include. Even if I delete it, fdt.h still references fdt32_t, so I get the same error again. Regards, Andre.
[Qemu-devel] [PATCH] vnc-tls: Fix compilation with newer versions of GNU-TLS
In my installation of GNU-TLS (v3.0.23) the type gnutls_anon_server_credentials is marked deprecated, so -Werror breaks compilation. Simply replacing it with the newer ..._t version fixed the compilation on my machine (Slackware 14.0). I cannot tell how far back this new type goes, at least the header file in RHEL 5.0 (v1.4.1) seems to have it already. If someone finds a broken distribution, tell me and I insert some compat code. Signed-off-by: Andre Przywara andre.przyw...@amd.com --- ui/vnc-tls.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/vnc-tls.c b/ui/vnc-tls.c index a7f7d07..ba3827b 100644 --- a/ui/vnc-tls.c +++ b/ui/vnc-tls.c @@ -99,9 +99,9 @@ static ssize_t vnc_tls_pull(gnutls_transport_ptr_t transport, } -static gnutls_anon_server_credentials vnc_tls_initialize_anon_cred(void) +static gnutls_anon_server_credentials_t vnc_tls_initialize_anon_cred(void) { -gnutls_anon_server_credentials anon_cred; +gnutls_anon_server_credentials_t anon_cred; int ret; if ((ret = gnutls_anon_allocate_server_credentials(anon_cred)) 0) { @@ -382,7 +382,7 @@ int vnc_tls_client_setup(struct VncState *vs, } } else { -gnutls_anon_server_credentials anon_cred = vnc_tls_initialize_anon_cred(); +gnutls_anon_server_credentials_t anon_cred = vnc_tls_initialize_anon_cred(); if (!anon_cred) { gnutls_deinit(vs-tls.session); vs-tls.session = NULL; -- 1.7.12.1
Re: [Qemu-devel] [PATCH] i386/cpu: name new CPUID bits
On 10/18/12 18:33, Eduardo Habkost wrote: On Wed, Oct 17, 2012 at 11:17:26PM +0200, Andre Przywara wrote: Update QEMU's knowledge of CPUID bit names. This allows to enable/disable those new features on QEMU's command line when using KVM and prepares future feature enablement in QEMU. ... @@ -79,10 +79,10 @@ static const char *ext3_feature_name[] = { lahf_lm /* AMD LahfSahf */, cmp_legacy, svm, extapic /* AMD ExtApicSpace */, cr8legacy /* AMD AltMovCr8 */, abm, sse4a, misalignsse, 3dnowprefetch, osvw, ibs, xop, -skinit, wdt, NULL, NULL, -fma4, NULL, cvt16, nodeid_msr, -NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, +skinit, wdt, NULL, lwp, +fma4, tce, NULL, nodeid_msr, You removed cvt16, here. On purpose, cvt16 is dead. It seems to have been advertised in the documentation for some time, but later disappeared. The respective instructions are now reported via the F16C flag in the Intel leaf. If you want to know more, I can dig deeper and ask some people. But the bit is now reserved and was never '1' in any silicon. (And was introduced by me into QEMU :-( All the rest of the flags look OK to me. Thanks. Regards, Andre.
[Qemu-devel] [PATCH] i386/cpu: name new CPUID bits
Update QEMU's knowledge of CPUID bit names. This allows to enable/disable those new features on QEMU's command line when using KVM and prepares future feature enablement in QEMU. This adds F16C, RDRAND, LWP, TBM, TopoExt, PerfCtr_Core, PerfCtr_NB, FSGSBASE, BMI1, AVX2, BMI2, ERMS, InvPCID, RTM, RDSeed and ADX. Sources where the AMD BKDG for Family 15h/Model 10h and the Linux kernel for the leaf 7 bits. Signed-off-by: Andre Przywara andre.przyw...@amd.com --- target-i386/cpu.c | 16 target-i386/cpu.h | 21 + 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index f3708e6..49f9561 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -59,7 +59,7 @@ static const char *ext_feature_name[] = { NULL, pcid, dca, sse4.1|sse4_1, sse4.2|sse4_2, x2apic, movbe, popcnt, tsc-deadline, aes, xsave, osxsave, -avx, NULL, NULL, hypervisor, +avx, f16c, rdrand, hypervisor, }; /* Feature names that are already defined on feature_name[] but are set on * CPUID[8000_0001].EDX on AMD CPUs don't have their names on @@ -79,10 +79,10 @@ static const char *ext3_feature_name[] = { lahf_lm /* AMD LahfSahf */, cmp_legacy, svm, extapic /* AMD ExtApicSpace */, cr8legacy /* AMD AltMovCr8 */, abm, sse4a, misalignsse, 3dnowprefetch, osvw, ibs, xop, -skinit, wdt, NULL, NULL, -fma4, NULL, cvt16, nodeid_msr, -NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, +skinit, wdt, NULL, lwp, +fma4, tce, NULL, nodeid_msr, +NULL, tbm, topoext, perfctr_core, +perfctr_nb, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; @@ -105,9 +105,9 @@ static const char *svm_feature_name[] = { }; static const char *cpuid_7_0_ebx_feature_name[] = { -NULL, NULL, NULL, NULL, NULL, NULL, NULL, smep, -NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -NULL, NULL, NULL, NULL, smap, NULL, NULL, NULL, +fsgsbase, NULL, NULL, bmi1, hle, avx2, NULL, smep, +bmi2, erms, invpcid, rtm, NULL, NULL, NULL, NULL, +NULL, NULL, rdseed, adx, smap, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 871c270..e496b5b 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -403,6 +403,7 @@ #define CPUID_EXT_TM2 (1 8) #define CPUID_EXT_SSSE3(1 9) #define CPUID_EXT_CID (1 10) +#define CPUID_EXT_FMA (1 12) #define CPUID_EXT_CX16 (1 13) #define CPUID_EXT_XTPR (1 14) #define CPUID_EXT_PDCM (1 15) @@ -417,6 +418,8 @@ #define CPUID_EXT_XSAVE(1 26) #define CPUID_EXT_OSXSAVE (1 27) #define CPUID_EXT_AVX (1 28) +#define CPUID_EXT_F16C (1 29) +#define CPUID_EXT_RDRAND (1 30) #define CPUID_EXT_HYPERVISOR (1 31) #define CPUID_EXT2_FPU (1 0) @@ -472,7 +475,15 @@ #define CPUID_EXT3_IBS (1 10) #define CPUID_EXT3_XOP (1 11) #define CPUID_EXT3_SKINIT (1 12) +#define CPUID_EXT3_WDT (1 13) +#define CPUID_EXT3_LWP (1 15) #define CPUID_EXT3_FMA4(1 16) +#define CPUID_EXT3_TCE (1 17) +#define CPUID_EXT3_NODEID (1 19) +#define CPUID_EXT3_TBM (1 21) +#define CPUID_EXT3_TOPOEXT (1 22) +#define CPUID_EXT3_PERFCORE (1 23) +#define CPUID_EXT3_PERFNB (1 24) #define CPUID_SVM_NPT (1 0) #define CPUID_SVM_LBRV (1 1) @@ -485,7 +496,17 @@ #define CPUID_SVM_PAUSEFILTER (1 10) #define CPUID_SVM_PFTHRESHOLD (1 12) +#define CPUID_7_0_EBX_FSGSBASE (1 0) +#define CPUID_7_0_EBX_BMI1 (1 3) +#define CPUID_7_0_EBX_HLE (1 4) +#define CPUID_7_0_EBX_AVX2 (1 5) #define CPUID_7_0_EBX_SMEP (1 7) +#define CPUID_7_0_EBX_BMI2 (1 8) +#define CPUID_7_0_EBX_ERMS (1 9) +#define CPUID_7_0_EBX_INVPCID (1 10) +#define CPUID_7_0_EBX_RTM (1 11) +#define CPUID_7_0_EBX_RDSEED (1 18) +#define CPUID_7_0_EBX_ADX (1 19) #define CPUID_7_0_EBX_SMAP (1 20) #define CPUID_VENDOR_INTEL_1 0x756e6547 /* Genu */ -- 1.7.12.1
Re: [Qemu-devel] qemu -numa option and non-contiguous CPU ranges
On 06/21/2012 07:51 PM, Eduardo Habkost wrote: Hi, I just noticed libvirt tries to use the -numa option in a way that qemu never understood: if a node is configured to have a non-contiguous set of CPUs, it tries to generate a command-line option that looks like: -numa node,nodeid=...,cpus=0,2,4,mem=... ^ But this format was never supported by qemu. This format is even a bit weird, as , is an option separator, and it is being used as a separator _inside_ an option. Exactly this was the reason back then to not support non-contiguous set of CPUs. Inside qemu there is no reason why this shouldn't work, it was just hard to write on the command line. So after a short discussion we decided to drop this for the time being. If you have a great idea how to specify this (I think a comma will not work, because it will be catched earlier), I am all ears. Regards, Andre. My question is: should we support this option format in qemu, or should we change libvirt to use another format (that has yet to be implemented, because currently there's no way to specify a non-contiguous set of CPUs for a NUMA node). Any suggestions? -- Andre Przywara AMD-Operating System Research Center (OSRC), Dresden, Germany
Re: [Qemu-devel] Semantics of -cpu host (was Re: [PATCH 2/2] Expose tsc deadline timer cpuid to guest)
On 05/07/2012 08:21 PM, Eduardo Habkost wrote: Andre? Are you able to help to answer the question below? Sorry for the delay, the easy answers first: I would like to clarify what's the expected behavior of -cpu host to be able to continue working on it. The purpose of -cpu host is to let guests use ISA features that the host CPU provides. Those would not need any KVM/QEMU intervention, because they work out of the box. Things like AES or SSE4.2, which are used by Linux and glibc, for instance. Users would expect those to be usable, and actually we only need to set the bits and are done. A second goal is to get rid of the awkward and artificial family/model/stepping settings and just let the guest see the actual CPU model. This has some strings attached, though, but other virtualization solution do it the same way and they can cope with it. A third thing currently not really addressed are the more informational bits like cache size and organization and TLB layout. Those are properties of the (core) CPU (except shared L3, cache maybe) and apply to guests as well. I don't see any reason why this should not be exposed to the guest. From the top of my head I don't know any prominent user (just glibc reading the cache size, but not really using it), but I guess there are applications which benefit from it. What clearly is not the intention of -cpu host is to provide access to every feature a certain CPU model provides. So things which require emulation or hypervisor intervention are not in the primary use case. That does not mean that they don't need to implemented, but that was not the purpose of -cpu host and they should be handled independently. Regards, Andre. I believe the code will need to be fixed on either case, but first we need to figure out what are the expectations/requirements, to know _which_ changes will be needed. On Tue, Apr 24, 2012 at 02:19:25PM -0300, Eduardo Habkost wrote: (CCing Andre Przywara, in case he can help to clarify what's the expected meaning of -cpu host) [...] I am not sure I understand what you are proposing. Let me explain the use case I am thinking about: - Feature FOO is of type (A) (e.g. just a new instruction set that doesn't require additional userspace support) - User has a Qemu vesion that doesn't know anything about feature FOO - User gets a new CPU that supports feature FOO - User gets a new kernel that supports feature FOO (i.e. has FOO in GET_SUPPORTED_CPUID) - User does _not_ upgrade Qemu. - User expects to get feature FOO enabled if using -cpu host, without upgrading Qemu. The problem here is: to support the above use-case, userspace need a probing mechanism that can differentiate _new_ (previously unknown) features that are in group (A) (safe to blindly enable) from features that are in group (B) (that can't be enabled without an userspace upgrade). In short, it becomes a problem if we consider the following case: - Feature BAR is of type (B) (it can't be enabled without extra userspace support) - User has a Qemu version that doesn't know anything about feature BAR - User gets a new CPU that supports feature BAR - User gets a new kernel that supports feature BAR (i.e. has BAR in GET_SUPPORTED_CPUID) - User does _not_ upgrade Qemu. - User simply shouldn't get feature BAR enabled, even if using -cpu host, otherwise Qemu would break. If userspace always limited itself to features it knows about, it would be really easy to implement the feature without any new probing mechanism from the kernel. But that's not how I think users expect -cpu host to work. Maybe I am wrong, I don't know. I am CCing Andre, who introduced the -cpu host feature, in case he can explain what's the expected semantics on the cases above. -- Andre Przywara AMD-Operating System Research Center (OSRC), Dresden, Germany
Re: [Qemu-devel] [PATCH resend] vl.c: Don't limit node count by smp count
On 06/30/2011 05:29 AM, Sasha Levin wrote: [I've sent this patch couple of months ago and noticed it didn't make it's way in - so I'm sending it again] It is possible to create CPU-less NUMA nodes, node amount shouldn't be limited by amount of CPUs. Tested-by: Michael Rothmdr...@linux.vnet.ibm.com Signed-off-by: Sasha Levinlevinsasha...@gmail.com --- vl.c |4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vl.c b/vl.c index e0191e1..b95ae8d 100644 --- a/vl.c +++ b/vl.c @@ -3147,8 +3147,8 @@ int main(int argc, char **argv, char **envp) if (nb_numa_nodes 0) { int i; -if (nb_numa_nodes smp_cpus) { -nb_numa_nodes = smp_cpus; +if (nb_numa_nodes MAX_NODES) { +nb_numa_nodes = MAX_NODES; } /* If no memory size if given for any node, assume the default case Acked-by: Andre Przywara andre.przyw...@amd.com Regards, Andre. -- Andre Przywara AMD-Operating System Research Center (OSRC), Dresden, Germany
[Qemu-devel] Re: CPU type qemu64 breaks guest code
On 03/14/2011 03:13 PM, Alexander Graf wrote: Hi guys, While I was off on vacation a pretty nasty bug emerged. It's our old friend the non-existent -cpu qemu64 CPU type. To refresh your memories, this is the definition of the default 64-bit CPU type in Qemu: { .name = qemu64, .level = 4, .vendor1 = CPUID_VENDOR_AMD_1, .vendor2 = CPUID_VENDOR_AMD_2, .vendor3 = CPUID_VENDOR_AMD_3, .family = 6, .model = 2, .stepping = 3, ... Well, yes, this is strange, and a different CPU model mimicking some really existing CPU would be better. But in my experience this opens up a can of worms, since a different family will trigger a lot of other nasty code that was silent before. Although I think that eventually we will not get around it doing so, but we should use a lot of testing before triggering tons of regressions. What about the kvm64 CPU model? Back then I used quite some testing to find a model which runs pretty well, so I came up with 15/6/1, which seemed to be relatively sane. We could try copying this F/M/S over to qemu64, I suppose with emulation the issues are easier to fix than in KVM. Another idea I think I already posted some time ago was to make kvm64 the new default if KVM is enabled. This wouldn't solve the above issue for TCG of course, but would make further development easier, since we would have a better separation between KVM and TCG and could tweak each independently. Before I left, we already had weird build breakages where gcc simply abort()ed when running inside of KVM. This breakage has been tracked down to libgmp, which has this code (http://gmplib.org:8000/gmp-5.0/file/1ebe39104437/mpn/x86_64/fat/fat.c): if (strcmp (vendor_string, GenuineIntel) == 0) { } else if (strcmp (vendor_string, AuthenticAMD) == 0) { switch (family) { case 5: case 6: abort (); break; case 15: /* CPUVEC_SETUP_athlon */ break; } The reasoning behind it is that for AMD, all 64-bit CPUs were family 15. I guess that should be fixed there, as it is obviously nonsense. I haven't check what they actually need that family 6 does not provide, if it is long mode, then this bit should be checked. This breakage is obviously pretty bad for guests running qemu and shows once again that deriving from real hardware is a bad idea. I guess the best way to move forward is to change the CPU type to something that actually exists in the real world - even if we have to strip off some features. I found that there is no valid combination for both Intel and AMD. We had to go to family 15, and it seems that there is no F/M/S combination that were both a valid K8 and a Pentium4 processor. The 15/6/1 mentioned before was the closest match I could find. Summarizing I would suggest: 1) Make kvm64 the new default model if KVM is used. Maybe we could tie this to the qemu-0.15 machine type. 2) Test as many OSes as possible whether they show strange behavior. In my experience we could catch most of the stuff with just booting the system, with Linux -kernel vmlinuz suffices (without a rootfs). 3) If we are happy with that, tweak the qemu64 model to those values, too. 4) Write some note somewhere to let users know what they could do to fix problems that rise due to the new model. I can easily send patches and will try to contribute to testing, if that plan sounds OK. -- Andre Przywara AMD-Operating System Research Center (OSRC), Dresden, Germany
[Qemu-devel] Re: [PATCH] kvm/x86: enlarge number of possible CPUID leaves
Avi, Marcello, can you please commit this simple fix? (turning 40 to 80?) Without it QEMU crashes reliably on our new CPUs (they return 46 leaves) and causes pain in our testing, because we have to manually apply this patch on each tree. Thanks! Andre. Currently the number of CPUID leaves KVM handles is limited to 40. My desktop machine (AthlonII) already has 35 and future CPUs will expand this well beyond the limit. Extend the limit to 80 to make room for future processors. Signed-off-by: Andre Przywara andre.przyw...@amd.com --- arch/x86/include/asm/kvm_host.h |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) Hi, I found that either KVM or QEMU (possibly both) are broken in respect to handling more CPUID entries than the limit dictates. KVM will return -E2BIG, which is the same error as if the user hasn't provided enough space to hold all entries. Now QEMU will continue to enlarge the allocated memory until it gets into an out-of-memory condition. I have tried to fix this with teaching KVM how to deal with a capped number of entries (there are some bugs in the current code), but this will limit the number of CPUID entries KVM handles, which will surely cut of the lastly appended PV leaves. A proper fix would be to make this allocation dynamic. Is this a feasible way or will this lead to issues or side-effects? Regards, Andre. diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 54e42c8..3cc80c4 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -79,7 +79,7 @@ #define KVM_NUM_MMU_PAGES (1 KVM_MMU_HASH_SHIFT) #define KVM_MIN_FREE_MMU_PAGES 5 #define KVM_REFILL_PAGES 25 -#define KVM_MAX_CPUID_ENTRIES 40 +#define KVM_MAX_CPUID_ENTRIES 80 #define KVM_NR_FIXED_MTRR_REGION 88 #define KVM_NR_VAR_MTRR 8
[Qemu-devel] [PATCH] kvm/x86: enlarge number of possible CPUID leaves
Currently the number of CPUID leaves KVM handles is limited to 40. My desktop machine (AthlonII) already has 35 and future CPUs will expand this well beyond the limit. Extend the limit to 80 to make room for future processors. Signed-off-by: Andre Przywara andre.przyw...@amd.com --- arch/x86/include/asm/kvm_host.h |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) Hi, I found that either KVM or QEMU (possibly both) are broken in respect to handling more CPUID entries than the limit dictates. KVM will return -E2BIG, which is the same error as if the user hasn't provided enough space to hold all entries. Now QEMU will continue to enlarge the allocated memory until it gets into an out-of-memory condition. I have tried to fix this with teaching KVM how to deal with a capped number of entries (there are some bugs in the current code), but this will limit the number of CPUID entries KVM handles, which will surely cut of the lastly appended PV leaves. A proper fix would be to make this allocation dynamic. Is this a feasible way or will this lead to issues or side-effects? Regards, Andre. diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 54e42c8..3cc80c4 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -79,7 +79,7 @@ #define KVM_NUM_MMU_PAGES (1 KVM_MMU_HASH_SHIFT) #define KVM_MIN_FREE_MMU_PAGES 5 #define KVM_REFILL_PAGES 25 -#define KVM_MAX_CPUID_ENTRIES 40 +#define KVM_MAX_CPUID_ENTRIES 80 #define KVM_NR_FIXED_MTRR_REGION 88 #define KVM_NR_VAR_MTRR 8 -- 1.6.4
[Qemu-devel] Re: [PATCH] kvm/x86: enlarge number of possible CPUID leaves
Avi Kivity wrote: On 12/01/2010 01:17 PM, Andre Przywara wrote: Currently the number of CPUID leaves KVM handles is limited to 40. My desktop machine (AthlonII) already has 35 and future CPUs will expand this well beyond the limit. Extend the limit to 80 to make room for future processors. Signed-off-by: Andre Przywaraandre.przyw...@amd.com --- arch/x86/include/asm/kvm_host.h |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) Hi, I found that either KVM or QEMU (possibly both) are broken in respect to handling more CPUID entries than the limit dictates. KVM will return -E2BIG, which is the same error as if the user hasn't provided enough space to hold all entries. Now QEMU will continue to enlarge the allocated memory until it gets into an out-of-memory condition. I have tried to fix this with teaching KVM how to deal with a capped number of entries (there are some bugs in the current code), but this will limit the number of CPUID entries KVM handles, which will surely cut of the lastly appended PV leaves. A proper fix would be to make this allocation dynamic. Is this a feasible way or will this lead to issues or side-effects? Well, there has to be some limit, or userspace can allocate unbounded kernel memory. But this limit should not be a compile-time constant, but a runtime one. The needed size depends on the host CPU (plus the KVM PV leaves) and thus could be determined once for all VMs and vCPUs at module load-time. But then we cannot use the static array allocation we currently have in struct kvm_vcpu_arch: struct kvm_cpuid_entry2 cpuid_entries[KVM_MAX_CPUID_ENTRIES]; So we would use a kind-of dynamic allocation bounded by the host CPU's need. But for the code is does not make much difference to a real dynamic allocation. Also we could implement kvm_dev_ioctl_get_supported_cpuid without the vmalloc, if we don't care about some dozens of copy_to_user() calls in this function. Then we would not need this limit in GET_SUPPORTED_CPUID at all, but it will strike us again at KVM_SET_CPUID[2], where we may not fulfill the promises we gave earlier. Having said this, what about that: kvm_dev_ioctl_get_supported_cpuid is invariant to the VM or vCPU (as it is used by a system ioctl), so it could be run once at initialization, which would limit the ioctl implementation to a plain bounded copy. Would you want such a patch (removing the vmalloc and maybe even the limit)? Regards, Andre. -- Andre Przywara AMD-OSRC (Dresden) Tel: x29712
Re: [Qemu-devel] New Bitmap module ?
Corentin Chary wrote: Hi, I was working on merging VNC updates into bigger ones to see if it lower the overhead (big updates sometime use less network/cpu than a lot of small updates). For that, I needed some new bitmap functions, and no we got, in vnc.c: - set_bit - clear_bit - set_bits - clear_bits - find_next_bit - find_next_zero_bit - find_next_zero_area Should we move that into bitmap.c/bitmap.h ? Definitely! For my NUMA work I have also coded some bitmap functions. Since mine are not performance critical, I reverted from implementing set_bits and clear_bits and replaced them with a loop in the calling code. So I could just could come around with a macro only implementation, for which a header file suffices (attached for reference). Which part of QEMU could use that (block.c maybe ?) As mentioned, the yet to be submitted NUMA code would benefit from it. Linux has also bitmap code, maybe you could leverage this (if not already done). Regards, Andre. -- Andre Przywara AMD-Operating System Research Center (OSRC), Dresden, Germany Tel: +49 351 448-3567-12 #ifndef __BITMAP_H__ #define __BITMAP_H__ #ifndef HOST_LONG_BITS #define HOST_LONG_BITS (sizeof(long) * 8) #endif #define bitmap_isset(bm,bit) \ (!!bm[(bit) / HOST_LONG_BITS] (1ULL ((bit) % HOST_LONG_BITS))) #define bitmap_set(bm,bit) \ (bm[(bit) / HOST_LONG_BITS] |= (1ULL ((bit) % HOST_LONG_BITS))) #define bitmap_unset(bm,bit) \ (bm[(bit) / HOST_LONG_BITS] = ~(1ULL ((bit) % HOST_LONG_BITS))) #define DECLARE_BITMAP(bm,len) \ unsigned long bm[((len) + HOST_LONG_BITS - 1) / HOST_LONG_BITS] #define bitmap_clear(bm,len) \ memset(bm, 0, (len + 7) / 8) #define bitmap_fill(bm,len) \ memset(bm, 0xFF, (len + 7) / 8) #endif
[Qemu-devel] Using Linux's CPUSET for KVM VCPUs
Hi all, while working on NUMA host pinning, I experimented with vCPU affinity within QEMU, but left it alone as it would complicate the code and would not achieve better experience than using taskset with the monitor provided thread ids like it is done currently. During that I looked at Linux' CPUSET implementation (/src/linux-2.6/Documentation/cgroups/cpusets.txt). In brief, this is a pseudo file system based, truly hierarchical implementation of restricting a set of processes (or threads, it uses PIDs) to a certain subset of the machine. Sadly we cannot leverage this for true guest NUMA memory assignment, but it would work nice for pinning (or not) guest vCPUs. I had the following structure in mind: For each guest there is a new CPUSET (mkdir $CPUSET_MNT/`cat /proc/$$/cpuset`/kvm_$guestname). One could then assign the guest global resources to this CPUSET. For each vCPU there is a separate CPUSET located under this guest global one. This would allow for easy manipulation of the pinning of vCPUs, even from the console without any mgt app (although this could be easily implemented in libvirt). / | +--/ kvm_guest_01 | | | +-- VCPU0 | | | +-- VCPU1 | +--/ kvm_guest_02 ... What do you think about it? It is worth implementing this? Regards, Andre. -- Andre Przywara AMD-Operating System Research Center (OSRC), Dresden, Germany Tel: +49 351 448-3567-12
Re: [Qemu-devel] [PATCH] resent: x86/cpuid: propagate further CPUID leafs when -cpu host
Anthony Liguori wrote: On 05/25/2010 08:21 AM, Andre Przywara wrote: What's the benefit of exposing this information to the guest? That is mostly to propagate the cache size and organization parameters to the guest: +/* safe CPUID leafs to propagate to guest if -cpu host is specified + * Intel defined leafs: + * Cache descriptors (0x02) + * Deterministic cache parameters (0x04) + * Monitor/MWAIT parameters (0x05) + * + * AMD defined leafs: + * L1 Cache and TLB (0x05) + * L2+L3 TLB (0x06) + * LongMode address size (0x08) + * 1GB page TLB (0x19) + * Performance optimization (0x1A) + */ Since at least L1 and L2 caches are mostly private to vCPUs, I see no reason to disguise them. But in practice, what is it useful for? Just because we can expose it doesn't mean we should. Beside the obvious high performance libraries (like the AMD ACML) also JVMs (and probably other managed code runtimes) use the cache information for optimization. Given the fact that we have a fairly large range of actual L2 cache sizes (from 256KB to 6MB on Intel) the fixed cache size that QEMU reports (1MB) is quite a bit off most of the times. -cpu host is targeted to give the best performance to the user, with the drawback of missing or very limited migration experience. So we should expose as many features as possible. Regards, Andre. -- Andre Przywara AMD-Operating System Research Center (OSRC), Dresden, Germany Tel: +49 351 448-3567-12
Re: [Qemu-devel] [PATCH] resent: x86/cpuid: propagate further CPUID leafs when -cpu host
Anthony Liguori wrote: On 05/21/2010 02:50 AM, Andre Przywara wrote: -cpu host currently only propagates the CPU's family/model/stepping, the brand name and the feature bits. Add a whitelist of safe CPUID leafs to let the guest see the actual CPU's cache details and other things. Signed-off-by: Andre Przywaraandre.przyw...@amd.com The problem I can see is that this greatly increases the chances of problems with live migration since we don't migrate the cpuid state. I think that should be fixed. Although -cpu host is not a wise choice for migration, even without these additional leaves the feature bits probably don't match between source and target. What's the benefit of exposing this information to the guest? That is mostly to propagate the cache size and organization parameters to the guest: +/* safe CPUID leafs to propagate to guest if -cpu host is specified + * Intel defined leafs: + * Cache descriptors (0x02) + * Deterministic cache parameters (0x04) + * Monitor/MWAIT parameters (0x05) + * + * AMD defined leafs: + * L1 Cache and TLB (0x05) + * L2+L3 TLB (0x06) + * LongMode address size (0x08) + * 1GB page TLB (0x19) + * Performance optimization (0x1A) + */ Since at least L1 and L2 caches are mostly private to vCPUs, I see no reason to disguise them. Regards, Andre. -- Andre Przywara AMD-Operating System Research Center (OSRC), Dresden, Germany Tel: +49 351 448-3567-12
[Qemu-devel] [PATCH] resent: fix CPUID vendor override
the meaning of vendor_override is actually the opposite of how it is currently used :-( Fix it to allow KVM to export the non-native CPUID vendor if explicitly requested by the user. The semantic is now as intended: - With TCG, the guest always sees the configured vendor. - With KVM, the default is to propagate the host's vendor - when explicitly requested via -cpu base,vendor=xxx obey this and use the specified vendor Signed-off-by: Andre Przywara andre.przyw...@amd.com --- target-i386/cpuid.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) Hi, this hasn't been picked up the last time I sent it out, are there any objections? Regards, Andre. diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c index 56938e2..99d1f44 100644 --- a/target-i386/cpuid.c +++ b/target-i386/cpuid.c @@ -962,7 +962,7 @@ static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx, * this if you want to use KVM's sysenter/syscall emulation * in compatibility mode and when doing cross vendor migration */ -if (kvm_enabled() env-cpuid_vendor_override) { +if (kvm_enabled() ! env-cpuid_vendor_override) { host_cpuid(0, 0, NULL, ebx, ecx, edx); } } -- 1.6.4
[Qemu-devel] [PATCH] resent: x86/cpuid: Add kvm32 CPU model
Create a kvm32 CPU model that describes a least common denominator for KVM capable guest CPUs. Useful for migration purposes. Signed-off-by: Andre Przywara andre.przyw...@amd.com --- target-i386/cpuid.c | 14 ++ 1 files changed, 14 insertions(+), 0 deletions(-) diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c index a80baa4..76b897d 100644 --- a/target-i386/cpuid.c +++ b/target-i386/cpuid.c @@ -363,6 +363,20 @@ static x86_def_t builtin_x86_defs[] = { .model_id = QEMU Virtual CPU version QEMU_VERSION, }, { +.name = kvm32, +.level = 5, +.family = 15, +.model = 6, +.stepping = 1, +.features = PPRO_FEATURES | +CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36, +.ext_features = CPUID_EXT_SSE3, +.ext2_features = PPRO_FEATURES EXT2_FEATURE_MASK, +.ext3_features = 0, +.xlevel = 0x8008, +.model_id = Common 32-bit KVM processor +}, +{ .name = coreduo, .level = 10, .family = 6, -- 1.6.4
[Qemu-devel] [PATCH] resent: x86/cpuid: propagate further CPUID leafs when -cpu host
-cpu host currently only propagates the CPU's family/model/stepping, the brand name and the feature bits. Add a whitelist of safe CPUID leafs to let the guest see the actual CPU's cache details and other things. Signed-off-by: Andre Przywara andre.przyw...@amd.com --- target-i386/cpu.h |6 +- target-i386/cpuid.c | 45 + 2 files changed, 42 insertions(+), 9 deletions(-) Again this patch was not yet applied, without any discussion I can remember. Please apply. Thanks, Andre. diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 548ab80..77cbbdb 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -581,6 +581,10 @@ typedef struct { #define NB_MMU_MODES 2 +#define CPUID_FLAGS_BUILTIN (1 0) +#define CPUID_FLAGS_VENDOR_OVERRIDE (1 1) +#define CPUID_FLAGS_HOST (1 2) + typedef struct CPUX86State { /* standard registers */ target_ulong regs[CPU_NB_REGS]; @@ -685,7 +689,7 @@ typedef struct CPUX86State { uint32_t cpuid_ext2_features; uint32_t cpuid_ext3_features; uint32_t cpuid_apic_id; -int cpuid_vendor_override; +uint32_t cpuid_flags; /* MTRRs */ uint64_t mtrr_fixed[11]; diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c index 99d1f44..a80baa4 100644 --- a/target-i386/cpuid.c +++ b/target-i386/cpuid.c @@ -213,7 +213,6 @@ typedef struct x86_def_t { uint32_t features, ext_features, ext2_features, ext3_features, kvm_features; uint32_t xlevel; char model_id[48]; -int vendor_override; uint32_t flags; } x86_def_t; @@ -489,7 +488,7 @@ static int cpu_x86_fill_host(x86_def_t *x86_cpu_def) x86_cpu_def-ext2_features = edx; x86_cpu_def-ext3_features = ecx; cpu_x86_fill_model_id(x86_cpu_def-model_id); -x86_cpu_def-vendor_override = 0; +x86_cpu_def-flags = CPUID_FLAGS_HOST; return 0; } @@ -633,7 +632,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) x86_cpu_def-vendor2 |= ((uint8_t)val[i + 4]) (8 * i); x86_cpu_def-vendor3 |= ((uint8_t)val[i + 8]) (8 * i); } -x86_cpu_def-vendor_override = 1; +x86_cpu_def-flags |= CPUID_FLAGS_VENDOR_OVERRIDE; } else if (!strcmp(featurestr, model_id)) { pstrcpy(x86_cpu_def-model_id, sizeof(x86_cpu_def-model_id), val); @@ -731,7 +730,8 @@ void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...), return; } for (def = x86_defs; def; def = def-next) { -snprintf(buf, sizeof (buf), def-flags ? [%s]: %s, def-name); +snprintf(buf, sizeof (buf), + def-flags CPUID_FLAGS_BUILTIN ? [%s]: %s, def-name); if (model || dump) { (*cpu_fprintf)(f, x86 %16s %-48s\n, buf, def-model_id); } else { @@ -785,7 +785,7 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model) env-cpuid_vendor2 = CPUID_VENDOR_INTEL_2; env-cpuid_vendor3 = CPUID_VENDOR_INTEL_3; } -env-cpuid_vendor_override = def-vendor_override; +env-cpuid_flags = def-flags; env-cpuid_level = def-level; if (def-family 0x0f) env-cpuid_version = 0xf00 | ((def-family - 0x0f) 20); @@ -941,7 +941,7 @@ void x86_cpudef_setup(void) for (i = 0; i ARRAY_SIZE(builtin_x86_defs); ++i) { builtin_x86_defs[i].next = x86_defs; -builtin_x86_defs[i].flags = 1; +builtin_x86_defs[i].flags |= CPUID_FLAGS_BUILTIN; x86_defs = builtin_x86_defs[i]; } #if !defined(CONFIG_USER_ONLY) @@ -962,22 +962,51 @@ static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx, * this if you want to use KVM's sysenter/syscall emulation * in compatibility mode and when doing cross vendor migration */ -if (kvm_enabled() ! env-cpuid_vendor_override) { +if (kvm_enabled() +(env-cpuid_flags CPUID_FLAGS_VENDOR_OVERRIDE) == 0) { host_cpuid(0, 0, NULL, ebx, ecx, edx); } } +/* safe CPUID leafs to propagate to guest if -cpu host is specified + * Intel defined leafs: + * Cache descriptors (0x02) + * Deterministic cache parameters (0x04) + * Monitor/MWAIT parameters (0x05) + */ +#define CPUID_LEAF_PROPAGATE ((1 0x02) | (1 0x04) | (1 0x05)) + +/* AMD defined leafs: + * L1 Cache and TLB (0x05) + * L2+L3 TLB (0x06) + * LongMode address size (0x08) + * 1GB page TLB (0x19) + * Performance optimization (0x1A) + */ +#define CPUID_LEAF_PROPAGATE_EXTENDED ((1 0x05) | (1 0x06) |\ + (1 0x08) | (1 0x19) | (1 0x1A)) + void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { -/* test if maximum index reached */ if (index 0x8000) { +/* test if maximum index reached */ if (index env
[Qemu-devel] [Bug 267542] Re: MINIX 3 won't boot in qemu 0.9.1
Is that still a problem? What was the exact error? I quickly tried the 3.1.2a on qemu 0.12.4 (with and without KVM) and I could easily login. ** Changed in: qemu Status: New = Incomplete -- MINIX 3 won't boot in qemu 0.9.1 https://bugs.launchpad.net/bugs/267542 You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. Status in QEMU: Incomplete Bug description: CD Image 3.1.2a was downloaded from http://www.minix3.org/download/ It booted with previous version of qemu but hangs at startup with 0.9.1. Hardware acceleration is disabled. Please ask if there is other information I can give you.
Re: [Qemu-devel] [RFC] Bug Day - June 1st, 2010
Michael Tokarev wrote: 20.05.2010 02:30, Anthony Liguori wrote: On 05/19/2010 05:29 PM, Andre Przywara wrote: Michael Tokarev wrote: ... Also, thanks to Andre Przywara, whole winNT thing works but it requires -cpu qemu64,level=1 (or level=2 or =3), -- _not_ with default CPU. This [] It'd be nice if we had more flexibility in defining custom machine types so you could just do qemu -M win98. This is wrong IMHO. win98 and winNT can run on various different machines, including all modern ones (yes I tried the same winNT on my Athlon X2-64, just had to switch SATA from AHCI to IDE; win95 works too)... just not in kvm :) Well, not really. You were lucky with your Athlon X2-64, actually it is the last machine not triggering the bug. I tried it on a AthlonII-X4 (which has maxleaf=5 as any newer AMD machines) and it showed the same bug. On Intel boxes this bug should trigger on every CPU starting with some Pentium4 models, including all Core chips. Have you tried versions with a newer service pack (SP6)? BTW: Does anyone knows what the problem with Windows95/98 on KVM is? I tried some tracing today, but couldn't find a hint. Um. The bugreport(s) come as a surprize for me: I tried to install win98 in kvm several times in the past but setup always failed - different messages in different versions of kvm, either unable to emulate or real mode trap or something else, or just lockup, usually on first reboot. So - the bugreports talks about mouse non-working, but this means win98 itself works somehow... I dunno :) I think these bug reports are about plain QEMU. I tried it yesterday, in fact the mouse is non-functional. In KVM Windows95 gives me a black screen after the welcome screen with the moving bottom row. There are just two lines at the top: (translated from the german version) While initializing device NTKERN: Windows protection fault. Restart the computer. KVM catched some #UDs due to ARPL from VM86 mode, but TCG got them too and it survived. So if anyone has some more hints, I'd be grateful. Regards, Andre. -- Andre Przywara AMD-Operating System Research Center (OSRC), Dresden, Germany Tel: +49 351 448-3567-12
Re: [Qemu-devel] [RFC] Bug Day - June 1st, 2010
Michael Tokarev wrote: ... Also, thanks to Andre Przywara, whole winNT thing works but it requires -cpu qemu64,level=1 (or level=2 or =3), -- _not_ with default CPU. This is also testing, but it's not obvious what to do witht the result... Can't we use the file based CPU models for that? Actually it looks like a template config file for certain guest operation systems (like -vga std -net nic,model=ne2k_pci for older Windows version) make sense. These could include all quirks that we find on the way. BTW: Does anyone knows what the problem with Windows95/98 on KVM is? I tried some tracing today, but couldn't find a hint. Regards, Andre. -- Andre Przywara AMD-Operating System Research Center (OSRC), Dresden, Germany Tel: +49 351 488-3567-12
Re: [Qemu-devel] Re: [PATCH][STABLE] fix CPUID vendor override
Aurelien Jarno wrote: On Sun, Apr 11, 2010 at 09:49:40PM +0200, Andre Przywara wrote: Avi Kivity wrote: On 04/11/2010 10:21 PM, Andre Przywara wrote: the meaning of vendor_override is actually the opposite of how it is currently used :-( Fix it to allow KVM to export the non-native CPUID vendor if explicitly requested by the user. Signed-off-by: Andre Przywaraandre.przyw...@amd.com --- target-i386/helper.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) I will send a refactoring patch including this fix for git HEAD later. Regards, Andre. diff --git a/target-i386/helper.c b/target-i386/helper.c index 9d7fec3..c17adc1 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1655,7 +1655,7 @@ static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx, * this if you want to use KVM's sysenter/syscall emulation * in compatibility mode and when doing cross vendor migration */ -if (kvm_enabled() env-cpuid_vendor_override) { +if (kvm_enabled() ! env-cpuid_vendor_override) { host_cpuid(0, 0, NULL, ebx, ecx, edx); } } Why is the original code wrong? I would say vendor_override means overriding the qemu-picked vendor ID in favour of the host cpuid. I meant it to mean: override the automatically chosen vendor ID (which is the host ID in case of KVM). I think the reason for KVM to use the host ID is valid, so I wanted to have an explicit override only if the user says so. If you look at the code, you will see that it is initialized to 0 and only set to 1 if one specifies an explicit vendor ID on the command line. Honestly I cannot say how this bug slipped through, I can only guess that I tricked myself while making the final version of the patch (lost-in-branches(TM)) While it clearly fixes the -cpu vendor option when kvm is enabled, it also forces the vendor id to the one of the host. Try for example -cpu qemu64. Before your patch the vendor id is Authentic AMD and after your patch it is Genuine Intel You are using the wrong CPU ;-) This is actually correct for KVM. (or are you seeing this with TCG?) To make sure we are actually talk about the same problem, the intended behavior is: With TCG: - always inject the configured vendor (either hard-coded, in config files or via ,vendor= commandline) With KVM: - by default inject the host's vendor - if the user specifies ,vendor= on the commandline, use this instead of the host's vendor - all pre-configured vendors (hard-coded, config file) are ignored The reason KVM is injecting the host's vendor is the following: There is a nasty difference between AMD and Intel chips in supporting syscall and sysenter in _compat_ mode (that is: running a 32bit binary while the OS is running 64bit). This mode is 99% compatible with the legacy protected mode, but AMD does not support sysenter here and Intel does not support syscall. So for instance the Linux kernel checks the vendor id and tells the userspace to use the supported instruction. On TCG we don't care as we properly emulate both(?), but on KVM the instruction is called natively. This leads to a crash (#UD exception) if the wrong vendor is used. So a long time ago the workaround of always propagating the host vendor was introduced. Later last year I introduced emulation of the missing instructions, so to overcome the former limitation (and allow for more hacking with KVM) I introduced the vendor override. Sadly my patch was broken (I used a slightly different version for development), that's why this fix. qemu-kvm had an additional fix to kind of work-around this bug. Hope that clarifies the issue, if you meant something else, tell me. Regards, Andre. -- Andre Przywara AMD-Operating System Research Center (OSRC), Dresden, Germany Tel: +49 351 488-3567-12
[Qemu-devel] Re: [PATCH][STABLE] fix CPUID vendor override
Avi Kivity wrote: On 04/11/2010 10:21 PM, Andre Przywara wrote: the meaning of vendor_override is actually the opposite of how it is currently used :-( Fix it to allow KVM to export the non-native CPUID vendor if explicitly requested by the user. Signed-off-by: Andre Przywaraandre.przyw...@amd.com --- target-i386/helper.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) I will send a refactoring patch including this fix for git HEAD later. The protocol is to first fix HEAD, then backport, so we don't introduce regressions inadvertently. Well, I just followed the call for 0.12.4. Actually this is the backport, one cannot easily cherry-pick the upstream patch, because it is in a different file now. I will send the (separated) upstream patch in a few minutes. Feel free to apply them in whatever order you prefer ;-) Regards, Andre. P.S. I also have a qemu-kvm patch in the queue (because there was a separate workaround for this bug). -- Andre Przywara AMD-Operating System Research Center (OSRC), Dresden, Germany Tel: +49 351 488-3567-12
[Qemu-devel] [PATCH][STABLE] fix CPUID vendor override
the meaning of vendor_override is actually the opposite of how it is currently used :-( Fix it to allow KVM to export the non-native CPUID vendor if explicitly requested by the user. Signed-off-by: Andre Przywara andre.przyw...@amd.com --- target-i386/helper.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) I will send a refactoring patch including this fix for git HEAD later. Regards, Andre. diff --git a/target-i386/helper.c b/target-i386/helper.c index 9d7fec3..c17adc1 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1655,7 +1655,7 @@ static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx, * this if you want to use KVM's sysenter/syscall emulation * in compatibility mode and when doing cross vendor migration */ -if (kvm_enabled() env-cpuid_vendor_override) { +if (kvm_enabled() ! env-cpuid_vendor_override) { host_cpuid(0, 0, NULL, ebx, ecx, edx); } } -- 1.6.4
[Qemu-devel] Re: [PATCH][STABLE] fix CPUID vendor override
Avi Kivity wrote: On 04/11/2010 10:21 PM, Andre Przywara wrote: the meaning of vendor_override is actually the opposite of how it is currently used :-( Fix it to allow KVM to export the non-native CPUID vendor if explicitly requested by the user. Signed-off-by: Andre Przywaraandre.przyw...@amd.com --- target-i386/helper.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) I will send a refactoring patch including this fix for git HEAD later. Regards, Andre. diff --git a/target-i386/helper.c b/target-i386/helper.c index 9d7fec3..c17adc1 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1655,7 +1655,7 @@ static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx, * this if you want to use KVM's sysenter/syscall emulation * in compatibility mode and when doing cross vendor migration */ -if (kvm_enabled() env-cpuid_vendor_override) { +if (kvm_enabled() ! env-cpuid_vendor_override) { host_cpuid(0, 0, NULL, ebx, ecx, edx); } } Why is the original code wrong? I would say vendor_override means overriding the qemu-picked vendor ID in favour of the host cpuid. I meant it to mean: override the automatically chosen vendor ID (which is the host ID in case of KVM). I think the reason for KVM to use the host ID is valid, so I wanted to have an explicit override only if the user says so. If you look at the code, you will see that it is initialized to 0 and only set to 1 if one specifies an explicit vendor ID on the command line. Honestly I cannot say how this bug slipped through, I can only guess that I tricked myself while making the final version of the patch (lost-in-branches(TM)) Regards, Andre. -- Andre Przywara AMD-Operating System Research Center (OSRC), Dresden, Germany Tel: +49 351 488-3567-12
[Qemu-devel] [PATCH] x86/cpuid: Add kvm32 CPU model
Create a kvm32 CPU model that describes a least common denominator for KVM capable guest CPUs. Useful for migration purposes. Signed-off-by: Andre Przywara andre.przyw...@amd.com --- target-i386/cpuid.c | 14 ++ 1 files changed, 14 insertions(+), 0 deletions(-) diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c index a80baa4..76b897d 100644 --- a/target-i386/cpuid.c +++ b/target-i386/cpuid.c @@ -363,6 +363,20 @@ static x86_def_t builtin_x86_defs[] = { .model_id = QEMU Virtual CPU version QEMU_VERSION, }, { +.name = kvm32, +.level = 5, +.family = 15, +.model = 6, +.stepping = 1, +.features = PPRO_FEATURES | +CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36, +.ext_features = CPUID_EXT_SSE3, +.ext2_features = PPRO_FEATURES EXT2_FEATURE_MASK, +.ext3_features = 0, +.xlevel = 0x8008, +.model_id = Common 32-bit KVM processor +}, +{ .name = coreduo, .level = 10, .family = 6, -- 1.6.4
[Qemu-devel] tainted Linux kernel in default SMP QEMU/KVM guests
Hi, since the default CPU model for QEMU (qemu64) is an AMD K7, the Linux kernel complains and taints the kernel when it detects multiple processors. The reason for this is a check for SMP safe CPUs in arch/x86/kernel/cpu/amd.c:amd_k7_smp_check(). In recent kernels (since about 2.6.29) this in only executed in 32bit kernels, since the check has been #ifdef'ed CONFIG_X86_32. The failing check triggers a nasty dump along with a call trace and taints the kernel, this confuses users, so I want to get rid of it. One can work around it (using -cpu kvm64 or -cpu host), but I want to avoid it in the default case, too. I see these possible solutions: 1) Change the default CPUID bits from 6/2/3 to 6/6/1, this passes the Linux kernel check. But I am not sure if that would introduce regressions, since some OSes apply quirks if they detect certain models (like we had with the sysenter issue in the past) 2) Only change the CPUID bits to 6/6/1 if we use SMP. Still has the above drawback, but would be limited to SMP guests only. 3) Set kvm64/kvm32 as the default CPU model if KVM is enabled. This would limit the report and taint to TCG, where SMP is rarely used. Additionally less people (if any) use it for production systems. 4) Make the Linux' kernel quirk dependent on the missing hypervisor bit. I don't think this will be accepted easily upstream (and I don't want to support Ingo's recent ideas ;-), also this would not fix older kernels. I can easily provide patches for all solutions, but I'd like to get advice from people on which one to pursue. Regards, Andre. -- Andre Przywara AMD-Operating System Research Center (OSRC), Dresden, Germany Tel: +49 351 448-3567-12
[Qemu-devel] [PATCH 03/13] x86/cpuid: fix missing feature set bits
This one was accidently removed with commit bb0300dc57c10b3721451b0ff566a03f9276cc77 Signed-off-by: Andre Przywara andre.przyw...@amd.com --- target-i386/cpuid.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c index 5e4f057..1bceb4b 100644 --- a/target-i386/cpuid.c +++ b/target-i386/cpuid.c @@ -754,6 +754,7 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model) env-pat = 0x0007040600070406ULL; env-cpuid_ext_features = def-ext_features; env-cpuid_ext2_features = def-ext2_features; +env-cpuid_ext3_features = def-ext3_features; env-cpuid_xlevel = def-xlevel; env-cpuid_kvm_features = def-kvm_features; { -- 1.6.4