On Mon, Jan 25, 2016 at 04:15:47PM +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 > --- > target-ppc/mmu-hash64.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++--- > 1 file changed, 70 insertions(+), 4 deletions(-) > > diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c > index 28ad361..bcad826 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,6 +475,43 @@ 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) { Gah. This needs to be (ps->pte_enc << HPTE64_R_RPN_SHIFT) or everything breaks. I remember fixing this earlier, but somehow I managed to lose the fix in both this posting and the previous one. -- David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson