Skip to content

Commit bc6678a

Browse files
committed
KVM: introduce kvm->srcu and convert kvm_set_memory_region to SRCU update
Use two steps for memslot deletion: mark the slot invalid (which stops instantiation of new shadow pages for that slot, but allows destruction), then instantiate the new empty slot. Also simplifies kvm_handle_hva locking. Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
1 parent 3ad26d8 commit bc6678a

File tree

8 files changed

+136
-64
lines changed

8 files changed

+136
-64
lines changed

arch/ia64/kvm/kvm-ia64.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1382,7 +1382,7 @@ static void kvm_release_vm_pages(struct kvm *kvm)
13821382
int i, j;
13831383
unsigned long base_gfn;
13841384

1385-
slots = kvm->memslots;
1385+
slots = rcu_dereference(kvm->memslots);
13861386
for (i = 0; i < slots->nmemslots; i++) {
13871387
memslot = &slots->memslots[i];
13881388
base_gfn = memslot->base_gfn;
@@ -1837,6 +1837,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
18371837
struct kvm_memory_slot *memslot;
18381838
int is_dirty = 0;
18391839

1840+
down_write(&kvm->slots_lock);
18401841
spin_lock(&kvm->arch.dirty_log_lock);
18411842

18421843
r = kvm_ia64_sync_dirty_log(kvm, log);
@@ -1856,6 +1857,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
18561857
}
18571858
r = 0;
18581859
out:
1860+
up_write(&kvm->slots_lock);
18591861
spin_unlock(&kvm->arch.dirty_log_lock);
18601862
return r;
18611863
}

arch/x86/kvm/mmu.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <linux/swap.h>
3030
#include <linux/hugetlb.h>
3131
#include <linux/compiler.h>
32+
#include <linux/srcu.h>
3233

