Message ID | 1467096514-18905-2-git-send-email-clg@kaod.org |
---|---|
State | New |
Headers | show |
On Tue, Jun 28, 2016 at 08:48:33AM +0200, Cédric Le Goater wrote: > From: Benjamin Herrenschmidt <benh@kernel.crashing.org> > > This adds proper support for translating real mode addresses based > on the combination of HV and LPCR bits. This handles HRMOR offset > for hypervisor real mode, and both RMA and VRMA modes for guest > real mode. PAPR mode adjusts the offsets appropriately to match the > RMA used in TCG, but we need to limit to the max supported by the > implementation (16G). > > Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> > [clg: fixed checkpatch.pl errors ] > Signed-off-by: Cédric Le Goater <clg@kaod.org> This looks correct and I've applied it. There are a couple of possible cleanups which might be a good idea to follow up with though. > --- > hw/ppc/spapr.c | 7 +++ > target-ppc/mmu-hash64.c | 146 ++++++++++++++++++++++++++++++++++++++------ > target-ppc/mmu-hash64.h | 1 + > target-ppc/translate_init.c | 10 ++- > 4 files changed, 144 insertions(+), 20 deletions(-) > > diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > index d26b4c26ed10..53ab1f84fb11 100644 > --- a/hw/ppc/spapr.c > +++ b/hw/ppc/spapr.c > @@ -1770,6 +1770,13 @@ static void ppc_spapr_init(MachineState *machine) > spapr->vrma_adjust = 1; > spapr->rma_size = MIN(spapr->rma_size, 0x10000000); > } > + > + /* Actually we don't support unbounded RMA anymore since we > + * added proper emulation of HV mode. The max we can get is > + * 16G which also happens to be what we configure for PAPR > + * mode so make sure we don't do anything bigger than that > + */ > + spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull); #1 - Instead of the various KVM / non-KVM cases here, it might be simpler to just always clamp the RMA to 256MiB. > } > > if (spapr->rma_size > node0_size) { > diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c > index 6d6f26c92957..ed353b2d1539 100644 > --- a/target-ppc/mmu-hash64.c > +++ b/target-ppc/mmu-hash64.c > @@ -653,13 +653,41 @@ static void ppc_hash64_set_dsi(CPUState *cs, CPUPPCState *env, uint64_t dar, > env->error_code = 0; > } > > +static int64_t ppc_hash64_get_rmls(CPUPPCState *env) > +{ > + uint64_t lpcr = env->spr[SPR_LPCR]; > + > + /* > + * This is the full 4 bits encoding of POWER8. Previous > + * CPUs only support a subset of these but the filtering > + * is done when writing LPCR > + */ > + switch ((lpcr & LPCR_RMLS) >> LPCR_RMLS_SHIFT) { > + case 0x8: /* 32MB */ > + return 0x2000000ull; > + case 0x3: /* 64MB */ > + return 0x4000000ull; > + case 0x7: /* 128MB */ > + return 0x8000000ull; > + case 0x4: /* 256MB */ > + return 0x10000000ull; > + case 0x2: /* 1GB */ > + return 0x40000000ull; > + case 0x1: /* 16GB */ > + return 0x400000000ull; > + default: > + /* What to do here ??? */ > + return 0; > + } > +} > > int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, > int rwx, int mmu_idx) > { > CPUState *cs = CPU(cpu); > CPUPPCState *env = &cpu->env; > - ppc_slb_t *slb; > + ppc_slb_t *slb_ptr; > + ppc_slb_t slb; > unsigned apshift; > hwaddr pte_offset; > ppc_hash_pte64_t pte; > @@ -670,11 +698,53 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, > > assert((rwx == 0) || (rwx == 1) || (rwx == 2)); > > + /* Note on LPCR usage: 970 uses HID4, but our special variant > + * of store_spr copies relevant fields into env->spr[SPR_LPCR]. > + * Similarily we filter unimplemented bits when storing into > + * LPCR depending on the MMU version. This code can thus just > + * use the LPCR "as-is". > + */ > + > /* 1. Handle real mode accesses */ > if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) { > - /* Translation is off */ > - /* In real mode the top 4 effective address bits are ignored */ > + /* Translation is supposedly "off" */ > + /* In real mode the top 4 effective address bits are (mostly) ignored */ > raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL; > + > + /* In HV mode, add HRMOR if top EA bit is clear */ > + if (msr_hv) { > + if (!(eaddr >> 63)) { > + raddr |= env->spr[SPR_HRMOR]; > + } > + } else { > + /* Otherwise, check VPM for RMA vs VRMA */ > + if (env->spr[SPR_LPCR] & LPCR_VPM0) { > + uint32_t vrmasd; > + /* VRMA, we make up an SLB entry */ > + slb.vsid = SLB_VSID_VRMA; > + vrmasd = (env->spr[SPR_LPCR] & LPCR_VRMASD) >> > + LPCR_VRMASD_SHIFT; > + slb.vsid |= (vrmasd << 4) & (SLB_VSID_L | SLB_VSID_LP); > + slb.esid = SLB_ESID_V; > + goto skip_slb; > + } > + /* RMA. Check bounds in RMLS */ > + if (raddr < ppc_hash64_get_rmls(env)) { > + raddr |= env->spr[SPR_RMOR]; > + } else { > + /* The access failed, generate the approriate interrupt */ > + if (rwx == 2) { > + ppc_hash64_set_isi(cs, env, 0x08000000); > + } else { > + dsisr = 0x08000000; > + if (rwx == 1) { > + dsisr |= 0x02000000; > + } > + ppc_hash64_set_dsi(cs, env, eaddr, dsisr); > + } > + return 1; > + } > + } > tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, > PAGE_READ | PAGE_WRITE | PAGE_EXEC, mmu_idx, > TARGET_PAGE_SIZE); > @@ -682,9 +752,8 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, > } > > /* 2. Translation is on, so look up the SLB */ > - slb = slb_lookup(cpu, eaddr); > - > - if (!slb) { > + slb_ptr = slb_lookup(cpu, eaddr); > + if (!slb_ptr) { > if (rwx == 2) { > cs->exception_index = POWERPC_EXCP_ISEG; > env->error_code = 0; > @@ -696,14 +765,29 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, > return 1; > } > > + /* We grab a local copy because we can modify it (or get a > + * pre-cooked one from the VRMA code > + */ > + slb = *slb_ptr; > + > + /* 2.5 Clamp L||LP in ISL mode */ > + if (env->spr[SPR_LPCR] & LPCR_ISL) { > + slb.vsid &= ~SLB_VSID_LLP_MASK; > + } > + > /* 3. Check for segment level no-execute violation */ > - if ((rwx == 2) && (slb->vsid & SLB_VSID_N)) { > + if ((rwx == 2) && (slb.vsid & SLB_VSID_N)) { > ppc_hash64_set_isi(cs, env, 0x10000000); > return 1; > } > > + /* We go straight here for VRMA translations as none of the > + * above applies in that case > + */ > + skip_slb: > + > /* 4. Locate the PTE in the hash table */ > - pte_offset = ppc_hash64_htab_lookup(cpu, slb, eaddr, &pte); > + pte_offset = ppc_hash64_htab_lookup(cpu, &slb, eaddr, &pte); > if (pte_offset == -1) { > dsisr = 0x40000000; > if (rwx == 2) { > @@ -720,7 +804,7 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, > "found PTE at offset %08" HWADDR_PRIx "\n", pte_offset); > > /* Validate page size encoding */ > - apshift = hpte_page_shift(slb->sps, pte.pte0, pte.pte1); > + apshift = hpte_page_shift(slb.sps, pte.pte0, pte.pte1); > if (!apshift) { > error_report("Bad page size encoding in HPTE 0x%"PRIx64" - 0x%"PRIx64 > " @ 0x%"HWADDR_PRIx, pte.pte0, pte.pte1, pte_offset); > @@ -733,7 +817,7 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, > > /* 5. Check access permissions */ > > - pp_prot = ppc_hash64_pte_prot(cpu, slb, pte); > + pp_prot = ppc_hash64_pte_prot(cpu, &slb, pte); > amr_prot = ppc_hash64_amr_prot(cpu, pte); > prot = pp_prot & amr_prot; > > @@ -789,27 +873,51 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, > hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr) > { > CPUPPCState *env = &cpu->env; > - ppc_slb_t *slb; > - hwaddr pte_offset; > + ppc_slb_t slb; > + ppc_slb_t *slb_ptr; > + hwaddr pte_offset, raddr; > ppc_hash_pte64_t pte; > unsigned apshift; > > + /* Handle real mode */ > if (msr_dr == 0) { > - /* In real mode the top 4 effective address bits are ignored */ > - return addr & 0x0FFFFFFFFFFFFFFFULL; > - } > + raddr = addr & 0x0FFFFFFFFFFFFFFFULL; > > - slb = slb_lookup(cpu, addr); > - if (!slb) { > + /* In HV mode, add HRMOR if top EA bit is clear */ > + if (msr_hv & !(addr >> 63)) { > + return raddr | env->spr[SPR_HRMOR]; > + } > + > + /* Otherwise, check VPM for RMA vs VRMA */ > + if (env->spr[SPR_LPCR] & LPCR_VPM0) { > + uint32_t vrmasd; > + > + /* VRMA, we make up an SLB entry */ > + slb.vsid = SLB_VSID_VRMA; > + vrmasd = (env->spr[SPR_LPCR] & LPCR_VRMASD) >> LPCR_VRMASD_SHIFT; > + slb.vsid |= (vrmasd << 4) & (SLB_VSID_L | SLB_VSID_LP); > + slb.esid = SLB_ESID_V; > + goto skip_slb; > + } > + /* RMA. Check bounds in RMLS */ > + if (raddr < ppc_hash64_get_rmls(env)) { > + return raddr | env->spr[SPR_RMOR]; > + } Now that the real-mode case is non-trivial, it would be nice if we could factor out some of this logic from the fault and page_debug cases into a common helper function. > return -1; > } > > - pte_offset = ppc_hash64_htab_lookup(cpu, slb, addr, &pte); > + slb_ptr = slb_lookup(cpu, addr); > + if (!slb_ptr) { > + return -1; > + } > + slb = *slb_ptr; > + skip_slb: > + pte_offset = ppc_hash64_htab_lookup(cpu, &slb, addr, &pte); > if (pte_offset == -1) { > return -1; > } > > - apshift = hpte_page_shift(slb->sps, pte.pte0, pte.pte1); > + apshift = hpte_page_shift(slb.sps, pte.pte0, pte.pte1); > if (!apshift) { > return -1; > } > diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h > index 6423b9f791e7..13ad060cfefb 100644 > --- a/target-ppc/mmu-hash64.h > +++ b/target-ppc/mmu-hash64.h > @@ -37,6 +37,7 @@ unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu, > #define SLB_VSID_B_256M 0x0000000000000000ULL > #define SLB_VSID_B_1T 0x4000000000000000ULL > #define SLB_VSID_VSID 0x3FFFFFFFFFFFF000ULL > +#define SLB_VSID_VRMA (0x0001FFFFFF000000ULL | SLB_VSID_B_1T) > #define SLB_VSID_PTEM (SLB_VSID_B | SLB_VSID_VSID) > #define SLB_VSID_KS 0x0000000000000800ULL > #define SLB_VSID_KP 0x0000000000000400ULL > diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c > index 55d1bfac97c4..4820c0bc99fb 100644 > --- a/target-ppc/translate_init.c > +++ b/target-ppc/translate_init.c > @@ -8791,11 +8791,19 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu) > /* Set emulated LPCR to not send interrupts to hypervisor. Note that > * under KVM, the actual HW LPCR will be set differently by KVM itself, > * the settings below ensure proper operations with TCG in absence of > - * a real hypervisor > + * a real hypervisor. > + * > + * Clearing VPM0 will also cause us to use RMOR in mmu-hash64.c for > + * real mode accesses, which thankfully defaults to 0 and isn't > + * accessible in guest mode. > */ > lpcr->default_value &= ~(LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV); > lpcr->default_value |= LPCR_LPES0 | LPCR_LPES1; > > + /* Set RMLS to the max (ie, 16G) */ > + lpcr->default_value &= ~LPCR_RMLS; > + lpcr->default_value |= 1ull << LPCR_RMLS_SHIFT; > + > /* P7 and P8 has slightly different PECE bits, mostly because P8 adds > * bit 47 and 48 which are reserved on P7. Here we set them all, which > * will work as expected for both implementations
On Wed, 2016-06-29 at 12:41 +1000, David Gibson wrote: > > + /* Actually we don't support unbounded RMA anymore since > we > > + * added proper emulation of HV mode. The max we can get > is > > + * 16G which also happens to be what we configure for PAPR > > + * mode so make sure we don't do anything bigger than that > > + */ > > + spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull); > > #1 - Instead of the various KVM / non-KVM cases here, it might be > simpler to just always clamp the RMA to 256MiB. That would be sad ... we benefit from having a larger RMA.. Cheers, Ben.
On Wed, Jun 29, 2016 at 12:59:05PM +1000, Benjamin Herrenschmidt wrote: > On Wed, 2016-06-29 at 12:41 +1000, David Gibson wrote: > > > + /* Actually we don't support unbounded RMA anymore since > > we > > > + * added proper emulation of HV mode. The max we can get > > is > > > + * 16G which also happens to be what we configure for PAPR > > > + * mode so make sure we don't do anything bigger than that > > > + */ > > > + spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull); > > > > #1 - Instead of the various KVM / non-KVM cases here, it might be > > simpler to just always clamp the RMA to 256MiB. > > That would be sad ... we benefit from having a larger RMA.. Ah, ok. Let's leave it as is, then.
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index d26b4c26ed10..53ab1f84fb11 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1770,6 +1770,13 @@ static void ppc_spapr_init(MachineState *machine) spapr->vrma_adjust = 1; spapr->rma_size = MIN(spapr->rma_size, 0x10000000); } + + /* Actually we don't support unbounded RMA anymore since we + * added proper emulation of HV mode. The max we can get is + * 16G which also happens to be what we configure for PAPR + * mode so make sure we don't do anything bigger than that + */ + spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull); } if (spapr->rma_size > node0_size) { diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c index 6d6f26c92957..ed353b2d1539 100644 --- a/target-ppc/mmu-hash64.c +++ b/target-ppc/mmu-hash64.c @@ -653,13 +653,41 @@ static void ppc_hash64_set_dsi(CPUState *cs, CPUPPCState *env, uint64_t dar, env->error_code = 0; } +static int64_t ppc_hash64_get_rmls(CPUPPCState *env) +{ + uint64_t lpcr = env->spr[SPR_LPCR]; + + /* + * This is the full 4 bits encoding of POWER8. Previous + * CPUs only support a subset of these but the filtering + * is done when writing LPCR + */ + switch ((lpcr & LPCR_RMLS) >> LPCR_RMLS_SHIFT) { + case 0x8: /* 32MB */ + return 0x2000000ull; + case 0x3: /* 64MB */ + return 0x4000000ull; + case 0x7: /* 128MB */ + return 0x8000000ull; + case 0x4: /* 256MB */ + return 0x10000000ull; + case 0x2: /* 1GB */ + return 0x40000000ull; + case 0x1: /* 16GB */ + return 0x400000000ull; + default: + /* What to do here ??? */ + return 0; + } +} int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx, int mmu_idx) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; - ppc_slb_t *slb; + ppc_slb_t *slb_ptr; + ppc_slb_t slb; unsigned apshift; hwaddr pte_offset; ppc_hash_pte64_t pte; @@ -670,11 +698,53 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, assert((rwx == 0) || (rwx == 1) || (rwx == 2)); + /* Note on LPCR usage: 970 uses HID4, but our special variant + * of store_spr copies relevant fields into env->spr[SPR_LPCR]. + * Similarily we filter unimplemented bits when storing into + * LPCR depending on the MMU version. This code can thus just + * use the LPCR "as-is". + */ + /* 1. Handle real mode accesses */ if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) { - /* Translation is off */ - /* In real mode the top 4 effective address bits are ignored */ + /* Translation is supposedly "off" */ + /* In real mode the top 4 effective address bits are (mostly) ignored */ raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL; + + /* In HV mode, add HRMOR if top EA bit is clear */ + if (msr_hv) { + if (!(eaddr >> 63)) { + raddr |= env->spr[SPR_HRMOR]; + } + } else { + /* Otherwise, check VPM for RMA vs VRMA */ + if (env->spr[SPR_LPCR] & LPCR_VPM0) { + uint32_t vrmasd; + /* VRMA, we make up an SLB entry */ + slb.vsid = SLB_VSID_VRMA; + vrmasd = (env->spr[SPR_LPCR] & LPCR_VRMASD) >> + LPCR_VRMASD_SHIFT; + slb.vsid |= (vrmasd << 4) & (SLB_VSID_L | SLB_VSID_LP); + slb.esid = SLB_ESID_V; + goto skip_slb; + } + /* RMA. Check bounds in RMLS */ + if (raddr < ppc_hash64_get_rmls(env)) { + raddr |= env->spr[SPR_RMOR]; + } else { + /* The access failed, generate the approriate interrupt */ + if (rwx == 2) { + ppc_hash64_set_isi(cs, env, 0x08000000); + } else { + dsisr = 0x08000000; + if (rwx == 1) { + dsisr |= 0x02000000; + } + ppc_hash64_set_dsi(cs, env, eaddr, dsisr); + } + return 1; + } + } tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK, PAGE_READ | PAGE_WRITE | PAGE_EXEC, mmu_idx, TARGET_PAGE_SIZE); @@ -682,9 +752,8 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, } /* 2. Translation is on, so look up the SLB */ - slb = slb_lookup(cpu, eaddr); - - if (!slb) { + slb_ptr = slb_lookup(cpu, eaddr); + if (!slb_ptr) { if (rwx == 2) { cs->exception_index = POWERPC_EXCP_ISEG; env->error_code = 0; @@ -696,14 +765,29 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, return 1; } + /* We grab a local copy because we can modify it (or get a + * pre-cooked one from the VRMA code + */ + slb = *slb_ptr; + + /* 2.5 Clamp L||LP in ISL mode */ + if (env->spr[SPR_LPCR] & LPCR_ISL) { + slb.vsid &= ~SLB_VSID_LLP_MASK; + } + /* 3. Check for segment level no-execute violation */ - if ((rwx == 2) && (slb->vsid & SLB_VSID_N)) { + if ((rwx == 2) && (slb.vsid & SLB_VSID_N)) { ppc_hash64_set_isi(cs, env, 0x10000000); return 1; } + /* We go straight here for VRMA translations as none of the + * above applies in that case + */ + skip_slb: + /* 4. Locate the PTE in the hash table */ - pte_offset = ppc_hash64_htab_lookup(cpu, slb, eaddr, &pte); + pte_offset = ppc_hash64_htab_lookup(cpu, &slb, eaddr, &pte); if (pte_offset == -1) { dsisr = 0x40000000; if (rwx == 2) { @@ -720,7 +804,7 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, "found PTE at offset %08" HWADDR_PRIx "\n", pte_offset); /* Validate page size encoding */ - apshift = hpte_page_shift(slb->sps, pte.pte0, pte.pte1); + apshift = hpte_page_shift(slb.sps, pte.pte0, pte.pte1); if (!apshift) { error_report("Bad page size encoding in HPTE 0x%"PRIx64" - 0x%"PRIx64 " @ 0x%"HWADDR_PRIx, pte.pte0, pte.pte1, pte_offset); @@ -733,7 +817,7 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, /* 5. Check access permissions */ - pp_prot = ppc_hash64_pte_prot(cpu, slb, pte); + pp_prot = ppc_hash64_pte_prot(cpu, &slb, pte); amr_prot = ppc_hash64_amr_prot(cpu, pte); prot = pp_prot & amr_prot; @@ -789,27 +873,51 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr) { CPUPPCState *env = &cpu->env; - ppc_slb_t *slb; - hwaddr pte_offset; + ppc_slb_t slb; + ppc_slb_t *slb_ptr; + hwaddr pte_offset, raddr; ppc_hash_pte64_t pte; unsigned apshift; + /* Handle real mode */ if (msr_dr == 0) { - /* In real mode the top 4 effective address bits are ignored */ - return addr & 0x0FFFFFFFFFFFFFFFULL; - } + raddr = addr & 0x0FFFFFFFFFFFFFFFULL; - slb = slb_lookup(cpu, addr); - if (!slb) { + /* In HV mode, add HRMOR if top EA bit is clear */ + if (msr_hv & !(addr >> 63)) { + return raddr | env->spr[SPR_HRMOR]; + } + + /* Otherwise, check VPM for RMA vs VRMA */ + if (env->spr[SPR_LPCR] & LPCR_VPM0) { + uint32_t vrmasd; + + /* VRMA, we make up an SLB entry */ + slb.vsid = SLB_VSID_VRMA; + vrmasd = (env->spr[SPR_LPCR] & LPCR_VRMASD) >> LPCR_VRMASD_SHIFT; + slb.vsid |= (vrmasd << 4) & (SLB_VSID_L | SLB_VSID_LP); + slb.esid = SLB_ESID_V; + goto skip_slb; + } + /* RMA. Check bounds in RMLS */ + if (raddr < ppc_hash64_get_rmls(env)) { + return raddr | env->spr[SPR_RMOR]; + } return -1; } - pte_offset = ppc_hash64_htab_lookup(cpu, slb, addr, &pte); + slb_ptr = slb_lookup(cpu, addr); + if (!slb_ptr) { + return -1; + } + slb = *slb_ptr; + skip_slb: + pte_offset = ppc_hash64_htab_lookup(cpu, &slb, addr, &pte); if (pte_offset == -1) { return -1; } - apshift = hpte_page_shift(slb->sps, pte.pte0, pte.pte1); + apshift = hpte_page_shift(slb.sps, pte.pte0, pte.pte1); if (!apshift) { return -1; } diff --git a/target-ppc/mmu-hash64.h b/target-ppc/mmu-hash64.h index 6423b9f791e7..13ad060cfefb 100644 --- a/target-ppc/mmu-hash64.h +++ b/target-ppc/mmu-hash64.h @@ -37,6 +37,7 @@ unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu, #define SLB_VSID_B_256M 0x0000000000000000ULL #define SLB_VSID_B_1T 0x4000000000000000ULL #define SLB_VSID_VSID 0x3FFFFFFFFFFFF000ULL +#define SLB_VSID_VRMA (0x0001FFFFFF000000ULL | SLB_VSID_B_1T) #define SLB_VSID_PTEM (SLB_VSID_B | SLB_VSID_VSID) #define SLB_VSID_KS 0x0000000000000800ULL #define SLB_VSID_KP 0x0000000000000400ULL diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 55d1bfac97c4..4820c0bc99fb 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -8791,11 +8791,19 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu) /* Set emulated LPCR to not send interrupts to hypervisor. Note that * under KVM, the actual HW LPCR will be set differently by KVM itself, * the settings below ensure proper operations with TCG in absence of - * a real hypervisor + * a real hypervisor. + * + * Clearing VPM0 will also cause us to use RMOR in mmu-hash64.c for + * real mode accesses, which thankfully defaults to 0 and isn't + * accessible in guest mode. */ lpcr->default_value &= ~(LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV); lpcr->default_value |= LPCR_LPES0 | LPCR_LPES1; + /* Set RMLS to the max (ie, 16G) */ + lpcr->default_value &= ~LPCR_RMLS; + lpcr->default_value |= 1ull << LPCR_RMLS_SHIFT; + /* P7 and P8 has slightly different PECE bits, mostly because P8 adds * bit 47 and 48 which are reserved on P7. Here we set them all, which * will work as expected for both implementations