ppc patch queue for 2022-07-28:

Short queue with 2 Coverity fixes and one fix of the
 'wait' insns that is causing hangs if the guest kernel uses
 the most up to date wait opcode.
 
 - target/ppc:
   - implement new wait variants to fix guest hang when using the new opcode
 - ppc440_uc: initialize length passed to cpu_physical_memory_map()
 - spapr_nvdimm: check if spapr_drc_index() returns NULL
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQQX6/+ZI9AYAK8oOBk82cqW3gMxZAUCYuK8VgAKCRA82cqW3gMx
 ZOc7AQDPMsFY9NHNqJ3O0MiX4Qoy8IGUreZ9dzZSS3zT1nxtEAD+Lwl0/aGO+dk+
 +NiIO80A5Agy/0g8PHie4qR3EqHEnwA=
 =Q4eR
 -----END PGP SIGNATURE-----

Merge tag 'pull-ppc-20220728' of https://gitlab.com/danielhb/qemu into staging

ppc patch queue for 2022-07-28:

Short queue with 2 Coverity fixes and one fix of the
'wait' insns that is causing hangs if the guest kernel uses
the most up to date wait opcode.

- target/ppc:
  - implement new wait variants to fix guest hang when using the new opcode
- ppc440_uc: initialize length passed to cpu_physical_memory_map()
- spapr_nvdimm: check if spapr_drc_index() returns NULL

# -----BEGIN PGP SIGNATURE-----
#
# iHUEABYKAB0WIQQX6/+ZI9AYAK8oOBk82cqW3gMxZAUCYuK8VgAKCRA82cqW3gMx
# ZOc7AQDPMsFY9NHNqJ3O0MiX4Qoy8IGUreZ9dzZSS3zT1nxtEAD+Lwl0/aGO+dk+
# +NiIO80A5Agy/0g8PHie4qR3EqHEnwA=
# =Q4eR
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu 28 Jul 2022 09:41:58 AM PDT
# gpg:                using EDDSA key 17EBFF9923D01800AF2838193CD9CA96DE033164
# gpg: Good signature from "Daniel Henrique Barboza <danielhb413@gmail.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 17EB FF99 23D0 1800 AF28  3819 3CD9 CA96 DE03 3164

* tag 'pull-ppc-20220728' of https://gitlab.com/danielhb/qemu:
  target/ppc: Implement new wait variants
  hw/ppc/ppc440_uc: Initialize length passed to cpu_physical_memory_map()
  hw/ppc: check if spapr_drc_index() returns NULL in spapr_nvdimm.c

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2022-07-28 15:06:42 -07:00
commit cc42559ab1
4 changed files with 109 additions and 13 deletions

View File

