aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/book3s_64_mmu_host.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kvm/book3s_64_mmu_host.c')
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_host.c74
1 files changed, 27 insertions, 47 deletions
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c
index 384179a5002b..fa2f08434ba5 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_host.c
@@ -20,7 +20,6 @@
20 */ 20 */
21 21
22#include <linux/kvm_host.h> 22#include <linux/kvm_host.h>
23#include <linux/hash.h>
24 23
25#include <asm/kvm_ppc.h> 24#include <asm/kvm_ppc.h>
26#include <asm/kvm_book3s.h> 25#include <asm/kvm_book3s.h>
@@ -28,24 +27,9 @@
28#include <asm/machdep.h> 27#include <asm/machdep.h>
29#include <asm/mmu_context.h> 28#include <asm/mmu_context.h>
30#include <asm/hw_irq.h> 29#include <asm/hw_irq.h>
30#include "trace.h"
31 31
32#define PTE_SIZE 12 32#define PTE_SIZE 12
33#define VSID_ALL 0
34
35/* #define DEBUG_MMU */
36/* #define DEBUG_SLB */
37
38#ifdef DEBUG_MMU
39#define dprintk_mmu(a, ...) printk(KERN_INFO a, __VA_ARGS__)
40#else
41#define dprintk_mmu(a, ...) do { } while(0)
42#endif
43
44#ifdef DEBUG_SLB
45#define dprintk_slb(a, ...) printk(KERN_INFO a, __VA_ARGS__)
46#else
47#define dprintk_slb(a, ...) do { } while(0)
48#endif
49 33
50void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte) 34void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
51{ 35{
@@ -58,34 +42,39 @@ void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
58 * a hash, so we don't waste cycles on looping */ 42 * a hash, so we don't waste cycles on looping */
59static u16 kvmppc_sid_hash(struct kvm_vcpu *vcpu, u64 gvsid) 43static u16 kvmppc_sid_hash(struct kvm_vcpu *vcpu, u64 gvsid)
60{ 44{
61 return hash_64(gvsid, SID_MAP_BITS); 45 return (u16)(((gvsid >> (SID_MAP_BITS * 7)) & SID_MAP_MASK) ^
46 ((gvsid >> (SID_MAP_BITS * 6)) & SID_MAP_MASK) ^
47 ((gvsid >> (SID_MAP_BITS * 5)) & SID_MAP_MASK) ^
48 ((gvsid >> (SID_MAP_BITS * 4)) & SID_MAP_MASK) ^
49 ((gvsid >> (SID_MAP_BITS * 3)) & SID_MAP_MASK) ^
50 ((gvsid >> (SID_MAP_BITS * 2)) & SID_MAP_MASK) ^
51 ((gvsid >> (SID_MAP_BITS * 1)) & SID_MAP_MASK) ^
52 ((gvsid >> (SID_MAP_BITS * 0)) & SID_MAP_MASK));
62} 53}
63 54
55
64static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid) 56static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)
65{ 57{
66 struct kvmppc_sid_map *map; 58 struct kvmppc_sid_map *map;
67 u16 sid_map_mask; 59 u16 sid_map_mask;
68 60
69 if (vcpu->arch.msr & MSR_PR) 61 if (vcpu->arch.shared->msr & MSR_PR)
70 gvsid |= VSID_PR; 62 gvsid |= VSID_PR;
71 63
72 sid_map_mask = kvmppc_sid_hash(vcpu, gvsid); 64 sid_map_mask = kvmppc_sid_hash(vcpu, gvsid);
73 map = &to_book3s(vcpu)->sid_map[sid_map_mask]; 65 map = &to_book3s(vcpu)->sid_map[sid_map_mask];
74 if (map->guest_vsid == gvsid) { 66 if (map->valid && (map->guest_vsid == gvsid)) {
75 dprintk_slb("SLB: Searching: 0x%llx -> 0x%llx\n", 67 trace_kvm_book3s_slb_found(gvsid, map->host_vsid);
76 gvsid, map->host_vsid);
77 return map; 68 return map;
78 } 69 }
79 70
80 map = &to_book3s(vcpu)->sid_map[SID_MAP_MASK - sid_map_mask]; 71 map = &to_book3s(vcpu)->sid_map[SID_MAP_MASK - sid_map_mask];
81 if (map->guest_vsid == gvsid) { 72 if (map->valid && (map->guest_vsid == gvsid)) {
82 dprintk_slb("SLB: Searching 0x%llx -> 0x%llx\n", 73 trace_kvm_book3s_slb_found(gvsid, map->host_vsid);
83 gvsid, map->host_vsid);
84 return map; 74 return map;
85 } 75 }
86 76
87 dprintk_slb("SLB: Searching %d/%d: 0x%llx -> not found\n", 77 trace_kvm_book3s_slb_fail(sid_map_mask, gvsid);
88 sid_map_mask, SID_MAP_MASK - sid_map_mask, gvsid);
89 return NULL; 78 return NULL;
90} 79}
91 80
@@ -101,18 +90,13 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
101 struct kvmppc_sid_map *map; 90 struct kvmppc_sid_map *map;
102 91
103 /* Get host physical address for gpa */ 92 /* Get host physical address for gpa */
104 hpaddr = gfn_to_pfn(vcpu->kvm, orig_pte->raddr >> PAGE_SHIFT); 93 hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT);
105 if (kvm_is_error_hva(hpaddr)) { 94 if (is_error_pfn(hpaddr)) {
106 printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", orig_pte->eaddr); 95 printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", orig_pte->eaddr);
107 return -EINVAL; 96 return -EINVAL;
108 } 97 }
109 hpaddr <<= PAGE_SHIFT; 98 hpaddr <<= PAGE_SHIFT;
110#if PAGE_SHIFT == 12 99 hpaddr |= orig_pte->raddr & (~0xfffULL & ~PAGE_MASK);
111#elif PAGE_SHIFT == 16
112 hpaddr |= orig_pte->raddr & 0xf000;
113#else
114#error Unknown page size
115#endif
116 100
117 /* and write the mapping ea -> hpa into the pt */ 101 /* and write the mapping ea -> hpa into the pt */
118 vcpu->arch.mmu.esid_to_vsid(vcpu, orig_pte->eaddr >> SID_SHIFT, &vsid); 102 vcpu->arch.mmu.esid_to_vsid(vcpu, orig_pte->eaddr >> SID_SHIFT, &vsid);
@@ -161,10 +145,7 @@ map_again:
161 } else { 145 } else {
162 struct hpte_cache *pte = kvmppc_mmu_hpte_cache_next(vcpu); 146 struct hpte_cache *pte = kvmppc_mmu_hpte_cache_next(vcpu);
163 147
164 dprintk_mmu("KVM: %c%c Map 0x%lx: [%lx] 0x%lx (0x%llx) -> %lx\n", 148 trace_kvm_book3s_64_mmu_map(rflags, hpteg, va, hpaddr, orig_pte);
165 ((rflags & HPTE_R_PP) == 3) ? '-' : 'w',
166 (rflags & HPTE_R_N) ? '-' : 'x',
167 orig_pte->eaddr, hpteg, va, orig_pte->vpage, hpaddr);
168 149
169 /* The ppc_md code may give us a secondary entry even though we 150 /* The ppc_md code may give us a secondary entry even though we
170 asked for a primary. Fix up. */ 151 asked for a primary. Fix up. */
@@ -191,7 +172,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
191 u16 sid_map_mask; 172 u16 sid_map_mask;
192 static int backwards_map = 0; 173 static int backwards_map = 0;
193 174
194 if (vcpu->arch.msr & MSR_PR) 175 if (vcpu->arch.shared->msr & MSR_PR)
195 gvsid |= VSID_PR; 176 gvsid |= VSID_PR;
196 177
197 /* We might get collisions that trap in preceding order, so let's 178 /* We might get collisions that trap in preceding order, so let's
@@ -219,8 +200,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid)
219 map->guest_vsid = gvsid; 200 map->guest_vsid = gvsid;
220 map->valid = true; 201 map->valid = true;
221 202
222 dprintk_slb("SLB: New mapping at %d: 0x%llx -> 0x%llx\n", 203 trace_kvm_book3s_slb_map(sid_map_mask, gvsid, map->host_vsid);
223 sid_map_mask, gvsid, map->host_vsid);
224 204
225 return map; 205 return map;
226} 206}
@@ -292,7 +272,7 @@ int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr)
292 to_svcpu(vcpu)->slb[slb_index].esid = slb_esid; 272 to_svcpu(vcpu)->slb[slb_index].esid = slb_esid;
293 to_svcpu(vcpu)->slb[slb_index].vsid = slb_vsid; 273 to_svcpu(vcpu)->slb[slb_index].vsid = slb_vsid;
294 274
295 dprintk_slb("slbmte %#llx, %#llx\n", slb_vsid, slb_esid); 275 trace_kvm_book3s_slbmte(slb_vsid, slb_esid);
296 276
297 return 0; 277 return 0;
298} 278}
@@ -306,7 +286,7 @@ void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu)
306void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) 286void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu)
307{ 287{
308 kvmppc_mmu_hpte_destroy(vcpu); 288 kvmppc_mmu_hpte_destroy(vcpu);
309 __destroy_context(to_book3s(vcpu)->context_id); 289 __destroy_context(to_book3s(vcpu)->context_id[0]);
310} 290}
311 291
312int kvmppc_mmu_init(struct kvm_vcpu *vcpu) 292int kvmppc_mmu_init(struct kvm_vcpu *vcpu)
@@ -317,10 +297,10 @@ int kvmppc_mmu_init(struct kvm_vcpu *vcpu)
317 err = __init_new_context(); 297 err = __init_new_context();
318 if (err < 0) 298 if (err < 0)
319 return -1; 299 return -1;
320 vcpu3s->context_id = err; 300 vcpu3s->context_id[0] = err;
321 301
322 vcpu3s->vsid_max = ((vcpu3s->context_id + 1) << USER_ESID_BITS) - 1; 302 vcpu3s->vsid_max = ((vcpu3s->context_id[0] + 1) << USER_ESID_BITS) - 1;
323 vcpu3s->vsid_first = vcpu3s->context_id << USER_ESID_BITS; 303 vcpu3s->vsid_first = vcpu3s->context_id[0] << USER_ESID_BITS;
324 vcpu3s->vsid_next = vcpu3s->vsid_first; 304 vcpu3s->vsid_next = vcpu3s->vsid_first;
325 305
326 kvmppc_mmu_hpte_init(vcpu); 306 kvmppc_mmu_hpte_init(vcpu);