Some linux-user/sparc fixes

-----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAl+qT5kSHGxhdXJlbnRA
 dml2aWVyLmV1AAoJEPMMOL0/L748PWIP/iBQgmTEd++g54aIvB/qWRMKPPXpqT3i
 YIX6yAPEKKaYFdQfHIZd1XLUd85Q33uu7Qeh55wIwjiFcFfnYRou6oDxiF9w3Ds1
 Ltl1DQZbi63Kif13aTbFlBQC1ggHmCLFXY7E7upNCvOv9mSq87rOoOviC60hWgXg
 9E2u2qhqy1wk9fJOj3t2+VjGAdNQHnBlyQRVGgJhqejC33hrZOPyMEwRlkXFBogY
 h3LPjOLgbAl5R8sDE4p4ugmWnhqoLF9qUQiXCNT93ol8Boj3BNyym88ptBlOdBdE
 UW4UTuT0VMItPNZG2aGOPqDiHLPM4AqBRtJfeMHg2Gxk7fm+oA5GhASQwtrbvGBf
 ND4+aJF+roqfrFe/oKQIU3PgLd8I7blpChu+Qo0K9bWIrt7/JGgx1AR5iX8n+2GV
 Av6r45xsJmRRlfIsZbhmNWLmSxs/80rowbABqUrdU3bgvs8S0Fjy2dZyAc6eiGjd
 KuXOKoNeZk8Q0XqLPWTfXeqom+uUqvP8bDHcUnxJj98+Xqi/WdzKAl70QDU5X+MO
 xOYR0mJ096aRtCwTf+36fO3ayrypzFsoiumXEowXuDI7ww8FCmbm3uoeRm/3at8X
 FmW94J3V9iHyNkqofzhWjxNkAUt6OpefIiHcNJAg0/ROlKv17BgjYRIjFIc6KFge
 JYd4mnk3CbjU
 =9iAg
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-5.2-pull-request' into staging

Some linux-user/sparc fixes

# gpg: Signature made Tue 10 Nov 2020 08:30:17 GMT
# gpg:                using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C
# gpg:                issuer "laurent@vivier.eu"
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full]
# gpg:                 aka "Laurent Vivier <laurent@vivier.eu>" [full]
# gpg:                 aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full]
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F  5173 F30C 38BD 3F2F BE3C

* remotes/vivier2/tags/linux-user-for-5.2-pull-request:
  linux-user/sparc: Don't zero high half of PC, NPC, PSR in sigreturn
  linux-user/sparc: Correct set/get_context handling of fp and i7
  linux-user/sparc: Fix errors in target_ucontext structures

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
master
Peter Maydell 2020-11-10 10:54:48 +00:00
commit 6c8e801f07
1 changed files with 32 additions and 30 deletions

View File

@ -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;
@ -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;
@ -398,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];
@ -442,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]));
@ -451,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:
@ -496,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;
@ -548,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]));
@ -557,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;