aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2012-09-11 09:27:01 -0400
committerAlexander Graf <agraf@suse.de>2012-10-05 17:38:51 -0400
commit2c9097e4c1340208ef93371abd4b3bd7e989381b (patch)
tree941f326bf93ad74e208a26d8d9942b5026e00643 /arch/powerpc
parentd61966fc08b84857b697ebae4489c652dd87e48a (diff)
KVM: PPC: Book3S HV: Take the SRCU read lock before looking up memslots
The generic KVM code uses SRCU (sleeping RCU) to protect accesses to the memslots data structures against updates due to userspace adding, modifying or removing memory slots. We need to do that too, both to avoid accessing stale copies of the memslots and to avoid lockdep warnings. This therefore adds srcu_read_lock/unlock pairs around code that accesses and uses memslots. Since the real-mode handlers for H_ENTER, H_REMOVE and H_BULK_REMOVE need to access the memslots, and we don't want to call the SRCU code in real mode (since we have no assurance that it would only access the linear mapping), we hold the SRCU read lock for the VM while in the guest. This does mean that adding or removing memory slots while some vcpus are executing in the guest will block for up to two jiffies. This tradeoff is acceptable since adding/removing memory slots only happens rarely, while H_ENTER/H_REMOVE/H_BULK_REMOVE are performance-critical hot paths. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_hv.c17
-rw-r--r--arch/powerpc/kvm/book3s_hv.c27
2 files changed, 36 insertions, 8 deletions
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index d95d11322a15..0f031c07f7e5 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -24,6 +24,7 @@
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/hugetlb.h> 25#include <linux/hugetlb.h>
26#include <linux/vmalloc.h> 26#include <linux/vmalloc.h>
27#include <linux/srcu.h>
27 28
28#include <asm/tlbflush.h> 29#include <asm/tlbflush.h>
29#include <asm/kvm_ppc.h> 30#include <asm/kvm_ppc.h>
@@ -1057,20 +1058,22 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
1057 unsigned long hva, psize, offset; 1058 unsigned long hva, psize, offset;
1058 unsigned long pa; 1059 unsigned long pa;
1059 unsigned long *physp; 1060 unsigned long *physp;
1061 int srcu_idx;
1060 1062
1063 srcu_idx = srcu_read_lock(&kvm->srcu);
1061 memslot = gfn_to_memslot(kvm, gfn); 1064 memslot = gfn_to_memslot(kvm, gfn);
1062 if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) 1065 if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
1063 return NULL; 1066 goto err;
1064 if (!kvm->arch.using_mmu_notifiers) { 1067 if (!kvm->arch.using_mmu_notifiers) {
1065 physp = kvm->arch.slot_phys[memslot->id]; 1068 physp = kvm->arch.slot_phys[memslot->id];
1066 if (!physp) 1069 if (!physp)
1067 return NULL; 1070 goto err;
1068 physp += gfn - memslot->base_gfn; 1071 physp += gfn - memslot->base_gfn;
1069 pa = *physp; 1072 pa = *physp;
1070 if (!pa) { 1073 if (!pa) {
1071 if (kvmppc_get_guest_page(kvm, gfn, memslot, 1074 if (kvmppc_get_guest_page(kvm, gfn, memslot,
1072 PAGE_SIZE) < 0) 1075 PAGE_SIZE) < 0)
1073 return NULL; 1076 goto err;
1074 pa = *physp; 1077 pa = *physp;
1075 } 1078 }
1076 page = pfn_to_page(pa >> PAGE_SHIFT); 1079 page = pfn_to_page(pa >> PAGE_SHIFT);
@@ -1079,9 +1082,11 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
1079 hva = gfn_to_hva_memslot(memslot, gfn); 1082 hva = gfn_to_hva_memslot(memslot, gfn);
1080 npages = get_user_pages_fast(hva, 1, 1, pages); 1083 npages = get_user_pages_fast(hva, 1, 1, pages);
1081 if (npages < 1) 1084 if (npages < 1)
1082 return NULL; 1085 goto err;
1083 page = pages[0]; 1086 page = pages[0];
1084 } 1087 }
1088 srcu_read_unlock(&kvm->srcu, srcu_idx);
1089
1085 psize = PAGE_SIZE; 1090 psize = PAGE_SIZE;
1086 if (PageHuge(page)) { 1091 if (PageHuge(page)) {
1087 page = compound_head(page); 1092 page = compound_head(page);
@@ -1091,6 +1096,10 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
1091 if (nb_ret) 1096 if (nb_ret)
1092 *nb_ret = psize - offset; 1097 *nb_ret = psize - offset;
1093 return page_address(page) + offset; 1098 return page_address(page) + offset;
1099
1100 err:
1101 srcu_read_unlock(&kvm->srcu, srcu_idx);
1102 return NULL;
1094} 1103}
1095 1104
1096void kvmppc_unpin_guest_page(struct kvm *kvm, void *va) 1105void kvmppc_unpin_guest_page(struct kvm *kvm, void *va)
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 83e929e66f9d..48b0d4a73b9d 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -30,6 +30,7 @@
30#include <linux/cpumask.h> 30#include <linux/cpumask.h>
31#include <linux/spinlock.h> 31#include <linux/spinlock.h>
32#include <linux/page-flags.h> 32#include <linux/page-flags.h>
33#include <linux/srcu.h>
33 34
34#include <asm/reg.h> 35#include <asm/reg.h>
35#include <asm/cputable.h> 36#include <asm/cputable.h>
@@ -366,13 +367,16 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
366 unsigned long req = kvmppc_get_gpr(vcpu, 3); 367 unsigned long req = kvmppc_get_gpr(vcpu, 3);
367 unsigned long target, ret = H_SUCCESS; 368 unsigned long target, ret = H_SUCCESS;
368 struct kvm_vcpu *tvcpu; 369 struct kvm_vcpu *tvcpu;
370 int idx;
369 371
370 switch (req) { 372 switch (req) {
371 case H_ENTER: 373 case H_ENTER:
374 idx = srcu_read_lock(&vcpu->kvm->srcu);
372 ret = kvmppc_virtmode_h_enter(vcpu, kvmppc_get_gpr(vcpu, 4), 375 ret = kvmppc_virtmode_h_enter(vcpu, kvmppc_get_gpr(vcpu, 4),
373 kvmppc_get_gpr(vcpu, 5), 376 kvmppc_get_gpr(vcpu, 5),
374 kvmppc_get_gpr(vcpu, 6), 377 kvmppc_get_gpr(vcpu, 6),
375 kvmppc_get_gpr(vcpu, 7)); 378 kvmppc_get_gpr(vcpu, 7));
379 srcu_read_unlock(&vcpu->kvm->srcu, idx);
376 break; 380 break;
377 case H_CEDE: 381 case H_CEDE:
378 break; 382 break;
@@ -411,6 +415,7 @@ static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
411 struct task_struct *tsk) 415 struct task_struct *tsk)
412{ 416{
413 int r = RESUME_HOST; 417 int r = RESUME_HOST;
418 int srcu_idx;
414 419
415 vcpu->stat.sum_exits++; 420 vcpu->stat.sum_exits++;
416 421
@@ -470,12 +475,16 @@ static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
470 * have been handled already. 475 * have been handled already.
471 */ 476 */
472 case BOOK3S_INTERRUPT_H_DATA_STORAGE: 477 case BOOK3S_INTERRUPT_H_DATA_STORAGE:
478 srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
473 r = kvmppc_book3s_hv_page_fault(run, vcpu, 479 r = kvmppc_book3s_hv_page_fault(run, vcpu,
474 vcpu->arch.fault_dar, vcpu->arch.fault_dsisr); 480 vcpu->arch.fault_dar, vcpu->arch.fault_dsisr);
481 srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
475 break; 482 break;
476 case BOOK3S_INTERRUPT_H_INST_STORAGE: 483 case BOOK3S_INTERRUPT_H_INST_STORAGE:
484 srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
477 r = kvmppc_book3s_hv_page_fault(run, vcpu, 485 r = kvmppc_book3s_hv_page_fault(run, vcpu,
478 kvmppc_get_pc(vcpu), 0); 486 kvmppc_get_pc(vcpu), 0);
487 srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
479 break; 488 break;
480 /* 489 /*
481 * This occurs if the guest executes an illegal instruction. 490 * This occurs if the guest executes an illegal instruction.
@@ -820,6 +829,7 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
820 long ret; 829 long ret;
821 u64 now; 830 u64 now;
822 int ptid, i, need_vpa_update; 831 int ptid, i, need_vpa_update;
832 int srcu_idx;
823 833
824 /* don't start if any threads have a signal pending */ 834 /* don't start if any threads have a signal pending */
825 need_vpa_update = 0; 835 need_vpa_update = 0;
@@ -898,6 +908,9 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
898 spin_unlock(&vc->lock); 908 spin_unlock(&vc->lock);
899 909
900 kvm_guest_enter(); 910 kvm_guest_enter();
911
912 srcu_idx = srcu_read_lock(&vcpu0->kvm->srcu);
913
901 __kvmppc_vcore_entry(NULL, vcpu0); 914 __kvmppc_vcore_entry(NULL, vcpu0);
902 for (i = 0; i < threads_per_core; ++i) 915 for (i = 0; i < threads_per_core; ++i)
903 kvmppc_release_hwthread(vc->pcpu + i); 916 kvmppc_release_hwthread(vc->pcpu + i);
@@ -913,6 +926,8 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
913 vc->vcore_state = VCORE_EXITING; 926 vc->vcore_state = VCORE_EXITING;
914 spin_unlock(&vc->lock); 927 spin_unlock(&vc->lock);
915 928
929 srcu_read_unlock(&vcpu0->kvm->srcu, srcu_idx);
930
916 /* make sure updates to secondary vcpu structs are visible now */ 931 /* make sure updates to secondary vcpu structs are visible now */
917 smp_mb(); 932 smp_mb();
918 kvm_guest_exit(); 933 kvm_guest_exit();
@@ -1362,6 +1377,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
1362 unsigned long rmls; 1377 unsigned long rmls;
1363 unsigned long *physp; 1378 unsigned long *physp;
1364 unsigned long i, npages; 1379 unsigned long i, npages;
1380 int srcu_idx;
1365 1381
1366 mutex_lock(&kvm->lock); 1382 mutex_lock(&kvm->lock);
1367 if (kvm->arch.rma_setup_done) 1383 if (kvm->arch.rma_setup_done)
@@ -1377,12 +1393,13 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
1377 } 1393 }
1378 1394
1379 /* Look up the memslot for guest physical address 0 */ 1395 /* Look up the memslot for guest physical address 0 */
1396 srcu_idx = srcu_read_lock(&kvm->srcu);
1380 memslot = gfn_to_memslot(kvm, 0); 1397 memslot = gfn_to_memslot(kvm, 0);
1381 1398
1382 /* We must have some memory at 0 by now */ 1399 /* We must have some memory at 0 by now */
1383 err = -EINVAL; 1400 err = -EINVAL;
1384 if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) 1401 if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
1385 goto out; 1402 goto out_srcu;
1386 1403
1387 /* Look up the VMA for the start of this memory slot */ 1404 /* Look up the VMA for the start of this memory slot */
1388 hva = memslot->userspace_addr; 1405 hva = memslot->userspace_addr;
@@ -1406,14 +1423,14 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
1406 err = -EPERM; 1423 err = -EPERM;
1407 if (cpu_has_feature(CPU_FTR_ARCH_201)) { 1424 if (cpu_has_feature(CPU_FTR_ARCH_201)) {
1408 pr_err("KVM: CPU requires an RMO\n"); 1425 pr_err("KVM: CPU requires an RMO\n");
1409 goto out; 1426 goto out_srcu;
1410 } 1427 }
1411 1428
1412 /* We can handle 4k, 64k or 16M pages in the VRMA */ 1429 /* We can handle 4k, 64k or 16M pages in the VRMA */
1413 err = -EINVAL; 1430 err = -EINVAL;
1414 if (!(psize == 0x1000 || psize == 0x10000 || 1431 if (!(psize == 0x1000 || psize == 0x10000 ||
1415 psize == 0x1000000)) 1432 psize == 0x1000000))
1416 goto out; 1433 goto out_srcu;
1417 1434
1418 /* Update VRMASD field in the LPCR */ 1435 /* Update VRMASD field in the LPCR */
1419 senc = slb_pgsize_encoding(psize); 1436 senc = slb_pgsize_encoding(psize);
@@ -1436,7 +1453,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
1436 err = -EINVAL; 1453 err = -EINVAL;
1437 if (rmls < 0) { 1454 if (rmls < 0) {
1438 pr_err("KVM: Can't use RMA of 0x%lx bytes\n", rma_size); 1455 pr_err("KVM: Can't use RMA of 0x%lx bytes\n", rma_size);
1439 goto out; 1456 goto out_srcu;
1440 } 1457 }
1441 atomic_inc(&ri->use_count); 1458 atomic_inc(&ri->use_count);
1442 kvm->arch.rma = ri; 1459 kvm->arch.rma = ri;
@@ -1476,6 +1493,8 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
1476 smp_wmb(); 1493 smp_wmb();
1477 kvm->arch.rma_setup_done = 1; 1494 kvm->arch.rma_setup_done = 1;
1478 err = 0; 1495 err = 0;
1496 out_srcu:
1497 srcu_read_unlock(&kvm->srcu, srcu_idx);
1479 out: 1498 out:
1480 mutex_unlock(&kvm->lock); 1499 mutex_unlock(&kvm->lock);
1481 return err; 1500 return err;