20 #include <linux/types.h>
21 #include <linux/string.h>
26 #include <asm/tlbflush.h>
35 #ifndef PPC44x_TLBE_SIZE
36 #define PPC44x_TLBE_SIZE PPC44x_TLB_4K
39 #define PAGE_SIZE_4K (1<<12)
40 #define PAGE_MASK_4K (~(PAGE_SIZE_4K - 1))
42 #define PPC44x_TLB_UATTR_MASK \
43 (PPC44x_TLB_U0|PPC44x_TLB_U1|PPC44x_TLB_U2|PPC44x_TLB_U3)
44 #define PPC44x_TLB_USER_PERM_MASK (PPC44x_TLB_UX|PPC44x_TLB_UR|PPC44x_TLB_UW)
45 #define PPC44x_TLB_SUPER_PERM_MASK (PPC44x_TLB_SX|PPC44x_TLB_SR|PPC44x_TLB_SW)
55 printk(
"| %2s | %3s | %8s | %8s | %8s |\n",
56 "nr",
"tid",
"word0",
"word1",
"word2");
61 printk(
" G%2d | %02X | %08X | %08X | %08X |\n",
68 static inline void kvmppc_44x_tlbie(
unsigned int index)
73 "tlbwe %[index], %[index], 0\n"
79 static inline void kvmppc_44x_tlbre(
unsigned int index,
83 "tlbre %[word0], %[index], 0\n"
84 "mfspr %[tid], %[sprn_mmucr]\n"
85 "andi. %[tid], %[tid], 0xff\n"
86 "tlbre %[word1], %[index], 1\n"
87 "tlbre %[word2], %[index], 2\n"
93 [sprn_mmucr]
"i"(SPRN_MMUCR)
98 static inline void kvmppc_44x_tlbwe(
unsigned int index,
104 "mfspr %[tmp], %[sprn_mmucr]\n"
105 "rlwimi %[tmp], %[tid], 0, 0xff\n"
106 "mtspr %[sprn_mmucr], %[tmp]\n"
107 "tlbwe %[word0], %[index], 0\n"
108 "tlbwe %[word1], %[index], 1\n"
109 "tlbwe %[word2], %[index], 2\n"
116 [sprn_mmucr]
"i"(SPRN_MMUCR)
120 static u32 kvmppc_44x_tlb_shadow_attrib(
u32 attrib,
int usermode)
150 if (get_tlb_v(stlbe) && get_tlb_ts(stlbe))
151 kvmppc_44x_tlbwe(i, stlbe);
155 static void kvmppc_44x_tlbe_set_modified(
struct kvmppc_vcpu_44x *vcpu_44x,
171 kvmppc_44x_tlbre(i, stlbe);
173 if (get_tlb_v(stlbe) && get_tlb_ts(stlbe))
191 if (eaddr < get_tlb_eaddr(tlbe))
194 if (eaddr > get_tlb_end(tlbe))
197 tid = get_tlb_tid(tlbe);
198 if (tid && (tid != pid))
201 if (!get_tlb_v(tlbe))
204 if (get_tlb_ts(tlbe) != as)
218 unsigned int pgmask = get_tlb_bytes(gtlbe) - 1;
220 return get_tlb_raddr(gtlbe) | (eaddr & pgmask);
225 unsigned int as = !!(vcpu->
arch.shared->msr & MSR_IS);
232 unsigned int as = !!(vcpu->
arch.shared->msr & MSR_DS);
245 static void kvmppc_44x_shadow_release(
struct kvmppc_vcpu_44x *vcpu_44x,
246 unsigned int stlb_index)
256 kvmppc_44x_tlbie(stlb_index);
268 trace_kvm_stlb_inval(stlb_index);
277 kvmppc_44x_shadow_release(vcpu_44x, i);
293 unsigned int gtlb_index)
299 struct page *new_page;
319 if (is_error_page(new_page)) {
321 (
unsigned long long)gfn);
327 kvmppc_44x_shadow_release(vcpu_44x, victim);
355 stlbe.
word1 = (hpaddr & 0xfffffc00) | ((hpaddr >> 32) & 0xf);
356 stlbe.
word2 = kvmppc_44x_tlb_shadow_attrib(flags,
357 vcpu->
arch.shared->msr & MSR_PR);
358 stlbe.
tid = !(asid & 0xff);
362 ref->
page = new_page;
368 kvmppc_44x_tlbe_set_modified(vcpu_44x, victim);
369 kvmppc_44x_tlbwe(victim, &stlbe);
370 trace_kvm_stlb_write(victim, stlbe.
tid, stlbe.
word0, stlbe.
word1,
376 static void kvmppc_44x_invalidate(
struct kvm_vcpu *vcpu,
377 unsigned int gtlb_index)
385 kvmppc_44x_shadow_release(vcpu_44x, i);
391 int usermode = vcpu->
arch.shared->msr & MSR_PR;
393 vcpu->
arch.shadow_pid = !usermode;
404 vcpu->
arch.pid = new_pid;
414 kvmppc_44x_shadow_release(vcpu_44x, i);
418 static int tlbe_is_host_safe(
const struct kvm_vcpu *vcpu,
423 if (!get_tlb_v(tlbe))
428 if (get_tlb_ts(tlbe) != !!(vcpu->
arch.shared->msr & MSR_IS))
431 gpa = get_tlb_raddr(tlbe);
443 unsigned int gtlb_index;
445 gtlb_index = kvmppc_get_gpr(vcpu, ra);
447 printk(
"%s: index %d\n", __func__, gtlb_index);
456 kvmppc_44x_invalidate(vcpu, gtlb_index);
460 tlbe->
tid = get_mmucr_stid(vcpu);
461 tlbe->
word0 = kvmppc_get_gpr(vcpu, rs);
465 tlbe->
word1 = kvmppc_get_gpr(vcpu, rs);
469 tlbe->
word2 = kvmppc_get_gpr(vcpu, rs);
476 if (tlbe_is_host_safe(vcpu, tlbe)) {
481 eaddr = get_tlb_eaddr(tlbe);
482 gpaddr = get_tlb_raddr(tlbe);
485 bytes = get_tlb_bytes(tlbe);
486 eaddr &= ~(bytes - 1);
487 gpaddr &= ~(bytes - 1);
492 trace_kvm_gtlb_write(gtlb_index, tlbe->
tid, tlbe->
word0, tlbe->
word1,
503 unsigned int as = get_mmucr_sts(vcpu);
504 unsigned int pid = get_mmucr_stid(vcpu);
506 ea = kvmppc_get_gpr(vcpu, rb);
508 ea += kvmppc_get_gpr(vcpu, ra);
512 u32 cr = kvmppc_get_cr(vcpu);
515 kvmppc_set_cr(vcpu, cr & ~0x20000000);
517 kvmppc_set_cr(vcpu, cr | 0x20000000);
519 kvmppc_set_gpr(vcpu, rt, gtlb_index);