Subject: Re: [kvm-unit-tests PATCH 12/32] powerpc: Fix emulator illegal instruction test for powernv

From: Thomas Huth <[email-masked]>
Date: Fri, 1 Mar 2024 12:50:10 +0100

On 26/02/2024 11.11, Nicholas Piggin wrote:
> Illegal instructions cause 0xe40 (HEAI) interrupts rather
> than program interrupts.
> 
> Acked-by: Thomas Huth <[email-masked]>
> Signed-off-by: Nicholas Piggin <[email-masked]>
> ---
>   lib/powerpc/asm/processor.h |  1 +
>   lib/powerpc/setup.c         | 13 +++++++++++++
>   powerpc/emulator.c          | 21 ++++++++++++++++++++-
>   3 files changed, 34 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/powerpc/asm/processor.h b/lib/powerpc/asm/processor.h
> index 9d8061962..cf1b9d8ff 100644
> --- a/lib/powerpc/asm/processor.h
> +++ b/lib/powerpc/asm/processor.h
> @@ -11,6 +11,7 @@ void do_handle_exception(struct pt_regs *regs);
>   #endif /* __ASSEMBLY__ */
>   
>   extern bool cpu_has_hv;
> +extern bool cpu_has_heai;
>   
>   static inline uint64_t mfspr(int nr)
>   {
> diff --git a/lib/powerpc/setup.c b/lib/powerpc/setup.c
> index 89e5157f2..3c81aee9e 100644
> --- a/lib/powerpc/setup.c
> +++ b/lib/powerpc/setup.c
> @@ -87,6 +87,7 @@ static void cpu_set(int fdtnode, u64 regval, void *info)
>   }
>   
>   bool cpu_has_hv;
> +bool cpu_has_heai;
>   
>   static void cpu_init(void)
>   {
> @@ -108,6 +109,18 @@ static void cpu_init(void)
>   		hcall(H_SET_MODE, 0, 4, 0, 0);
>   #endif
>   	}
> +
> +	switch (mfspr(SPR_PVR) & PVR_VERSION_MASK) {
> +	case PVR_VER_POWER10:
> +	case PVR_VER_POWER9:
> +	case PVR_VER_POWER8E:
> +	case PVR_VER_POWER8NVL:
> +	case PVR_VER_POWER8:
> +		cpu_has_heai = true;
> +		break;
> +	default:
> +		break;
> +	}
>   }
>   
>   static void mem_init(phys_addr_t freemem_start)
> diff --git a/powerpc/emulator.c b/powerpc/emulator.c
> index 39dd59645..c9b17f742 100644
> --- a/powerpc/emulator.c
> +++ b/powerpc/emulator.c
> @@ -31,6 +31,20 @@ static void program_check_handler(struct pt_regs *regs, void *opaque)
>   	regs->nip += 4;
>   }
>   
> +static void heai_handler(struct pt_regs *regs, void *opaque)
> +{
> +	int *data = opaque;
> +
> +	if (verbose) {
> +		printf("Detected invalid instruction %#018lx: %08x\n",
> +		       regs->nip, *(uint32_t*)regs->nip);
> +	}
> +
> +	*data = 8; /* Illegal instruction */
> +
> +	regs->nip += 4;
> +}
> +
>   static void alignment_handler(struct pt_regs *regs, void *opaque)
>   {
>   	int *data = opaque;
> @@ -362,7 +376,12 @@ int main(int argc, char **argv)
>   {
>   	int i;
>   
> -	handle_exception(0x700, program_check_handler, (void *)&is_invalid);
> +	if (cpu_has_heai) {
> +		handle_exception(0xe40, heai_handler, (void *)&is_invalid);
> +		handle_exception(0x700, program_check_handler, (void *)&is_invalid);
> +	} else {
> +		handle_exception(0x700, program_check_handler, (void *)&is_invalid);

The 0x700 line looks identical to the other part of the if-statement ... I'd 
suggest to leave it outside of the if-statement, drop the else-part and just 
set 0xe40 if cpu_has_heai.

  Thomas

> +	}
>   	handle_exception(0x600, alignment_handler, (void *)&alignment);
>   
>   	for (i = 1; i < argc; i++) {