qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

linux-user/ppc: Fix padding in mcontext_t for ppc64

The padding that was added in 95cda4c44ee was added to a union,
and so it had no effect. This fixes misalignment errors detected
by clang sanitizers for ppc64 and ppc64le.

In addition, only ppc64 allocates space for VSX registers, so do
not save them for ppc32. The kernel only has references to
CONFIG_SPE in signal_32.c, so do not attempt to save them for ppc64.

Fixes: 95cda4c44ee
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20200407032105.26711-1-richard.henderson@linaro.org>
Acked-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

authored by

Richard Henderson and committed by
David Gibson
5da5f47e 20038cd7

+29 -40
+29 -40
linux-user/ppc/signal.c
··· 35 35 target_ulong mc_gregs[48]; 36 36 /* Includes fpscr. */ 37 37 uint64_t mc_fregs[33]; 38 + 38 39 #if defined(TARGET_PPC64) 39 40 /* Pointer to the vector regs */ 40 41 target_ulong v_regs; 42 + /* 43 + * On ppc64, this mcontext structure is naturally *unaligned*, 44 + * or rather it is aligned on a 8 bytes boundary but not on 45 + * a 16 byte boundary. This pad fixes it up. This is why we 46 + * cannot use ppc_avr_t, which would force alignment. This is 47 + * also why the vector regs are referenced in the ABI by the 48 + * v_regs pointer above so any amount of padding can be added here. 49 + */ 50 + target_ulong pad; 51 + /* VSCR and VRSAVE are saved separately. Also reserve space for VSX. */ 52 + struct { 53 + uint64_t altivec[34 + 16][2]; 54 + } mc_vregs; 41 55 #else 42 56 target_ulong mc_pad[2]; 43 - #endif 57 + 44 58 /* We need to handle Altivec and SPE at the same time, which no 45 59 kernel needs to do. Fortunately, the kernel defines this bit to 46 60 be Altivec-register-large all the time, rather than trying to ··· 48 62 union { 49 63 /* SPE vector registers. One extra for SPEFSCR. */ 50 64 uint32_t spe[33]; 51 - /* Altivec vector registers. The packing of VSCR and VRSAVE 52 - varies depending on whether we're PPC64 or not: PPC64 splits 53 - them apart; PPC32 stuffs them together. 54 - We also need to account for the VSX registers on PPC64 55 - */ 56 - #if defined(TARGET_PPC64) 57 - #define QEMU_NVRREG (34 + 16) 58 - /* On ppc64, this mcontext structure is naturally *unaligned*, 59 - * or rather it is aligned on a 8 bytes boundary but not on 60 - * a 16 bytes one. This pad fixes it up. This is also why the 61 - * vector regs are referenced by the v_regs pointer above so 62 - * any amount of padding can be added here 65 + /* 66 + * Altivec vector registers. One extra for VRSAVE. 67 + * On ppc32, we are already aligned to 16 bytes. We could 68 + * use ppc_avr_t, but choose to share the same type as ppc64. 63 69 */ 64 - target_ulong pad; 65 - #else 66 - /* On ppc32, we are already aligned to 16 bytes */ 67 - #define QEMU_NVRREG 33 70 + uint64_t altivec[33][2]; 71 + } mc_vregs; 68 72 #endif 69 - /* We cannot use ppc_avr_t here as we do *not* want the implied 70 - * 16-bytes alignment that would result from it. This would have 71 - * the effect of making the whole struct target_mcontext aligned 72 - * which breaks the layout of struct target_ucontext on ppc64. 73 - */ 74 - uint64_t altivec[QEMU_NVRREG][2]; 75 - #undef QEMU_NVRREG 76 - } mc_vregs; 77 73 }; 78 74 79 75 /* See arch/powerpc/include/asm/sigcontext.h. */ ··· 278 274 __put_user((uint32_t)env->spr[SPR_VRSAVE], vrsave); 279 275 } 280 276 277 + #if defined(TARGET_PPC64) 281 278 /* Save VSX second halves */ 282 279 if (env->insns_flags2 & PPC2_VSX) { 283 280 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34]; ··· 286 283 __put_user(*vsrl, &vsregs[i]); 287 284 } 288 285 } 286 + #endif 289 287 290 288 /* Save floating point registers. */ 291 289 if (env->insns_flags & PPC_FLOAT) { ··· 296 294 __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]); 297 295 } 298 296 297 + #if !defined(TARGET_PPC64) 299 298 /* Save SPE registers. The kernel only saves the high half. */ 300 299 if (env->insns_flags & PPC_SPE) { 301 - #if defined(TARGET_PPC64) 302 - for (i = 0; i < ARRAY_SIZE(env->gpr); i++) { 303 - __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]); 304 - } 305 - #else 306 300 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) { 307 301 __put_user(env->gprh[i], &frame->mc_vregs.spe[i]); 308 302 } 309 - #endif 310 303 /* Set MSR_SPE in the saved MSR value to indicate that 311 304 frame->mc_vregs contains valid data. */ 312 305 msr |= MSR_SPE; 313 306 __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]); 314 307 } 308 + #endif 315 309 316 310 /* Store MSR. */ 317 311 __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]); ··· 392 386 __get_user(env->spr[SPR_VRSAVE], vrsave); 393 387 } 394 388 389 + #if defined(TARGET_PPC64) 395 390 /* Restore VSX second halves */ 396 391 if (env->insns_flags2 & PPC2_VSX) { 397 392 uint64_t *vsregs = (uint64_t *)&frame->mc_vregs.altivec[34]; ··· 400 395 __get_user(*vsrl, &vsregs[i]); 401 396 } 402 397 } 398 + #endif 403 399 404 400 /* Restore floating point registers. */ 405 401 if (env->insns_flags & PPC_FLOAT) { ··· 412 408 env->fpscr = (uint32_t) fpscr; 413 409 } 414 410 411 + #if !defined(TARGET_PPC64) 415 412 /* Save SPE registers. The kernel only saves the high half. */ 416 413 if (env->insns_flags & PPC_SPE) { 417 - #if defined(TARGET_PPC64) 418 - for (i = 0; i < ARRAY_SIZE(env->gpr); i++) { 419 - uint32_t hi; 420 - 421 - __get_user(hi, &frame->mc_vregs.spe[i]); 422 - env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]); 423 - } 424 - #else 425 414 for (i = 0; i < ARRAY_SIZE(env->gprh); i++) { 426 415 __get_user(env->gprh[i], &frame->mc_vregs.spe[i]); 427 416 } 428 - #endif 429 417 __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]); 430 418 } 419 + #endif 431 420 } 432 421 433 422 #if !defined(TARGET_PPC64)