KVM: PPC: Make large pages work
authorAlexander Graf <agraf@suse.de>
Sun, 10 Jan 2010 02:27:47 +0000 (03:27 +0100)
committerMarcelo Tosatti <mtosatti@redhat.com>
Mon, 1 Mar 2010 15:35:50 +0000 (12:35 -0300)
An SLB entry contains two pieces of information related to size:

  1) PTE size
  2) SLB size

The L bit defines the PTE be "large" (usually means 16MB),
SLB_VSID_B_1T defines that the SLB should span 1 GB instead of the
default 256MB.

Apparently I messed things up and just put those two in one box,
shaked it heavily and came up with the current code which handles
large pages incorrectly, because it also treats large page SLB entries
as "1TB" segment entries.

This patch splits those two features apart, making Linux guests boot
even when they have > 256MB.

Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Avi Kivity <avi@redhat.com>
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/kvm/book3s_64_mmu.c

index 79ab8faf18e75e041ea1bb4d959453bbc09bb723..c7db69f1e7796879bcf1525a3ac55a2465995d13 100644 (file)
@@ -34,7 +34,8 @@ struct kvmppc_slb {
        bool Ks;
        bool Kp;
        bool nx;
-       bool large;
+       bool large;     /* PTEs are 16MB */
+       bool tb;        /* 1TB segment */
        bool class;
 };
 
index e4beeb371a732fecdf3fc5fe1291ae01aa40b2a6..512dcff77554aa6d76bd3b432b2b1aa0cdb7cd93 100644 (file)
@@ -54,7 +54,7 @@ static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe(
                if (!vcpu_book3s->slb[i].valid)
                        continue;
 
-               if (vcpu_book3s->slb[i].large)
+               if (vcpu_book3s->slb[i].tb)
                        cmp_esid = esid_1t;
 
                if (vcpu_book3s->slb[i].esid == cmp_esid)
@@ -65,9 +65,10 @@ static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe(
                eaddr, esid, esid_1t);
        for (i = 0; i < vcpu_book3s->slb_nr; i++) {
            if (vcpu_book3s->slb[i].vsid)
-               dprintk("  %d: %c%c %llx %llx\n", i,
+               dprintk("  %d: %c%c%c %llx %llx\n", i,
                        vcpu_book3s->slb[i].valid ? 'v' : ' ',
                        vcpu_book3s->slb[i].large ? 'l' : ' ',
+                       vcpu_book3s->slb[i].tb    ? 't' : ' ',
                        vcpu_book3s->slb[i].esid,
                        vcpu_book3s->slb[i].vsid);
        }
@@ -84,7 +85,7 @@ static u64 kvmppc_mmu_book3s_64_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr,
        if (!slb)
                return 0;
 
-       if (slb->large)
+       if (slb->tb)
                return (((u64)eaddr >> 12) & 0xfffffff) |
                       (((u64)slb->vsid) << 28);
 
@@ -309,7 +310,8 @@ static void kvmppc_mmu_book3s_64_slbmte(struct kvm_vcpu *vcpu, u64 rs, u64 rb)
        slbe = &vcpu_book3s->slb[slb_nr];
 
        slbe->large = (rs & SLB_VSID_L) ? 1 : 0;
-       slbe->esid  = slbe->large ? esid_1t : esid;
+       slbe->tb    = (rs & SLB_VSID_B_1T) ? 1 : 0;
+       slbe->esid  = slbe->tb ? esid_1t : esid;
        slbe->vsid  = rs >> 12;
        slbe->valid = (rb & SLB_ESID_V) ? 1 : 0;
        slbe->Ks    = (rs & SLB_VSID_KS) ? 1 : 0;