diff options
Diffstat (limited to 'drivers/lguest/page_tables.c')
-rw-r--r-- | drivers/lguest/page_tables.c | 25 |
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) | |||
123 | static unsigned long get_pfn(unsigned long virtpfn, int write) | 122 | static 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(¤t->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(¤t->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: */ |
175 | static void release_pte(pte_t pte) | 168 | static 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))); |