svn commit: r241362 - in projects/bhyve/sys/amd64/vmm: . amd intel io

Neel Natu neel at FreeBSD.org
Mon Oct 8 23:41:27 UTC 2012


Author: neel
Date: Mon Oct  8 23:41:26 2012
New Revision: 241362
URL: http://svn.freebsd.org/changeset/base/241362

Log:
  Allocate memory pages for the guest from the host's free page queue.
  
  It is no longer necessary to hard-partition the memory between the host
  and guests at boot time.

Modified:
  projects/bhyve/sys/amd64/vmm/amd/amdv.c
  projects/bhyve/sys/amd64/vmm/intel/vtd.c
  projects/bhyve/sys/amd64/vmm/io/iommu.c
  projects/bhyve/sys/amd64/vmm/io/iommu.h
  projects/bhyve/sys/amd64/vmm/vmm.c
  projects/bhyve/sys/amd64/vmm/vmm_dev.c
  projects/bhyve/sys/amd64/vmm/vmm_mem.c
  projects/bhyve/sys/amd64/vmm/vmm_mem.h

Modified: projects/bhyve/sys/amd64/vmm/amd/amdv.c
==============================================================================
--- projects/bhyve/sys/amd64/vmm/amd/amdv.c	Mon Oct  8 23:02:35 2012	(r241361)
+++ projects/bhyve/sys/amd64/vmm/amd/amdv.c	Mon Oct  8 23:41:26 2012	(r241362)
@@ -230,6 +230,14 @@ amd_iommu_create_mapping(void *domain, v
 	return (0);
 }
 
+static uint64_t
+amd_iommu_remove_mapping(void *domain, vm_paddr_t gpa, uint64_t len)
+{
+
+	printf("amd_iommu_remove_mapping: not implemented\n");
+	return (0);
+}
+
 static void
 amd_iommu_add_device(void *domain, int bus, int slot, int func)
 {
@@ -244,6 +252,13 @@ amd_iommu_remove_device(void *domain, in
 	printf("amd_iommu_remove_device: not implemented\n");
 }
 
+static void
+amd_iommu_invalidate_tlb(void *domain)
+{
+
+	printf("amd_iommu_invalidate_tlb: not implemented\n");
+}
+
 struct iommu_ops iommu_ops_amd = {
 	amd_iommu_init,
 	amd_iommu_cleanup,
@@ -252,6 +267,8 @@ struct iommu_ops iommu_ops_amd = {
 	amd_iommu_create_domain,
 	amd_iommu_destroy_domain,
 	amd_iommu_create_mapping,
+	amd_iommu_remove_mapping,
 	amd_iommu_add_device,
 	amd_iommu_remove_device,
+	amd_iommu_invalidate_tlb,
 };

Modified: projects/bhyve/sys/amd64/vmm/intel/vtd.c
==============================================================================
--- projects/bhyve/sys/amd64/vmm/intel/vtd.c	Mon Oct  8 23:02:35 2012	(r241361)
+++ projects/bhyve/sys/amd64/vmm/intel/vtd.c	Mon Oct  8 23:41:26 2012	(r241362)
@@ -444,8 +444,12 @@ vtd_remove_device(void *arg, int bus, in
 	}
 }
 
+#define	CREATE_MAPPING	0
+#define	REMOVE_MAPPING	1
+
 static uint64_t
-vtd_create_mapping(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, uint64_t len)
+vtd_update_mapping(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, uint64_t len,
+		   int remove)
 {
 	struct domain *dom;
 	int i, spshift, ptpshift, ptpindex, nlevels;
@@ -513,16 +517,50 @@ vtd_create_mapping(void *arg, vm_paddr_t
 		panic("gpa 0x%lx and ptpshift %d mismatch", gpa, ptpshift);
 
 	/*
-	 * Create a 'gpa' -> 'hpa' mapping
+	 * Update the 'gpa' -> 'hpa' mapping
 	 */
-	ptp[ptpindex] = hpa | VTD_PTE_RD | VTD_PTE_WR;
+	if (remove) {
+		ptp[ptpindex] = 0;
+	} else {
+		ptp[ptpindex] = hpa | VTD_PTE_RD | VTD_PTE_WR;
 
-	if (nlevels > 0)
-		ptp[ptpindex] |= VTD_PTE_SUPERPAGE;
+		if (nlevels > 0)
+			ptp[ptpindex] |= VTD_PTE_SUPERPAGE;
+	}
 
 	return (1UL << ptpshift);
 }
 
+static uint64_t
+vtd_create_mapping(void *arg, vm_paddr_t gpa, vm_paddr_t hpa, uint64_t len)
+{
+
+	return (vtd_update_mapping(arg, gpa, hpa, len, CREATE_MAPPING));
+}
+
+static uint64_t
+vtd_remove_mapping(void *arg, vm_paddr_t gpa, uint64_t len)
+{
+
+	return (vtd_update_mapping(arg, gpa, 0, len, REMOVE_MAPPING));
+}
+
+static void
+vtd_invalidate_tlb(void *dom)
+{
+	int i;
+	struct vtdmap *vtdmap;
+
+	/*
+	 * Invalidate the IOTLB.
+	 * XXX use domain-selective invalidation for IOTLB
+	 */
+	for (i = 0; i < drhd_num; i++) {
+		vtdmap = vtdmaps[i];
+		vtd_iotlb_global_invalidate(vtdmap);
+	}
+}
+
 static void *
 vtd_create_domain(vm_paddr_t maxaddr)
 {
@@ -632,6 +670,8 @@ struct iommu_ops iommu_ops_intel = {
 	vtd_create_domain,
 	vtd_destroy_domain,
 	vtd_create_mapping,
+	vtd_remove_mapping,
 	vtd_add_device,
 	vtd_remove_device,
+	vtd_invalidate_tlb,
 };

Modified: projects/bhyve/sys/amd64/vmm/io/iommu.c
==============================================================================
--- projects/bhyve/sys/amd64/vmm/io/iommu.c	Mon Oct  8 23:02:35 2012	(r241361)
+++ projects/bhyve/sys/amd64/vmm/io/iommu.c	Mon Oct  8 23:41:26 2012	(r241362)
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
 #include <machine/md_var.h>
 
 #include "vmm_util.h"
+#include "vmm_mem.h"
 #include "iommu.h"
 
 static boolean_t iommu_avail;
@@ -90,6 +91,16 @@ IOMMU_CREATE_MAPPING(void *domain, vm_pa
 		return (len);		/* XXX */
 }
 
+static __inline uint64_t
+IOMMU_REMOVE_MAPPING(void *domain, vm_paddr_t gpa, uint64_t len)
+{
+
+	if (ops != NULL && iommu_avail)
+		return ((*ops->remove_mapping)(domain, gpa, len));
+	else
+		return (len);		/* XXX */
+}
+
 static __inline void
 IOMMU_ADD_DEVICE(void *domain, int bus, int slot, int func)
 {
@@ -107,6 +118,14 @@ IOMMU_REMOVE_DEVICE(void *domain, int bu
 }
 
 static __inline void
+IOMMU_INVALIDATE_TLB(void *domain)
+{
+
+	if (ops != NULL && iommu_avail)
+		(*ops->invalidate_tlb)(domain);
+}
+
+static __inline void
 IOMMU_ENABLE(void)
 {
 
@@ -146,13 +165,13 @@ iommu_init(void)
 	/*
 	 * Create a domain for the devices owned by the host
 	 */
-	maxaddr = ptoa(Maxmem);
+	maxaddr = vmm_mem_maxaddr();
 	host_domain = IOMMU_CREATE_DOMAIN(maxaddr);
 	if (host_domain == NULL)
 		panic("iommu_init: unable to create a host domain");
 
 	/*
-	 * Create 1:1 mappings from '0' to 'Maxmem' for devices assigned to
+	 * Create 1:1 mappings from '0' to 'maxaddr' for devices assigned to
 	 * the host
 	 */
 	iommu_create_mapping(host_domain, 0, 0, maxaddr);
@@ -216,6 +235,27 @@ iommu_create_mapping(void *dom, vm_paddr
 }
 
 void
+iommu_remove_mapping(void *dom, vm_paddr_t gpa, size_t len)
+{
+	uint64_t unmapped, remaining;
+
+	remaining = len;
+
+	while (remaining > 0) {
+		unmapped = IOMMU_REMOVE_MAPPING(dom, gpa, remaining);
+		gpa += unmapped;
+		remaining -= unmapped;
+	}
+}
+
+void *
+iommu_host_domain(void)
+{
+
+	return (host_domain);
+}
+
+void
 iommu_add_device(void *dom, int bus, int slot, int func)
 {
 
@@ -228,3 +268,10 @@ iommu_remove_device(void *dom, int bus, 
 
 	IOMMU_REMOVE_DEVICE(dom, bus, slot, func);
 }
+
+void
+iommu_invalidate_tlb(void *domain)
+{
+
+	IOMMU_INVALIDATE_TLB(domain);
+}

Modified: projects/bhyve/sys/amd64/vmm/io/iommu.h
==============================================================================
--- projects/bhyve/sys/amd64/vmm/io/iommu.h	Mon Oct  8 23:02:35 2012	(r241361)
+++ projects/bhyve/sys/amd64/vmm/io/iommu.h	Mon Oct  8 23:41:26 2012	(r241362)
@@ -37,8 +37,11 @@ typedef void *(*iommu_create_domain_t)(v
 typedef void (*iommu_destroy_domain_t)(void *domain);
 typedef uint64_t (*iommu_create_mapping_t)(void *domain, vm_paddr_t gpa,
 					   vm_paddr_t hpa, uint64_t len);
+typedef uint64_t (*iommu_remove_mapping_t)(void *domain, vm_paddr_t gpa,
+					   uint64_t len);
 typedef void (*iommu_add_device_t)(void *domain, int bus, int slot, int func);
 typedef void (*iommu_remove_device_t)(void *dom, int bus, int slot, int func);
+typedef void (*iommu_invalidate_tlb_t)(void *dom);
 
 struct iommu_ops {
 	iommu_init_func_t	init;		/* module wide */
@@ -49,8 +52,10 @@ struct iommu_ops {
 	iommu_create_domain_t	create_domain;	/* domain-specific */
 	iommu_destroy_domain_t	destroy_domain;
 	iommu_create_mapping_t	create_mapping;
+	iommu_remove_mapping_t	remove_mapping;
 	iommu_add_device_t	add_device;
 	iommu_remove_device_t	remove_device;
+	iommu_invalidate_tlb_t	invalidate_tlb;
 };
 
 extern struct iommu_ops iommu_ops_intel;
@@ -58,10 +63,13 @@ extern struct iommu_ops iommu_ops_amd;
 
 void	iommu_init(void);
 void	iommu_cleanup(void);
+void	*iommu_host_domain(void);
 void	*iommu_create_domain(vm_paddr_t maxaddr);
 void	iommu_destroy_domain(void *dom);
 void	iommu_create_mapping(void *dom, vm_paddr_t gpa, vm_paddr_t hpa,
 			     size_t len);
+void	iommu_remove_mapping(void *dom, vm_paddr_t gpa, size_t len);
 void	iommu_add_device(void *dom, int bus, int slot, int func);
 void	iommu_remove_device(void *dom, int bus, int slot, int func);
+void	iommu_invalidate_tlb(void *domain);
 #endif

Modified: projects/bhyve/sys/amd64/vmm/vmm.c
==============================================================================
--- projects/bhyve/sys/amd64/vmm/vmm.c	Mon Oct  8 23:02:35 2012	(r241361)
+++ projects/bhyve/sys/amd64/vmm/vmm.c	Mon Oct  8 23:41:26 2012	(r241362)
@@ -280,6 +280,9 @@ vm_free_mem_seg(struct vm *vm, struct vm
 {
 	size_t len;
 	vm_paddr_t hpa;
+	void *host_domain;
+
+	host_domain = iommu_host_domain();
 
 	len = 0;
 	while (len < seg->len) {
@@ -289,11 +292,24 @@ vm_free_mem_seg(struct vm *vm, struct vm
 			      "associated with gpa 0x%016lx", seg->gpa + len);
 		}
 
+		/*
+		 * Remove the 'gpa' to 'hpa' mapping in VMs domain.
+		 * And resurrect the 1:1 mapping for 'hpa' in 'host_domain'.
+		 */
+		iommu_remove_mapping(vm->iommu, seg->gpa + len, PAGE_SIZE);
+		iommu_create_mapping(host_domain, hpa, hpa, PAGE_SIZE);
+
 		vmm_mem_free(hpa, PAGE_SIZE);
 
 		len += PAGE_SIZE;
 	}
 
+	/*
+	 * Invalidate cached translations associated with 'vm->iommu' since
+	 * we have now moved some pages from it.
+	 */
+	iommu_invalidate_tlb(vm->iommu);
+
 	bzero(seg, sizeof(struct vm_memory_segment));
 }
 
@@ -371,6 +387,7 @@ vm_malloc(struct vm *vm, vm_paddr_t gpa,
 	int error, available, allocated;
 	struct vm_memory_segment *seg;
 	vm_paddr_t g, hpa;
+	void *host_domain;
 
 	const boolean_t spok = TRUE;	/* superpage mappings are ok */
 
@@ -405,8 +422,11 @@ vm_malloc(struct vm *vm, vm_paddr_t gpa,
 	if (vm->num_mem_segs >= VM_MAX_MEMORY_SEGMENTS)
 		return (E2BIG);
 
+	host_domain = iommu_host_domain();
+
 	seg = &vm->mem_segs[vm->num_mem_segs];
 
+	error = 0;
 	seg->gpa = gpa;
 	seg->len = 0;
 	while (seg->len < len) {
@@ -421,16 +441,27 @@ vm_malloc(struct vm *vm, vm_paddr_t gpa,
 		if (error)
 			break;
 
+		/*
+		 * Remove the 1:1 mapping for 'hpa' from the 'host_domain'.
+		 * Add mapping for 'gpa + seg->len' to 'hpa' in the VMs domain.
+		 */
+		iommu_remove_mapping(host_domain, hpa, PAGE_SIZE);
 		iommu_create_mapping(vm->iommu, gpa + seg->len, hpa, PAGE_SIZE);
 
 		seg->len += PAGE_SIZE;
 	}
 
-	if (seg->len != len) {
+	if (error) {
 		vm_free_mem_seg(vm, seg);
 		return (error);
 	}
 
+	/*
+	 * Invalidate cached translations associated with 'host_domain' since
+	 * we have now moved some pages from it.
+	 */
+	iommu_invalidate_tlb(host_domain);
+
 	vm->num_mem_segs++;
 
 	return (0);

Modified: projects/bhyve/sys/amd64/vmm/vmm_dev.c
==============================================================================
--- projects/bhyve/sys/amd64/vmm/vmm_dev.c	Mon Oct  8 23:02:35 2012	(r241361)
+++ projects/bhyve/sys/amd64/vmm/vmm_dev.c	Mon Oct  8 23:41:26 2012	(r241362)
@@ -471,24 +471,6 @@ sysctl_vmm_create(SYSCTL_HANDLER_ARGS)
 SYSCTL_PROC(_hw_vmm, OID_AUTO, create, CTLTYPE_STRING | CTLFLAG_RW,
 	    NULL, 0, sysctl_vmm_create, "A", NULL);
 
-static int
-sysctl_vmm_mem_total(SYSCTL_HANDLER_ARGS)
-{
-	size_t val = vmm_mem_get_mem_total();
-	return sysctl_handle_long(oidp, &val, 0, req);
-}
-SYSCTL_PROC(_hw_vmm, OID_AUTO, mem_total, CTLTYPE_LONG | CTLFLAG_RD,
-		0, 0, sysctl_vmm_mem_total, "LU", "Amount of Total memory");
-
-static int
-sysctl_vmm_mem_free(SYSCTL_HANDLER_ARGS)
-{
-	size_t val = vmm_mem_get_mem_free();
-	return sysctl_handle_long(oidp, &val, 0, req);
-}
-SYSCTL_PROC(_hw_vmm, OID_AUTO, mem_free, CTLTYPE_LONG | CTLFLAG_RD,
-		0, 0, sysctl_vmm_mem_free, "LU", "Amount of Free memory");
-
 void
 vmmdev_init(void)
 {

Modified: projects/bhyve/sys/amd64/vmm/vmm_mem.c
==============================================================================
--- projects/bhyve/sys/amd64/vmm/vmm_mem.c	Mon Oct  8 23:02:35 2012	(r241361)
+++ projects/bhyve/sys/amd64/vmm/vmm_mem.c	Mon Oct  8 23:41:26 2012	(r241362)
@@ -36,9 +36,12 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/malloc.h>
 #include <sys/kernel.h>
+#include <sys/sysctl.h>
 
 #include <vm/vm.h>
 #include <vm/pmap.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pageout.h>
 
 #include <machine/md_var.h>
 #include <machine/metadata.h>
@@ -49,265 +52,21 @@ __FBSDID("$FreeBSD$");
 #include "vmm_util.h"
 #include "vmm_mem.h"
 
-static MALLOC_DEFINE(M_VMM_MEM, "vmm memory", "vmm memory");
+SYSCTL_DECL(_hw_vmm);
 
-#define	MB		(1024 * 1024)
-#define	GB		(1024 * MB)
-
-#define	VMM_MEM_MAXSEGS	64
-
-/* protected by vmm_mem_mtx */
-static struct {
-	vm_paddr_t	base;
-	vm_size_t	length;
-} vmm_mem_avail[VMM_MEM_MAXSEGS];
-
-static int vmm_mem_nsegs;
-size_t vmm_mem_total_bytes;
-
-static vm_paddr_t maxaddr;
-
-static struct mtx vmm_mem_mtx;
-
-/*
- * Steal any memory that was deliberately hidden from FreeBSD either by
- * the use of MAXMEM kernel config option or the hw.physmem loader tunable.
- */
-static int
-vmm_mem_steal_memory(void)
-{
-	int nsegs;
-	caddr_t kmdp;
-	uint32_t smapsize;
-	uint64_t base, length;
-	struct bios_smap *smapbase, *smap, *smapend;
-
-	/*
-	 * Borrowed from hammer_time() and getmemsize() in machdep.c
-	 */
-	kmdp = preload_search_by_type("elf kernel");
-	if (kmdp == NULL)
-		kmdp = preload_search_by_type("elf64 kernel");
-
-	smapbase = (struct bios_smap *)preload_search_info(kmdp,
-		MODINFO_METADATA | MODINFOMD_SMAP);
-	if (smapbase == NULL)
-		panic("No BIOS smap info from loader!");
-
-	smapsize = *((uint32_t *)smapbase - 1);
-	smapend = (struct bios_smap *)((uintptr_t)smapbase + smapsize);
-
-	vmm_mem_total_bytes = 0;
-	nsegs = 0;
-	for (smap = smapbase; smap < smapend; smap++) {
-		/*
-		 * XXX
-		 * Assuming non-overlapping, monotonically increasing
-		 * memory segments.
-		 */
-		if (smap->type != SMAP_TYPE_MEMORY)
-			continue;
-		if (smap->length == 0)
-			break;
-
-		base = roundup(smap->base, NBPDR);
-		length = rounddown(smap->length, NBPDR);
-
-		/* Skip this segment if FreeBSD is using all of it. */
-		if (base + length <= ptoa(Maxmem))
-			continue;
-
-		/*
-		 * If FreeBSD is using part of this segment then adjust
-		 * 'base' and 'length' accordingly.
-		 */
-		if (base < ptoa(Maxmem)) {
-			uint64_t used;
-			used = roundup(ptoa(Maxmem), NBPDR) - base;
-			base += used;
-			length -= used;
-		}
-
-		if (length == 0)
-			continue;
-
-		vmm_mem_avail[nsegs].base = base;
-		vmm_mem_avail[nsegs].length = length;
-		vmm_mem_total_bytes += length;
-
-		if (base + length > maxaddr)
-			maxaddr = base + length;
-
-		if (0 && bootverbose) {
-			printf("vmm_mem_populate: index %d, base 0x%0lx, "
-			       "length %ld\n",
-			       nsegs, vmm_mem_avail[nsegs].base,
-			       vmm_mem_avail[nsegs].length);
-		}
-
-		nsegs++;
-		if (nsegs >= VMM_MEM_MAXSEGS) {
-			printf("vmm_mem_populate: maximum number of vmm memory "
-			       "segments reached!\n");
-			return (ENOSPC);
-		}
-	}
-
-	vmm_mem_nsegs = nsegs;
-
-	return (0);
-}
+static u_long pages_allocated;
+SYSCTL_ULONG(_hw_vmm, OID_AUTO, pages_allocated, CTLFLAG_RD,
+	     &pages_allocated, 0, "4KB pages allocated");
 
 static void
-vmm_mem_direct_map(vm_paddr_t start, vm_paddr_t end)
+update_pages_allocated(int howmany)
 {
-	vm_paddr_t addr, remaining;
-	int pdpi, pdi, superpage_size;
-	pml4_entry_t *pml4p;
-	pdp_entry_t *pdp;
-	pd_entry_t *pd;
-	uint64_t page_attr_bits;
-
-	if (end >= NBPML4)
-		panic("Cannot map memory beyond %ldGB", NBPML4 / GB);
-
-	if (vmm_supports_1G_pages())
-		superpage_size = NBPDP;
-	else
-		superpage_size = NBPDR;
-
-	/*
-	 * Get the page directory pointer page that contains the direct
-	 * map address mappings.
-	 */
-	pml4p = kernel_pmap->pm_pml4;
-	pdp = (pdp_entry_t *)PHYS_TO_DMAP(pml4p[DMPML4I] & ~PAGE_MASK);
-
-	page_attr_bits = PG_RW | PG_V | PG_PS | PG_G;
-	addr = start;
-	while (addr < end) {
-		remaining = end - addr;
-		pdpi = addr / NBPDP;
-		if (superpage_size == NBPDP &&
-		    remaining >= NBPDP &&
-		    addr % NBPDP == 0) {
-			/*
-			 * If there isn't a mapping for this address then
-			 * create one but if there is one already make sure
-			 * it matches what we expect it to be.
-			 */
-			if (pdp[pdpi] == 0) {
-				pdp[pdpi] = addr | page_attr_bits;
-				if (0 && bootverbose) {
-					printf("vmm_mem_populate: mapping "
-					       "0x%lx with 1GB page at "
-					       "pdpi %d\n", addr, pdpi);
-				}
-			} else {
-				pdp_entry_t pdpe = pdp[pdpi];
-				if ((pdpe & ~PAGE_MASK) != addr ||
-				    (pdpe & page_attr_bits) != page_attr_bits) {
-					panic("An invalid mapping 0x%016lx "
-					      "already exists for 0x%016lx\n",
-					      pdpe, addr);
-				}
-			}
-			addr += NBPDP;
-		} else {
-			if (remaining < NBPDR) {
-				panic("vmm_mem_populate: remaining (%ld) must "
-				      "be greater than NBPDR (%d)\n",
-				      remaining, NBPDR);
-			}
-			if (pdp[pdpi] == 0) {
-				/*
-				 * XXX we lose this memory forever because
-				 * we do not keep track of the virtual address
-				 * that would be required to free this page.
-				 */
-				pd = malloc(PAGE_SIZE, M_VMM_MEM,
-					    M_WAITOK | M_ZERO);
-				if ((uintptr_t)pd & PAGE_MASK) {
-					panic("vmm_mem_populate: page directory"
-					      "page not aligned on %d "
-					      "boundary\n", PAGE_SIZE);
-				}
-				pdp[pdpi] = vtophys(pd);
-				pdp[pdpi] |= PG_RW | PG_V | PG_U;
-				if (0 && bootverbose) {
-					printf("Creating page directory "
-					       "at pdp index %d for 0x%016lx\n",
-					       pdpi, addr);
-				}
-			}
-			pdi = (addr % NBPDP) / NBPDR;
-			pd = (pd_entry_t *)PHYS_TO_DMAP(pdp[pdpi] & ~PAGE_MASK);
-
-			/*
-			 * Create a new mapping if one doesn't already exist
-			 * or validate it if it does.
-			 */
-			if (pd[pdi] == 0) {
-				pd[pdi] = addr | page_attr_bits;
-				if (0 && bootverbose) {
-					printf("vmm_mem_populate: mapping "
-					       "0x%lx with 2MB page at "
-					       "pdpi %d, pdi %d\n",
-					       addr, pdpi, pdi);
-				}
-			} else {
-				pd_entry_t pde = pd[pdi];
-				if ((pde & ~PAGE_MASK) != addr ||
-				    (pde & page_attr_bits) != page_attr_bits) {
-					panic("An invalid mapping 0x%016lx "
-					      "already exists for 0x%016lx\n",
-					      pde, addr);
-				}
-			}
-			addr += NBPDR;
-		}
-	}
-}
-
-static int
-vmm_mem_populate(void)
-{
-	int seg, error;
-	vm_paddr_t start, end;
-
-	/* populate the vmm_mem_avail[] array */
-	error = vmm_mem_steal_memory();
-	if (error)
-		return (error);
-	
-	/*
-	 * Now map the memory that was hidden from FreeBSD in
-	 * the direct map VA space.
-	 */
-	for (seg = 0; seg < vmm_mem_nsegs; seg++) {
-		start = vmm_mem_avail[seg].base;
-		end = start + vmm_mem_avail[seg].length;
-		if ((start & PDRMASK) != 0 || (end & PDRMASK) != 0) {
-			panic("start (0x%016lx) and end (0x%016lx) must be "
-			      "aligned on a %dMB boundary\n",
-			      start, end, NBPDR / MB);
-		}
-		vmm_mem_direct_map(start, end);
-	}
-
-	return (0);
+	pages_allocated += howmany;	/* XXX locking? */
 }
 
 int
 vmm_mem_init(void)
 {
-	int error;
-
-	mtx_init(&vmm_mem_mtx, "vmm_mem_mtx", NULL, MTX_DEF);
-
-	error = vmm_mem_populate();
-	if (error)
-		return (error);
 
 	return (0);
 }
@@ -315,122 +74,61 @@ vmm_mem_init(void)
 vm_paddr_t
 vmm_mem_alloc(size_t size)
 {
-	int i;
-	vm_paddr_t addr;
+	int flags;
+	vm_page_t m;
+	vm_paddr_t pa;
 
-	if ((size & PAGE_MASK) != 0) {
-		panic("vmm_mem_alloc: size 0x%0lx must be "
-		      "aligned on a 0x%0x boundary\n", size, PAGE_SIZE);
-	}
+	if (size != PAGE_SIZE)
+		panic("vmm_mem_alloc: invalid allocation size %lu", size);
 
-	addr = 0;
+	flags = VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED |
+		VM_ALLOC_ZERO;
 
-	mtx_lock(&vmm_mem_mtx);
-	for (i = 0; i < vmm_mem_nsegs; i++) {
-		if (vmm_mem_avail[i].length >= size) {
-			addr = vmm_mem_avail[i].base;
-			vmm_mem_avail[i].base += size;
-			vmm_mem_avail[i].length -= size;
-			/* remove a zero length segment */
-			if (vmm_mem_avail[i].length == 0) {
-				memmove(&vmm_mem_avail[i],
-					&vmm_mem_avail[i + 1],
-					(vmm_mem_nsegs - (i + 1)) *
-					 sizeof(vmm_mem_avail[0]));
-				vmm_mem_nsegs--;
-			}
+	while (1) {
+		/*
+		 * XXX need policy to determine when to back off the allocation
+		 */
+		m = vm_page_alloc(NULL, 0, flags);
+		if (m == NULL)
+			VM_WAIT;
+		else
 			break;
-		}
 	}
-	mtx_unlock(&vmm_mem_mtx);
-
-	return (addr);
-}
-
-size_t
-vmm_mem_get_mem_total(void)
-{
-	return vmm_mem_total_bytes;
-}
 
-size_t
-vmm_mem_get_mem_free(void)
-{
-	size_t length = 0;
-	int i;
+	pa = VM_PAGE_TO_PHYS(m);
+	
+	if ((m->flags & PG_ZERO) == 0)
+		pagezero((void *)PHYS_TO_DMAP(pa));
 
-	mtx_lock(&vmm_mem_mtx);
-	for (i = 0; i < vmm_mem_nsegs; i++) {
-		length += vmm_mem_avail[i].length;
-	}
-	mtx_unlock(&vmm_mem_mtx);
+	update_pages_allocated(1);
 
-	return(length);
+	return (pa);
 }
 
 void
 vmm_mem_free(vm_paddr_t base, size_t length)
 {
-	int i;
+	vm_page_t m;
 
-	if ((base & PAGE_MASK) != 0 || (length & PAGE_MASK) != 0) {
-		panic("vmm_mem_free: base 0x%0lx and length 0x%0lx must be "
-		      "aligned on a 0x%0x boundary\n", base, length, PAGE_SIZE);
+	if (base & PAGE_MASK) {
+		panic("vmm_mem_free: base 0x%0lx must be aligned on a "
+		      "0x%0x boundary\n", base, PAGE_SIZE);
 	}
 
-	mtx_lock(&vmm_mem_mtx);
+	if (length != PAGE_SIZE)
+		panic("vmm_mem_free: invalid length %lu", length);
 
-	for (i = 0; i < vmm_mem_nsegs; i++) {
-		if (vmm_mem_avail[i].base > base)
-			break;
-	}
-
-	if (vmm_mem_nsegs >= VMM_MEM_MAXSEGS)
-		panic("vmm_mem_free: cannot free any more segments");
+	m = PHYS_TO_VM_PAGE(base);
+	m->wire_count--;
+	vm_page_free(m);
+	atomic_subtract_int(&cnt.v_wire_count, 1);
 
-	/* Create a new segment at index 'i' */
-	memmove(&vmm_mem_avail[i + 1], &vmm_mem_avail[i],
-		(vmm_mem_nsegs - i) * sizeof(vmm_mem_avail[0]));
-
-	vmm_mem_avail[i].base = base;
-	vmm_mem_avail[i].length = length;
-
-	vmm_mem_nsegs++;
-
-coalesce_some_more:
-	for (i = 0; i < vmm_mem_nsegs - 1; i++) {
-		if (vmm_mem_avail[i].base + vmm_mem_avail[i].length ==
-		    vmm_mem_avail[i + 1].base) {
-			vmm_mem_avail[i].length += vmm_mem_avail[i + 1].length;
-			memmove(&vmm_mem_avail[i + 1], &vmm_mem_avail[i + 2],
-			  (vmm_mem_nsegs - (i + 2)) * sizeof(vmm_mem_avail[0]));
-			vmm_mem_nsegs--;
-			goto coalesce_some_more;
-		}
-	}
-
-	mtx_unlock(&vmm_mem_mtx);
+	update_pages_allocated(-1);
 }
 
 vm_paddr_t
 vmm_mem_maxaddr(void)
 {
 
-	return (maxaddr);
-}
-
-void
-vmm_mem_dump(void)
-{
-	int i;
-	vm_paddr_t base;
-	vm_size_t length;
-
-	mtx_lock(&vmm_mem_mtx);
-	for (i = 0; i < vmm_mem_nsegs; i++) {
-		base = vmm_mem_avail[i].base;
-		length = vmm_mem_avail[i].length;
-		printf("%-4d0x%016lx    0x%016lx\n", i, base, base + length);
-	}
-	mtx_unlock(&vmm_mem_mtx);
+	return (ptoa(Maxmem));
 }

Modified: projects/bhyve/sys/amd64/vmm/vmm_mem.h
==============================================================================
--- projects/bhyve/sys/amd64/vmm/vmm_mem.h	Mon Oct  8 23:02:35 2012	(r241361)
+++ projects/bhyve/sys/amd64/vmm/vmm_mem.h	Mon Oct  8 23:41:26 2012	(r241362)
@@ -33,9 +33,5 @@ int		vmm_mem_init(void);
 vm_paddr_t	vmm_mem_alloc(size_t size);
 void		vmm_mem_free(vm_paddr_t start, size_t size);
 vm_paddr_t	vmm_mem_maxaddr(void);
-void		vmm_mem_dump(void);
-
-size_t		vmm_mem_get_mem_total(void);
-size_t		vmm_mem_get_mem_free(void);
 
 #endif


More information about the svn-src-projects mailing list