The final step moves the vmalloc and vmap implementation to generic code, rewriting vmalloc and vfree as an alloc_ops implementation that is installed by setup_vm. This way all architectures can benefit from it just by calling setup_vm and providing the implementation of install_page. Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx> --- lib/alloc.c | 1 + lib/alloc.h | 2 -- lib/vmalloc.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/vmalloc.h | 5 +++++ lib/x86/io.c | 2 +- lib/x86/isr.c | 5 +++-- lib/x86/vm.c | 48 --------------------------------------------- lib/x86/vm.h | 5 ----- x86/Makefile.common | 1 + x86/asyncpf.c | 4 +++- x86/pmu.c | 4 ++-- x86/rmap_chain.c | 1 + x86/sieve.c | 6 +++--- 13 files changed, 76 insertions(+), 64 deletions(-) diff --git a/lib/alloc.c b/lib/alloc.c index 61cb292..ecdbbc4 100644 --- a/lib/alloc.c +++ b/lib/alloc.c @@ -1,4 +1,5 @@ #include "alloc.h" +#include "asm/page.h" void *malloc(size_t size) { diff --git a/lib/alloc.h b/lib/alloc.h index f560c4a..c44d459 100644 --- a/lib/alloc.h +++ b/lib/alloc.h @@ -35,6 +35,4 @@ void *calloc(size_t nmemb, size_t size); void free(void *ptr); void *memalign(size_t alignment, size_t size); -extern struct alloc_ops *alloc_ops; - #endif /* _ALLOC_H_ */ diff --git a/lib/vmalloc.c b/lib/vmalloc.c index efeb100..ca36bf8 100644 --- a/lib/vmalloc.c +++ b/lib/vmalloc.c @@ -9,6 +9,7 @@ #include "asm/spinlock.h" #include "asm/page.h" #include "asm/io.h" +#include "alloc.h" #include "alloc_phys.h" #include "alloc_page.h" #include "vmalloc.h" @@ -35,12 +36,67 @@ void init_alloc_vpage(void *top) vfree_top = top; } +void *vmap(phys_addr_t phys, size_t size) +{ + void *mem, *p; + unsigned pages; + + size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + pages = size / PAGE_SIZE; + mem = p = alloc_vpages(pages); + + phys &= ~(unsigned long long)(PAGE_SIZE - 1); + while (pages--) { + install_page(page_root, phys, p); + phys += PAGE_SIZE; + p += PAGE_SIZE; + } + return mem; +} + +static void *vm_memalign(size_t alignment, size_t size) +{ + void *mem, *p; + unsigned pages; + + assert(alignment <= PAGE_SIZE); + size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + pages = size / PAGE_SIZE; + mem = p = alloc_vpages(pages); + while (pages--) { + phys_addr_t pa = virt_to_phys(alloc_page()); + install_page(page_root, pa, p); + p += PAGE_SIZE; + } + return mem; +} + +static void vm_free(void *mem, size_t size) +{ + while (size) { + free_page(phys_to_virt(virt_to_pte_phys(page_root, mem))); + mem += PAGE_SIZE; + size -= PAGE_SIZE; + } +} + +static struct alloc_ops vmalloc_ops = { + .memalign = vm_memalign, + .free = vm_free, + .align_min = PAGE_SIZE, +}; + void setup_vm() { phys_addr_t base, top; + + if (alloc_ops == &vmalloc_ops) + return; + phys_alloc_get_unused(&base, &top); base = (base + PAGE_SIZE - 1) & -PAGE_SIZE; top = top & -PAGE_SIZE; free_pages(phys_to_virt(base), top - base); page_root = setup_mmu(top); + alloc_ops = &vmalloc_ops; } diff --git a/lib/vmalloc.h b/lib/vmalloc.h index ec3fe36..b4cde65 100644 --- a/lib/vmalloc.h +++ b/lib/vmalloc.h @@ -1,6 +1,8 @@ #ifndef VMALLOC_H #define VMALLOC_H 1 +#include <asm/page.h> + extern void *alloc_vpages(ulong nr); extern void *alloc_vpage(void); extern void init_alloc_vpage(void *top); @@ -8,5 +10,8 @@ extern void setup_vm(); extern void *setup_mmu(phys_addr_t top); extern phys_addr_t virt_to_pte_phys(pgd_t *pgtable, void *virt); +extern pteval_t *install_page(pgd_t *pgtable, phys_addr_t phys, void *virt); + +void *vmap(phys_addr_t phys, size_t size); #endif diff --git a/lib/x86/io.c b/lib/x86/io.c index cc5ac58..7e1c16d 100644 --- a/lib/x86/io.c +++ b/lib/x86/io.c @@ -1,8 +1,8 @@ #include "libcflat.h" -#include "vm.h" #include "smp.h" #include "asm/io.h" #include "asm/page.h" +#include "vmalloc.h" #ifndef USE_SERIAL #define USE_SERIAL #endif diff --git a/lib/x86/isr.c b/lib/x86/isr.c index 9b1d505..53c0c2b 100644 --- a/lib/x86/isr.c +++ b/lib/x86/isr.c @@ -1,6 +1,7 @@ #include "libcflat.h" +#include "processor.h" #include "isr.h" -#include "vm.h" +#include "alloc.h" #include "desc.h" extern char isr_entry_point[]; @@ -65,7 +66,7 @@ asm ( void handle_irq(unsigned vec, void (*func)(isr_regs_t *regs)) { - u8 *thunk = vmalloc(50); + u8 *thunk = malloc(50); set_idt_entry(vec, thunk, 0); diff --git a/lib/x86/vm.c b/lib/x86/vm.c index 223f14a..73d9be4 100644 --- a/lib/x86/vm.c +++ b/lib/x86/vm.c @@ -173,55 +173,7 @@ void *setup_mmu(phys_addr_t end_of_memory) return cr3; } -void *vmalloc(unsigned long size) -{ - void *mem, *p; - unsigned pages; - - size += sizeof(unsigned long); - - size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); - pages = size / PAGE_SIZE; - mem = p = alloc_vpages(pages); - while (pages--) { - install_page(phys_to_virt(read_cr3()), virt_to_phys(alloc_page()), p); - p += PAGE_SIZE; - } - *(unsigned long *)mem = size; - mem += sizeof(unsigned long); - return mem; -} - phys_addr_t virt_to_pte_phys(pgd_t *cr3, void *mem) { return (*get_pte(cr3, mem) & PT_ADDR_MASK) + ((ulong)mem & (PAGE_SIZE - 1)); } - -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) & PT_ADDR_MASK)); - mem += PAGE_SIZE; - size -= PAGE_SIZE; - } -} - -void *vmap(unsigned long long phys, unsigned long size) -{ - void *mem, *p; - unsigned pages; - - size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); - pages = size / PAGE_SIZE; - mem = p = alloc_vpages(pages); - - phys &= ~(unsigned long long)(PAGE_SIZE - 1); - while (pages--) { - install_page(phys_to_virt(read_cr3()), phys, p); - phys += PAGE_SIZE; - p += PAGE_SIZE; - } - return mem; -} diff --git a/lib/x86/vm.h b/lib/x86/vm.h index 1d8b805..ae1b769 100644 --- a/lib/x86/vm.h +++ b/lib/x86/vm.h @@ -7,10 +7,6 @@ void setup_5level_page_table(); -void *vmalloc(unsigned long size); -void vfree(void *mem); -void *vmap(unsigned long long phys, unsigned long size); - struct pte_search { int level; pteval_t *pte; @@ -39,7 +35,6 @@ pteval_t *install_pte(pgd_t *cr3, pteval_t *pt_page); pteval_t *install_large_page(pgd_t *cr3, phys_addr_t phys, void *virt); -pteval_t *install_page(pgd_t *cr3, phys_addr_t phys, void *virt); void install_pages(pgd_t *cr3, phys_addr_t phys, size_t len, void *virt); bool any_present_pages(pgd_t *cr3, void *virt, size_t len); diff --git a/x86/Makefile.common b/x86/Makefile.common index f0fbadf..5f7eac4 100644 --- a/x86/Makefile.common +++ b/x86/Makefile.common @@ -4,6 +4,7 @@ all: directories test_cases cflatobjs += lib/pci.o cflatobjs += lib/pci-edu.o +cflatobjs += lib/alloc.o cflatobjs += lib/vmalloc.o cflatobjs += lib/alloc_page.o cflatobjs += lib/alloc_phys.o diff --git a/x86/asyncpf.c b/x86/asyncpf.c index ee8baf9..de3d592 100644 --- a/x86/asyncpf.c +++ b/x86/asyncpf.c @@ -22,6 +22,8 @@ #include "x86/isr.h" #include "x86/vm.h" +#include "asm/page.h" +#include "alloc.h" #include "libcflat.h" #include "vmalloc.h" #include <stdint.h> @@ -95,7 +97,7 @@ int main(int ac, char **av) wrmsr(MSR_KVM_ASYNC_PF_EN, virt_to_phys((void*)&apf_reason) | KVM_ASYNC_PF_SEND_ALWAYS | KVM_ASYNC_PF_ENABLED); printf("alloc memory\n"); - buf = vmalloc(MEM); + buf = malloc(MEM); irq_enable(); while(loop--) { printf("start loop\n"); diff --git a/x86/pmu.c b/x86/pmu.c index b56b61e..12a5880 100644 --- a/x86/pmu.c +++ b/x86/pmu.c @@ -5,7 +5,7 @@ #include "x86/apic.h" #include "x86/desc.h" #include "x86/isr.h" -#include "x86/vm.h" +#include "alloc.h" #include "libcflat.h" #include <stdint.h> @@ -380,7 +380,7 @@ int main(int ac, char **av) setup_vm(); setup_idt(); handle_irq(PC_VECTOR, cnt_overflow); - buf = vmalloc(N*64); + buf = malloc(N*64); eax.full = id.a; ebx.full = id.b; diff --git a/x86/rmap_chain.c b/x86/rmap_chain.c index 97591f9..3433dda 100644 --- a/x86/rmap_chain.c +++ b/x86/rmap_chain.c @@ -3,6 +3,7 @@ #include "libcflat.h" #include "fwcfg.h" #include "vm.h" +#include "vmalloc.h" #include "smp.h" #include "alloc_page.h" diff --git a/x86/sieve.c b/x86/sieve.c index 6cbcd6d..2ee2919 100644 --- a/x86/sieve.c +++ b/x86/sieve.c @@ -1,4 +1,4 @@ -#include "vm.h" +#include "alloc.h" #include "libcflat.h" int sieve(char* data, int size) @@ -42,9 +42,9 @@ int main() setup_vm(); test_sieve("mapped", static_data, STATIC_SIZE); for (i = 0; i < 3; ++i) { - v = vmalloc(VSIZE); + v = malloc(VSIZE); test_sieve("virtual", v, VSIZE); - vfree(v); + free(v); } return 0; -- 2.14.2