aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/include/asm
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2012-02-19 12:46:32 -0500
committerAvi Kivity <avi@redhat.com>2012-04-08 07:01:27 -0400
commit2e25aa5f64b18a97f35266e51c71ff4dc644db0c (patch)
tree7b26cf15534d54bc2c370f1e5393cd9e58eb7141 /arch/powerpc/include/asm
parentf0888f70151c7f53de2b45ee20ff1905837943e8 (diff)
KVM: PPC: Book3S HV: Make virtual processor area registration more robust
The PAPR API allows three sorts of per-virtual-processor areas to be registered (VPA, SLB shadow buffer, and dispatch trace log), and furthermore, these can be registered and unregistered for another virtual CPU. Currently we just update the vcpu fields pointing to these areas at the time of registration or unregistration. If this is done on another vcpu, there is the possibility that the target vcpu is using those fields at the time and could end up using a bogus pointer and corrupting memory. This fixes the race by making the target cpu itself do the update, so we can be sure that the update happens at a time when the fields aren't being used. Each area now has a struct kvmppc_vpa which is used to manage these updates. There is also a spinlock which protects access to all of the kvmppc_vpa structs, other than to the pinned_addr fields. (We could have just taken the spinlock when using the vpa, slb_shadow or dtl fields, but that would mean taking the spinlock on every guest entry and exit.) This also changes 'struct dtl' (which was undefined) to 'struct dtl_entry', which is what the rest of the kernel uses. Thanks to Michael Ellerman <michael@ellerman.id.au> for pointing out the need to initialize vcpu->arch.vpa_update_lock. 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/asm')
-rw-r--r--arch/powerpc/include/asm/hvcall.h10
-rw-r--r--arch/powerpc/include/asm/kvm_host.h27
2 files changed, 31 insertions, 6 deletions
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 1c324ff55ea8..318bac9f8752 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -114,6 +114,16 @@
114#define H_PP1 (1UL<<(63-62)) 114#define H_PP1 (1UL<<(63-62))
115#define H_PP2 (1UL<<(63-63)) 115#define H_PP2 (1UL<<(63-63))
116 116
117/* Flags for H_REGISTER_VPA subfunction field */
118#define H_VPA_FUNC_SHIFT (63-18) /* Bit posn of subfunction code */
119#define H_VPA_FUNC_MASK 7UL
120#define H_VPA_REG_VPA 1UL /* Register Virtual Processor Area */
121#define H_VPA_REG_DTL 2UL /* Register Dispatch Trace Log */
122#define H_VPA_REG_SLB 3UL /* Register SLB shadow buffer */
123#define H_VPA_DEREG_VPA 5UL /* Deregister Virtual Processor Area */
124#define H_VPA_DEREG_DTL 6UL /* Deregister Dispatch Trace Log */
125#define H_VPA_DEREG_SLB 7UL /* Deregister SLB shadow buffer */
126
117/* VASI States */ 127/* VASI States */
118#define H_VASI_INVALID 0 128#define H_VASI_INVALID 0
119#define H_VASI_ENABLED 1 129#define H_VASI_ENABLED 1
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 97ecdaf82956..93ffd8dd8554 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -82,7 +82,7 @@ struct kvm_vcpu;
82 82
83struct lppaca; 83struct lppaca;
84struct slb_shadow; 84struct slb_shadow;
85struct dtl; 85struct dtl_entry;
86 86
87struct kvm_vm_stat { 87struct kvm_vm_stat {
88 u32 remote_tlb_flush; 88 u32 remote_tlb_flush;
@@ -279,6 +279,19 @@ struct kvmppc_vcore {
279#define VCORE_EXITING 2 279#define VCORE_EXITING 2
280#define VCORE_SLEEPING 3 280#define VCORE_SLEEPING 3
281 281
282/*
283 * Struct used to manage memory for a virtual processor area
284 * registered by a PAPR guest. There are three types of area
285 * that a guest can register.
286 */
287struct kvmppc_vpa {
288 void *pinned_addr; /* Address in kernel linear mapping */
289 void *pinned_end; /* End of region */
290 unsigned long next_gpa; /* Guest phys addr for update */
291 unsigned long len; /* Number of bytes required */
292 u8 update_pending; /* 1 => update pinned_addr from next_gpa */
293};
294
282struct kvmppc_pte { 295struct kvmppc_pte {
283 ulong eaddr; 296 ulong eaddr;
284 u64 vpage; 297 u64 vpage;
@@ -473,11 +486,6 @@ struct kvm_vcpu_arch {
473 u8 prodded; 486 u8 prodded;
474 u32 last_inst; 487 u32 last_inst;
475 488
476 struct lppaca *vpa;
477 struct slb_shadow *slb_shadow;
478 struct dtl *dtl;
479 struct dtl *dtl_end;
480
481 wait_queue_head_t *wqp; 489 wait_queue_head_t *wqp;
482 struct kvmppc_vcore *vcore; 490 struct kvmppc_vcore *vcore;
483 int ret; 491 int ret;
@@ -502,6 +510,13 @@ struct kvm_vcpu_arch {
502 struct task_struct *run_task; 510 struct task_struct *run_task;
503 struct kvm_run *kvm_run; 511 struct kvm_run *kvm_run;
504 pgd_t *pgdir; 512 pgd_t *pgdir;
513
514 spinlock_t vpa_update_lock;
515 struct kvmppc_vpa vpa;
516 struct kvmppc_vpa dtl;
517 struct dtl_entry *dtl_ptr;
518 unsigned long dtl_index;
519 struct kvmppc_vpa slb_shadow;
505#endif 520#endif
506}; 521};
507 522