Message ID | 20230822170209.1130173-4-richard.henderson@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | linux-user/aarch64: Add ESR signal frame record | expand |
On Tue, 22 Aug 2023 at 18:02, Richard Henderson <richard.henderson@linaro.org> wrote: > > The PACFAIL fault uses ILL_ILLOPN and includes ESR. > > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > linux-user/aarch64/cpu_loop.c | 7 ++++++- > linux-user/aarch64/signal.c | 6 ++++++ > tests/tcg/aarch64/pauth-2.c | 25 ++++++++++++++++++++++++- > 3 files changed, 36 insertions(+), 2 deletions(-) > > diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c > index 22c9789326..5af17e8724 100644 > --- a/linux-user/aarch64/cpu_loop.c > +++ b/linux-user/aarch64/cpu_loop.c > @@ -110,7 +110,12 @@ void cpu_loop(CPUARMState *env) > /* just indicate that signals should be handled asap */ > break; > case EXCP_UDEF: > - force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); > + /* See kernel's do_el0_fpac, and our need_save_esr(). */ > + if (syn_get_ec(env->exception.syndrome) == EC_PACFAIL) { > + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->pc); > + } else { > + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); > + } > break; > case EXCP_PREFETCH_ABORT: > case EXCP_DATA_ABORT: > diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c > index b2280fa9e3..bcdd796cc2 100644 > --- a/linux-user/aarch64/signal.c > +++ b/linux-user/aarch64/signal.c > @@ -582,6 +582,7 @@ static bool need_save_esr(target_siginfo_t *info, CPUARMState *env) > { > int sig = info->si_signo; > int type = info->si_code >> 16; > + int code = info->si_code & 0xffff; > > if (type != QEMU_SI_FAULT) { > return false; > @@ -592,6 +593,11 @@ static bool need_save_esr(target_siginfo_t *info, CPUARMState *env) > return true; > } > > + /* See arch/arm64/kernel/traps.c, do_el0_fpac, and our cpu_loop(). */ > + if (sig == TARGET_SIGILL && code == TARGET_ILL_ILLOPN) { > + return true; > + } This works, but we'll need to do something else if the kernel adds some other fault later that is reported as ILLOPN but without an ESR record... > + > return false; > } Reviewed-by: Peter Maydell <peter.maydell@linaro.org> thanks -- PMM
On 8/29/23 07:46, Peter Maydell wrote: >> + /* See arch/arm64/kernel/traps.c, do_el0_fpac, and our cpu_loop(). */ >> + if (sig == TARGET_SIGILL && code == TARGET_ILL_ILLOPN) { >> + return true; >> + } > > This works, but we'll need to do something else if the kernel adds > some other fault later that is reported as ILLOPN but without > an ESR record... Yes. I'm not happy about the separation in logic, but I can't think of a better way at present. r~
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c index 22c9789326..5af17e8724 100644 --- a/linux-user/aarch64/cpu_loop.c +++ b/linux-user/aarch64/cpu_loop.c @@ -110,7 +110,12 @@ void cpu_loop(CPUARMState *env) /* just indicate that signals should be handled asap */ break; case EXCP_UDEF: - force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); + /* See kernel's do_el0_fpac, and our need_save_esr(). */ + if (syn_get_ec(env->exception.syndrome) == EC_PACFAIL) { + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->pc); + } else { + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); + } break; case EXCP_PREFETCH_ABORT: case EXCP_DATA_ABORT: diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c index b2280fa9e3..bcdd796cc2 100644 --- a/linux-user/aarch64/signal.c +++ b/linux-user/aarch64/signal.c @@ -582,6 +582,7 @@ static bool need_save_esr(target_siginfo_t *info, CPUARMState *env) { int sig = info->si_signo; int type = info->si_code >> 16; + int code = info->si_code & 0xffff; if (type != QEMU_SI_FAULT) { return false; @@ -592,6 +593,11 @@ static bool need_save_esr(target_siginfo_t *info, CPUARMState *env) return true; } + /* See arch/arm64/kernel/traps.c, do_el0_fpac, and our cpu_loop(). */ + if (sig == TARGET_SIGILL && code == TARGET_ILL_ILLOPN) { + return true; + } + return false; } diff --git a/tests/tcg/aarch64/pauth-2.c b/tests/tcg/aarch64/pauth-2.c index d498d7dd8b..62b39af3d0 100644 --- a/tests/tcg/aarch64/pauth-2.c +++ b/tests/tcg/aarch64/pauth-2.c @@ -4,14 +4,37 @@ #include <assert.h> #include <sys/auxv.h> +static inline struct _aarch64_ctx *first_ctx(ucontext_t *uc) +{ + return (struct _aarch64_ctx *)&uc->uc_mcontext.__reserved; +} + +static inline struct _aarch64_ctx *next_ctx(struct _aarch64_ctx *hdr) +{ + return (struct _aarch64_ctx *)((char *)hdr + hdr->size); +} + static void sigill(int sig, siginfo_t *info, void *vuc) { ucontext_t *uc = vuc; - uint64_t test; + struct _aarch64_ctx *hdr; + struct esr_context *ec; + uint64_t test, esr; /* There is only one insn below that is allowed to fault. */ asm volatile("adr %0, auth2_insn" : "=r"(test)); assert(test == uc->uc_mcontext.pc); + + /* Find the esr_context. */ + for (hdr = first_ctx(uc); hdr->magic != ESR_MAGIC; hdr = next_ctx(hdr)) { + assert(hdr->magic != 0); + } + + ec = (struct esr_context *)hdr; + esr = ec->esr; + + assert((esr >> 26) == 0x1c); /* EC_PACFAIL */ + assert((esr & 3) == 2); /* AUTDA: data=1 key=0 */ exit(0); }
The PACFAIL fault uses ILL_ILLOPN and includes ESR. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- linux-user/aarch64/cpu_loop.c | 7 ++++++- linux-user/aarch64/signal.c | 6 ++++++ tests/tcg/aarch64/pauth-2.c | 25 ++++++++++++++++++++++++- 3 files changed, 36 insertions(+), 2 deletions(-)