aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/include
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2011-12-12 07:31:00 -0500
committerAvi Kivity <avi@redhat.com>2012-03-05 07:52:36 -0500
commitc77162dee7aff6ab5f075da9b60f649cbbeb86cc (patch)
treec1f3f4f71a9fdad6612da20c67520b4fc8fa0b65 /arch/powerpc/include
parent075295dd322b0c0de0c9ecf8e0cb19ee813438ed (diff)
KVM: PPC: Only get pages when actually needed, not in prepare_memory_region()
This removes the code from kvmppc_core_prepare_memory_region() that looked up the VMA for the region being added and called hva_to_page to get the pfns for the memory. We have no guarantee that there will be anything mapped there at the time of the KVM_SET_USER_MEMORY_REGION ioctl call; userspace can do that ioctl and then map memory into the region later. Instead we defer looking up the pfn for each memory page until it is needed, which generally means when the guest does an H_ENTER hcall on the page. Since we can't call get_user_pages in real mode, if we don't already have the pfn for the page, kvmppc_h_enter() will return H_TOO_HARD and we then call kvmppc_virtmode_h_enter() once we get back to kernel context. That calls kvmppc_get_guest_page() to get the pfn for the page, and then calls back to kvmppc_h_enter() to redo the HPTE insertion. When the first vcpu starts executing, we need to have the RMO or VRMA region mapped so that the guest's real mode accesses will work. Thus we now have a check in kvmppc_vcpu_run() to see if the RMO/VRMA is set up and if not, call kvmppc_hv_setup_rma(). It checks if the memslot starting at guest physical 0 now has RMO memory mapped there; if so it sets it up for the guest, otherwise on POWER7 it sets up the VRMA. The function that does that, kvmppc_map_vrma, is now a bit simpler, as it calls kvmppc_virtmode_h_enter instead of creating the HPTE itself. Since we are now potentially updating entries in the slot_phys[] arrays from multiple vcpu threads, we now have a spinlock protecting those updates to ensure that we don't lose track of any references to pages. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc/include')
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h4
-rw-r--r--arch/powerpc/include/asm/kvm_book3s_64.h12
-rw-r--r--arch/powerpc/include/asm/kvm_host.h2
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h4
4 files changed, 20 insertions, 2 deletions
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index bcf6f4f52a22..c700f43ba178 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -141,6 +141,10 @@ extern pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn);
141extern void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long addr, 141extern void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long addr,
142 unsigned long *nb_ret); 142 unsigned long *nb_ret);
143extern void kvmppc_unpin_guest_page(struct kvm *kvm, void *addr); 143extern void kvmppc_unpin_guest_page(struct kvm *kvm, void *addr);
144extern long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
145 long pte_index, unsigned long pteh, unsigned long ptel);
146extern long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
147 long pte_index, unsigned long pteh, unsigned long ptel);
144 148
145extern void kvmppc_entry_trampoline(void); 149extern void kvmppc_entry_trampoline(void);
146extern void kvmppc_hv_entry_trampoline(void); 150extern void kvmppc_hv_entry_trampoline(void);
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index 300ec04a8381..7e6f2ede44ac 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -101,4 +101,16 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
101 return rb; 101 return rb;
102} 102}
103 103
104static inline unsigned long hpte_page_size(unsigned long h, unsigned long l)
105{
106 /* only handle 4k, 64k and 16M pages for now */
107 if (!(h & HPTE_V_LARGE))
108 return 1ul << 12; /* 4k page */
109 if ((l & 0xf000) == 0x1000 && cpu_has_feature(CPU_FTR_ARCH_206))
110 return 1ul << 16; /* 64k page */
111 if ((l & 0xff000) == 0)
112 return 1ul << 24; /* 16M page */
113 return 0; /* error */
114}
115
104#endif /* __ASM_KVM_BOOK3S_64_H__ */ 116#endif /* __ASM_KVM_BOOK3S_64_H__ */
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 7a17ab5b9058..beb22ba71e26 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -194,7 +194,9 @@ struct kvm_arch {
194 unsigned long lpcr; 194 unsigned long lpcr;
195 unsigned long rmor; 195 unsigned long rmor;
196 struct kvmppc_rma_info *rma; 196 struct kvmppc_rma_info *rma;
197 int rma_setup_done;
197 struct list_head spapr_tce_tables; 198 struct list_head spapr_tce_tables;
199 spinlock_t slot_phys_lock;
198 unsigned long *slot_phys[KVM_MEM_SLOTS_NUM]; 200 unsigned long *slot_phys[KVM_MEM_SLOTS_NUM];
199 int slot_npages[KVM_MEM_SLOTS_NUM]; 201 int slot_npages[KVM_MEM_SLOTS_NUM];
200 unsigned short last_vcpu[NR_CPUS]; 202 unsigned short last_vcpu[NR_CPUS];
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 5192c2e70583..1458c6740ea3 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -121,8 +121,8 @@ extern long kvmppc_alloc_hpt(struct kvm *kvm);
121extern void kvmppc_free_hpt(struct kvm *kvm); 121extern void kvmppc_free_hpt(struct kvm *kvm);
122extern long kvmppc_prepare_vrma(struct kvm *kvm, 122extern long kvmppc_prepare_vrma(struct kvm *kvm,
123 struct kvm_userspace_memory_region *mem); 123 struct kvm_userspace_memory_region *mem);
124extern void kvmppc_map_vrma(struct kvm *kvm, 124extern void kvmppc_map_vrma(struct kvm_vcpu *vcpu,
125 struct kvm_userspace_memory_region *mem); 125 struct kvm_memory_slot *memslot);
126extern int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu); 126extern int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu);
127extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, 127extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
128 struct kvm_create_spapr_tce *args); 128 struct kvm_create_spapr_tce *args);