aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/virtual/kvm/ppc-pv.txt8
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h1
-rw-r--r--arch/powerpc/kvm/booke.c11
-rw-r--r--arch/powerpc/kvm/e500_tlb.c22
-rw-r--r--arch/powerpc/kvm/powerpc.c3
5 files changed, 40 insertions, 5 deletions
diff --git a/Documentation/virtual/kvm/ppc-pv.txt b/Documentation/virtual/kvm/ppc-pv.txt
index 3ab969c59046..2b7ce190cde4 100644
--- a/Documentation/virtual/kvm/ppc-pv.txt
+++ b/Documentation/virtual/kvm/ppc-pv.txt
@@ -68,9 +68,11 @@ page that contains parts of supervisor visible register state. The guest can
68map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE. 68map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE.
69 69
70With this hypercall issued the guest always gets the magic page mapped at the 70With this hypercall issued the guest always gets the magic page mapped at the
71desired location in effective and physical address space. For now, we always 71desired location. The first parameter indicates the effective address when the
72map the page to -4096. This way we can access it using absolute load and store 72MMU is enabled. The second parameter indicates the address in real mode, if
73functions. The following instruction reads the first field of the magic page: 73applicable to the target. For now, we always map the page to -4096. This way we
74can access it using absolute load and store functions. The following
75instruction reads the first field of the magic page:
74 76
75 ld rX, -4096(0) 77 ld rX, -4096(0)
76 78
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 9345238edecf..c662f140283a 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -109,6 +109,7 @@ extern void kvmppc_booke_exit(void);
109 109
110extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu); 110extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu);
111extern int kvmppc_kvm_pv(struct kvm_vcpu *vcpu); 111extern int kvmppc_kvm_pv(struct kvm_vcpu *vcpu);
112extern void kvmppc_map_magic(struct kvm_vcpu *vcpu);
112 113
113/* 114/*
114 * Cuts out inst bits with ordering according to spec. 115 * Cuts out inst bits with ordering according to spec.
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 0ecbecb2f7cc..4538956daecf 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -472,6 +472,17 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
472 gpa_t gpaddr; 472 gpa_t gpaddr;
473 gfn_t gfn; 473 gfn_t gfn;
474 474
475#ifdef CONFIG_KVM_E500
476 if (!(vcpu->arch.shared->msr & MSR_PR) &&
477 (eaddr & PAGE_MASK) == vcpu->arch.magic_page_ea) {
478 kvmppc_map_magic(vcpu);
479 kvmppc_account_exit(vcpu, DTLB_VIRT_MISS_EXITS);
480 r = RESUME_GUEST;
481
482 break;
483 }
484#endif
485
475 /* Check the guest TLB. */ 486 /* Check the guest TLB. */
476 gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr); 487 gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr);
477 if (gtlb_index < 0) { 488 if (gtlb_index < 0) {
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index 7f808c52e64a..c09e642ee537 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -76,7 +76,8 @@ static inline unsigned int tlb0_get_next_victim(
76 76
77static inline unsigned int tlb1_max_shadow_size(void) 77static inline unsigned int tlb1_max_shadow_size(void)
78{ 78{
79 return tlb1_entry_num - tlbcam_index; 79 /* reserve one entry for magic page */
80 return tlb1_entry_num - tlbcam_index - 1;
80} 81}
81 82
82static inline int tlbe_is_writable(struct tlbe *tlbe) 83static inline int tlbe_is_writable(struct tlbe *tlbe)
@@ -142,6 +143,25 @@ static inline void write_host_tlbe(struct kvmppc_vcpu_e500 *vcpu_e500,
142 } 143 }
143} 144}
144 145
146void kvmppc_map_magic(struct kvm_vcpu *vcpu)
147{
148 struct tlbe magic;
149 ulong shared_page = ((ulong)vcpu->arch.shared) & PAGE_MASK;
150 pfn_t pfn;
151
152 pfn = (pfn_t)virt_to_phys((void *)shared_page) >> PAGE_SHIFT;
153 get_page(pfn_to_page(pfn));
154
155 magic.mas1 = MAS1_VALID | MAS1_TS |
156 MAS1_TSIZE(BOOK3E_PAGESZ_4K);
157 magic.mas2 = vcpu->arch.magic_page_ea | MAS2_M;
158 magic.mas3 = (pfn << PAGE_SHIFT) |
159 MAS3_SW | MAS3_SR | MAS3_UW | MAS3_UR;
160 magic.mas7 = pfn >> (32 - PAGE_SHIFT);
161
162 __write_host_tlbe(&magic, MAS0_TLBSEL(1) | MAS0_ESEL(tlbcam_index));
163}
164
145void kvmppc_e500_tlb_load(struct kvm_vcpu *vcpu, int cpu) 165void kvmppc_e500_tlb_load(struct kvm_vcpu *vcpu, int cpu)
146{ 166{
147} 167}
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 616dd516ca1f..24e2b64b6a48 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -73,7 +73,8 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
73 } 73 }
74 case HC_VENDOR_KVM | KVM_HC_FEATURES: 74 case HC_VENDOR_KVM | KVM_HC_FEATURES:
75 r = HC_EV_SUCCESS; 75 r = HC_EV_SUCCESS;
76#if defined(CONFIG_PPC_BOOK3S) /* XXX Missing magic page on BookE */ 76#if defined(CONFIG_PPC_BOOK3S) || defined(CONFIG_KVM_E500)
77 /* XXX Missing magic page on 44x */
77 r2 |= (1 << KVM_FEATURE_MAGIC_PAGE); 78 r2 |= (1 << KVM_FEATURE_MAGIC_PAGE);
78#endif 79#endif
79 80