diff options
Diffstat (limited to 'sys/amd64')
-rw-r--r-- | sys/amd64/vmm/amd/amdv.c | 17 | ||||
-rw-r--r-- | sys/amd64/vmm/intel/vtd.c | 50 | ||||
-rw-r--r-- | sys/amd64/vmm/io/iommu.c | 51 | ||||
-rw-r--r-- | sys/amd64/vmm/io/iommu.h | 8 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm.c | 33 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm_dev.c | 18 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm_mem.c | 386 | ||||
-rw-r--r-- | sys/amd64/vmm/vmm_mem.h | 4 |
8 files changed, 193 insertions, 374 deletions
diff --git a/sys/amd64/vmm/amd/amdv.c b/sys/amd64/vmm/amd/amdv.c index b50f972..020743f 100644 --- a/sys/amd64/vmm/amd/amdv.c +++ b/sys/amd64/vmm/amd/amdv.c @@ -230,6 +230,14 @@ amd_iommu_create_mapping(void *domain, vm_paddr_t gpa, vm_paddr_t hpa, 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, int bus, int slot, int func) 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, }; diff --git a/sys/amd64/vmm/intel/vtd.c b/sys/amd64/vmm/intel/vtd.c index 24495a9..ef0e9bc 100644 --- a/sys/amd64/vmm/intel/vtd.c +++ b/sys/amd64/vmm/intel/vtd.c @@ -444,8 +444,12 @@ vtd_remove_device(void *arg, int bus, int slot, int func) } } +#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 gpa, vm_paddr_t hpa, uint64_t len) 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, }; diff --git a/sys/amd64/vmm/io/iommu.c b/sys/amd64/vmm/io/iommu.c index baf2447..c8447cc 100644 --- a/sys/amd64/vmm/io/iommu.c +++ b/sys/amd64/vmm/io/iommu.c @@ -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_paddr_t gpa, vm_paddr_t hpa, uint64_t len) 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 bus, int slot, int func) } 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_t gpa, vm_paddr_t hpa, size_t len) } 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, int slot, int func) IOMMU_REMOVE_DEVICE(dom, bus, slot, func); } + +void +iommu_invalidate_tlb(void *domain) +{ + + IOMMU_INVALIDATE_TLB(domain); +} diff --git a/sys/amd64/vmm/io/iommu.h b/sys/amd64/vmm/io/iommu.h index e4f7229..d5c1d6e 100644 --- a/sys/amd64/vmm/io/iommu.h +++ b/sys/amd64/vmm/io/iommu.h @@ -37,8 +37,11 @@ typedef void *(*iommu_create_domain_t)(vm_paddr_t maxaddr); 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 diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c index 7bd3f7f..bcd322a 100644 --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -280,6 +280,9 @@ vm_free_mem_seg(struct vm *vm, struct vm_memory_segment *seg) { 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_memory_segment *seg) "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, size_t len) 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, size_t len) 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, size_t len) 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); diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c index 91edbe8..66f5184 100644 --- a/sys/amd64/vmm/vmm_dev.c +++ b/sys/amd64/vmm/vmm_dev.c @@ -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) { diff --git a/sys/amd64/vmm/vmm_mem.c b/sys/amd64/vmm/vmm_mem.c index eb05b9d..8745339 100644 --- a/sys/amd64/vmm/vmm_mem.c +++ b/sys/amd64/vmm/vmm_mem.c @@ -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); - - 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"); - - /* 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; + if (length != PAGE_SIZE) + panic("vmm_mem_free: invalid length %lu", length); - vmm_mem_nsegs++; + m = PHYS_TO_VM_PAGE(base); + m->wire_count--; + vm_page_free(m); + atomic_subtract_int(&cnt.v_wire_count, 1); -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)); } diff --git a/sys/amd64/vmm/vmm_mem.h b/sys/amd64/vmm/vmm_mem.h index a83e9be..7d45c74 100644 --- a/sys/amd64/vmm/vmm_mem.h +++ b/sys/amd64/vmm/vmm_mem.h @@ -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 |