Skip to content

Commit

Permalink
target/ppc: Fix regression in Radix MMU
Browse files Browse the repository at this point in the history
Commit 47e83d9 ended up unintentionally changing the control flow
of ppc_radix64_process_scoped_xlate(). When guest_visible is false,
it must not raise an exception, even if the radix configuration is
not valid.

This regression prevented Linux boot in a nested environment with
L1 using TCG and emulating KVM (cap-nested-hv=on) and L2 using
KVM. L2 would hang on Linux's futex_init(), when it tested how a
futex_atomic_cmpxchg_inatomic() handled a fault, because L1 would
start a loop of trying to perform partition scoped translations
and raising exceptions.

Fixes: 47e83d9 ("target/ppc: Improve Radix xlate level validation")
Reported-by: Victor Colombo <victor.colombo@eldorado.org.br>
Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
Tested-by: Víctor Colombo <victor.colombo@eldorado.org.br>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Message-Id: <20221028183617.121786-1-leandro.lupori@eldorado.org.br>
[danielhb: use %"PRIu64" to print 'nls']
Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
  • Loading branch information
Leandro Lupori authored and danielhb committed Oct 29, 2022
1 parent 63e4bf8 commit fb22d74
Showing 1 changed file with 21 additions and 8 deletions.
29 changes: 21 additions & 8 deletions target/ppc/mmu-radix64.c
Expand Up @@ -238,6 +238,8 @@ static void ppc_radix64_set_rc(PowerPCCPU *cpu, MMUAccessType access_type,

static bool ppc_radix64_is_valid_level(int level, int psize, uint64_t nls)
{
bool ret;

/*
* Check if this is a valid level, according to POWER9 and POWER10
* Processor User's Manuals, sections 4.10.4.1 and 5.10.6.1, respectively:
Expand All @@ -249,16 +251,25 @@ static bool ppc_radix64_is_valid_level(int level, int psize, uint64_t nls)
*/
switch (level) {
case 0: /* Root Page Dir */
return psize == 52 && nls == 13;
ret = psize == 52 && nls == 13;
break;
case 1:
case 2:
return nls == 9;
ret = nls == 9;
break;
case 3:
return nls == 9 || nls == 5;
ret = nls == 9 || nls == 5;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "invalid radix level: %d\n", level);
return false;
ret = false;
}

if (unlikely(!ret)) {
qemu_log_mask(LOG_GUEST_ERROR, "invalid radix configuration: "
"level %d size %d nls %"PRIu64"\n",
level, psize, nls);
}
return ret;
}

static int ppc_radix64_next_level(AddressSpace *as, vaddr eaddr,
Expand Down Expand Up @@ -519,11 +530,13 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu,

if (!ppc_radix64_is_valid_level(level++, *g_page_size, nls)) {
fault_cause |= DSISR_R_BADCONFIG;
return 1;
ret = 1;
} else {
ret = ppc_radix64_next_level(cs->as, eaddr & R_EADDR_MASK,
&h_raddr, &nls, g_page_size,
&pte, &fault_cause);
}

ret = ppc_radix64_next_level(cs->as, eaddr & R_EADDR_MASK, &h_raddr,
&nls, g_page_size, &pte, &fault_cause);
if (ret) {
/* No valid pte */
if (guest_visible) {
Expand Down

0 comments on commit fb22d74

Please sign in to comment.