[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-ppc] [PATCHv2 05/10] target-ppc: Use actual page size encoding
From: |
Benjamin Herrenschmidt |
Subject: |
Re: [Qemu-ppc] [PATCHv2 05/10] target-ppc: Use actual page size encodings from HPTE |
Date: |
Thu, 28 Jan 2016 15:18:56 +1100 |
On Wed, 2016-01-27 at 21:13 +1100, David Gibson wrote:
> At present the 64-bit hash MMU code uses information from the SLB to
> determine the page size of a translation. We do need that
> information to
> correctly look up the hash table. However the MMU also allows a
> possibly larger page size to be encoded into the HPTE itself, which
> is used
> to populate the TLB. At present qemu doesn't check that, and so
> doesn't
> support the MPSS "Multiple Page Size per Segment" feature.
>
> This makes a start on allowing this, by adding an hpte_page_shift()
> function which looks up the page size of an HPTE. We use this to
> validate
> page sizes encodings on faults, and populate the qemu TLB with larger
> page sizes when appropriate.
>
> Signed-off-by: David Gibson <address@hidden>
Acked-by: Benjamin Herrenschmidt <address@hidden>
(Note that we don't actually populate the QEMU TLB with alrger page
sizes, it doesn't support it ... Also it tries to keep track of
the presence of large pages to deal with targetted invalidations
but we don't do the latter on hash64 and we wouldn't need that
extra care anyway since our tlbie carries the page size as well).
Cheers,
Ben.
> ---
> target-ppc/mmu-hash64.c | 63
> ++++++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 60 insertions(+), 3 deletions(-)
>
> diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
> index b784791..ee1e8bf 100644
> --- a/target-ppc/mmu-hash64.c
> +++ b/target-ppc/mmu-hash64.c
> @@ -21,6 +21,7 @@
> #include "exec/helper-proto.h"
> #include "qemu/error-report.h"
> #include "sysemu/kvm.h"
> +#include "qemu/error-report.h"
> #include "kvm_ppc.h"
> #include "mmu-hash64.h"
>
> @@ -474,12 +475,50 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU
> *cpu,
> return pte_offset;
> }
>
> +static unsigned hpte_page_shift(const struct ppc_one_seg_page_size
> *sps,
> + uint64_t pte0, uint64_t pte1)
> +{
> + int i;
> +
> + if (!(pte0 & HPTE64_V_LARGE)) {
> + if (sps->page_shift != 12) {
> + /* 4kiB page in a non 4kiB segment */
> + return 0;
> + }
> + /* Normal 4kiB page */
> + return 12;
> + }
> +
> + for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
> + const struct ppc_one_page_size *ps = &sps->enc[i];
> + uint64_t mask;
> +
> + if (!ps->page_shift) {
> + break;
> + }
> +
> + if (ps->page_shift == 12) {
> + /* L bit is set so this can't be a 4kiB page */
> + continue;
> + }
> +
> + mask = ((1ULL << ps->page_shift) - 1) & HPTE64_R_RPN;
> +
> + if ((pte1 & mask) == (ps->pte_enc << HPTE64_R_RPN_SHIFT)) {
> + return ps->page_shift;
> + }
> + }
> +
> + return 0; /* Bad page size encoding */
> +}
> +
> int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, target_ulong eaddr,
> int rwx, int mmu_idx)
> {
> CPUState *cs = CPU(cpu);
> CPUPPCState *env = &cpu->env;
> ppc_slb_t *slb;
> + unsigned apshift;
> hwaddr pte_offset;
> ppc_hash_pte64_t pte;
> int pp_prot, amr_prot, prot;
> @@ -543,6 +582,18 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu,
> target_ulong eaddr,
> qemu_log_mask(CPU_LOG_MMU,
> "found PTE at offset %08" HWADDR_PRIx "\n",
> pte_offset);
>
> + /* Validate page size encoding */
> + 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);
> + /* Not entirely sure what the right action here, but machine
> + * check seems reasonable */
> + cs->exception_index = POWERPC_EXCP_MCHECK;
> + env->error_code = 0;
> + return 1;
> + }
> +
> /* 5. Check access permissions */
>
> pp_prot = ppc_hash64_pte_prot(cpu, slb, pte);
> @@ -595,10 +646,10 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU
> *cpu, target_ulong eaddr,
>
> /* 7. Determine the real address from the PTE */
>
> - raddr = deposit64(pte.pte1 & HPTE64_R_RPN, 0, slb->sps-
> >page_shift, eaddr);
> + raddr = deposit64(pte.pte1 & HPTE64_R_RPN, 0, apshift, eaddr);
>
> tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr &
> TARGET_PAGE_MASK,
> - prot, mmu_idx, TARGET_PAGE_SIZE);
> + prot, mmu_idx, 1ULL << apshift);
>
> return 0;
> }
> @@ -609,6 +660,7 @@ hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU
> *cpu, target_ulong addr)
> ppc_slb_t *slb;
> hwaddr pte_offset;
> ppc_hash_pte64_t pte;
> + unsigned apshift;
>
> if (msr_dr == 0) {
> /* In real mode the top 4 effective address bits are ignored
> */
> @@ -625,7 +677,12 @@ hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU
> *cpu, target_ulong addr)
> return -1;
> }
>
> - return deposit64(pte.pte1 & HPTE64_R_RPN, 0, slb->sps-
> >page_shift, addr)
> + apshift = hpte_page_shift(slb->sps, pte.pte0, pte.pte1);
> + if (!apshift) {
> + return -1;
> + }
> +
> + return deposit64(pte.pte1 & HPTE64_R_RPN, 0, apshift, addr)
> & TARGET_PAGE_MASK;
> }
>
- Re: [Qemu-ppc] [PATCHv2 08/10] target-ppc: Add new TLB invalidate by HPTE call for hash64 MMUs, (continued)
- [Qemu-ppc] [PATCHv2 07/10] target-ppc: Split 44x tlbiva from ppc_tlb_invalidate_one(), David Gibson, 2016/01/27
- [Qemu-ppc] [PATCHv2 04/10] target-ppc: Rework SLB page size lookup, David Gibson, 2016/01/27
- [Qemu-ppc] [PATCHv2 09/10] target-ppc: Helper to determine page size information from hpte alone, David Gibson, 2016/01/27
- [Qemu-ppc] [PATCHv2 05/10] target-ppc: Use actual page size encodings from HPTE, David Gibson, 2016/01/27
- Re: [Qemu-ppc] [PATCHv2 05/10] target-ppc: Use actual page size encodings from HPTE,
Benjamin Herrenschmidt <=
- [Qemu-ppc] [PATCHv2 03/10] target-ppc: Rework ppc_store_slb, David Gibson, 2016/01/27
- [Qemu-ppc] [PATCHv2 02/10] target-ppc: Convert mmu-hash{32, 64}.[ch] from CPUPPCState to PowerPCCPU, David Gibson, 2016/01/27
- [Qemu-ppc] [PATCHv2 01/10] target-ppc: Remove unused kvmppc_read_segment_page_sizes() stub, David Gibson, 2016/01/27
- [Qemu-ppc] [PATCHv2 10/10] target-ppc: Allow more page sizes for POWER7 & POWER8 in TCG, David Gibson, 2016/01/27