This lets us modify the flags for the PTE corresponding to a virtual address. The SMAP testcase will use this to build supervisor-mode pages. Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx> --- lib/x86/vm.c | 41 +++++++++++++++++++++-------------------- lib/x86/vm.h | 17 +++++++++-------- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/lib/x86/vm.c b/lib/x86/vm.c index 93aea71..3e7ca97 100644 --- a/lib/x86/vm.c +++ b/lib/x86/vm.c @@ -54,11 +54,11 @@ static unsigned long end_of_memory; #define PGDIR_MASK 1023 #endif -void install_pte(unsigned long *cr3, - int pte_level, - void *virt, - unsigned long pte, - unsigned long *pt_page) +unsigned long *install_pte(unsigned long *cr3, + int pte_level, + void *virt, + unsigned long pte, + unsigned long *pt_page) { int level; unsigned long *pt = cr3; @@ -79,9 +79,10 @@ void install_pte(unsigned long *cr3, } offset = ((unsigned long)virt >> ((level-1) * PGDIR_WIDTH + 12)) & PGDIR_MASK; pt[offset] = pte; + return &pt[offset]; } -static unsigned long get_pte(unsigned long *cr3, void *virt) +unsigned long *get_pte(unsigned long *cr3, void *virt) { int level; unsigned long *pt = cr3, pte; @@ -91,28 +92,28 @@ static unsigned long get_pte(unsigned long *cr3, void *virt) offset = ((unsigned long)virt >> (((level-1) * PGDIR_WIDTH) + 12)) & PGDIR_MASK; pte = pt[offset]; if (!(pte & PTE_PRESENT)) - return 0; + return NULL; if (level == 2 && (pte & PTE_PSE)) - return pte; + return &pt[offset]; pt = phys_to_virt(pte & 0xffffffffff000ull); } offset = ((unsigned long)virt >> (((level-1) * PGDIR_WIDTH) + 12)) & PGDIR_MASK; - pte = pt[offset]; - return pte; + return &pt[offset]; } -void install_large_page(unsigned long *cr3, - unsigned long phys, - void *virt) +unsigned long *install_large_page(unsigned long *cr3, + unsigned long phys, + void *virt) { - install_pte(cr3, 2, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER | PTE_PSE, 0); + return install_pte(cr3, 2, virt, + phys | PTE_PRESENT | PTE_WRITE | PTE_USER | PTE_PSE, 0); } -void install_page(unsigned long *cr3, - unsigned long phys, - void *virt) +unsigned long *install_page(unsigned long *cr3, + unsigned long phys, + void *virt) { - install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER, 0); + return install_pte(cr3, 1, virt, phys | PTE_PRESENT | PTE_WRITE | PTE_USER, 0); } @@ -194,7 +195,7 @@ void *vmalloc(unsigned long size) uint64_t virt_to_phys_cr3(void *mem) { - return (get_pte(phys_to_virt(read_cr3()), mem) & PTE_ADDR) + ((ulong)mem & (PAGE_SIZE - 1)); + return (*get_pte(phys_to_virt(read_cr3()), mem) & PTE_ADDR) + ((ulong)mem & (PAGE_SIZE - 1)); } void vfree(void *mem) @@ -202,7 +203,7 @@ void vfree(void *mem) unsigned long size = ((unsigned long *)mem)[-1]; while (size) { - free_page(phys_to_virt(get_pte(phys_to_virt(read_cr3()), mem) & PTE_ADDR)); + free_page(phys_to_virt(*get_pte(phys_to_virt(read_cr3()), mem) & PTE_ADDR)); mem += PAGE_SIZE; size -= PAGE_SIZE; } diff --git a/lib/x86/vm.h b/lib/x86/vm.h index 0b5b5c7..bd73840 100644 --- a/lib/x86/vm.h +++ b/lib/x86/vm.h @@ -25,17 +25,18 @@ void *alloc_vpage(void); void *alloc_vpages(ulong nr); uint64_t virt_to_phys_cr3(void *mem); -void install_pte(unsigned long *cr3, - int pte_level, - void *virt, - unsigned long pte, - unsigned long *pt_page); +unsigned long *get_pte(unsigned long *cr3, void *virt); +unsigned long *install_pte(unsigned long *cr3, + int pte_level, + void *virt, + unsigned long pte, + unsigned long *pt_page); void *alloc_page(); -void install_large_page(unsigned long *cr3,unsigned long phys, - void *virt); -void install_page(unsigned long *cr3, unsigned long phys, void *virt); +unsigned long *install_large_page(unsigned long *cr3,unsigned long phys, + void *virt); +unsigned long *install_page(unsigned long *cr3, unsigned long phys, void *virt); static inline unsigned long virt_to_phys(const void *virt) { -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html