KVM: optimize memslots searching
v3 cover KVM: optimize memslots searching
Changelog:
- rebase it on current kvm tree and some cleanups
This patchset is tested on x86 and build tested on powerpc and ia64
PATCH v3 1/6 KVM: introduce KVM_MEM_SLOTS_NUM macro
From: Xiao Guangrong <[email protected]>
Introduce KVM_MEM_SLOTS_NUM macro to instead ofKVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS
--- arch/x86/include/asm/kvm_host.h | 4 +++- arch/x86/kvm/mmu.c | 2 +- include/linux/kvm_host.h | 7 +++++-- virt/kvm/kvm_main.c | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-)
arch/x86/include/asm/kvm_host.h +3 -1
@@ -31,6 +31,8 @@#define KVM_MEMORY_SLOTS 32/* memory slots that does not exposed to userspace */ #define KVM_PRIVATE_MEM_SLOTS 4 +#define KVM_MEM_SLOTS_NUM (KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS) +#define KVM_MMIO_SIZE 16#define KVM_PIO_PAGE_OFFSET 1
@@ -228,7 +230,7 @@ struct kvm_mmu_page {* One bit set per slot which has memory * in this shadow page. */ -DECLARE_BITMAP (slot_bitmap,KVM_MEMORY_SLOTS +KVM_PRIVATE_MEM_SLOTS ); +DECLARE_BITMAP (slot_bitmap,KVM_MEM_SLOTS_NUM );bool unsync;int root_count;/* Currently serving as active root */ unsigned int unsync_children;
arch/x86/kvm/mmu.c +1 -1
@@ -1349,7 +1349,7 @@ static struct kvm_mmu_page *kvm_mmu_alloc_page(struct kvm_vcpu *vcpu, PAGE_SIZE);set_page_private (virt_to_page (sp->spt), (unsigned long )sp);list_add (&sp->link, &vcpu->kvm->arch.active_mmu_pages); -bitmap_zero (sp->slot_bitmap,KVM_MEMORY_SLOTS +KVM_PRIVATE_MEM_SLOTS ); +bitmap_zero (sp->slot_bitmap,KVM_MEM_SLOTS_NUM ); sp->parent_ptes =0 ;mmu_page_add_parent_pte (vcpu, sp, parent_pte);kvm_mod_used_mmu_pages (vcpu->kvm,+1 );
include/linux/kvm_host.h +5 -2
@@ -227,11 +227,14 @@ struct kvm_irq_routing_table {};#endif +#ifndef KVM_MEM_SLOTS_NUM +#define KVM_MEM_SLOTS_NUM (KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS) +#endif +struct kvm_memslots {int nmemslots;u64 generation; -struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS + -KVM_PRIVATE_MEM_SLOTS ]; +struct kvm_memory_slot memslots[KVM_MEM_SLOTS_NUM ]; };struct kvm {
virt/kvm/kvm_main.c +1 -1
@@ -663,7 +663,7 @@ int __kvm_set_memory_region(struct kvm *kvm, (void __user *)(unsigned long)mem->userspace_addr, mem->memory_size))) goto out; -if (mem->slot >=KVM_MEMORY_SLOTS +KVM_PRIVATE_MEM_SLOTS ) +if (mem->slot >=KVM_MEM_SLOTS_NUM ) goto out;if (mem->guest_phys_addr + mem->memory_size < mem->guest_phys_addr) goto out;
Signature · 1 line
1.7.7.3
PATCH v3 2/6 KVM: introduce update_memslots function
In reply to Xiao GuangrongFrom: Xiao Guangrong <[email protected]>
Introduce update_memslots to update slot which will be update to kvm->memslots
--- arch/x86/kvm/x86.c | 2 +- include/linux/kvm_host.h | 1 + virt/kvm/kvm_main.c | 22 +++++++++++++++------- 3 files changed, 17 insertions(+), 8 deletions(-)
arch/x86/kvm/x86.c +1 -1
@@ -3547,7 +3547,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, memslot = &slots->memslots[log->slot]; memslot->dirty_bitmap = dirty_bitmap; memslot->nr_dirty_pages =0 ; - slots->generation++; +update_memslots (slots,NULL ); old_slots = kvm->memslots;rcu_assign_pointer (kvm->memslots, slots);
include/linux/kvm_host.h +1 -0
@@ -320,6 +320,7 @@ void kvm_exit(void);void kvm_get_kvm (struct kvm *kvm);void kvm_put_kvm (struct kvm *kvm); +void update_memslots (struct kvm_memslots *slots,struct kvm_memory_slot *new);static inline struct kvm_memslots *kvm_memslots (struct kvm *kvm) {
virt/kvm/kvm_main.c +15 -7
@@ -630,6 +630,19 @@ static int kvm_create_dirty_bitmap(struct kvm_memory_slot *memslot) }#endif /* !CONFIG_S390 */ +void update_memslots (struct kvm_memslots *slots,struct kvm_memory_slot *new) +{ +if (new) { +int id = new->id; + + slots->memslots[id] = *new; +if (id >= slots->nmemslots) + slots->nmemslots = id +1 ; + } + + slots->generation++; +} +/* * Allocate some memory and give it an address in the guest physical address * space.
@@ -780,10 +793,8 @@ skip_lpage: GFP_KERNEL);if (!slots) goto out_free; -if (mem->slot >= slots->nmemslots) - slots->nmemslots = mem->slot +1 ; - slots->generation++; slots->memslots[mem->slot].flags |=KVM_MEMSLOT_INVALID ; +update_memslots (slots,NULL ); old_memslots = kvm->memslots;rcu_assign_pointer (kvm->memslots, slots);
@@ -815,9 +826,6 @@ skip_lpage: GFP_KERNEL);if (!slots) goto out_free; -if (mem->slot >= slots->nmemslots) - slots->nmemslots = mem->slot +1 ; - slots->generation++;/* actual memory is freed via old in kvm_free_physmem_slot below */ if (!npages) {
@@ -827,7 +835,7 @@ skip_lpage: new.lpage_info[i] =NULL ; } - slots->memslots[mem->slot] = new; +update_memslots (slots, &new); old_memslots = kvm->memslots;rcu_assign_pointer (kvm->memslots, slots);synchronize_srcu_expedited (&kvm->srcu);
Signature · 1 line
1.7.7.3
PATCH v3 3/6 KVM: introduce kvm_for_each_memslot macro
In reply to Xiao GuangrongFrom: Xiao Guangrong <[email protected]>
Introduce kvm_for_each_memslot to walk all valid memslot
--- arch/ia64/kvm/kvm-ia64.c | 6 ++---- arch/x86/kvm/mmu.c | 12 ++++++------ include/linux/kvm_host.h | 4 ++++ virt/kvm/iommu.c | 17 +++++++++-------- virt/kvm/kvm_main.c | 14 ++++++-------- 5 files changed, 27 insertions(+), 26 deletions(-)
arch/ia64/kvm/kvm-ia64.c +2 -4
@@ -1366,14 +1366,12 @@ static void kvm_release_vm_pages(struct kvm *kvm) {struct kvm_memslots *slots;struct kvm_memory_slot *memslot; -int i, j; +int j;unsigned long base_gfn; slots =kvm_memslots (kvm); -for (i =0 ; i < slots->nmemslots; i++) { - memslot = &slots->memslots[i]; +kvm_for_each_memslot (memslot, slots) { base_gfn = memslot->base_gfn; -for (j =0 ; j < memslot->npages; j++) {if (memslot->rmap[j])put_page ((struct page *)memslot->rmap[j]);
arch/x86/kvm/mmu.c +6 -6
@@ -1128,15 +1128,15 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,int (*handler)(struct kvm *kvm,unsigned long *rmapp, unsigned long data)) { -int i, j; +int j;int ret;int retval =0 ;struct kvm_memslots *slots; +struct kvm_memory_slot *memslot; slots =kvm_memslots (kvm); -for (i =0 ; i < slots->nmemslots; i++) { -struct kvm_memory_slot *memslot = &slots->memslots[i]; +kvm_for_each_memslot (memslot, slots) {unsigned long start = memslot->userspace_addr;unsigned long end;
@@ -3985,15 +3985,15 @@ nomem:*/ unsigned int kvm_mmu_calculate_mmu_pages (struct kvm *kvm) { -int i;unsigned int nr_mmu_pages;unsigned int nr_pages =0 ;struct kvm_memslots *slots; +struct kvm_memory_slot *memslot; slots =kvm_memslots (kvm); -for (i =0 ; i < slots->nmemslots; i++) - nr_pages += slots->memslots[i].npages; +kvm_for_each_memslot (memslot, slots) + nr_pages += memslot->npages; nr_mmu_pages = nr_pages *KVM_PERMILLE_MMU_PAGES /1000 ; nr_mmu_pages = max(nr_mmu_pages,
include/linux/kvm_host.h +4 -0
@@ -308,6 +308,10 @@ static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i) (vcpup =kvm_get_vcpu (kvm, idx)) !=NULL ; \ idx++) +#define kvm_for_each_memslot (memslot, slots) \ + for (memslot = &slots->memslots[0]; \ + memslot < slots->memslots + (slots)->nmemslots; memslot++) +int kvm_vcpu_init (struct kvm_vcpu *vcpu,struct kvm *kvm,unsigned id);void kvm_vcpu_uninit (struct kvm_vcpu *vcpu);
virt/kvm/iommu.c +9 -8
@@ -134,14 +134,15 @@ unmap_pages:static int kvm_iommu_map_memslots (struct kvm *kvm) { -int i, idx, r =0 ; +int idx, r =0 ;struct kvm_memslots *slots; +struct kvm_memory_slot *memslot; idx =srcu_read_lock (&kvm->srcu); slots =kvm_memslots (kvm); -for (i =0 ; i < slots->nmemslots; i++) { - r =kvm_iommu_map_pages (kvm, &slots->memslots[i]); +kvm_for_each_memslot (memslot, slots) { + r =kvm_iommu_map_pages (kvm, memslot);if (r)break ; }
@@ -311,16 +312,16 @@ static void kvm_iommu_put_pages(struct kvm *kvm,static int kvm_iommu_unmap_memslots (struct kvm *kvm) { -int i, idx; +int idx;struct kvm_memslots *slots; +struct kvm_memory_slot *memslot; idx =srcu_read_lock (&kvm->srcu); slots =kvm_memslots (kvm); -for (i =0 ; i < slots->nmemslots; i++) { -kvm_iommu_put_pages (kvm, slots->memslots[i].base_gfn, - slots->memslots[i].npages); - } +kvm_for_each_memslot (memslot, slots) +kvm_iommu_put_pages (kvm, memslot->base_gfn, memslot->npages); +srcu_read_unlock (&kvm->srcu, idx);return 0 ;
virt/kvm/kvm_main.c +6 -8
@@ -547,11 +547,11 @@ static void kvm_free_physmem_slot(struct kvm_memory_slot *free,void kvm_free_physmem (struct kvm *kvm) { -int i;struct kvm_memslots *slots = kvm->memslots; +struct kvm_memory_slot *memslot; -for (i =0 ; i < slots->nmemslots; ++i) -kvm_free_physmem_slot (&slots->memslots[i],NULL ); +kvm_for_each_memslot (memslot, slots) +kvm_free_physmem_slot (memslot,NULL );kfree (kvm->memslots); }
@@ -975,15 +975,13 @@ EXPORT_SYMBOL_GPL(kvm_is_error_hva);static struct kvm_memory_slot *__gfn_to_memslot (struct kvm_memslots *slots,gfn_t gfn) { -int i; - -for (i =0 ; i < slots->nmemslots; ++i) { -struct kvm_memory_slot *memslot = &slots->memslots[i]; +struct kvm_memory_slot *memslot; +kvm_for_each_memslot (memslot, slots)if (gfn >= memslot->base_gfn && gfn < memslot->base_gfn + memslot->npages)return memslot; - } +return NULL ; }
Signature · 1 line
1.7.7.3
PATCH v3 4/6 KVM: introduce id_to_memslot function
In reply to Xiao GuangrongFrom: Xiao Guangrong <[email protected]>
Introduce id_to_memslot to get memslot by slot id
--- arch/ia64/kvm/kvm-ia64.c | 2 +- arch/powerpc/kvm/book3s.c | 2 +- arch/x86/kvm/vmx.c | 6 ++++-- arch/x86/kvm/x86.c | 9 +++++---- include/linux/kvm_host.h | 6 ++++++ virt/kvm/kvm_main.c | 13 +++++++++---- 6 files changed, 26 insertions(+), 12 deletions(-)
arch/ia64/kvm/kvm-ia64.c +1 -1
@@ -1818,7 +1818,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,if (log->slot >=KVM_MEMORY_SLOTS ) goto out; - memslot = &kvm->memslots->memslots[log->slot]; + memslot =id_to_memslot (kvm->memslots, log->slot); r = -ENOENT ;if (!memslot->dirty_bitmap) goto out;
arch/powerpc/kvm/book3s.c +1 -1
@@ -498,7 +498,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,/* If nothing is dirty, don't bother messing with page tables. */ if (is_dirty) { - memslot = &kvm->memslots->memslots[log->slot]; + memslot =id_to_memslot (kvm->memslots, log->slot); ga = memslot->base_gfn <<PAGE_SHIFT ; ga_end = ga + (memslot->npages <<PAGE_SHIFT );
arch/x86/kvm/vmx.c +4 -2
@@ -2711,11 +2711,13 @@ static gva_t rmode_tss_base(struct kvm *kvm) {if (!kvm->arch.tss_addr) {struct kvm_memslots *slots; +struct kvm_memory_slot *slot;gfn_t base_gfn; slots =kvm_memslots (kvm); - base_gfn = slots->memslots[0 ].base_gfn + - kvm->memslots->memslots[0 ].npages -3 ; + slot =id_to_memslot (slots,0 ); + base_gfn = slot->base_gfn + slot->npages -3 ; +return base_gfn <<PAGE_SHIFT ; }return kvm->arch.tss_addr;
arch/x86/kvm/x86.c +5 -4
@@ -3521,7 +3521,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,if (log->slot >=KVM_MEMORY_SLOTS ) goto out; - memslot = &kvm->memslots->memslots[log->slot]; + memslot =id_to_memslot (kvm->memslots, log->slot); r = -ENOENT ;if (!memslot->dirty_bitmap) goto out;
@@ -3544,15 +3544,16 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,if (!slots) goto out;memcpy (slots, kvm->memslots,sizeof (struct kvm_memslots )); - memslot = &slots->memslots[log->slot]; - memslot->dirty_bitmap = dirty_bitmap; + memslot =id_to_memslot (slots, log->slot); memslot->nr_dirty_pages =0 ; + memslot->dirty_bitmap = dirty_bitmap;update_memslots (slots,NULL ); old_slots = kvm->memslots;rcu_assign_pointer (kvm->memslots, slots);synchronize_srcu_expedited (&kvm->srcu); - dirty_bitmap = old_slots->memslots[log->slot].dirty_bitmap; + dirty_bitmap =id_to_memslot (old_slots, + log->slot)->dirty_bitmap;kfree (old_slots);write_protect_slot (kvm, memslot, dirty_bitmap, nr_dirty_pages);
include/linux/kvm_host.h +6 -0
@@ -333,6 +333,12 @@ static inline struct kvm_memslots *kvm_memslots(struct kvm *kvm) || lockdep_is_held(&kvm->slots_lock)); } +static inline struct kvm_memory_slot * +id_to_memslot (struct kvm_memslots *slots,int id) +{ +return &slots->memslots[id]; +} +#define HPA_MSB ((sizeof(hpa_t) * 8) - 1)#define HPA_ERR_MASK ((hpa_t)1 << HPA_MSB)static inline int is_error_hpa (hpa_t hpa) {return hpa >>HPA_MSB ; }
virt/kvm/kvm_main.c +9 -4
@@ -634,8 +634,9 @@ void update_memslots(struct kvm_memslots *slots, struct kvm_memory_slot *new) {if (new) {int id = new->id; +struct kvm_memory_slot *old =id_to_memslot (slots, id); - slots->memslots[id] = *new; + *old = *new;if (id >= slots->nmemslots) slots->nmemslots = id +1 ; }
@@ -681,7 +682,7 @@ int __kvm_set_memory_region(struct kvm *kvm,if (mem->guest_phys_addr + mem->memory_size < mem->guest_phys_addr) goto out; - memslot = &kvm->memslots->memslots[mem->slot]; + memslot =id_to_memslot (kvm->memslots, mem->slot); base_gfn = mem->guest_phys_addr >>PAGE_SHIFT ; npages = mem->memory_size >>PAGE_SHIFT ;
@@ -788,12 +789,16 @@ skip_lpage:#endif /* not defined CONFIG_S390 */ if (!npages) { +struct kvm_memory_slot *slot; + r = -ENOMEM ; slots =kmemdup (kvm->memslots,sizeof (struct kvm_memslots ),GFP_KERNEL );if (!slots) goto out_free; - slots->memslots[mem->slot].flags |=KVM_MEMSLOT_INVALID ; + slot =id_to_memslot (slots, mem->slot); + slot->flags |=KVM_MEMSLOT_INVALID ; +update_memslots (slots,NULL ); old_memslots = kvm->memslots;
@@ -897,7 +902,7 @@ int kvm_get_dirty_log(struct kvm *kvm,if (log->slot >=KVM_MEMORY_SLOTS ) goto out; - memslot = &kvm->memslots->memslots[log->slot]; + memslot =id_to_memslot (kvm->memslots, log->slot); r = -ENOENT ;if (!memslot->dirty_bitmap) goto out;
Signature · 1 line
1.7.7.3
PATCH v3 5/6 KVM: sort memslots by its size and use line search
In reply to Xiao GuangrongFrom: Xiao Guangrong <[email protected]>
Sort memslots base on its size and use line search to find it, so that the larger memslots have better fit
The idea is from Avi
--- include/linux/kvm_host.h | 18 +++++++++-- virt/kvm/kvm_main.c | 79 +++++++++++++++++++++++++++++++++------------- 2 files changed, 72 insertions(+), 25 deletions(-)
include/linux/kvm_host.h +15 -3
@@ -231,8 +231,12 @@ struct kvm_irq_routing_table {};#define KVM_MEM_SLOTS_NUM (KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS)#endif +/* +* Note: +* memslots are not sorted by id anymore, please use id_to_memslot() +* to get the memslot by its id. +*/ struct kvm_memslots { -int nmemslots;u64 generation;struct kvm_memory_slot memslots[KVM_MEM_SLOTS_NUM ]; };
@@ -310,7 +314,8 @@ static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i)#define kvm_for_each_memslot (memslot, slots) \ for (memslot = &slots->memslots[0]; \ - memslot < slots->memslots + (slots)->nmemslots; memslot++) + memslot < slots->memslots + KVM_MEM_SLOTS_NUM && memslot->npages;\ + memslot++)int kvm_vcpu_init (struct kvm_vcpu *vcpu,struct kvm *kvm,unsigned id);void kvm_vcpu_uninit (struct kvm_vcpu *vcpu);
@@ -336,7 +341,14 @@ static inline struct kvm_memslots *kvm_memslots(struct kvm *kvm)static inline struct kvm_memory_slot *id_to_memslot (struct kvm_memslots *slots,int id) { -return &slots->memslots[id]; +int i; + +for (i =0 ; i <KVM_MEM_SLOTS_NUM ; i++) +if (slots->memslots[i].id == id) +return &slots->memslots[i]; + +WARN_ON (1 ); +return NULL ; }#define HPA_MSB ((sizeof(hpa_t) * 8) - 1)
virt/kvm/kvm_main.c +57 -22
118 lines not on this page · raw message
Signature · 1 line
1.7.7.3
PATCH v3 6/6 KVM: introduce a table to map slot id to index in memslots array
In reply to Xiao GuangrongFrom: Xiao Guangrong <[email protected]>
The operation of getting dirty log is frequent when framebuffer-based displays are used(for example, Xwindow), so, we introduce a mapping table to speed up id_to_memslot()
--- include/linux/kvm_host.h | 13 +++++++------ virt/kvm/kvm_main.c | 7 ++++++- 2 files changed, 13 insertions(+), 7 deletions(-)
include/linux/kvm_host.h +7 -6
@@ -239,6 +239,8 @@ struct kvm_irq_routing_table {};struct kvm_memslots {u64 generation;struct kvm_memory_slot memslots[KVM_MEM_SLOTS_NUM ]; +/* The mapping table from slot id to the index in memslots[]. */ +int id_to_index[KVM_MEM_SLOTS_NUM ]; };struct kvm {
@@ -341,14 +343,13 @@ static inline struct kvm_memslots *kvm_memslots(struct kvm *kvm)static inline struct kvm_memory_slot *id_to_memslot (struct kvm_memslots *slots,int id) { -int i; +int index = slots->id_to_index[id]; +struct kvm_memory_slot *slot; -for (i =0 ; i <KVM_MEM_SLOTS_NUM ; i++) -if (slots->memslots[i].id == id) -return &slots->memslots[i]; + slot = &slots->memslots[index]; -WARN_ON (1 ); -return NULL ; +WARN_ON (slot->id != id); +return slot; }#define HPA_MSB ((sizeof(hpa_t) * 8) - 1)
virt/kvm/kvm_main.c +6 -1
@@ -446,7 +446,7 @@ static void kvm_init_memslots_id(struct kvm *kvm)struct kvm_memslots *slots = kvm->memslots;for (i =0 ; i <KVM_MEM_SLOTS_NUM ; i++) - slots->memslots[i].id = i; + slots->id_to_index[i] = slots->memslots[i].id = i; }static struct kvm *kvm_create_vm (void )
@@ -674,8 +674,13 @@ static int cmp_memslot(const void *slot1, const void *slot2)*/ static void sort_memslots (struct kvm_memslots *slots) { +int i; +sort (slots->memslots,KVM_MEM_SLOTS_NUM ,sizeof (struct kvm_memory_slot ), cmp_memslot,NULL ); + +for (i =0 ; i <KVM_MEM_SLOTS_NUM ; i++) + slots->id_to_index[slots->memslots[i].id] = i; }void update_memslots (struct kvm_memslots *slots,struct kvm_memory_slot *new)
Signature · 1 line
1.7.7.3
Re: [PATCH v3 4/6] KVM: introduce id_to_memslot function
In reply to Xiao Guangrong(2011/11/24 18:40), Xiao Guangrong wrote:
...
Quoted 18 lines
arch/x86/kvm/x86.c +2
-3@@ -3521,7 +3521,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,if (log->slot>=KVM_MEMORY_SLOTS ) goto out; - memslot =&kvm->memslots->memslots[log->slot]; + memslot =id_to_memslot (kvm->memslots, log->slot); r = -ENOENT ;if (!memslot->dirty_bitmap) goto out;@@ -3544,15 +3544,16 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,if (!slots) goto out;memcpy (slots, kvm->memslots,sizeof (struct kvm_memslots )); - memslot =&slots->memslots[log->slot]; - memslot->dirty_bitmap = dirty_bitmap; + memslot =id_to_memslot (slots, log->slot);
arch/x86/kvm/x86.c int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, · line 3556
Quoted 10 lines
arch/x86/kvm/x86.c +3
-1memslot->nr_dirty_pages =0 ; + memslot->dirty_bitmap = dirty_bitmap;update_memslots (slots,NULL ); old_slots = kvm->memslots;rcu_assign_pointer (kvm->memslots, slots);synchronize_srcu_expedited (&kvm->srcu); - dirty_bitmap = old_slots->memslots[log->slot].dirty_bitmap; + dirty_bitmap =id_to_memslot (old_slots, + log->slot)->dirty_bitmap;
You can eliminate this if you use old_slot and new_slot for the two memory slots.
Takuya
Quoted 3 lines
arch/x86/kvm/x86.c +0
-0kfree (old_slots);write_protect_slot (kvm, memslot, dirty_bitmap, nr_dirty_pages);
Re: [PATCH v3 4/6] KVM: introduce id_to_memslot function
Quoted 3 lines · Takuya Yoshikawa
(2011/11/24 18:40), Xiao Guangrong wrote:
You can eliminate this if you use
old_slotandnew_slotfor the two memory slots.
Or old_bitmap and new_bitmap. Anyway, calling id_to_memslot() for getting the same slot twice is not good, IMO.
Takuya
Re: [PATCH v3 4/6] KVM: introduce id_to_memslot function
Quoted 8 lines · Takuya Yoshikawa
Quoted 3 lines · Takuya Yoshikawa
(2011/11/24 18:40), Xiao Guangrong wrote:
You can eliminate this if you use
old_slotandnew_slotfor the two memory slots.Or
old_bitmapandnew_bitmap. Anyway, callingid_to_memslot()for getting the same slot twice is not good, IMO.
Sure. Thanks for your review, Takuya!
From: Xiao Guangrong <[email protected]>
Subject: KVM: introduce id_to_memslot function
Introduce id_to_memslot to get memslot by slot id
--- arch/ia64/kvm/kvm-ia64.c | 2 +- arch/powerpc/kvm/book3s.c | 2 +- arch/x86/kvm/vmx.c | 6 ++++-- arch/x86/kvm/x86.c | 18 +++++++++--------- include/linux/kvm_host.h | 6 ++++++ virt/kvm/kvm_main.c | 13 +++++++++---- 6 files changed, 30 insertions(+), 17 deletions(-)
arch/ia64/kvm/kvm-ia64.c +1 -1
@@ -1818,7 +1818,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,if (log->slot >=KVM_MEMORY_SLOTS ) goto out; - memslot = &kvm->memslots->memslots[log->slot]; + memslot =id_to_memslot (kvm->memslots, log->slot); r = -ENOENT ;if (!memslot->dirty_bitmap) goto out;
arch/powerpc/kvm/book3s.c +1 -1
@@ -498,7 +498,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,/* If nothing is dirty, don't bother messing with page tables. */ if (is_dirty) { - memslot = &kvm->memslots->memslots[log->slot]; + memslot =id_to_memslot (kvm->memslots, log->slot); ga = memslot->base_gfn <<PAGE_SHIFT ; ga_end = ga + (memslot->npages <<PAGE_SHIFT );
arch/x86/kvm/vmx.c +4 -2
@@ -2711,11 +2711,13 @@ static gva_t rmode_tss_base(struct kvm *kvm) {if (!kvm->arch.tss_addr) {struct kvm_memslots *slots; +struct kvm_memory_slot *slot;gfn_t base_gfn; slots =kvm_memslots (kvm); - base_gfn = slots->memslots[0 ].base_gfn + - kvm->memslots->memslots[0 ].npages -3 ; + slot =id_to_memslot (slots,0 ); + base_gfn = slot->base_gfn + slot->npages -3 ; +return base_gfn <<PAGE_SHIFT ; }return kvm->arch.tss_addr;
arch/x86/kvm/x86.c +9 -9
@@ -3521,7 +3521,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,if (log->slot >=KVM_MEMORY_SLOTS ) goto out; - memslot = &kvm->memslots->memslots[log->slot]; + memslot =id_to_memslot (kvm->memslots, log->slot); r = -ENOENT ;if (!memslot->dirty_bitmap) goto out;
@@ -3532,27 +3532,27 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,/* If nothing is dirty, don't bother messing with page tables. */ if (nr_dirty_pages) {struct kvm_memslots *slots, *old_slots; -unsigned long *dirty_bitmap; +unsigned long *dirty_bitmap, *dirty_bitmap_head; - dirty_bitmap = memslot->dirty_bitmap_head; -if (memslot->dirty_bitmap == dirty_bitmap) - dirty_bitmap += n /sizeof (long ); -memset (dirty_bitmap,0 , n); + dirty_bitmap = memslot->dirty_bitmap; + dirty_bitmap_head = memslot->dirty_bitmap_head; +if (dirty_bitmap == dirty_bitmap_head) + dirty_bitmap_head += n /sizeof (long ); +memset (dirty_bitmap_head,0 , n); r = -ENOMEM ; slots =kzalloc (sizeof (struct kvm_memslots ),GFP_KERNEL );if (!slots) goto out;memcpy (slots, kvm->memslots,sizeof (struct kvm_memslots )); - memslot = &slots->memslots[log->slot]; - memslot->dirty_bitmap = dirty_bitmap; + memslot =id_to_memslot (slots, log->slot); memslot->nr_dirty_pages =0 ; + memslot->dirty_bitmap = dirty_bitmap_head;update_memslots (slots,NULL ); old_slots = kvm->memslots;rcu_assign_pointer (kvm->memslots, slots);synchronize_srcu_expedited (&kvm->srcu); - dirty_bitmap = old_slots->memslots[log->slot].dirty_bitmap;kfree (old_slots);write_protect_slot (kvm, memslot, dirty_bitmap, nr_dirty_pages);
include/linux/kvm_host.h +6 -0
@@ -333,6 +333,12 @@ static inline struct kvm_memslots *kvm_memslots(struct kvm *kvm) || lockdep_is_held(&kvm->slots_lock)); } +static inline struct kvm_memory_slot * +id_to_memslot (struct kvm_memslots *slots,int id) +{ +return &slots->memslots[id]; +} +#define HPA_MSB ((sizeof(hpa_t) * 8) - 1)#define HPA_ERR_MASK ((hpa_t)1 << HPA_MSB)static inline int is_error_hpa (hpa_t hpa) {return hpa >>HPA_MSB ; }
virt/kvm/kvm_main.c +9 -4
@@ -634,8 +634,9 @@ void update_memslots(struct kvm_memslots *slots, struct kvm_memory_slot *new) {if (new) {int id = new->id; +struct kvm_memory_slot *old =id_to_memslot (slots, id); - slots->memslots[id] = *new; + *old = *new;if (id >= slots->nmemslots) slots->nmemslots = id +1 ; }
@@ -681,7 +682,7 @@ int __kvm_set_memory_region(struct kvm *kvm,if (mem->guest_phys_addr + mem->memory_size < mem->guest_phys_addr) goto out; - memslot = &kvm->memslots->memslots[mem->slot]; + memslot =id_to_memslot (kvm->memslots, mem->slot); base_gfn = mem->guest_phys_addr >>PAGE_SHIFT ; npages = mem->memory_size >>PAGE_SHIFT ;
@@ -788,12 +789,16 @@ skip_lpage:#endif /* not defined CONFIG_S390 */ if (!npages) { +struct kvm_memory_slot *slot; + r = -ENOMEM ; slots =kmemdup (kvm->memslots,sizeof (struct kvm_memslots ),GFP_KERNEL );if (!slots) goto out_free; - slots->memslots[mem->slot].flags |=KVM_MEMSLOT_INVALID ; + slot =id_to_memslot (slots, mem->slot); + slot->flags |=KVM_MEMSLOT_INVALID ; +update_memslots (slots,NULL ); old_memslots = kvm->memslots;
@@ -897,7 +902,7 @@ int kvm_get_dirty_log(struct kvm *kvm,if (log->slot >=KVM_MEMORY_SLOTS ) goto out; - memslot = &kvm->memslots->memslots[log->slot]; + memslot =id_to_memslot (kvm->memslots, log->slot); r = -ENOENT ;if (!memslot->dirty_bitmap) goto out;
Signature · 1 line
1.7.7.3
Avi Kivity
AppliedQuoted 5 lines · Xiao Guangrong
Changelog:
- rebase it on current kvm tree and some cleanupsThis patchset is tested on x86 and build tested on powerpc and ia64
Thanks, applied all.
Signature · 1 line
error compiling committee.c: too many arguments to function