Message ID | 20240226101218.1472843-13-npiggin@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | powerpc improvements | expand |
On 26/02/2024 11.11, Nicholas Piggin wrote: > Illegal instructions cause 0xe40 (HEAI) interrupts rather > than program interrupts. > > Acked-by: Thomas Huth <thuth@redhat.com> > Signed-off-by: Nicholas Piggin <npiggin@gmail.com> > --- > 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++) {
On Fri Mar 1, 2024 at 9:50 PM AEST, Thomas Huth wrote: > On 26/02/2024 11.11, Nicholas Piggin wrote: > > Illegal instructions cause 0xe40 (HEAI) interrupts rather > > than program interrupts. > > > > Acked-by: Thomas Huth <thuth@redhat.com> > > Signed-off-by: Nicholas Piggin <npiggin@gmail.com> > > --- > > 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. Can do. Thanks, Nick
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); + } handle_exception(0x600, alignment_handler, (void *)&alignment); for (i = 1; i < argc; i++) {