summaryrefslogtreecommitdiff
path: root/arch/powerpc/kvm/e500_tlb.c
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2011-06-14 18:34:41 -0500
committerAvi Kivity <avi@redhat.com>2011-07-12 13:16:37 +0300
commita4cd8b23ac5786943202c0174c717956947db43c (patch)
tree46e1dc4646d6c2a27fc83944e24aad1c1fafb292 /arch/powerpc/kvm/e500_tlb.c
parent9973d54eeafcd1c3a2e89f0f59280c4c1e03e73b (diff)
KVM: PPC: e500: enable magic page
This is a shared page used for paravirtualization. It is always present in the guest kernel's effective address space at the address indicated by the hypercall that enables it. The physical address specified by the hypercall is not used, as e500 does not have real mode. Signed-off-by: Scott Wood <scottwood@freescale.com> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/kvm/e500_tlb.c')
-rw-r--r--arch/powerpc/kvm/e500_tlb.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index 7f808c52e64..c09e642ee53 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(
static inline unsigned int tlb1_max_shadow_size(void)
{
- return tlb1_entry_num - tlbcam_index;
+ /* reserve one entry for magic page */
+ return tlb1_entry_num - tlbcam_index - 1;
}
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,
}
}
+void kvmppc_map_magic(struct kvm_vcpu *vcpu)
+{
+ struct tlbe magic;
+ ulong shared_page = ((ulong)vcpu->arch.shared) & PAGE_MASK;
+ pfn_t pfn;
+
+ pfn = (pfn_t)virt_to_phys((void *)shared_page) >> PAGE_SHIFT;
+ get_page(pfn_to_page(pfn));
+
+ magic.mas1 = MAS1_VALID | MAS1_TS |
+ MAS1_TSIZE(BOOK3E_PAGESZ_4K);
+ magic.mas2 = vcpu->arch.magic_page_ea | MAS2_M;
+ magic.mas3 = (pfn << PAGE_SHIFT) |
+ MAS3_SW | MAS3_SR | MAS3_UW | MAS3_UR;
+ magic.mas7 = pfn >> (32 - PAGE_SHIFT);
+
+ __write_host_tlbe(&magic, MAS0_TLBSEL(1) | MAS0_ESEL(tlbcam_index));
+}
+
void kvmppc_e500_tlb_load(struct kvm_vcpu *vcpu, int cpu)
{
}