3334
#include <asm/page.h>
3435
#include <asm/cmpxchg.h>
@@ -807,21 +808,15 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
807808
{
808809
int i, j;
809810
int retval = 0;
810-
struct kvm_memslots *slots = kvm->memslots;
811+
struct kvm_memslots *slots;
812+
813+
slots = rcu_dereference(kvm->memslots);
811814

812-
/*
813-
* If mmap_sem isn't taken, we can look the memslots with only
814-
* the mmu_lock by skipping over the slots with userspace_addr == 0.
815-
*/
816815
for (i = 0; i < slots->nmemslots; i++) {
817816
struct kvm_memory_slot *memslot = &slots->memslots[i];
818817
unsigned long start = memslot->userspace_addr;
819818
unsigned long end;
820819

821-
/* mmu_lock protects userspace_addr */
822-
if (!start)
823-
continue;
824-
825820
end = start + (memslot->npages << PAGE_SHIFT);
826821
if (hva >= start && hva < end) {
827822
gfn_t gfn_offset = (hva - start) >> PAGE_SHIFT;
@@ -1617,7 +1612,7 @@ static void mmu_unshadow(struct kvm *kvm, gfn_t gfn)
16171612

16181613
static void page_header_update_slot(struct kvm *kvm, void *pte, gfn_t gfn)
16191614
{
1620-
int slot = memslot_id(kvm, gfn_to_memslot(kvm, gfn));
1615+
int slot = memslot_id(kvm, gfn);
16211616
struct kvm_mmu_page *sp = page_header(__pa(pte));
16221617

16231618
__set_bit(slot, sp->slot_bitmap);
@@ -3021,9 +3016,11 @@ unsigned int kvm_mmu_calculate_mmu_pages(struct kvm *kvm)
30213016
int i;
30223017
unsigned int nr_mmu_pages;
30233018
unsigned int nr_pages = 0;
3019+
struct kvm_memslots *slots;
30243020

3025-
for (i = 0; i < kvm->memslots->nmemslots; i++)
3026-
nr_pages += kvm->memslots->memslots[i].npages;
3021+
slots = rcu_dereference(kvm->memslots);
3022+
for (i = 0; i < slots->nmemslots; i++)
3023+
nr_pages += slots->memslots[i].npages;
30273024

30283025
nr_mmu_pages = nr_pages * KVM_PERMILLE_MMU_PAGES / 1000;
30293026
nr_mmu_pages = max(nr_mmu_pages,
@@ -3293,10 +3290,12 @@ static void audit_mappings(struct kvm_vcpu *vcpu)
32933290
static int count_rmaps(struct kvm_vcpu *vcpu)
32943291
{
32953292
int nmaps = 0;
3296-
int i, j, k;
3293+
int i, j, k, idx;
32973294

3295+
idx = srcu_read_lock(&kvm->srcu);
3296+
slots = rcu_dereference(kvm->memslots);
32983297
for (i = 0; i < KVM_MEMORY_SLOTS; ++i) {
3299-
struct kvm_memory_slot *m = &vcpu->kvm->memslots->memslots[i];
3298+
struct kvm_memory_slot *m = &slots->memslots[i];
33003299
struct kvm_rmap_desc *d;
33013300

33023301
for (j = 0; j < m->npages; ++j) {
@@ -3319,6 +3318,7 @@ static int count_rmaps(struct kvm_vcpu *vcpu)
33193318
}
33203319
}
33213320
}
3321+
srcu_read_unlock(&kvm->srcu, idx);
33223322
return nmaps;
33233323
}
33243324

arch/x86/kvm/vmx.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1503,7 +1503,11 @@ static void enter_pmode(struct kvm_vcpu *vcpu)
15031503
static gva_t rmode_tss_base(struct kvm *kvm)
15041504
{
15051505
if (!kvm->arch.tss_addr) {
1506-
gfn_t base_gfn = kvm->memslots->memslots[0].base_gfn +
1506+
struct kvm_memslots *slots;
1507+
gfn_t base_gfn;
1508+
1509+
slots = rcu_dereference(kvm->memslots);
1510+
base_gfn = kvm->memslots->memslots[0].base_gfn +
15071511
kvm->memslots->memslots[0].npages - 3;
15081512
return base_gfn << PAGE_SHIFT;
15091513
}

include/linux/kvm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ struct kvm_userspace_memory_region {
103103

104104
/* for kvm_memory_region::flags */
105105
#define KVM_MEM_LOG_DIRTY_PAGES 1UL
106-
106+
#define KVM_MEMSLOT_INVALID (1UL << 1)
107107

108108
/* for KVM_IRQ_LINE */
109109
struct kvm_irq_level {

include/linux/kvm_host.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ struct kvm {
162162
struct rw_semaphore slots_lock;
163163
struct mm_struct *mm; /* userspace tied to this vm */
164164
struct kvm_memslots *memslots;
165+
struct srcu_struct srcu;
165166
#ifdef CONFIG_KVM_APIC_ARCHITECTURE
166167
u32 bsp_vcpu_id;
167168
struct kvm_vcpu *bsp_vcpu;
@@ -275,6 +276,7 @@ void kvm_set_page_accessed(struct page *page);
275276
pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn);
276277
pfn_t gfn_to_pfn_memslot(struct kvm *kvm,
277278
struct kvm_memory_slot *slot, gfn_t gfn);
279+
int memslot_id(struct kvm *kvm, gfn_t gfn);
278280
void kvm_release_pfn_dirty(pfn_t);
279281
void kvm_release_pfn_clean(pfn_t pfn);
280282
void kvm_set_pfn_dirty(pfn_t pfn);
@@ -490,11 +492,6 @@ static inline void kvm_guest_exit(void)
490492
current->flags &= ~PF_VCPU;
491493
}
492494

493-
static inline int memslot_id(struct kvm *kvm, struct kvm_memory_slot *slot)
494-
{
495-
return slot - kvm->memslots->memslots;
496-
}
497-
498495
static inline gpa_t gfn_to_gpa(gfn_t gfn)
499496
{
500497
return (gpa_t)gfn << PAGE_SHIFT;

virt/kvm/assigned-dev.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -504,12 +504,12 @@ static int kvm_vm_ioctl_deassign_dev_irq(struct kvm *kvm,
504504
static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
505505
struct kvm_assigned_pci_dev *assigned_dev)
506506
{
507-
int r = 0;
507+
int r = 0, idx;
508508
struct kvm_assigned_dev_kernel *match;
509509
struct pci_dev *dev;
510510

511511
mutex_lock(&kvm->lock);
512-
down_read(&kvm->slots_lock);
512+
idx = srcu_read_lock(&kvm->srcu);
513513

514514
match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
515515
assigned_dev->assigned_dev_id);
@@ -573,7 +573,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
573573
}
574574

575575
out:
576-
up_read(&kvm->slots_lock);
576+
srcu_read_unlock(&kvm->srcu, idx);
577577
mutex_unlock(&kvm->lock);
578578
return r;
579579
out_list_del:
@@ -585,7 +585,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
585585
pci_dev_put(dev);
586586
out_free:
587587
kfree(match);
588-
up_read(&kvm->slots_lock);
588+
srcu_read_unlock(&kvm->srcu, idx);
589589
mutex_unlock(&kvm->lock);
590590
return r;
591591
}

virt/kvm/iommu.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ static int kvm_iommu_map_memslots(struct kvm *kvm)
7878
int i, r = 0;
7979
struct kvm_memslots *slots;
8080

81-
slots = kvm->memslots;
81+
slots = rcu_dereference(kvm->memslots);
8282

8383
for (i = 0; i < slots->nmemslots; i++) {
8484
r = kvm_iommu_map_pages(kvm, &slots->memslots[i]);
@@ -214,7 +214,7 @@ static int kvm_iommu_unmap_memslots(struct kvm *kvm)
214214
int i;
215215
struct kvm_memslots *slots;
216216

217-
slots = kvm->memslots;
217+
slots = rcu_dereference(kvm->memslots);
218218

219219
for (i = 0; i < slots->nmemslots; i++) {
220220
kvm_iommu_put_pages(kvm, slots->memslots[i].base_gfn,

0 commit comments

Comments
 (0)