[kvm-unit-tests PATCH 14/32] powerpc: general interrupt tests
Thomas Huth
thuth at redhat.com
Fri Mar 1 23:41:22 AEDT 2024
On 26/02/2024 11.12, Nicholas Piggin wrote:
> Add basic testing of various kinds of interrupts, machine check,
> page fault, illegal, decrementer, trace, syscall, etc.
>
> This has a known failure on QEMU TCG pseries machines where MSR[ME]
> can be incorrectly set to 0.
Two questions out of curiosity:
Any chance that this could be fixed easily in QEMU?
Or is there a way to detect TCG from within the test? (for example, we have
a host_is_tcg() function for s390x so we can e.g. use report_xfail() for
tests that are known to fail on TCG there)
> Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
> ---
> lib/powerpc/asm/processor.h | 4 +
> lib/powerpc/asm/reg.h | 17 ++
> lib/powerpc/setup.c | 11 +
> lib/ppc64/asm/ptrace.h | 16 ++
> powerpc/Makefile.common | 3 +-
> powerpc/interrupts.c | 415 ++++++++++++++++++++++++++++++++++++
> powerpc/unittests.cfg | 3 +
> 7 files changed, 468 insertions(+), 1 deletion(-)
> create mode 100644 powerpc/interrupts.c
>
> diff --git a/lib/powerpc/asm/processor.h b/lib/powerpc/asm/processor.h
> index cf1b9d8ff..eed37d1f4 100644
> --- a/lib/powerpc/asm/processor.h
> +++ b/lib/powerpc/asm/processor.h
> @@ -11,7 +11,11 @@ void do_handle_exception(struct pt_regs *regs);
> #endif /* __ASSEMBLY__ */
>
> extern bool cpu_has_hv;
> +extern bool cpu_has_power_mce;
> +extern bool cpu_has_siar;
> extern bool cpu_has_heai;
> +extern bool cpu_has_prefix;
> +extern bool cpu_has_sc_lev;
>
> static inline uint64_t mfspr(int nr)
> {
> diff --git a/lib/powerpc/asm/reg.h b/lib/powerpc/asm/reg.h
> index 782e75527..d6097f48f 100644
> --- a/lib/powerpc/asm/reg.h
> +++ b/lib/powerpc/asm/reg.h
> @@ -5,8 +5,15 @@
>
> #define UL(x) _AC(x, UL)
>
> +#define SPR_DSISR 0x012
> +#define SPR_DAR 0x013
> +#define SPR_DEC 0x016
> #define SPR_SRR0 0x01a
> #define SPR_SRR1 0x01b
> +#define SRR1_PREFIX UL(0x20000000)
> +#define SPR_FSCR 0x099
> +#define FSCR_PREFIX UL(0x2000)
> +#define SPR_HFSCR 0x0be
> #define SPR_TB 0x10c
> #define SPR_SPRG0 0x110
> #define SPR_SPRG1 0x111
> @@ -22,12 +29,17 @@
> #define PVR_VER_POWER8 UL(0x004d0000)
> #define PVR_VER_POWER9 UL(0x004e0000)
> #define PVR_VER_POWER10 UL(0x00800000)
> +#define SPR_HDEC 0x136
> #define SPR_HSRR0 0x13a
> #define SPR_HSRR1 0x13b
> +#define SPR_LPCR 0x13e
> +#define LPCR_HDICE UL(0x1)
> +#define SPR_HEIR 0x153
> #define SPR_MMCR0 0x31b
> #define MMCR0_FC UL(0x80000000)
> #define MMCR0_PMAE UL(0x04000000)
> #define MMCR0_PMAO UL(0x00000080)
> +#define SPR_SIAR 0x31c
>
> /* Machine State Register definitions: */
> #define MSR_LE_BIT 0
> @@ -35,6 +47,11 @@
> #define MSR_HV_BIT 60 /* Hypervisor mode */
> #define MSR_SF_BIT 63 /* 64-bit mode */
>
> +#define MSR_DR UL(0x0010)
> +#define MSR_IR UL(0x0020)
> +#define MSR_BE UL(0x0200) /* Branch Trace Enable */
> +#define MSR_SE UL(0x0400) /* Single Step Enable */
> +#define MSR_EE UL(0x8000)
> #define MSR_ME UL(0x1000)
>
> #endif
> diff --git a/lib/powerpc/setup.c b/lib/powerpc/setup.c
> index 3c81aee9e..9b665f59c 100644
> --- a/lib/powerpc/setup.c
> +++ b/lib/powerpc/setup.c
> @@ -87,7 +87,11 @@ static void cpu_set(int fdtnode, u64 regval, void *info)
> }
>
> bool cpu_has_hv;
> +bool cpu_has_power_mce; /* POWER CPU machine checks */
> +bool cpu_has_siar;
> bool cpu_has_heai;
> +bool cpu_has_prefix;
> +bool cpu_has_sc_lev; /* sc interrupt has LEV field in SRR1 */
>
> static void cpu_init(void)
> {
> @@ -112,15 +116,22 @@ static void cpu_init(void)
>
> switch (mfspr(SPR_PVR) & PVR_VERSION_MASK) {
> case PVR_VER_POWER10:
> + cpu_has_prefix = true;
> + cpu_has_sc_lev = true;
> case PVR_VER_POWER9:
> case PVR_VER_POWER8E:
> case PVR_VER_POWER8NVL:
> case PVR_VER_POWER8:
> + cpu_has_power_mce = true;
> cpu_has_heai = true;
> + cpu_has_siar = true;
> break;
> default:
> break;
> }
> +
> + if (!cpu_has_hv) /* HEIR is HV register */
> + cpu_has_heai = false;
> }
>
> static void mem_init(phys_addr_t freemem_start)
> diff --git a/lib/ppc64/asm/ptrace.h b/lib/ppc64/asm/ptrace.h
> index 12de7499b..db263a59e 100644
> --- a/lib/ppc64/asm/ptrace.h
> +++ b/lib/ppc64/asm/ptrace.h
> @@ -5,6 +5,9 @@
> #define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */
>
> #ifndef __ASSEMBLY__
> +
> +#include <asm/reg.h>
> +
> struct pt_regs {
> unsigned long gpr[32];
> unsigned long nip;
> @@ -17,6 +20,19 @@ struct pt_regs {
> unsigned long _pad; /* stack must be 16-byte aligned */
> };
>
> +static inline bool regs_is_prefix(volatile struct pt_regs *regs)
> +{
> + return regs->msr & SRR1_PREFIX;
> +}
> +
> +static inline void regs_advance_insn(struct pt_regs *regs)
> +{
> + if (regs_is_prefix(regs))
> + regs->nip += 8;
> + else
> + regs->nip += 4;
> +}
> +
> #define STACK_INT_FRAME_SIZE (sizeof(struct pt_regs) + \
> STACK_FRAME_OVERHEAD + KERNEL_REDZONE_SIZE)
>
> diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common
> index 1e181da69..68165fc25 100644
> --- a/powerpc/Makefile.common
> +++ b/powerpc/Makefile.common
> @@ -12,7 +12,8 @@ tests-common = \
> $(TEST_DIR)/rtas.elf \
> $(TEST_DIR)/emulator.elf \
> $(TEST_DIR)/tm.elf \
> - $(TEST_DIR)/sprs.elf
> + $(TEST_DIR)/sprs.elf \
> + $(TEST_DIR)/interrupts.elf
>
> tests-all = $(tests-common) $(tests)
> all: directories $(TEST_DIR)/boot_rom.bin $(tests-all)
> diff --git a/powerpc/interrupts.c b/powerpc/interrupts.c
> new file mode 100644
> index 000000000..442f8c569
> --- /dev/null
> +++ b/powerpc/interrupts.c
> @@ -0,0 +1,415 @@
> +/*
> + * Test interrupts
> + *
> + * Copyright 2024 Nicholas Piggin, IBM Corp.
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
I know, we're using this line in a lot of source files ... but maybe we
should do better for new files at least: "LGPL, version 2" is a little bit
ambiguous: Does it mean the "Library GPL version 2.0" or the "Lesser GPL
version 2.1"? Maybe you could clarify by additionally providing a SPDX
identifier here, or by explicitly writing 2.0 or 2.1.
Thanks,
Thomas
More information about the Linuxppc-dev
mailing list