vmm_mem.c revision 256072
11556Srgrimes/*- 21556Srgrimes * Copyright (c) 2011 NetApp, Inc. 31556Srgrimes * All rights reserved. 41556Srgrimes * 51556Srgrimes * Redistribution and use in source and binary forms, with or without 61556Srgrimes * modification, are permitted provided that the following conditions 71556Srgrimes * are met: 81556Srgrimes * 1. Redistributions of source code must retain the above copyright 91556Srgrimes * notice, this list of conditions and the following disclaimer. 101556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111556Srgrimes * notice, this list of conditions and the following disclaimer in the 121556Srgrimes * documentation and/or other materials provided with the distribution. 131556Srgrimes * 141556Srgrimes * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 151556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 181556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241556Srgrimes * SUCH DAMAGE. 251556Srgrimes * 261556Srgrimes * $FreeBSD: head/sys/amd64/vmm/vmm_mem.c 256072 2013-10-05 21:22:35Z neel $ 271556Srgrimes */ 281556Srgrimes 291556Srgrimes#include <sys/cdefs.h> 301556Srgrimes__FBSDID("$FreeBSD: head/sys/amd64/vmm/vmm_mem.c 256072 2013-10-05 21:22:35Z neel $"); 311556Srgrimes 321556Srgrimes#include <sys/param.h> 331556Srgrimes#include <sys/systm.h> 3436150Scharnier#include <sys/malloc.h> 3536150Scharnier#include <sys/sglist.h> 3636150Scharnier#include <sys/lock.h> 371556Srgrimes#include <sys/rwlock.h> 3899110Sobrien 3999110Sobrien#include <vm/vm.h> 401556Srgrimes#include <vm/vm_param.h> 4117987Speter#include <vm/pmap.h> 42149017Sstefanf#include <vm/vm_map.h> 4317987Speter#include <vm/vm_object.h> 441556Srgrimes#include <vm/vm_page.h> 451556Srgrimes#include <vm/vm_pager.h> 461556Srgrimes 471556Srgrimes#include <machine/md_var.h> 481556Srgrimes 491556Srgrimes#include "vmm_mem.h" 501556Srgrimes 511556Srgrimesint 521556Srgrimesvmm_mem_init(void) 531556Srgrimes{ 541556Srgrimes 551556Srgrimes return (0); 561556Srgrimes} 5717987Speter 5859436Scracauervm_object_t 5917987Spetervmm_mmio_alloc(struct vmspace *vmspace, vm_paddr_t gpa, size_t len, 601556Srgrimes vm_paddr_t hpa) 6117987Speter{ 621556Srgrimes int error; 631556Srgrimes vm_object_t obj; 641556Srgrimes struct sglist *sg; 651556Srgrimes 661556Srgrimes sg = sglist_alloc(1, M_WAITOK); 67142845Sobrien error = sglist_append_phys(sg, hpa, len); 68142845Sobrien KASSERT(error == 0, ("error %d appending physaddr to sglist", error)); 691556Srgrimes 701556Srgrimes obj = vm_pager_allocate(OBJT_SG, sg, len, VM_PROT_RW, 0, NULL); 7117987Speter if (obj != NULL) { 721556Srgrimes /* 731556Srgrimes * VT-x ignores the MTRR settings when figuring out the 741556Srgrimes * memory type for translations obtained through EPT. 751556Srgrimes * 761556Srgrimes * Therefore we explicitly force the pages provided by 771556Srgrimes * this object to be mapped as uncacheable. 781556Srgrimes */ 791556Srgrimes VM_OBJECT_WLOCK(obj); 801556Srgrimes error = vm_object_set_memattr(obj, VM_MEMATTR_UNCACHEABLE); 811556Srgrimes VM_OBJECT_WUNLOCK(obj); 821556Srgrimes if (error != KERN_SUCCESS) { 831556Srgrimes panic("vmm_mmio_alloc: vm_object_set_memattr error %d", 84117261Sdds error); 85117261Sdds } 86117261Sdds error = vm_map_find(&vmspace->vm_map, obj, 0, &gpa, len, 0, 87117261Sdds VMFS_NO_SPACE, VM_PROT_RW, VM_PROT_RW, 0); 881556Srgrimes if (error != KERN_SUCCESS) { 89117261Sdds vm_object_deallocate(obj); 901556Srgrimes obj = NULL; 91117261Sdds } 92117261Sdds } 93117261Sdds 94117261Sdds /* 95117261Sdds * Drop the reference on the sglist. 96179022Sstefanf * 971556Srgrimes * If the scatter/gather object was successfully allocated then it 9818018Speter * has incremented the reference count on the sglist. Dropping the 9918018Speter * initial reference count ensures that the sglist will be freed 1001556Srgrimes * when the object is deallocated. 1011556Srgrimes * 10290111Simp * If the object could not be allocated then we end up freeing the 10390111Simp * sglist. 10490111Simp */ 10590111Simp sglist_free(sg); 10690111Simp 10790111Simp return (obj); 10890111Simp} 10990111Simp 11090111Simpvoid 11190111Simpvmm_mmio_free(struct vmspace *vmspace, vm_paddr_t gpa, size_t len) 11290111Simp{ 11390111Simp 11490111Simp vm_map_remove(&vmspace->vm_map, gpa, gpa + len); 11590111Simp} 11690111Simp 11790111Simpvm_object_t 1181556Srgrimesvmm_mem_alloc(struct vmspace *vmspace, vm_paddr_t gpa, size_t len) 11917987Speter{ 1201556Srgrimes int error; 1211556Srgrimes vm_object_t obj; 1221556Srgrimes 1231556Srgrimes if (gpa & PAGE_MASK) 1241556Srgrimes panic("vmm_mem_alloc: invalid gpa %#lx", gpa); 1251556Srgrimes 12690111Simp if (len == 0 || (len & PAGE_MASK) != 0) 12717987Speter panic("vmm_mem_alloc: invalid allocation size %lu", len); 1281556Srgrimes 1291556Srgrimes obj = vm_object_allocate(OBJT_DEFAULT, len >> PAGE_SHIFT); 13060593Scracauer if (obj != NULL) { 1311556Srgrimes error = vm_map_find(&vmspace->vm_map, obj, 0, &gpa, len, 0, 1321556Srgrimes VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0); 1331556Srgrimes if (error != KERN_SUCCESS) { 1341556Srgrimes vm_object_deallocate(obj); 1351556Srgrimes obj = NULL; 1361556Srgrimes } 1371556Srgrimes } 1381556Srgrimes 1391556Srgrimes return (obj); 1401556Srgrimes} 1411556Srgrimes 1421556Srgrimesvoid 1431556Srgrimesvmm_mem_free(struct vmspace *vmspace, vm_paddr_t gpa, size_t len) 1441556Srgrimes{ 1451556Srgrimes 1461556Srgrimes vm_map_remove(&vmspace->vm_map, gpa, gpa + len); 1471556Srgrimes} 14890111Simp 14917987Spetervm_paddr_t 1501556Srgrimesvmm_mem_maxaddr(void) 15117987Speter{ 1521556Srgrimes 1531556Srgrimes return (ptoa(Maxmem)); 1541556Srgrimes} 1551556Srgrimes