Skip to content

Commit

Permalink
KVM: Split lpage_info creation out from __kvm_set_memory_region()
Browse files Browse the repository at this point in the history
This makes it easy to make lpage_info architecture specific.

Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
  • Loading branch information
Takuya Yoshikawa authored and avikivity committed Mar 8, 2012
1 parent fb03cb6 commit a64f273
Showing 1 changed file with 52 additions and 31 deletions.
83 changes: 52 additions & 31 deletions virt/kvm/kvm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,56 @@ void update_memslots(struct kvm_memslots *slots, struct kvm_memory_slot *new)
slots->generation++;
}

#ifndef CONFIG_S390
static int create_lpage_info(struct kvm_memory_slot *slot, unsigned long npages)
{
int i;

for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) {
unsigned long ugfn;
int lpages;
int level = i + 2;

if (slot->lpage_info[i])
continue;

lpages = gfn_to_index(slot->base_gfn + npages - 1,
slot->base_gfn, level) + 1;

slot->lpage_info[i] = vzalloc(lpages * sizeof(*slot->lpage_info[i]));
if (!slot->lpage_info[i])
goto out_free;

if (slot->base_gfn & (KVM_PAGES_PER_HPAGE(level) - 1))
slot->lpage_info[i][0].write_count = 1;
if ((slot->base_gfn + npages) & (KVM_PAGES_PER_HPAGE(level) - 1))
slot->lpage_info[i][lpages - 1].write_count = 1;
ugfn = slot->userspace_addr >> PAGE_SHIFT;
/*
* If the gfn and userspace address are not aligned wrt each
* other, or if explicitly asked to, disable large page
* support for this slot
*/
if ((slot->base_gfn ^ ugfn) & (KVM_PAGES_PER_HPAGE(level) - 1) ||
!largepages_enabled) {
unsigned long j;

for (j = 0; j < lpages; ++j)
slot->lpage_info[i][j].write_count = 1;
}
}

return 0;

out_free:
for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) {
vfree(slot->lpage_info[i]);
slot->lpage_info[i] = NULL;
}
return -ENOMEM;
}
#endif /* not defined CONFIG_S390 */

/*
* Allocate some memory and give it an address in the guest physical address
* space.
Expand Down Expand Up @@ -778,37 +828,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
if (!npages)
goto skip_lpage;

for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) {
unsigned long ugfn;
unsigned long j;
int lpages;
int level = i + 2;

if (new.lpage_info[i])
continue;

lpages = gfn_to_index(base_gfn + npages - 1, base_gfn, level) + 1;

new.lpage_info[i] = vzalloc(lpages * sizeof(*new.lpage_info[i]));

if (!new.lpage_info[i])
goto out_free;

if (base_gfn & (KVM_PAGES_PER_HPAGE(level) - 1))
new.lpage_info[i][0].write_count = 1;
if ((base_gfn+npages) & (KVM_PAGES_PER_HPAGE(level) - 1))
new.lpage_info[i][lpages - 1].write_count = 1;
ugfn = new.userspace_addr >> PAGE_SHIFT;
/*
* If the gfn and userspace address are not aligned wrt each
* other, or if explicitly asked to, disable large page
* support for this slot
*/
if ((base_gfn ^ ugfn) & (KVM_PAGES_PER_HPAGE(level) - 1) ||
!largepages_enabled)
for (j = 0; j < lpages; ++j)
new.lpage_info[i][j].write_count = 1;
}
if (create_lpage_info(&new, npages))
goto out_free;

skip_lpage:

Expand Down

0 comments on commit a64f273

Please sign in to comment.