* [PATCH for-5.2 0/3] linux-user: fix various sparc64 guest bugs @ 2020-11-05 21:23 Peter Maydell 2020-11-05 21:23 ` [PATCH for-5.2 1/3] linux-user/sparc: Fix errors in target_ucontext structures Peter Maydell ` (3 more replies) 0 siblings, 4 replies; 15+ messages in thread From: Peter Maydell @ 2020-11-05 21:23 UTC (permalink / raw) To: qemu-devel Cc: Giuseppe Musacchio, Richard Henderson, Mark Cave-Ayland, Laurent Vivier This set of patches fixes bugs which were preventing the Debian sparc64 /bin/bash from running: * the target_ucontext structure put the registers in the wrong place (missing alignment specifier, mostly) * the set_context and get_context traps weren't saving fp and i7, which meant that guest code that did a longjmp would crash shortly afterwards (SPARC64 uses these traps to implement setjmp/longjmp) * we were trying to stuff a 64-bit PC into a uint32_t in sigreturn, which caused a SEGV on return from a signal handler Review very much desired in particular from anybody who understands SPARC register windows and how we handle them in linux-user for patch 2! The other patches are straightforward. This patchset is sufficient that I can at least chroot into a Debian sparc64 chroot and run basic commands like 'ls' from the shell prompt (together with Giuseppe Musacchio's patch that fixes the stack_t struct). There are clearly a bunch of other bugs in sparc signal handling (starting with the fact that rt_frame support is simply not implemented, but there are also some XXX/FIXME comments about TSTATE save/restore in set/get_context and about the FPU state in the signal frame code). There's also a Coverity issue about accessing off the end of the sregs[] array in the target_mc_fpu struct -- the error is actually harmless (we're accessing into the space in the union for dregs[16..31] which is what we want to be doing) but I'll probably put together a patch to make Coverity happier. thanks -- PMM Peter Maydell (3): linux-user/sparc: Fix errors in target_ucontext structures linux-user/sparc: Correct set/get_context handling of fp and i7 linux-user/sparc: Don't zero high half of PC, NPC, PSR in sigreturn linux-user/sparc/signal.c | 62 ++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 30 deletions(-) -- 2.20.1 ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH for-5.2 1/3] linux-user/sparc: Fix errors in target_ucontext structures 2020-11-05 21:23 [PATCH for-5.2 0/3] linux-user: fix various sparc64 guest bugs Peter Maydell @ 2020-11-05 21:23 ` Peter Maydell 2020-11-05 22:15 ` Richard Henderson 2020-11-10 6:53 ` Laurent Vivier 2020-11-05 21:23 ` [PATCH for-5.2 2/3] linux-user/sparc: Correct set/get_context handling of fp and i7 Peter Maydell ` (2 subsequent siblings) 3 siblings, 2 replies; 15+ messages in thread From: Peter Maydell @ 2020-11-05 21:23 UTC (permalink / raw) To: qemu-devel Cc: Giuseppe Musacchio, Richard Henderson, Mark Cave-Ayland, Laurent Vivier The various structs that make up the SPARC target_ucontext had some errors: * target structures must not include fields which are host pointers, which might be the wrong size. These should be abi_ulong instead * because we don't have the 'long double' part of the mcfpu_fregs union in our version of the target_mc_fpu struct, we need to manually force it to be 16-aligned In particular, the lack of 16-alignment caused sparc64_get_context() and sparc64_set_context() to read and write all the registers at the wrong offset, which triggered a guest glibc stack check in siglongjmp: *** longjmp causes uninitialized stack frame ***: terminated when trying to run bash. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- linux-user/sparc/signal.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index d796f50f665..57ea1593bfc 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -349,10 +349,15 @@ typedef abi_ulong target_mc_greg_t; typedef target_mc_greg_t target_mc_gregset_t[SPARC_MC_NGREG]; struct target_mc_fq { - abi_ulong *mcfq_addr; + abi_ulong mcfq_addr; uint32_t mcfq_insn; }; +/* + * Note the manual 16-alignment; the kernel gets this because it + * includes a "long double qregs[16]" in the mcpu_fregs union, + * which we can't do. + */ struct target_mc_fpu { union { uint32_t sregs[32]; @@ -362,11 +367,11 @@ struct target_mc_fpu { abi_ulong mcfpu_fsr; abi_ulong mcfpu_fprs; abi_ulong mcfpu_gsr; - struct target_mc_fq *mcfpu_fq; + abi_ulong mcfpu_fq; unsigned char mcfpu_qcnt; unsigned char mcfpu_qentsz; unsigned char mcfpu_enab; -}; +} __attribute__((aligned(16))); typedef struct target_mc_fpu target_mc_fpu_t; typedef struct { @@ -377,7 +382,7 @@ typedef struct { } target_mcontext_t; struct target_ucontext { - struct target_ucontext *tuc_link; + abi_ulong tuc_link; abi_ulong tuc_flags; target_sigset_t tuc_sigmask; target_mcontext_t tuc_mcontext; -- 2.20.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH for-5.2 1/3] linux-user/sparc: Fix errors in target_ucontext structures 2020-11-05 21:23 ` [PATCH for-5.2 1/3] linux-user/sparc: Fix errors in target_ucontext structures Peter Maydell @ 2020-11-05 22:15 ` Richard Henderson 2020-11-05 23:36 ` Peter Maydell 2020-11-10 6:53 ` Laurent Vivier 1 sibling, 1 reply; 15+ messages in thread From: Richard Henderson @ 2020-11-05 22:15 UTC (permalink / raw) To: Peter Maydell, qemu-devel Cc: Giuseppe Musacchio, Mark Cave-Ayland, Laurent Vivier On 11/5/20 1:23 PM, Peter Maydell wrote: > The various structs that make up the SPARC target_ucontext had some > errors: > * target structures must not include fields which are host pointers, > which might be the wrong size. These should be abi_ulong instead > * because we don't have the 'long double' part of the mcfpu_fregs > union in our version of the target_mc_fpu struct, we need to > manually force it to be 16-aligned > > In particular, the lack of 16-alignment caused sparc64_get_context() > and sparc64_set_context() to read and write all the registers at the > wrong offset, which triggered a guest glibc stack check in > siglongjmp: > *** longjmp causes uninitialized stack frame ***: terminated > when trying to run bash. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> > +} __attribute__((aligned(16))); Hmph, 96 uses of the attribute directly, 20 uses of QEMU_ALIGNED. I suppose we should just remove the wrapper... r~ ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH for-5.2 1/3] linux-user/sparc: Fix errors in target_ucontext structures 2020-11-05 22:15 ` Richard Henderson @ 2020-11-05 23:36 ` Peter Maydell 0 siblings, 0 replies; 15+ messages in thread From: Peter Maydell @ 2020-11-05 23:36 UTC (permalink / raw) To: Richard Henderson Cc: Giuseppe Musacchio, Mark Cave-Ayland, QEMU Developers, Laurent Vivier On Thu, 5 Nov 2020 at 22:15, Richard Henderson <richard.henderson@linaro.org> wrote: > > On 11/5/20 1:23 PM, Peter Maydell wrote: > > +} __attribute__((aligned(16))); > > Hmph, 96 uses of the attribute directly, 20 uses of QEMU_ALIGNED. I suppose we > should just remove the wrapper... Oops, I forget about that. We're better at adhering to use of QEMU_SENTINEL and QEMU_NORETURN, at least. And a fair chunk of those 96 are in code-that's-not-ours like the headers imported from Linux or the pc-bios/s390-ccw code. I'm in two minds here -- the wrappers look less clunky than the __attribute__ syntax, but on the other hand "there is only one way this can be written" results in less inconsistency than "there are two ways". thanks -- PMM ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH for-5.2 1/3] linux-user/sparc: Fix errors in target_ucontext structures 2020-11-05 21:23 ` [PATCH for-5.2 1/3] linux-user/sparc: Fix errors in target_ucontext structures Peter Maydell 2020-11-05 22:15 ` Richard Henderson @ 2020-11-10 6:53 ` Laurent Vivier 2020-11-10 9:02 ` LemonBoy 1 sibling, 1 reply; 15+ messages in thread From: Laurent Vivier @ 2020-11-10 6:53 UTC (permalink / raw) To: Peter Maydell, qemu-devel Cc: Giuseppe Musacchio, Mark Cave-Ayland, Richard Henderson Le 05/11/2020 à 22:23, Peter Maydell a écrit : > The various structs that make up the SPARC target_ucontext had some > errors: > * target structures must not include fields which are host pointers, > which might be the wrong size. These should be abi_ulong instead > * because we don't have the 'long double' part of the mcfpu_fregs > union in our version of the target_mc_fpu struct, we need to > manually force it to be 16-aligned > > In particular, the lack of 16-alignment caused sparc64_get_context() > and sparc64_set_context() to read and write all the registers at the > wrong offset, which triggered a guest glibc stack check in > siglongjmp: > *** longjmp causes uninitialized stack frame ***: terminated > when trying to run bash. > > Signed-off-by: Peter Maydell <peter.maydell@linaro.org> > --- > linux-user/sparc/signal.c | 13 +++++++++---- > 1 file changed, 9 insertions(+), 4 deletions(-) > > diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c > index d796f50f665..57ea1593bfc 100644 > --- a/linux-user/sparc/signal.c > +++ b/linux-user/sparc/signal.c > @@ -349,10 +349,15 @@ typedef abi_ulong target_mc_greg_t; > typedef target_mc_greg_t target_mc_gregset_t[SPARC_MC_NGREG]; > > struct target_mc_fq { > - abi_ulong *mcfq_addr; > + abi_ulong mcfq_addr; > uint32_t mcfq_insn; > }; > > +/* > + * Note the manual 16-alignment; the kernel gets this because it > + * includes a "long double qregs[16]" in the mcpu_fregs union, > + * which we can't do. > + */ > struct target_mc_fpu { > union { > uint32_t sregs[32]; > @@ -362,11 +367,11 @@ struct target_mc_fpu { > abi_ulong mcfpu_fsr; > abi_ulong mcfpu_fprs; > abi_ulong mcfpu_gsr; > - struct target_mc_fq *mcfpu_fq; > + abi_ulong mcfpu_fq; > unsigned char mcfpu_qcnt; > unsigned char mcfpu_qentsz; > unsigned char mcfpu_enab; > -}; > +} __attribute__((aligned(16))); > typedef struct target_mc_fpu target_mc_fpu_t; > > typedef struct { > @@ -377,7 +382,7 @@ typedef struct { > } target_mcontext_t; > > struct target_ucontext { > - struct target_ucontext *tuc_link; > + abi_ulong tuc_link; > abi_ulong tuc_flags; > target_sigset_t tuc_sigmask; > target_mcontext_t tuc_mcontext; > Applied to my linux-user-for-5.2 branch. Thanks, Laurent ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH for-5.2 1/3] linux-user/sparc: Fix errors in target_ucontext structures 2020-11-10 6:53 ` Laurent Vivier @ 2020-11-10 9:02 ` LemonBoy 2020-11-10 9:41 ` Laurent Vivier 0 siblings, 1 reply; 15+ messages in thread From: LemonBoy @ 2020-11-10 9:02 UTC (permalink / raw) To: Laurent Vivier, Peter Maydell, qemu-devel Cc: Mark Cave-Ayland, Richard Henderson Hello Laurent, you probably want to also apply my patch for stack_t definitions [1] that was mentioned in Peter Maydell's cover letter for the patch series. [1] https://patchew.org/QEMU/e9d47692-ee92-009f-6007-0abc3f502b97@gmail.com/ On 10/11/20 07:53, Laurent Vivier wrote: > Le 05/11/2020 à 22:23, Peter Maydell a écrit : >> The various structs that make up the SPARC target_ucontext had some >> errors: >> * target structures must not include fields which are host pointers, >> which might be the wrong size. These should be abi_ulong instead >> * because we don't have the 'long double' part of the mcfpu_fregs >> union in our version of the target_mc_fpu struct, we need to >> manually force it to be 16-aligned >> >> In particular, the lack of 16-alignment caused sparc64_get_context() >> and sparc64_set_context() to read and write all the registers at the >> wrong offset, which triggered a guest glibc stack check in >> siglongjmp: >> *** longjmp causes uninitialized stack frame ***: terminated >> when trying to run bash. >> >> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> >> --- >> linux-user/sparc/signal.c | 13 +++++++++---- >> 1 file changed, 9 insertions(+), 4 deletions(-) >> >> diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c >> index d796f50f665..57ea1593bfc 100644 >> --- a/linux-user/sparc/signal.c >> +++ b/linux-user/sparc/signal.c >> @@ -349,10 +349,15 @@ typedef abi_ulong target_mc_greg_t; >> typedef target_mc_greg_t target_mc_gregset_t[SPARC_MC_NGREG]; >> >> struct target_mc_fq { >> - abi_ulong *mcfq_addr; >> + abi_ulong mcfq_addr; >> uint32_t mcfq_insn; >> }; >> >> +/* >> + * Note the manual 16-alignment; the kernel gets this because it >> + * includes a "long double qregs[16]" in the mcpu_fregs union, >> + * which we can't do. >> + */ >> struct target_mc_fpu { >> union { >> uint32_t sregs[32]; >> @@ -362,11 +367,11 @@ struct target_mc_fpu { >> abi_ulong mcfpu_fsr; >> abi_ulong mcfpu_fprs; >> abi_ulong mcfpu_gsr; >> - struct target_mc_fq *mcfpu_fq; >> + abi_ulong mcfpu_fq; >> unsigned char mcfpu_qcnt; >> unsigned char mcfpu_qentsz; >> unsigned char mcfpu_enab; >> -}; >> +} __attribute__((aligned(16))); >> typedef struct target_mc_fpu target_mc_fpu_t; >> >> typedef struct { >> @@ -377,7 +382,7 @@ typedef struct { >> } target_mcontext_t; >> >> struct target_ucontext { >> - struct target_ucontext *tuc_link; >> + abi_ulong tuc_link; >> abi_ulong tuc_flags; >> target_sigset_t tuc_sigmask; >> target_mcontext_t tuc_mcontext; >> > > Applied to my linux-user-for-5.2 branch. > > Thanks, > Laurent > ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH for-5.2 1/3] linux-user/sparc: Fix errors in target_ucontext structures 2020-11-10 9:02 ` LemonBoy @ 2020-11-10 9:41 ` Laurent Vivier 0 siblings, 0 replies; 15+ messages in thread From: Laurent Vivier @ 2020-11-10 9:41 UTC (permalink / raw) To: qemu-devel Le 10/11/2020 à 10:02, LemonBoy a écrit : > Hello Laurent, > you probably want to also apply my patch for stack_t definitions [1] that > was mentioned in Peter Maydell's cover letter for the patch series. > > [1] https://patchew.org/QEMU/e9d47692-ee92-009f-6007-0abc3f502b97@gmail.com/ Yes, you're right. But as it touches more architectures it needs more test. I will send a pull request with your patch once this one will be merged. Thanks, Laurent ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH for-5.2 2/3] linux-user/sparc: Correct set/get_context handling of fp and i7 2020-11-05 21:23 [PATCH for-5.2 0/3] linux-user: fix various sparc64 guest bugs Peter Maydell 2020-11-05 21:23 ` [PATCH for-5.2 1/3] linux-user/sparc: Fix errors in target_ucontext structures Peter Maydell @ 2020-11-05 21:23 ` Peter Maydell 2020-11-05 22:22 ` Richard Henderson 2020-11-10 6:53 ` Laurent Vivier 2020-11-05 21:23 ` [PATCH for-5.2 3/3] linux-user/sparc: Don't zero high half of PC, NPC, PSR in sigreturn Peter Maydell 2020-11-10 12:56 ` [PATCH for-5.2 0/3] linux-user: fix various sparc64 guest bugs Mark Cave-Ayland 3 siblings, 2 replies; 15+ messages in thread From: Peter Maydell @ 2020-11-05 21:23 UTC (permalink / raw) To: qemu-devel Cc: Giuseppe Musacchio, Richard Henderson, Mark Cave-Ayland, Laurent Vivier Because QEMU's user-mode emulation just directly accesses guest CPU state, for SPARC the guest register window state is not the same in the sparc64_get_context() and sparc64_set_context() functions as it is for the real kernel's versions of those functions. Specifically, for the kernel it has saved the user space state such that the O* registers go into a pt_regs struct as UREG_I*, and the I* registers have been spilled onto the userspace stack. For QEMU, we haven't done that, so the guest's O* registers are still in WREG_O* and the I* registers in WREG_I*. The code was already accessing the O* registers correctly for QEMU, but had copied the kernel code for accessing the I* registers off the userspace stack. Replace this with direct accesses to fp and i7 in the CPU state, and add a comment explaining why we differ from the kernel code here. This fix is sufficient to get bash to a shell prompt. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- I'm really pretty unsure about our handling of SPARC register windows here. This fix works, but should we instead be ensuring that the flush_windows() call cpu_loop() does before handling this trap has written the I* regs to the stack ??? --- linux-user/sparc/signal.c | 47 ++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index 57ea1593bfc..c315704b389 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -403,7 +403,6 @@ void sparc64_set_context(CPUSPARCState *env) struct target_ucontext *ucp; target_mc_gregset_t *grp; abi_ulong pc, npc, tstate; - abi_ulong fp, i7, w_addr; unsigned int i; ucp_addr = env->regwptr[WREG_O0]; @@ -447,6 +446,15 @@ void sparc64_set_context(CPUSPARCState *env) __get_user(env->gregs[5], (&(*grp)[SPARC_MC_G5])); __get_user(env->gregs[6], (&(*grp)[SPARC_MC_G6])); __get_user(env->gregs[7], (&(*grp)[SPARC_MC_G7])); + + /* + * Note that unlike the kernel, we didn't need to mess with the + * guest register window state to save it into a pt_regs to run + * the kernel. So for us the guest's O regs are still in WREG_O* + * (unlike the kernel which has put them in UREG_I* in a pt_regs) + * and the fp and i7 are still in WREG_I6 and WREG_I7 and don't + * need to be written back to userspace memory. + */ __get_user(env->regwptr[WREG_O0], (&(*grp)[SPARC_MC_O0])); __get_user(env->regwptr[WREG_O1], (&(*grp)[SPARC_MC_O1])); __get_user(env->regwptr[WREG_O2], (&(*grp)[SPARC_MC_O2])); @@ -456,18 +464,9 @@ void sparc64_set_context(CPUSPARCState *env) __get_user(env->regwptr[WREG_O6], (&(*grp)[SPARC_MC_O6])); __get_user(env->regwptr[WREG_O7], (&(*grp)[SPARC_MC_O7])); - __get_user(fp, &(ucp->tuc_mcontext.mc_fp)); - __get_user(i7, &(ucp->tuc_mcontext.mc_i7)); + __get_user(env->regwptr[WREG_FP], &(ucp->tuc_mcontext.mc_fp)); + __get_user(env->regwptr[WREG_I7], &(ucp->tuc_mcontext.mc_i7)); - w_addr = TARGET_STACK_BIAS + env->regwptr[WREG_O6]; - if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), - abi_ulong) != 0) { - goto do_sigsegv; - } - if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), - abi_ulong) != 0) { - goto do_sigsegv; - } /* FIXME this does not match how the kernel handles the FPU in * its sparc64_set_context implementation. In particular the FPU * is only restored if fenab is non-zero in: @@ -501,7 +500,6 @@ void sparc64_get_context(CPUSPARCState *env) struct target_ucontext *ucp; target_mc_gregset_t *grp; target_mcontext_t *mcp; - abi_ulong fp, i7, w_addr; int err; unsigned int i; target_sigset_t target_set; @@ -553,6 +551,15 @@ void sparc64_get_context(CPUSPARCState *env) __put_user(env->gregs[5], &((*grp)[SPARC_MC_G5])); __put_user(env->gregs[6], &((*grp)[SPARC_MC_G6])); __put_user(env->gregs[7], &((*grp)[SPARC_MC_G7])); + + /* + * Note that unlike the kernel, we didn't need to mess with the + * guest register window state to save it into a pt_regs to run + * the kernel. So for us the guest's O regs are still in WREG_O* + * (unlike the kernel which has put them in UREG_I* in a pt_regs) + * and the fp and i7 are still in WREG_I6 and WREG_I7 and don't + * need to be fished out of userspace memory. + */ __put_user(env->regwptr[WREG_O0], &((*grp)[SPARC_MC_O0])); __put_user(env->regwptr[WREG_O1], &((*grp)[SPARC_MC_O1])); __put_user(env->regwptr[WREG_O2], &((*grp)[SPARC_MC_O2])); @@ -562,18 +569,8 @@ void sparc64_get_context(CPUSPARCState *env) __put_user(env->regwptr[WREG_O6], &((*grp)[SPARC_MC_O6])); __put_user(env->regwptr[WREG_O7], &((*grp)[SPARC_MC_O7])); - w_addr = TARGET_STACK_BIAS + env->regwptr[WREG_O6]; - fp = i7 = 0; - if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), - abi_ulong) != 0) { - goto do_sigsegv; - } - if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), - abi_ulong) != 0) { - goto do_sigsegv; - } - __put_user(fp, &(mcp->mc_fp)); - __put_user(i7, &(mcp->mc_i7)); + __put_user(env->regwptr[WREG_FP], &(mcp->mc_fp)); + __put_user(env->regwptr[WREG_I7], &(mcp->mc_i7)); { uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs; -- 2.20.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH for-5.2 2/3] linux-user/sparc: Correct set/get_context handling of fp and i7 2020-11-05 21:23 ` [PATCH for-5.2 2/3] linux-user/sparc: Correct set/get_context handling of fp and i7 Peter Maydell @ 2020-11-05 22:22 ` Richard Henderson 2020-11-10 6:53 ` Laurent Vivier 1 sibling, 0 replies; 15+ messages in thread From: Richard Henderson @ 2020-11-05 22:22 UTC (permalink / raw) To: Peter Maydell, qemu-devel Cc: Giuseppe Musacchio, Mark Cave-Ayland, Laurent Vivier On 11/5/20 1:23 PM, Peter Maydell wrote: > Because QEMU's user-mode emulation just directly accesses guest CPU > state, for SPARC the guest register window state is not the same in > the sparc64_get_context() and sparc64_set_context() functions as it > is for the real kernel's versions of those functions. Specifically, > for the kernel it has saved the user space state such that the O* > registers go into a pt_regs struct as UREG_I*, and the I* registers > have been spilled onto the userspace stack. For QEMU, we haven't > done that, so the guest's O* registers are still in WREG_O* and the > I* registers in WREG_I*. > > The code was already accessing the O* registers correctly for QEMU, > but had copied the kernel code for accessing the I* registers off the > userspace stack. Replace this with direct accesses to fp and i7 in > the CPU state, and add a comment explaining why we differ from the > kernel code here. > > This fix is sufficient to get bash to a shell prompt. > > Signed-off-by: Peter Maydell <peter.maydell@linaro.org> > --- > I'm really pretty unsure about our handling of SPARC register > windows here. This fix works, but should we instead be > ensuring that the flush_windows() call cpu_loop() does > before handling this trap has written the I* regs to the > stack ??? > --- Ach, I was so close to being right the last time I tried to clean up this code. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> r~ ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH for-5.2 2/3] linux-user/sparc: Correct set/get_context handling of fp and i7 2020-11-05 21:23 ` [PATCH for-5.2 2/3] linux-user/sparc: Correct set/get_context handling of fp and i7 Peter Maydell 2020-11-05 22:22 ` Richard Henderson @ 2020-11-10 6:53 ` Laurent Vivier 1 sibling, 0 replies; 15+ messages in thread From: Laurent Vivier @ 2020-11-10 6:53 UTC (permalink / raw) To: Peter Maydell, qemu-devel Cc: Giuseppe Musacchio, Mark Cave-Ayland, Richard Henderson Le 05/11/2020 à 22:23, Peter Maydell a écrit : > Because QEMU's user-mode emulation just directly accesses guest CPU > state, for SPARC the guest register window state is not the same in > the sparc64_get_context() and sparc64_set_context() functions as it > is for the real kernel's versions of those functions. Specifically, > for the kernel it has saved the user space state such that the O* > registers go into a pt_regs struct as UREG_I*, and the I* registers > have been spilled onto the userspace stack. For QEMU, we haven't > done that, so the guest's O* registers are still in WREG_O* and the > I* registers in WREG_I*. > > The code was already accessing the O* registers correctly for QEMU, > but had copied the kernel code for accessing the I* registers off the > userspace stack. Replace this with direct accesses to fp and i7 in > the CPU state, and add a comment explaining why we differ from the > kernel code here. > > This fix is sufficient to get bash to a shell prompt. > > Signed-off-by: Peter Maydell <peter.maydell@linaro.org> > --- > I'm really pretty unsure about our handling of SPARC register > windows here. This fix works, but should we instead be > ensuring that the flush_windows() call cpu_loop() does > before handling this trap has written the I* regs to the > stack ??? > --- > linux-user/sparc/signal.c | 47 ++++++++++++++++++--------------------- > 1 file changed, 22 insertions(+), 25 deletions(-) > > diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c > index 57ea1593bfc..c315704b389 100644 > --- a/linux-user/sparc/signal.c > +++ b/linux-user/sparc/signal.c > @@ -403,7 +403,6 @@ void sparc64_set_context(CPUSPARCState *env) > struct target_ucontext *ucp; > target_mc_gregset_t *grp; > abi_ulong pc, npc, tstate; > - abi_ulong fp, i7, w_addr; > unsigned int i; > > ucp_addr = env->regwptr[WREG_O0]; > @@ -447,6 +446,15 @@ void sparc64_set_context(CPUSPARCState *env) > __get_user(env->gregs[5], (&(*grp)[SPARC_MC_G5])); > __get_user(env->gregs[6], (&(*grp)[SPARC_MC_G6])); > __get_user(env->gregs[7], (&(*grp)[SPARC_MC_G7])); > + > + /* > + * Note that unlike the kernel, we didn't need to mess with the > + * guest register window state to save it into a pt_regs to run > + * the kernel. So for us the guest's O regs are still in WREG_O* > + * (unlike the kernel which has put them in UREG_I* in a pt_regs) > + * and the fp and i7 are still in WREG_I6 and WREG_I7 and don't > + * need to be written back to userspace memory. > + */ > __get_user(env->regwptr[WREG_O0], (&(*grp)[SPARC_MC_O0])); > __get_user(env->regwptr[WREG_O1], (&(*grp)[SPARC_MC_O1])); > __get_user(env->regwptr[WREG_O2], (&(*grp)[SPARC_MC_O2])); > @@ -456,18 +464,9 @@ void sparc64_set_context(CPUSPARCState *env) > __get_user(env->regwptr[WREG_O6], (&(*grp)[SPARC_MC_O6])); > __get_user(env->regwptr[WREG_O7], (&(*grp)[SPARC_MC_O7])); > > - __get_user(fp, &(ucp->tuc_mcontext.mc_fp)); > - __get_user(i7, &(ucp->tuc_mcontext.mc_i7)); > + __get_user(env->regwptr[WREG_FP], &(ucp->tuc_mcontext.mc_fp)); > + __get_user(env->regwptr[WREG_I7], &(ucp->tuc_mcontext.mc_i7)); > > - w_addr = TARGET_STACK_BIAS + env->regwptr[WREG_O6]; > - if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), > - abi_ulong) != 0) { > - goto do_sigsegv; > - } > - if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), > - abi_ulong) != 0) { > - goto do_sigsegv; > - } > /* FIXME this does not match how the kernel handles the FPU in > * its sparc64_set_context implementation. In particular the FPU > * is only restored if fenab is non-zero in: > @@ -501,7 +500,6 @@ void sparc64_get_context(CPUSPARCState *env) > struct target_ucontext *ucp; > target_mc_gregset_t *grp; > target_mcontext_t *mcp; > - abi_ulong fp, i7, w_addr; > int err; > unsigned int i; > target_sigset_t target_set; > @@ -553,6 +551,15 @@ void sparc64_get_context(CPUSPARCState *env) > __put_user(env->gregs[5], &((*grp)[SPARC_MC_G5])); > __put_user(env->gregs[6], &((*grp)[SPARC_MC_G6])); > __put_user(env->gregs[7], &((*grp)[SPARC_MC_G7])); > + > + /* > + * Note that unlike the kernel, we didn't need to mess with the > + * guest register window state to save it into a pt_regs to run > + * the kernel. So for us the guest's O regs are still in WREG_O* > + * (unlike the kernel which has put them in UREG_I* in a pt_regs) > + * and the fp and i7 are still in WREG_I6 and WREG_I7 and don't > + * need to be fished out of userspace memory. > + */ > __put_user(env->regwptr[WREG_O0], &((*grp)[SPARC_MC_O0])); > __put_user(env->regwptr[WREG_O1], &((*grp)[SPARC_MC_O1])); > __put_user(env->regwptr[WREG_O2], &((*grp)[SPARC_MC_O2])); > @@ -562,18 +569,8 @@ void sparc64_get_context(CPUSPARCState *env) > __put_user(env->regwptr[WREG_O6], &((*grp)[SPARC_MC_O6])); > __put_user(env->regwptr[WREG_O7], &((*grp)[SPARC_MC_O7])); > > - w_addr = TARGET_STACK_BIAS + env->regwptr[WREG_O6]; > - fp = i7 = 0; > - if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), > - abi_ulong) != 0) { > - goto do_sigsegv; > - } > - if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), > - abi_ulong) != 0) { > - goto do_sigsegv; > - } > - __put_user(fp, &(mcp->mc_fp)); > - __put_user(i7, &(mcp->mc_i7)); > + __put_user(env->regwptr[WREG_FP], &(mcp->mc_fp)); > + __put_user(env->regwptr[WREG_I7], &(mcp->mc_i7)); > > { > uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs; > Applied to my linux-user-for-5.2 branch. Thanks, Laurent ^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH for-5.2 3/3] linux-user/sparc: Don't zero high half of PC, NPC, PSR in sigreturn 2020-11-05 21:23 [PATCH for-5.2 0/3] linux-user: fix various sparc64 guest bugs Peter Maydell 2020-11-05 21:23 ` [PATCH for-5.2 1/3] linux-user/sparc: Fix errors in target_ucontext structures Peter Maydell 2020-11-05 21:23 ` [PATCH for-5.2 2/3] linux-user/sparc: Correct set/get_context handling of fp and i7 Peter Maydell @ 2020-11-05 21:23 ` Peter Maydell 2020-11-05 22:23 ` Richard Henderson 2020-11-10 6:55 ` Laurent Vivier 2020-11-10 12:56 ` [PATCH for-5.2 0/3] linux-user: fix various sparc64 guest bugs Mark Cave-Ayland 3 siblings, 2 replies; 15+ messages in thread From: Peter Maydell @ 2020-11-05 21:23 UTC (permalink / raw) To: qemu-devel Cc: Giuseppe Musacchio, Richard Henderson, Mark Cave-Ayland, Laurent Vivier The function do_sigreturn() tries to store the PC, NPC and PSR in uint32_t local variables, which implicitly drops the high half of these fields for 64-bit guests. The usual effect was that a guest which used signals would crash on return from a signal unless it was lucky enough to take it while the PC was in the low 4GB of the address space. In particular, Debian /bin/dash and /bin/bash would segfault after executing external commands. Use abi_ulong, which is the type these fields all have in the __siginfo_t struct. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- linux-user/sparc/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c index c315704b389..d12adc8e6ff 100644 --- a/linux-user/sparc/signal.c +++ b/linux-user/sparc/signal.c @@ -247,7 +247,7 @@ long do_sigreturn(CPUSPARCState *env) { abi_ulong sf_addr; struct target_signal_frame *sf; - uint32_t up_psr, pc, npc; + abi_ulong up_psr, pc, npc; target_sigset_t set; sigset_t host_set; int i; -- 2.20.1 ^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH for-5.2 3/3] linux-user/sparc: Don't zero high half of PC, NPC, PSR in sigreturn 2020-11-05 21:23 ` [PATCH for-5.2 3/3] linux-user/sparc: Don't zero high half of PC, NPC, PSR in sigreturn Peter Maydell @ 2020-11-05 22:23 ` Richard Henderson 2020-11-10 6:55 ` Laurent Vivier 1 sibling, 0 replies; 15+ messages in thread From: Richard Henderson @ 2020-11-05 22:23 UTC (permalink / raw) To: Peter Maydell, qemu-devel Cc: Giuseppe Musacchio, Mark Cave-Ayland, Laurent Vivier On 11/5/20 1:23 PM, Peter Maydell wrote: > The function do_sigreturn() tries to store the PC, NPC and PSR in > uint32_t local variables, which implicitly drops the high half of > these fields for 64-bit guests. > > The usual effect was that a guest which used signals would crash on > return from a signal unless it was lucky enough to take it while the > PC was in the low 4GB of the address space. In particular, Debian > /bin/dash and /bin/bash would segfault after executing external > commands. > > Use abi_ulong, which is the type these fields all have in the > __siginfo_t struct. > > Signed-off-by: Peter Maydell <peter.maydell@linaro.org> > --- > linux-user/sparc/signal.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) Reviewed-by: Richard Henderson <richard.henderson@linaro.org> r~ ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH for-5.2 3/3] linux-user/sparc: Don't zero high half of PC, NPC, PSR in sigreturn 2020-11-05 21:23 ` [PATCH for-5.2 3/3] linux-user/sparc: Don't zero high half of PC, NPC, PSR in sigreturn Peter Maydell 2020-11-05 22:23 ` Richard Henderson @ 2020-11-10 6:55 ` Laurent Vivier 1 sibling, 0 replies; 15+ messages in thread From: Laurent Vivier @ 2020-11-10 6:55 UTC (permalink / raw) To: Peter Maydell, qemu-devel Cc: Giuseppe Musacchio, Mark Cave-Ayland, Richard Henderson Le 05/11/2020 à 22:23, Peter Maydell a écrit : > The function do_sigreturn() tries to store the PC, NPC and PSR in > uint32_t local variables, which implicitly drops the high half of > these fields for 64-bit guests. > > The usual effect was that a guest which used signals would crash on > return from a signal unless it was lucky enough to take it while the > PC was in the low 4GB of the address space. In particular, Debian > /bin/dash and /bin/bash would segfault after executing external > commands. > > Use abi_ulong, which is the type these fields all have in the > __siginfo_t struct. > > Signed-off-by: Peter Maydell <peter.maydell@linaro.org> > --- > linux-user/sparc/signal.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c > index c315704b389..d12adc8e6ff 100644 > --- a/linux-user/sparc/signal.c > +++ b/linux-user/sparc/signal.c > @@ -247,7 +247,7 @@ long do_sigreturn(CPUSPARCState *env) > { > abi_ulong sf_addr; > struct target_signal_frame *sf; > - uint32_t up_psr, pc, npc; > + abi_ulong up_psr, pc, npc; > target_sigset_t set; > sigset_t host_set; > int i; > Applied to my linux-user-for-5.2 branch. Thanks, Laurent ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH for-5.2 0/3] linux-user: fix various sparc64 guest bugs 2020-11-05 21:23 [PATCH for-5.2 0/3] linux-user: fix various sparc64 guest bugs Peter Maydell ` (2 preceding siblings ...) 2020-11-05 21:23 ` [PATCH for-5.2 3/3] linux-user/sparc: Don't zero high half of PC, NPC, PSR in sigreturn Peter Maydell @ 2020-11-10 12:56 ` Mark Cave-Ayland 2020-11-10 13:01 ` Laurent Vivier 3 siblings, 1 reply; 15+ messages in thread From: Mark Cave-Ayland @ 2020-11-10 12:56 UTC (permalink / raw) To: Peter Maydell, qemu-devel Cc: Giuseppe Musacchio, Richard Henderson, Laurent Vivier On 05/11/2020 21:23, Peter Maydell wrote: > This set of patches fixes bugs which were preventing the > Debian sparc64 /bin/bash from running: > * the target_ucontext structure put the registers in the > wrong place (missing alignment specifier, mostly) > * the set_context and get_context traps weren't saving fp > and i7, which meant that guest code that did a longjmp would > crash shortly afterwards (SPARC64 uses these traps to > implement setjmp/longjmp) > * we were trying to stuff a 64-bit PC into a uint32_t in > sigreturn, which caused a SEGV on return from a signal handler > > Review very much desired in particular from anybody who understands > SPARC register windows and how we handle them in linux-user for > patch 2! The other patches are straightforward. > > This patchset is sufficient that I can at least chroot into > a Debian sparc64 chroot and run basic commands like 'ls' from > the shell prompt (together with Giuseppe Musacchio's patch that > fixes the stack_t struct). > > There are clearly a bunch of other bugs in sparc signal handling > (starting with the fact that rt_frame support is simply not > implemented, but there are also some XXX/FIXME comments about TSTATE > save/restore in set/get_context and about the FPU state in the signal > frame code). There's also a Coverity issue about accessing off the > end of the sregs[] array in the target_mc_fpu struct -- the error is > actually harmless (we're accessing into the space in the union for > dregs[16..31] which is what we want to be doing) but I'll probably > put together a patch to make Coverity happier. Thanks Peter! This has been broken for a very long time indeed. Once this is merged I should probably look at getting a test environment set up. ATB, Mark. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH for-5.2 0/3] linux-user: fix various sparc64 guest bugs 2020-11-10 12:56 ` [PATCH for-5.2 0/3] linux-user: fix various sparc64 guest bugs Mark Cave-Ayland @ 2020-11-10 13:01 ` Laurent Vivier 0 siblings, 0 replies; 15+ messages in thread From: Laurent Vivier @ 2020-11-10 13:01 UTC (permalink / raw) To: Mark Cave-Ayland, Peter Maydell, qemu-devel Cc: Giuseppe Musacchio, Richard Henderson Le 10/11/2020 à 13:56, Mark Cave-Ayland a écrit : > On 05/11/2020 21:23, Peter Maydell wrote: > >> This set of patches fixes bugs which were preventing the >> Debian sparc64 /bin/bash from running: >> * the target_ucontext structure put the registers in the >> wrong place (missing alignment specifier, mostly) >> * the set_context and get_context traps weren't saving fp >> and i7, which meant that guest code that did a longjmp would >> crash shortly afterwards (SPARC64 uses these traps to >> implement setjmp/longjmp) >> * we were trying to stuff a 64-bit PC into a uint32_t in >> sigreturn, which caused a SEGV on return from a signal handler >> >> Review very much desired in particular from anybody who understands >> SPARC register windows and how we handle them in linux-user for >> patch 2! The other patches are straightforward. >> >> This patchset is sufficient that I can at least chroot into >> a Debian sparc64 chroot and run basic commands like 'ls' from >> the shell prompt (together with Giuseppe Musacchio's patch that >> fixes the stack_t struct). >> >> There are clearly a bunch of other bugs in sparc signal handling >> (starting with the fact that rt_frame support is simply not >> implemented, but there are also some XXX/FIXME comments about TSTATE >> save/restore in set/get_context and about the FPU state in the signal >> frame code). There's also a Coverity issue about accessing off the >> end of the sregs[] array in the target_mc_fpu struct -- the error is >> actually harmless (we're accessing into the space in the union for >> dregs[16..31] which is what we want to be doing) but I'll probably >> put together a patch to make Coverity happier. > > Thanks Peter! This has been broken for a very long time indeed. Once > this is merged I should probably look at getting a test environment set up. +1 With these patches, on sparc, debootstrap (wheezy) has some issues but after some hacks around the packages I've been able to build and run LTP. on sparc64, debootstrap (sid) seems to work well but after that there are some issues with apt (URI error) Thanks, Laurent ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2020-11-10 13:03 UTC | newest] Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-11-05 21:23 [PATCH for-5.2 0/3] linux-user: fix various sparc64 guest bugs Peter Maydell 2020-11-05 21:23 ` [PATCH for-5.2 1/3] linux-user/sparc: Fix errors in target_ucontext structures Peter Maydell 2020-11-05 22:15 ` Richard Henderson 2020-11-05 23:36 ` Peter Maydell 2020-11-10 6:53 ` Laurent Vivier 2020-11-10 9:02 ` LemonBoy 2020-11-10 9:41 ` Laurent Vivier 2020-11-05 21:23 ` [PATCH for-5.2 2/3] linux-user/sparc: Correct set/get_context handling of fp and i7 Peter Maydell 2020-11-05 22:22 ` Richard Henderson 2020-11-10 6:53 ` Laurent Vivier 2020-11-05 21:23 ` [PATCH for-5.2 3/3] linux-user/sparc: Don't zero high half of PC, NPC, PSR in sigreturn Peter Maydell 2020-11-05 22:23 ` Richard Henderson 2020-11-10 6:55 ` Laurent Vivier 2020-11-10 12:56 ` [PATCH for-5.2 0/3] linux-user: fix various sparc64 guest bugs Mark Cave-Ayland 2020-11-10 13:01 ` Laurent Vivier
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.