diff options
-rw-r--r-- | Documentation/virtual/kvm/ppc-pv.txt | 8 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_ppc.h | 1 | ||||
-rw-r--r-- | arch/powerpc/kvm/booke.c | 11 | ||||
-rw-r--r-- | arch/powerpc/kvm/e500_tlb.c | 22 | ||||
-rw-r--r-- | arch/powerpc/kvm/powerpc.c | 3 |
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 | |||
68 | map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE. | 68 | map this shared page using the KVM hypercall KVM_HC_PPC_MAP_MAGIC_PAGE. |
69 | 69 | ||
70 | With this hypercall issued the guest always gets the magic page mapped at the | 70 | With this hypercall issued the guest always gets the magic page mapped at the |
71 | desired location in effective and physical address space. For now, we always | 71 | desired location. The first parameter indicates the effective address when the |
72 | map the page to -4096. This way we can access it using absolute load and store | 72 | MMU is enabled. The second parameter indicates the address in real mode, if |
73 | functions. The following instruction reads the first field of the magic page: | 73 | applicable to the target. For now, we always map the page to -4096. This way we |
74 | can access it using absolute load and store functions. The following | ||
75 | instruction 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 | ||
110 | extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu); | 110 | extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu); |
111 | extern int kvmppc_kvm_pv(struct kvm_vcpu *vcpu); | 111 | extern int kvmppc_kvm_pv(struct kvm_vcpu *vcpu); |
112 | extern 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 | ||
77 | static inline unsigned int tlb1_max_shadow_size(void) | 77 | static 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 | ||
82 | static inline int tlbe_is_writable(struct tlbe *tlbe) | 83 | static 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 | ||
146 | void 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 | |||
145 | void kvmppc_e500_tlb_load(struct kvm_vcpu *vcpu, int cpu) | 165 | void 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 | ||