kvm, faster and simpler version of get_user_page_and_protection()
PATCH 6/6 kvm, faster and simpler version of get_user_page_and_protection()
a light weight version of get_user_page_and_protection()
---
arch/x86/include/asm/pgtable.h +2 -0
@@ -618,6 +618,8 @@ static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count) memcpy(dst, src, count * sizeof(pgd_t)); } +extern +struct page *get_user_page_and_protection (unsigned long addr,int *writable);#include <asm-generic/pgtable.h> #endif /* __ASSEMBLY__ */
arch/x86/kvm/mmu.c +0 -17
@@ -1832,23 +1832,6 @@ static void kvm_unsync_pages(struct kvm_vcpu *vcpu, gfn_t gfn) } } -/* get a current mapped page fast, and test whether the page is writable. */ -static struct page *get_user_page_and_protection (unsigned long addr, -int *writable) -{ -struct page *page[1 ]; - -if (__get_user_pages_fast (addr,1 ,1 , page) ==1 ) { - *writable =1 ; -return page[0 ]; - } -if (__get_user_pages_fast (addr,1 ,0 , page) ==1 ) { - *writable =0 ; -return page[0 ]; - } -return NULL ; -} -static pfn_t kvm_get_pfn_for_page_fault (struct kvm *kvm,gfn_t gfn,int write_fault,int *host_writable) {
arch/x86/mm/gup.c +80 -1
90 lines not on this page · raw message
Quoted 89 lines · Lai Jiangshan
a light weight version of
get_user_page_and_protection()Signed-off-by Lai Jiangshan <[email protected]>---
arch/x86/include/asm/pgtable.h +2
-0@@ -618,6 +618,8 @@ static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count) memcpy(dst, src, count * sizeof(pgd_t)); } +extern +struct page *get_user_page_and_protection (unsigned long addr,int *writable);#include <asm-generic/pgtable.h> #endif /* __ASSEMBLY__ */ arch/x86/kvm/mmu.c +0
-17@@ -1832,23 +1832,6 @@ static void kvm_unsync_pages(struct kvm_vcpu *vcpu, gfn_t gfn) } } -/* get a current mapped page fast, and test whether the page is writable. */ -static struct page *get_user_page_and_protection (unsigned long addr, -int *writable) -{ -struct page *page[1 ]; - -if (__get_user_pages_fast (addr,1 ,1 , page) ==1 ) { - *writable =1 ; -return page[0 ]; - } -if (__get_user_pages_fast (addr,1 ,0 , page) ==1 ) { - *writable =0 ; -return page[0 ]; - } -return NULL ; -} -static pfn_t kvm_get_pfn_for_page_fault (struct kvm *kvm,gfn_t gfn,int write_fault,int *host_writable) {arch/x86/mm/gup.c +27
-1@@ -275,7 +275,6 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,return nr; } -EXPORT_SYMBOL_GPL (__get_user_pages_fast);/** * get_user_pages_fast() - pin user pages in memory @@ -375,3 +374,83 @@ slow_irqon:return ret; } } + +/* +* get a current mapped page fast, and test whether the page is writable. +* equivalent version(but slower): +* { +* struct page *page[1]; +* +* if (__get_user_pages_fast(addr, 1, 1, page) == 1) { +* *writable = 1; +* return page[0]; +* } +* if (__get_user_pages_fast(addr, 1, 0, page) == 1) { +* *writable = 0; +* return page[0]; +* } +* return NULL; +* } +*/ +struct page *get_user_page_and_protection (unsigned long addr,int *writable) +{ +unsigned long flags; +struct mm_struct *mm = current->mm; +pgd_t *pgdp; +pud_t *pudp; +pmd_t *pmdp; +pte_t pte, *ptep; +
arch/x86/mm/gup.c slow_irqon: · line 413
Quoted 10 lines
arch/x86/mm/gup.c +10
-0+unsigned long mask = _PAGE_PRESENT | _PAGE_USER; +unsigned long offset =0 ; +struct page *head, *page =NULL ; + + addr &=PAGE_MASK ; + +local_irq_save (flags); + pgdp =pgd_offset (mm, addr); +if (!pgd_present (*pgdp)) + goto out;
Better introduce __get_user_pages_ptes_fast, and share code with __get_user_pages_fast (except _ptes_fast copies the pte values to pte_t array).
Quoted 19 lines · Lai Jiangshan
a light weight version of
get_user_page_and_protection()arch/x86/mm/gup.c +10
-0@@ -375,3 +374,83 @@ slow_irqon:return ret; } } + +/* +* get a current mapped page fast, and test whether the page is writable. +* equivalent version(but slower): +* { +* struct page *page[1]; +* +* if (__get_user_pages_fast(addr, 1, 1, page) == 1) { +* *writable = 1; +* return page[0];
arch/x86/mm/gup.c slow_irqon: · line 396
Quoted 10 lines
arch/x86/mm/gup.c +10
-0+* } +* if (__get_user_pages_fast(addr, 1, 0, page) == 1) { +* *writable = 0; +* return page[0]; +* } +* return NULL; +* } +*/ +struct page *get_user_page_and_protection (unsigned long addr,int *writable) +{
<snip lots of code>
arch/x86/mm/gup.c slow_irqon: · line 456
Quoted 4 lines
arch/x86/mm/gup.c +3
-0+} +EXPORT_SYMBOL_GPL (get_user_page_and_protection); +
This a duplication of __get_user_pages_fast(), no?
I think a better way is to have a __get_user_pages_ptes(..., struct page *pages, pte_t *ptes, ...), and write __get_user_pages_fast() in terms of that. There's lots of useful info from the pte we can use:
- writeable bit (used here)
- page size (we can stick it in some user bits, speeds up host_mapping_level())
- dirty bit (if set, we can set it for speculative sptes and save the CPU a RMW)
- page attribute (for device assignment, when snooping is not available)
Nick, is __get_user_pages_ptes() fine with you?
Signature · 1 line
error compiling committee.c: too many arguments to function