@ -904,14 +904,17 @@ static void dcr_write_dma(void *opaque, int dcrn, uint32_t val)
int width, i, sidx, didx;
uint8_t *rptr, *wptr;
hwaddr rlen, wlen;
hwaddr xferlen;
sidx = didx = 0;
width = 1 << ((val & DMA0_CR_PW) >> 25);
xferlen = count * width;
wlen = rlen = xferlen;
rptr = cpu_physical_memory_map(dma->ch[chnl].sa, &rlen,
false);
wptr = cpu_physical_memory_map(dma->ch[chnl].da, &wlen,
true);
if (rptr && wptr) {
if (rptr && rlen == xferlen && wptr && wlen == xferlen) {
if (!(val & DMA0_CR_DEC) &&
val & DMA0_CR_SAI && val & DMA0_CR_DAI) {
/* optimise common case */

View File

@ -447,9 +447,15 @@ static int flush_worker_cb(void *opaque)
{
SpaprNVDIMMDeviceFlushState *state = opaque;
SpaprDrc *drc = spapr_drc_by_index(state->drcidx);
PCDIMMDevice *dimm = PC_DIMM(drc->dev);
HostMemoryBackend *backend = MEMORY_BACKEND(dimm->hostmem);
int backend_fd = memory_region_get_fd(&backend->mr);
PCDIMMDevice *dimm;
HostMemoryBackend *backend;
int backend_fd;
g_assert(drc != NULL);
dimm = PC_DIMM(drc->dev);
backend = MEMORY_BACKEND(dimm->hostmem);
backend_fd = memory_region_get_fd(&backend->mr);
if (object_property_get_bool(OBJECT(backend), "pmem", NULL)) {
MemoryRegion *mr = host_memory_backend_get_memory(dimm->hostmem);
@ -475,7 +481,11 @@ static void spapr_nvdimm_flush_completion_cb(void *opaque, int hcall_ret)
{
SpaprNVDIMMDeviceFlushState *state = opaque;
SpaprDrc *drc = spapr_drc_by_index(state->drcidx);
SpaprNVDIMMDevice *s_nvdimm = SPAPR_NVDIMM(drc->dev);
SpaprNVDIMMDevice *s_nvdimm;
g_assert(drc != NULL);
s_nvdimm = SPAPR_NVDIMM(drc->dev);
state->hcall_ret = hcall_ret;
QLIST_REMOVE(state, node);

View File

@ -165,6 +165,9 @@ EXTRACT_HELPER_SPLIT_3(DX, 10, 6, 6, 5, 16, 1, 1, 0, 0)
/* darn */
EXTRACT_HELPER(L, 16, 2);
#endif
/* wait */
EXTRACT_HELPER(WC, 21, 2);
EXTRACT_HELPER(PL, 16, 2);
/*** Jump target decoding ***/
/* Immediate address */

View File

@ -4071,12 +4071,91 @@ static void gen_sync(DisasContext *ctx)
/* wait */
static void gen_wait(DisasContext *ctx)
{
TCGv_i32 t0 = tcg_const_i32(1);
tcg_gen_st_i32(t0, cpu_env,
-offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
tcg_temp_free_i32(t0);
/* Stop translation, as the CPU is supposed to sleep from now */
gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
uint32_t wc;
if (ctx->insns_flags & PPC_WAIT) {
/* v2.03-v2.07 define an older incompatible 'wait' encoding. */
if (ctx->insns_flags2 & PPC2_PM_ISA206) {
/* v2.06 introduced the WC field. WC > 0 may be treated as no-op. */
wc = WC(ctx->opcode);
} else {
wc = 0;
}
} else if (ctx->insns_flags2 & PPC2_ISA300) {
/* v3.0 defines a new 'wait' encoding. */
wc = WC(ctx->opcode);
if (ctx->insns_flags2 & PPC2_ISA310) {
uint32_t pl = PL(ctx->opcode);
/* WC 1,2 may be treated as no-op. WC 3 is reserved. */
if (wc == 3) {
gen_invalid(ctx);
return;
}
/* PL 1-3 are reserved. If WC=2 then the insn is treated as noop. */
if (pl > 0 && wc != 2) {
gen_invalid(ctx);
return;
}
} else { /* ISA300 */
/* WC 1-3 are reserved */
if (wc > 0) {
gen_invalid(ctx);
return;
}
}
} else {
warn_report("wait instruction decoded with wrong ISA flags.");
gen_invalid(ctx);
return;
}
/*
* wait without WC field or with WC=0 waits for an exception / interrupt
* to occur.
*/
if (wc == 0) {
TCGv_i32 t0 = tcg_const_i32(1);
tcg_gen_st_i32(t0, cpu_env,
-offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
tcg_temp_free_i32(t0);
/* Stop translation, as the CPU is supposed to sleep from now */
gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
}
/*
* Other wait types must not just wait until an exception occurs because
* ignoring their other wake-up conditions could cause a hang.
*
* For v2.06 and 2.07, wc=1,2,3 are architected but may be implemented as
* no-ops.
*
* wc=1 and wc=3 explicitly allow the instruction to be treated as a no-op.
*
* wc=2 waits for an implementation-specific condition, such could be
* always true, so it can be implemented as a no-op.
*
* For v3.1, wc=1,2 are architected but may be implemented as no-ops.
*
* wc=1 (waitrsv) waits for an exception or a reservation to be lost.
* Reservation-loss may have implementation-specific conditions, so it
* can be implemented as a no-op.
*
* wc=2 waits for an exception or an amount of time to pass. This
* amount is implementation-specific so it can be implemented as a
* no-op.
*
* ISA v3.1 allows for execution to resume "in the rare case of
* an implementation-dependent event", so in any case software must
* not depend on the architected resumption condition to become
* true, so no-op implementations should be architecturally correct
* (if suboptimal).
*/
}
#if defined(TARGET_PPC64)
@ -6691,8 +6770,9 @@ GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B),
GEN_HANDLER_E(stqcx_, 0x1F, 0x16, 0x05, 0, PPC_NONE, PPC2_LSQ_ISA207),
#endif
GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC),
GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT),
GEN_HANDLER_E(wait, 0x1F, 0x1E, 0x00, 0x039FF801, PPC_NONE, PPC2_ISA300),
/* ISA v3.0 changed the extended opcode from 62 to 30 */
GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x039FF801, PPC_WAIT),
GEN_HANDLER_E(wait, 0x1F, 0x1E, 0x00, 0x039CF801, PPC_NONE, PPC2_ISA300),
GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW),
GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW),