Commit 4b5c9b7f authored by Alexander Graf's avatar Alexander Graf Committed by Marcelo Tosatti

KVM: PPC: Make large pages work

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: default avatarAlexander Graf <agraf@suse.de>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 5f2b105a
...@@ -34,7 +34,8 @@ struct kvmppc_slb { ...@@ -34,7 +34,8 @@ struct kvmppc_slb {
bool Ks; bool Ks;
bool Kp; bool Kp;
bool nx; bool nx;
bool large; bool large; /* PTEs are 16MB */
bool tb; /* 1TB segment */
bool class; bool class;
}; };
......
...@@ -54,7 +54,7 @@ static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe( ...@@ -54,7 +54,7 @@ static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe(
if (!vcpu_book3s->slb[i].valid) if (!vcpu_book3s->slb[i].valid)
continue; continue;
if (vcpu_book3s->slb[i].large) if (vcpu_book3s->slb[i].tb)
cmp_esid = esid_1t; cmp_esid = esid_1t;
if (vcpu_book3s->slb[i].esid == cmp_esid) if (vcpu_book3s->slb[i].esid == cmp_esid)
...@@ -65,9 +65,10 @@ static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe( ...@@ -65,9 +65,10 @@ static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe(
eaddr, esid, esid_1t); eaddr, esid, esid_1t);
for (i = 0; i < vcpu_book3s->slb_nr; i++) { for (i = 0; i < vcpu_book3s->slb_nr; i++) {
if (vcpu_book3s->slb[i].vsid) 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].valid ? 'v' : ' ',
vcpu_book3s->slb[i].large ? 'l' : ' ', vcpu_book3s->slb[i].large ? 'l' : ' ',
vcpu_book3s->slb[i].tb ? 't' : ' ',
vcpu_book3s->slb[i].esid, vcpu_book3s->slb[i].esid,
vcpu_book3s->slb[i].vsid); 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, ...@@ -84,7 +85,7 @@ static u64 kvmppc_mmu_book3s_64_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr,
if (!slb) if (!slb)
return 0; return 0;
if (slb->large) if (slb->tb)
return (((u64)eaddr >> 12) & 0xfffffff) | return (((u64)eaddr >> 12) & 0xfffffff) |
(((u64)slb->vsid) << 28); (((u64)slb->vsid) << 28);
...@@ -309,7 +310,8 @@ static void kvmppc_mmu_book3s_64_slbmte(struct kvm_vcpu *vcpu, u64 rs, u64 rb) ...@@ -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 = &vcpu_book3s->slb[slb_nr];
slbe->large = (rs & SLB_VSID_L) ? 1 : 0; 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->vsid = rs >> 12;
slbe->valid = (rb & SLB_ESID_V) ? 1 : 0; slbe->valid = (rb & SLB_ESID_V) ? 1 : 0;
slbe->Ks = (rs & SLB_VSID_KS) ? 1 : 0; slbe->Ks = (rs & SLB_VSID_KS) ? 1 : 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment