[PATCH kvm-unit-tests 11/18] vmalloc: convert to alloc_ops

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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






[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux