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