public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Izik Eidus <izike-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
To: Anthony Liguori <aliguori-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org,
	Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
Subject: Re: [RFC] Expose infrastructure for unpinning guest memory
Date: Thu, 11 Oct 2007 23:59:18 +0200	[thread overview]
Message-ID: <470E9CB6.4030107@qumranet.com> (raw)
In-Reply-To: <1192138344500-git-send-email-aliguori-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

Anthony Liguori wrote:
> Now that we have userspace memory allocation, I wanted to play with ballooning.
> The idea is that when a guest "balloons" down, we simply unpin the underlying
> physical memory and the host kernel may or may not swap it.  To reclaim
> ballooned memory, the guest can just start using it and we'll pin it on demand.
>
> The following patch is a stab at providing the right infrastructure for pinning
> and automatic repinning.  I don't have a lot of comfort in the MMU code so I
> thought I'd get some feedback before going much further.
>
> gpa_to_hpa is a little awkward to hook, but it seems like the right place in the
> code.  I'm most uncertain about the SMP safety of the unpinning.  Presumably,
> I have to hold the kvm lock around the mmu_unshadow and page_cache release to
> ensure that another VCPU doesn't fault the page back in after mmu_unshadow?
>
> Feedback would be greatly appreciated!
>
> diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
> index 4a52d6e..8abe770 100644
> --- a/drivers/kvm/kvm.h
> +++ b/drivers/kvm/kvm.h
> @@ -409,6 +409,7 @@ struct kvm_memory_slot {
>  	unsigned long *rmap;
>  	unsigned long *dirty_bitmap;
>  	int user_alloc; /* user allocated memory */
> +	unsigned long userspace_addr;
>  };
>  
>  struct kvm {
> @@ -652,6 +653,7 @@ int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva);
>  void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu);
>  int kvm_mmu_load(struct kvm_vcpu *vcpu);
>  void kvm_mmu_unload(struct kvm_vcpu *vcpu);
> +int kvm_mmu_unpin(struct kvm *kvm, gfn_t gfn);
>  
>  int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
>  
> diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
> index a0f8366..74105d1 100644
> --- a/drivers/kvm/kvm_main.c
> +++ b/drivers/kvm/kvm_main.c
> @@ -774,6 +774,7 @@ static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
>  			unsigned long pages_num;
>  
>  			new.user_alloc = 1;
> +			new.userspace_addr = mem->userspace_addr;
>  			down_read(&current->mm->mmap_sem);
>  
>  			pages_num = get_user_pages(current, current->mm,
> @@ -1049,12 +1050,36 @@ struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn)
>  struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
>  {
>  	struct kvm_memory_slot *slot;
> +	struct page *page;
> +	uint64_t slot_index;
>  
>  	gfn = unalias_gfn(kvm, gfn);
>  	slot = __gfn_to_memslot(kvm, gfn);
>  	if (!slot)
>  		return NULL;
> -	return slot->phys_mem[gfn - slot->base_gfn];
> +
> +	slot_index = gfn - slot->base_gfn;
> +	page = slot->phys_mem[slot_index];
> +	if (unlikely(page == NULL)) {
> +		unsigned long pages_num;
> +
> +		down_read(&current->mm->mmap_sem);
> +
> +		pages_num = get_user_pages(current, current->mm,
> +					   slot->userspace_addr +
> +					   (slot_index << PAGE_SHIFT),
> +					   1, 1, 0, &slot->phys_mem[slot_index],
> +					   NULL);
> +
> +		up_read(&current->mm->mmap_sem);
> +
> +		if (pages_num != 1)
> +			page = NULL;
> +		else
> +			page = slot->phys_mem[slot_index];
> +	}
> +
> +	return page;
>  }
>  EXPORT_SYMBOL_GPL(gfn_to_page);
>  
> diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
> index f52604a..1820816 100644
> --- a/drivers/kvm/mmu.c
> +++ b/drivers/kvm/mmu.c
> @@ -25,6 +25,7 @@
>  #include <linux/mm.h>
>  #include <linux/highmem.h>
>  #include <linux/module.h>
> +#include <linux/pagemap.h>
>  
>  #include <asm/page.h>
>  #include <asm/cmpxchg.h>
> @@ -820,6 +821,33 @@ static void mmu_unshadow(struct kvm *kvm, gfn_t gfn)
>  	}
>  }
>  
> +int kvm_mmu_unpin(struct kvm *kvm, gfn_t gfn)
> +{
> +	struct kvm_memory_slot *slot;
> +	struct page *page;
> +
> +	/* FIXME for each active vcpu */
> +
> +	gfn = unalias_gfn(kvm, gfn);
> +	slot = gfn_to_memslot(kvm, gfn);
> +	if (!gfn)
> +		return -EINVAL;
> +
> +	/* FIXME: do we need to hold a lock here? */
> +
> +	/* Remove page from shadow MMU and unpin page */
> +	mmu_unshadow(kvm, gfn);
> +	page = slot->phys_mem[gfn - slot->base_gfn];
> +	if (page) {
> +		if (!PageReserved(page))
> +			SetPageDirty(page);
> +		page_cache_release(page);
> +		slot->phys_mem[gfn - slot->base_gfn] = NULL;
> +	}
> +
> +	return 0;
> +}
> +
>  static void page_header_update_slot(struct kvm *kvm, void *pte, gpa_t gpa)
>  {
>  	int slot = memslot_id(kvm, gfn_to_memslot(kvm, gpa >> PAGE_SHIFT));
>
> -------------------------------------------------------------------------
>   
kvm_memory_slot

heh, i am working on similir patch, and our gfn_to_page and the change 
to  kvm_memory_slot even by varible names :)
few things you have to do to make this work:
make gfn_to_page safe always function (return bad_page in case of 
failure, i have patch for this if you want)
hacking the kvm_read_guest_page / kvm_write_guest_page 
kvm_clear_guest_page to do put_page after the usage of the page
secoend, is hacking the rmap to do reverse mapping to every present pte 
and put_page() the pages at rmap_remove()
and this about all, to make this work.




-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/

  parent reply	other threads:[~2007-10-11 21:59 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-10-11 21:32 [RFC] Expose infrastructure for unpinning guest memory Anthony Liguori
     [not found] ` <1192138344500-git-send-email-aliguori-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2007-10-11 21:59   ` Izik Eidus [this message]
     [not found]     ` <470E9CB6.4030107-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-10-11 22:18       ` Anthony Liguori
     [not found]         ` <470EA136.8020100-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2007-10-11 22:31           ` Izik Eidus
2007-10-12  0:11           ` Dor Laor
2007-10-12  6:32   ` Avi Kivity
     [not found]     ` <470F14F2.7050800-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-10-12 18:52       ` Anthony Liguori
     [not found]         ` <470FC25A.70607-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2007-10-13  7:21           ` Avi Kivity
2007-10-15  8:10           ` Carsten Otte

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=470E9CB6.4030107@qumranet.com \
    --to=izike-atkuwr5tajbwk0htik3j/w@public.gmane.org \
    --cc=aliguori-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org \
    --cc=avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org \
    --cc=kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox