[PATCH kvm-unit-tests 03/18] lib: move page allocator here from x86

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

 



This is another step in porting the x86 (v)malloc implementation to
other architectures.

Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
---
 lib/alloc_page.c         | 130 +++++++++++++++++++++++++++++++++++++++++++++++
 lib/alloc_page.h         |  16 ++++++
 lib/x86/intel-iommu.c    |   2 +
 lib/x86/intel-iommu.h    |   1 -
 lib/x86/vm.c             | 108 +--------------------------------------
 lib/x86/vm.h             |   4 --
 x86/Makefile.common      |   1 +
 x86/emulator.c           |   1 +
 x86/eventinj.c           |   3 +-
 x86/hypercall.c          |   1 +
 x86/hyperv_clock.c       |   1 +
 x86/hyperv_connections.c |   1 +
 x86/hyperv_stimer.c      |   1 +
 x86/hyperv_synic.c       |   1 +
 x86/intel-iommu.c        |   2 +
 x86/rmap_chain.c         |   1 +
 x86/svm.c                |   1 +
 x86/taskswitch2.c        |   1 +
 x86/vmx.c                |   1 +
 x86/vmx_tests.c          |   1 +
 20 files changed, 166 insertions(+), 112 deletions(-)
 create mode 100644 lib/alloc_page.c
 create mode 100644 lib/alloc_page.h

diff --git a/lib/alloc_page.c b/lib/alloc_page.c
new file mode 100644
index 0000000..15f6721
--- /dev/null
+++ b/lib/alloc_page.c
@@ -0,0 +1,130 @@
+/*
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ *
+ * This is a simple allocator that provides contiguous physical addresses
+ * with page granularity.
+ */
+#include "libcflat.h"
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/spinlock.h>
+
+static struct spinlock lock;
+static void *freelist = 0;
+
+void free_pages(void *mem, unsigned long size)
+{
+	void *old_freelist;
+	void *end;
+
+	assert_msg((unsigned long) mem % PAGE_SIZE == 0,
+		   "mem not page aligned: %p", mem);
+
+	assert_msg(size % PAGE_SIZE == 0, "size not page aligned: %#lx", size);
+
+	assert_msg(size == 0 || mem + size > mem,
+		   "mem + size overflow: %p + %#lx", mem, size);
+
+	if (size == 0) {
+		freelist = NULL;
+		return;
+	}
+
+	spin_lock(&lock);
+	old_freelist = freelist;
+	freelist = mem;
+	end = mem + size;
+	while (mem + PAGE_SIZE != end) {
+		*(void **)mem = (mem + PAGE_SIZE);
+		mem += PAGE_SIZE;
+	}
+
+	*(void **)mem = old_freelist;
+	spin_unlock(&lock);
+}
+
+void *alloc_page()
+{
+	void *p;
+
+	if (!freelist)
+		return 0;
+
+	spin_lock(&lock);
+	p = freelist;
+	freelist = *(void **)freelist;
+	spin_unlock(&lock);
+
+	return p;
+}
+
+/*
+ * Allocates (1 << order) physically contiguous and naturally aligned pages.
+ * Returns NULL if there's no memory left.
+ */
+void *alloc_pages(unsigned long order)
+{
+	/* Generic list traversal. */
+	void *prev;
+	void *curr = NULL;
+	void *next = freelist;
+
+	/* Looking for a run of length (1 << order). */
+	unsigned long run = 0;
+	const unsigned long n = 1ul << order;
+	const unsigned long align_mask = (n << PAGE_SHIFT) - 1;
+	void *run_start = NULL;
+	void *run_prev = NULL;
+	unsigned long run_next_pa = 0;
+	unsigned long pa;
+
+	assert(order < sizeof(unsigned long) * 8);
+
+	spin_lock(&lock);
+	for (;;) {
+		prev = curr;
+		curr = next;
+
+		if (!curr) {
+			run_start = NULL;
+			break;
+		}
+
+		next = *((void **) curr);
+		pa = virt_to_phys(curr);
+
+		if (run == 0) {
+			if (!(pa & align_mask)) {
+				run_start = curr;
+				run_prev = prev;
+				run_next_pa = pa + PAGE_SIZE;
+				run = 1;
+			}
+		} else if (pa == run_next_pa) {
+			run_next_pa += PAGE_SIZE;
+			run += 1;
+		} else {
+			run = 0;
+		}
+
+		if (run == n) {
+			if (run_prev)
+				*((void **) run_prev) = next;
+			else
+				freelist = next;
+			break;
+		}
+	}
+	spin_unlock(&lock);
+	return run_start;
+}
+
+
+void free_page(void *page)
+{
+	spin_lock(&lock);
+	*(void **)page = freelist;
+	freelist = page;
+	spin_unlock(&lock);
+}
+
diff --git a/lib/alloc_page.h b/lib/alloc_page.h
new file mode 100644
index 0000000..1884c7a
--- /dev/null
+++ b/lib/alloc_page.h
@@ -0,0 +1,16 @@
+/*
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ *
+ * This is a simple allocator that provides contiguous physical addresses
+ * with byte granularity.
+ */
+
+#ifndef ALLOC_PAGE_H
+#define ALLOC_PAGE_H 1
+
+void *alloc_page();
+void *alloc_pages(unsigned long order);
+void free_page(void *page);
+void free_pages(void *mem, unsigned long size);
+
+#endif
diff --git a/lib/x86/intel-iommu.c b/lib/x86/intel-iommu.c
index 9fdbd3b..af92fab 100644
--- a/lib/x86/intel-iommu.c
+++ b/lib/x86/intel-iommu.c
@@ -12,8 +12,10 @@
 
 #include "intel-iommu.h"
 #include "libcflat.h"
+#include "vm.h"
 #include "pci.h"
 #include "atomic.h"
+#include "alloc_page.h"
 
 /*
  * VT-d in QEMU currently only support 39 bits address width, which is
diff --git a/lib/x86/intel-iommu.h b/lib/x86/intel-iommu.h
index 885be53..05b9744 100644
--- a/lib/x86/intel-iommu.h
+++ b/lib/x86/intel-iommu.h
@@ -16,7 +16,6 @@
 #define __INTEL_IOMMU_H__
 
 #include "libcflat.h"
-#include "vm.h"
 #include "isr.h"
 #include "smp.h"
 #include "desc.h"
diff --git a/lib/x86/vm.c b/lib/x86/vm.c
index b975a73..d2a3c59 100644
--- a/lib/x86/vm.c
+++ b/lib/x86/vm.c
@@ -2,111 +2,7 @@
 #include "vm.h"
 #include "libcflat.h"
 #include "vmalloc.h"
-
-static void *free = 0;
-
-static void free_memory(void *mem, unsigned long size)
-{
-	void *end;
-
-	assert_msg((unsigned long) mem % PAGE_SIZE == 0,
-		   "mem not page aligned: %p", mem);
-
-	assert_msg(size % PAGE_SIZE == 0, "size not page aligned: %#lx", size);
-
-	assert_msg(size == 0 || mem + size > mem,
-		   "mem + size overflow: %p + %#lx", mem, size);
-
-	if (size == 0) {
-		free = NULL;
-		return;
-	}
-
-	free = mem;
-	end = mem + size;
-	while (mem + PAGE_SIZE != end) {
-		*(void **)mem = (mem + PAGE_SIZE);
-		mem += PAGE_SIZE;
-	}
-
-	*(void **)mem = NULL;
-}
-
-void *alloc_page()
-{
-    void *p;
-
-    if (!free)
-	return 0;
-
-    p = free;
-    free = *(void **)free;
-
-    return p;
-}
-
-/*
- * Allocates (1 << order) physically contiguous and naturally aligned pages.
- * Returns NULL if there's no memory left.
- */
-void *alloc_pages(unsigned long order)
-{
-	/* Generic list traversal. */
-	void *prev;
-	void *curr = NULL;
-	void *next = free;
-
-	/* Looking for a run of length (1 << order). */
-	unsigned long run = 0;
-	const unsigned long n = 1ul << order;
-	const unsigned long align_mask = (n << PAGE_SHIFT) - 1;
-	void *run_start = NULL;
-	void *run_prev = NULL;
-	unsigned long run_next_pa = 0;
-	unsigned long pa;
-
-	assert(order < sizeof(unsigned long) * 8);
-
-	for (;;) {
-		prev = curr;
-		curr = next;
-		next = curr ? *((void **) curr) : NULL;
-
-		if (!curr)
-			return 0;
-
-		pa = virt_to_phys(curr);
-
-		if (run == 0) {
-			if (!(pa & align_mask)) {
-				run_start = curr;
-				run_prev = prev;
-				run_next_pa = pa + PAGE_SIZE;
-				run = 1;
-			}
-		} else if (pa == run_next_pa) {
-			run_next_pa += PAGE_SIZE;
-			run += 1;
-		} else {
-			run = 0;
-		}
-
-		if (run == n) {
-			if (run_prev)
-				*((void **) run_prev) = next;
-			else
-				free = next;
-			return run_start;
-		}
-	}
-}
-
-
-void free_page(void *page)
-{
-    *(void **)page = free;
-    free = page;
-}
+#include "alloc_page.h"
 
 extern char edata;
 static unsigned long end_of_memory;
@@ -290,7 +186,7 @@ void setup_vm()
 {
     assert(!end_of_memory);
     end_of_memory = fwcfg_get_u64(FW_CFG_RAM_SIZE);
-    free_memory(&edata, end_of_memory - (unsigned long)&edata);
+    free_pages(&edata, end_of_memory - (unsigned long)&edata);
     setup_mmu(end_of_memory);
 }
 
diff --git a/lib/x86/vm.h b/lib/x86/vm.h
index 543da33..4a7888b 100644
--- a/lib/x86/vm.h
+++ b/lib/x86/vm.h
@@ -40,10 +40,6 @@ unsigned long *install_pte(unsigned long *cr3,
                            unsigned long pte,
                            unsigned long *pt_page);
 
-void *alloc_page();
-void *alloc_pages(unsigned long order);
-void free_page(void *page);
-
 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);
diff --git a/x86/Makefile.common b/x86/Makefile.common
index f3f3742..fce0801 100644
--- a/x86/Makefile.common
+++ b/x86/Makefile.common
@@ -5,6 +5,7 @@ all: directories test_cases
 cflatobjs += lib/pci.o
 cflatobjs += lib/pci-edu.o
 cflatobjs += lib/vmalloc.o
+cflatobjs += lib/alloc_page.o
 cflatobjs += lib/x86/setup.o
 cflatobjs += lib/x86/io.o
 cflatobjs += lib/x86/smp.o
diff --git a/x86/emulator.c b/x86/emulator.c
index 4fb0f32..e6f27cc 100644
--- a/x86/emulator.c
+++ b/x86/emulator.c
@@ -5,6 +5,7 @@
 #include "types.h"
 #include "processor.h"
 #include "vmalloc.h"
+#include "alloc_page.h"
 
 #define memset __builtin_memset
 #define TESTDEV_IO_PORT 0xe0
diff --git a/x86/eventinj.c b/x86/eventinj.c
index 61e1b96..247604c 100644
--- a/x86/eventinj.c
+++ b/x86/eventinj.c
@@ -1,11 +1,12 @@
 #include "libcflat.h"
-#include "processor.h"
 #include "vm.h"
+#include "processor.h"
 #include "desc.h"
 #include "isr.h"
 #include "apic.h"
 #include "apic-defs.h"
 #include "vmalloc.h"
+#include "alloc_page.h"
 
 #ifdef __x86_64__
 #  define R "r"
diff --git a/x86/hypercall.c b/x86/hypercall.c
index 9380f78..37fec8e 100644
--- a/x86/hypercall.c
+++ b/x86/hypercall.c
@@ -1,6 +1,7 @@
 #include "libcflat.h"
 #include "vm.h"
 #include "desc.h"
+#include "alloc_page.h"
 
 #define KVM_HYPERCALL_INTEL ".byte 0x0f,0x01,0xc1"
 #define KVM_HYPERCALL_AMD ".byte 0x0f,0x01,0xd9"
diff --git a/x86/hyperv_clock.c b/x86/hyperv_clock.c
index 9497269..b72e357 100644
--- a/x86/hyperv_clock.c
+++ b/x86/hyperv_clock.c
@@ -4,6 +4,7 @@
 #include "processor.h"
 #include "hyperv.h"
 #include "vm.h"
