target/ppc: fix Hash64 MMU update of PTE bit R

When updating the R bit of a PTE, the Hash64 MMU was using a wrong byte
offset, causing the first byte of the adjacent PTE to be corrupted.
This caused a panic when booting FreeBSD, using the Hash MMU.

Fixes: a2dd4e83e7 ("ppc/hash64: Rework R and C bit updates")
Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
This commit is contained in:
Leandro Lupori 2021-11-29 15:57:51 -03:00 committed by Cédric Le Goater
parent a0fd8a5492
commit 7bf00dfb51
4 changed files with 12 additions and 7 deletions

View File

@ -1414,7 +1414,7 @@ void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
kvmppc_write_hpte(ptex, pte0, pte1); kvmppc_write_hpte(ptex, pte0, pte1);
} else { } else {
if (pte0 & HPTE64_V_VALID) { if (pte0 & HPTE64_V_VALID) {
stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); stq_p(spapr->htab + offset + HPTE64_DW1, pte1);
/* /*
* When setting valid, we write PTE1 first. This ensures * When setting valid, we write PTE1 first. This ensures
* proper synchronization with the reading code in * proper synchronization with the reading code in
@ -1430,7 +1430,7 @@ void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
* ppc_hash64_pteg_search() * ppc_hash64_pteg_search()
*/ */
smp_wmb(); smp_wmb();
stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); stq_p(spapr->htab + offset + HPTE64_DW1, pte1);
} }
} }
} }
@ -1438,7 +1438,7 @@ void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
static void spapr_hpte_set_c(PPCVirtualHypervisor *vhyp, hwaddr ptex, static void spapr_hpte_set_c(PPCVirtualHypervisor *vhyp, hwaddr ptex,
uint64_t pte1) uint64_t pte1)
{ {
hwaddr offset = ptex * HASH_PTE_SIZE_64 + 15; hwaddr offset = ptex * HASH_PTE_SIZE_64 + HPTE64_DW1_C;
SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
if (!spapr->htab) { if (!spapr->htab) {
@ -1454,7 +1454,7 @@ static void spapr_hpte_set_c(PPCVirtualHypervisor *vhyp, hwaddr ptex,
static void spapr_hpte_set_r(PPCVirtualHypervisor *vhyp, hwaddr ptex, static void spapr_hpte_set_r(PPCVirtualHypervisor *vhyp, hwaddr ptex,
uint64_t pte1) uint64_t pte1)
{ {
hwaddr offset = ptex * HASH_PTE_SIZE_64 + 14; hwaddr offset = ptex * HASH_PTE_SIZE_64 + HPTE64_DW1_R;
SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
if (!spapr->htab) { if (!spapr->htab) {

View File

@ -426,7 +426,7 @@ static void new_hpte_store(void *htab, uint64_t pteg, int slot,
addr += slot * HASH_PTE_SIZE_64; addr += slot * HASH_PTE_SIZE_64;
stq_p(addr, pte0); stq_p(addr, pte0);
stq_p(addr + HASH_PTE_SIZE_64 / 2, pte1); stq_p(addr + HPTE64_DW1, pte1);
} }
static int rehash_hpte(PowerPCCPU *cpu, static int rehash_hpte(PowerPCCPU *cpu,

View File

@ -786,7 +786,7 @@ static void ppc_hash64_set_dsi(CPUState *cs, int mmu_idx, uint64_t dar, uint64_t
static void ppc_hash64_set_r(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1) static void ppc_hash64_set_r(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1)
{ {
hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 16; hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + HPTE64_DW1_R;
if (cpu->vhyp) { if (cpu->vhyp) {
PPCVirtualHypervisorClass *vhc = PPCVirtualHypervisorClass *vhc =
@ -803,7 +803,7 @@ static void ppc_hash64_set_r(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1)
static void ppc_hash64_set_c(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1) static void ppc_hash64_set_c(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1)
{ {
hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 15; hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + HPTE64_DW1_C;
if (cpu->vhyp) { if (cpu->vhyp) {
PPCVirtualHypervisorClass *vhc = PPCVirtualHypervisorClass *vhc =

View File

@ -97,6 +97,11 @@ void ppc_hash64_finalize(PowerPCCPU *cpu);
#define HPTE64_V_1TB_SEG 0x4000000000000000ULL #define HPTE64_V_1TB_SEG 0x4000000000000000ULL
#define HPTE64_V_VRMA_MASK 0x4001ffffff000000ULL #define HPTE64_V_VRMA_MASK 0x4001ffffff000000ULL
/* PTE offsets */
#define HPTE64_DW1 (HASH_PTE_SIZE_64 / 2)
#define HPTE64_DW1_R (HPTE64_DW1 + 6)
#define HPTE64_DW1_C (HPTE64_DW1 + 7)
/* Format changes for ARCH v3 */ /* Format changes for ARCH v3 */
#define HPTE64_V_COMMON_BITS 0x000fffffffffffffULL #define HPTE64_V_COMMON_BITS 0x000fffffffffffffULL
#define HPTE64_R_3_0_SSIZE_SHIFT 58 #define HPTE64_R_3_0_SSIZE_SHIFT 58