As the next step in making vmalloc/vfree available to every other architecture, register the available memory with phys_alloc for x86 too, and add a service to return the unused phys_alloc region. This makes setup_vm architecture- independent. Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx> --- lib/alloc_page.c | 2 +- lib/alloc_phys.c | 6 ++++++ lib/alloc_phys.h | 6 ++++++ lib/libcflat.h | 2 ++ lib/vmalloc.c | 14 ++++++++++++++ lib/x86/asm/page.h | 2 ++ lib/x86/setup.c | 4 ++++ lib/x86/vm.c | 27 ++++++++------------------- lib/x86/vm.h | 1 - x86/Makefile.common | 1 + 10 files changed, 44 insertions(+), 21 deletions(-) diff --git a/lib/alloc_page.c b/lib/alloc_page.c index de6fd6f..271b8aa 100644 --- a/lib/alloc_page.c +++ b/lib/alloc_page.c @@ -5,6 +5,7 @@ * with page granularity. */ #include "libcflat.h" +#include "alloc_phys.h" #include <asm/page.h> #include <asm/io.h> @@ -113,4 +114,3 @@ void free_page(void *page) *(void **)page = free; free = page; } - diff --git a/lib/alloc_phys.c b/lib/alloc_phys.c index 3972277..6befb5c 100644 --- a/lib/alloc_phys.c +++ b/lib/alloc_phys.c @@ -107,6 +107,12 @@ static phys_addr_t phys_alloc_aligned_safe(phys_addr_t size, return addr; } +void phys_alloc_get_unused(phys_addr_t *p_base, phys_addr_t *p_top) +{ + *p_base = base; + *p_top = top; +} + static void *early_memalign(size_t alignment, size_t size) { phys_addr_t addr; diff --git a/lib/alloc_phys.h b/lib/alloc_phys.h index f09d667..848d3db 100644 --- a/lib/alloc_phys.h +++ b/lib/alloc_phys.h @@ -36,4 +36,10 @@ extern void phys_alloc_set_minimum_alignment(phys_addr_t align); */ extern void phys_alloc_show(void); +/* + * phys_alloc_get_unused returns the addresses for the still-unused part + * of the initial free memory region passed to phys_alloc_init. + */ +extern void phys_alloc_get_unused(phys_addr_t *p_base, phys_addr_t *p_top); + #endif /* _ALLOC_PHYS_H_ */ diff --git a/lib/libcflat.h b/lib/libcflat.h index a5c4290..fb46541 100644 --- a/lib/libcflat.h +++ b/lib/libcflat.h @@ -156,4 +156,6 @@ static inline bool is_power_of_2(unsigned long n) void binstr(unsigned long x, char out[BINSTR_SZ]); void print_binstr(unsigned long x); +extern void setup_vm(void); + #endif diff --git a/lib/vmalloc.c b/lib/vmalloc.c index 877c883..c2abe3c 100644 --- a/lib/vmalloc.c +++ b/lib/vmalloc.c @@ -8,9 +8,12 @@ #include "libcflat.h" #include "asm/spinlock.h" #include "asm/page.h" +#include "alloc_phys.h" +#include "alloc_page.h" static struct spinlock lock; static void *vfree_top = 0; +static void *page_root; void *alloc_vpages(ulong nr) { @@ -29,3 +32,14 @@ void init_alloc_vpage(void *top) { vfree_top = top; } + +void setup_vm() +{ + phys_addr_t base, top; + phys_alloc_get_unused(&base, &top); + base = (base + PAGE_SIZE - 1) & -PAGE_SIZE; + top = top & -PAGE_SIZE; + + free_pages((void *)base, top - base); + page_root = setup_mmu(top); +} diff --git a/lib/x86/asm/page.h b/lib/x86/asm/page.h index 562594d..154d45e 100644 --- a/lib/x86/asm/page.h +++ b/lib/x86/asm/page.h @@ -46,5 +46,7 @@ #define PGDIR_BITS(lvl) (((lvl) - 1) * PGDIR_WIDTH + PAGE_SHIFT) #define PGDIR_OFFSET(va, lvl) (((va) >> PGDIR_BITS(lvl)) & PGDIR_MASK) +extern void *setup_mmu(unsigned long top); + #endif /* !__ASSEMBLY__ */ #endif diff --git a/lib/x86/setup.c b/lib/x86/setup.c index 22257a7..f6a8ea8 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -53,6 +53,10 @@ void setup_multiboot(struct mbi_bootinfo *bootinfo) initrd = (char *)(uintptr_t) mods->start; initrd_size = mods->end - mods->start; + + /* TODO: use e820 */ + u64 end_of_memory = bootinfo->mem_upper * 1024ull; + phys_alloc_init((uintptr_t) &edata, end_of_memory - (uintptr_t)edata); } void setup_libcflat(void) diff --git a/lib/x86/vm.c b/lib/x86/vm.c index d2a3c59..f6f20e5 100644 --- a/lib/x86/vm.c +++ b/lib/x86/vm.c @@ -1,12 +1,8 @@ -#include "fwcfg.h" #include "vm.h" #include "libcflat.h" #include "vmalloc.h" #include "alloc_page.h" -extern char edata; -static unsigned long end_of_memory; - unsigned long *install_pte(unsigned long *cr3, int pte_level, void *virt, @@ -149,23 +145,23 @@ static void setup_mmu_range(unsigned long *cr3, unsigned long start, install_pages(cr3, phys, max - phys, (void *)(ulong)phys); } -static void setup_mmu(unsigned long len) +void *setup_mmu(unsigned long end_of_memory) { unsigned long *cr3 = alloc_page(); memset(cr3, 0, PAGE_SIZE); #ifdef __x86_64__ - if (len < (1ul << 32)) - len = (1ul << 32); /* map mmio 1:1 */ + if (end_of_memory < (1ul << 32)) + end_of_memory = (1ul << 32); /* map mmio 1:1 */ - setup_mmu_range(cr3, 0, len); + setup_mmu_range(cr3, 0, end_of_memory); #else - if (len > (1ul << 31)) - len = (1ul << 31); + if (end_of_memory > (1ul << 31)) + end_of_memory = (1ul << 31); /* 0 - 2G memory, 2G-3G valloc area, 3G-4G mmio */ - setup_mmu_range(cr3, 0, len); + setup_mmu_range(cr3, 0, end_of_memory); setup_mmu_range(cr3, 3ul << 30, (1ul << 30)); init_alloc_vpage((void*)(3ul << 30)); #endif @@ -180,14 +176,7 @@ static void setup_mmu(unsigned long len) printf("cr0 = %lx\n", read_cr0()); printf("cr3 = %lx\n", read_cr3()); printf("cr4 = %lx\n", read_cr4()); -} - -void setup_vm() -{ - assert(!end_of_memory); - end_of_memory = fwcfg_get_u64(FW_CFG_RAM_SIZE); - free_pages(&edata, end_of_memory - (unsigned long)&edata); - setup_mmu(end_of_memory); + return cr3; } void *vmalloc(unsigned long size) diff --git a/lib/x86/vm.h b/lib/x86/vm.h index 4a7888b..c3211eb 100644 --- a/lib/x86/vm.h +++ b/lib/x86/vm.h @@ -5,7 +5,6 @@ #include "asm/page.h" #include "asm/io.h" -void setup_vm(); void setup_5level_page_table(); void *vmalloc(unsigned long size); diff --git a/x86/Makefile.common b/x86/Makefile.common index fce0801..f0fbadf 100644 --- a/x86/Makefile.common +++ b/x86/Makefile.common @@ -6,6 +6,7 @@ cflatobjs += lib/pci.o cflatobjs += lib/pci-edu.o cflatobjs += lib/vmalloc.o cflatobjs += lib/alloc_page.o +cflatobjs += lib/alloc_phys.o cflatobjs += lib/x86/setup.o cflatobjs += lib/x86/io.o cflatobjs += lib/x86/smp.o -- 2.14.2