aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lguest/page_tables.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/lguest/page_tables.c')
-rw-r--r--drivers/lguest/page_tables.c25
1 files changed, 9 insertions, 16 deletions
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c
index d93500f24fbb..81d0c6053447 100644
--- a/drivers/lguest/page_tables.c
+++ b/drivers/lguest/page_tables.c
@@ -108,9 +108,8 @@ static unsigned long gpte_addr(pgd_t gpgd, unsigned long vaddr)
108} 108}
109/*:*/ 109/*:*/
110 110
111/*M:014 get_pfn is slow; it takes the mmap sem and calls get_user_pages. We 111/*M:014 get_pfn is slow: we could probably try to grab batches of pages here as
112 * could probably try to grab batches of pages here as an optimization 112 * an optimization (ie. pre-faulting). :*/
113 * (ie. pre-faulting). :*/
114 113
115/*H:350 This routine takes a page number given by the Guest and converts it to 114/*H:350 This routine takes a page number given by the Guest and converts it to
116 * an actual, physical page number. It can fail for several reasons: the 115 * an actual, physical page number. It can fail for several reasons: the
@@ -123,19 +122,13 @@ static unsigned long gpte_addr(pgd_t gpgd, unsigned long vaddr)
123static unsigned long get_pfn(unsigned long virtpfn, int write) 122static unsigned long get_pfn(unsigned long virtpfn, int write)
124{ 123{
125 struct page *page; 124 struct page *page;
126 /* This value indicates failure. */
127 unsigned long ret = -1UL;
128 125
129 /* get_user_pages() is a complex interface: it gets the "struct 126 /* gup me one page at this address please! */
130 * vm_area_struct" and "struct page" assocated with a range of pages. 127 if (get_user_pages_fast(virtpfn << PAGE_SHIFT, 1, write, &page) == 1)
131 * It also needs the task's mmap_sem held, and is not very quick. 128 return page_to_pfn(page);
132 * It returns the number of pages it got. */ 129
133 down_read(&current->mm->mmap_sem); 130 /* This value indicates failure. */
134 if (get_user_pages(current, current->mm, virtpfn << PAGE_SHIFT, 131 return -1UL;
135 1, write, 1, &page, NULL) == 1)
136 ret = page_to_pfn(page);
137 up_read(&current->mm->mmap_sem);
138 return ret;
139} 132}
140 133
141/*H:340 Converting a Guest page table entry to a shadow (ie. real) page table 134/*H:340 Converting a Guest page table entry to a shadow (ie. real) page table
@@ -174,7 +167,7 @@ static pte_t gpte_to_spte(struct lg_cpu *cpu, pte_t gpte, int write)
174/*H:460 And to complete the chain, release_pte() looks like this: */ 167/*H:460 And to complete the chain, release_pte() looks like this: */
175static void release_pte(pte_t pte) 168static void release_pte(pte_t pte)
176{ 169{
177 /* Remember that get_user_pages() took a reference to the page, in 170 /* Remember that get_user_pages_fast() took a reference to the page, in
178 * get_pfn()? We have to put it back now. */ 171 * get_pfn()? We have to put it back now. */
179 if (pte_flags(pte) & _PAGE_PRESENT) 172 if (pte_flags(pte) & _PAGE_PRESENT)
180 put_page(pfn_to_page(pte_pfn(pte))); 173 put_page(pfn_to_page(pte_pfn(pte)));