+#include "alloc_page.h"
 
 #define MAX_CPU 4
 #define TICKS_PER_SEC (1000000000 / 100)
diff --git a/x86/hyperv_connections.c b/x86/hyperv_connections.c
index b061048..5d541c9 100644
--- a/x86/hyperv_connections.c
+++ b/x86/hyperv_connections.c
@@ -5,6 +5,7 @@
 #include "atomic.h"
 #include "hyperv.h"
 #include "bitops.h"
+#include "alloc_page.h"
 
 #define MAX_CPUS 64
 
diff --git a/x86/hyperv_stimer.c b/x86/hyperv_stimer.c
index bd7f966..b6332fd 100644
--- a/x86/hyperv_stimer.c
+++ b/x86/hyperv_stimer.c
@@ -9,6 +9,7 @@
 #include "atomic.h"
 #include "hyperv.h"
 #include "asm/barrier.h"
+#include "alloc_page.h"
 
 #define MAX_CPUS 4
 
diff --git a/x86/hyperv_synic.c b/x86/hyperv_synic.c
index 1ccf1a0..9a5f53f 100644
--- a/x86/hyperv_synic.c
+++ b/x86/hyperv_synic.c
@@ -8,6 +8,7 @@
 #include "smp.h"
 #include "atomic.h"
 #include "hyperv.h"
+#include "alloc_page.h"
 
 #define MAX_CPUS 4
 
diff --git a/x86/intel-iommu.c b/x86/intel-iommu.c
index 610cc65..82b8234 100644
--- a/x86/intel-iommu.c
+++ b/x86/intel-iommu.c
@@ -13,6 +13,8 @@
 #include "intel-iommu.h"
 #include "pci-edu.h"
 #include "x86/apic.h"
+#include "vm.h"
+#include "alloc_page.h"
 
 #define VTD_TEST_DMAR_4B ("DMAR 4B memcpy test")
 #define VTD_TEST_IR_MSI ("IR MSI")
diff --git a/x86/rmap_chain.c b/x86/rmap_chain.c
index 7bf6275..97591f9 100644
--- a/x86/rmap_chain.c
+++ b/x86/rmap_chain.c
@@ -4,6 +4,7 @@
 #include "fwcfg.h"
 #include "vm.h"
 #include "smp.h"
+#include "alloc_page.h"
 
 int main (void)
 {
diff --git a/x86/svm.c b/x86/svm.c
index 25ac0ce..162632c 100644
--- a/x86/svm.c
+++ b/x86/svm.c
@@ -6,6 +6,7 @@
 #include "vm.h"
 #include "smp.h"
 #include "types.h"
+#include "alloc_page.h"
 
 /* for the nested page table*/
 u64 *pml4e;
diff --git a/x86/taskswitch2.c b/x86/taskswitch2.c
index e442fa6..8714ade 100644
--- a/x86/taskswitch2.c
+++ b/x86/taskswitch2.c
@@ -5,6 +5,7 @@
 #include "processor.h"
 #include "vm.h"
 #include "vmalloc.h"
+#include "alloc_page.h"
 
 #define MAIN_TSS_SEL (FIRST_SPARE_SEL + 0)
 #define VM86_TSS_SEL (FIRST_SPARE_SEL + 8)
diff --git a/x86/vmx.c b/x86/vmx.c
index 786c70f..cc76b5b 100644
--- a/x86/vmx.c
+++ b/x86/vmx.c
@@ -30,6 +30,7 @@
 
 #include "libcflat.h"
 #include "processor.h"
+#include "alloc_page.h"
 #include "vm.h"
 #include "desc.h"
 #include "vmx.h"
diff --git a/x86/vmx_tests.c b/x86/vmx_tests.c
index d9bbe10..1c9c747 100644
--- a/x86/vmx_tests.c
+++ b/x86/vmx_tests.c
@@ -13,6 +13,7 @@
 #include "apic.h"
 #include "types.h"
 #include "vmalloc.h"
+#include "alloc_page.h"
 
 #define NONCANONICAL            0xaaaaaaaaaaaaaaaaull
 
-- 
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