Message ID | 20210618192951.125651-3-richard.henderson@linaro.org |
---|---|
State | New |
Headers | show |
Series | linux-user: Move signal trampolines to new page | expand |
On Fri, 18 Jun 2021 at 20:33, Richard Henderson <richard.henderson@linaro.org> wrote: > > Create and record the rt signal trampoline. > Use it when the guest does not use SA_RESTORER. > > Cc: qemu-arm@nongnu.org > Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > linux-user/aarch64/target_signal.h | 2 ++ > linux-user/aarch64/signal.c | 28 ++++++++++++++++++---------- > 2 files changed, 20 insertions(+), 10 deletions(-) > > diff --git a/linux-user/aarch64/target_signal.h b/linux-user/aarch64/target_signal.h > index 18013e1b23..7580d99403 100644 > --- a/linux-user/aarch64/target_signal.h > +++ b/linux-user/aarch64/target_signal.h > @@ -25,4 +25,6 @@ typedef struct target_sigaltstack { > #define TARGET_SEGV_MTESERR 9 /* Synchronous ARM MTE exception */ > > #define TARGET_ARCH_HAS_SETUP_FRAME > +#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1 > + > #endif /* AARCH64_TARGET_SIGNAL_H */ > diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c > index 662bcd1c4e..65b84eb04e 100644 > --- a/linux-user/aarch64/signal.c > +++ b/linux-user/aarch64/signal.c > @@ -108,7 +108,6 @@ struct target_rt_sigframe { > struct target_rt_frame_record { > uint64_t fp; > uint64_t lr; > - uint32_t tramp[2]; > }; > > static void target_setup_general_frame(struct target_rt_sigframe *sf, > @@ -495,15 +494,7 @@ static void target_setup_frame(int usig, struct target_sigaction *ka, A little way up from here there's a comment: /* Reserve space for the return code. On a real system this would * be within the VDSO. So, despite the name this is not a "real" * record within the frame. */ fr_ofs = layout.total_size; layout.total_size += sizeof(struct target_rt_frame_record); That now needs updating, because we're no longer putting the return code in that target_rt_frame_record. I think the 'struct target_rt_frame_record' now does correspond to the kernel's 'struct frame_record', right? Otherwise Reviewed-by: Peter Maydell <peter.maydell@linaro.org> thanks -- PMM
On 6/29/21 6:36 AM, Peter Maydell wrote: > A little way up from here there's a comment: > > /* Reserve space for the return code. On a real system this would > * be within the VDSO. So, despite the name this is not a "real" > * record within the frame. > */ > fr_ofs = layout.total_size; > layout.total_size += sizeof(struct target_rt_frame_record); > > That now needs updating, because we're no longer putting the return > code in that target_rt_frame_record. Updated to /* * Reserve space for the standard frame unwind pair: fp, lr. * Despite the name this is not a "real" record within the frame. */ > I think the 'struct target_rt_frame_record' now does correspond > to the kernel's 'struct frame_record', right? Yes. r~
diff --git a/linux-user/aarch64/target_signal.h b/linux-user/aarch64/target_signal.h index 18013e1b23..7580d99403 100644 --- a/linux-user/aarch64/target_signal.h +++ b/linux-user/aarch64/target_signal.h @@ -25,4 +25,6 @@ typedef struct target_sigaltstack { #define TARGET_SEGV_MTESERR 9 /* Synchronous ARM MTE exception */ #define TARGET_ARCH_HAS_SETUP_FRAME +#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1 + #endif /* AARCH64_TARGET_SIGNAL_H */ diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c index 662bcd1c4e..65b84eb04e 100644 --- a/linux-user/aarch64/signal.c +++ b/linux-user/aarch64/signal.c @@ -108,7 +108,6 @@ struct target_rt_sigframe { struct target_rt_frame_record { uint64_t fp; uint64_t lr; - uint32_t tramp[2]; }; static void target_setup_general_frame(struct target_rt_sigframe *sf, @@ -495,15 +494,7 @@ static void target_setup_frame(int usig, struct target_sigaction *ka, if (ka->sa_flags & TARGET_SA_RESTORER) { return_addr = ka->sa_restorer; } else { - /* - * mov x8,#__NR_rt_sigreturn; svc #0 - * Since these are instructions they need to be put as little-endian - * regardless of target default or current CPU endianness. - */ - __put_user_e(0xd2801168, &fr->tramp[0], le); - __put_user_e(0xd4000001, &fr->tramp[1], le); - return_addr = frame_addr + fr_ofs - + offsetof(struct target_rt_frame_record, tramp); + return_addr = default_rt_sigreturn; } env->xregs[0] = usig; env->xregs[29] = frame_addr + fr_ofs; @@ -576,3 +567,20 @@ long do_sigreturn(CPUARMState *env) { return do_rt_sigreturn(env); } + +void setup_sigtramp(abi_ulong sigtramp_page) +{ + uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0); + assert(tramp != NULL); + + /* + * mov x8,#__NR_rt_sigreturn; svc #0 + * Since these are instructions they need to be put as little-endian + * regardless of target default or current CPU endianness. + */ + __put_user_e(0xd2801168, &tramp[0], le); + __put_user_e(0xd4000001, &tramp[1], le); + + default_rt_sigreturn = sigtramp_page; + unlock_user(tramp, sigtramp_page, 8); +}