177943Sdfr/*-
277943Sdfr * Copyright (c) 2011 NetApp, Inc.
377943Sdfr * All rights reserved.
477943Sdfr *
577943Sdfr * Redistribution and use in source and binary forms, with or without
677943Sdfr * modification, are permitted provided that the following conditions
7163898Smarcel * are met:
8163898Smarcel * 1. Redistributions of source code must retain the above copyright
9163898Smarcel *    notice, this list of conditions and the following disclaimer.
10163898Smarcel * 2. Redistributions in binary form must reproduce the above copyright
11163898Smarcel *    notice, this list of conditions and the following disclaimer in the
12163898Smarcel *    documentation and/or other materials provided with the distribution.
13163898Smarcel *
14163898Smarcel * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
1577943Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1677943Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1777943Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
1877943Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1977943Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2077943Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2177943Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2277943Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2377943Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2477943Sdfr * SUCH DAMAGE.
2577943Sdfr *
2677943Sdfr * $FreeBSD$
2777943Sdfr */
2877943Sdfr
2977943Sdfr#include <sys/cdefs.h>
30163898Smarcel__FBSDID("$FreeBSD$");
31163898Smarcel
32163898Smarcel#include <sys/param.h>
3377943Sdfr#include <sys/systm.h>
3477943Sdfr#include <sys/malloc.h>
35294981Ssmh#include <sys/sglist.h>
3677943Sdfr#include <sys/lock.h>
3777943Sdfr#include <sys/rwlock.h>
3877943Sdfr
39163898Smarcel#include <vm/vm.h>
4077943Sdfr#include <vm/vm_param.h>
41163898Smarcel#include <vm/pmap.h>
42163898Smarcel#include <vm/vm_map.h>
43163898Smarcel#include <vm/vm_object.h>
4477943Sdfr#include <vm/vm_page.h>
4577943Sdfr#include <vm/vm_pager.h>
4677943Sdfr
4777943Sdfr#include <machine/md_var.h>
4877943Sdfr
4977943Sdfr#include "vmm_mem.h"
5077943Sdfr
5177943Sdfrint
5277943Sdfrvmm_mem_init(void)
53163898Smarcel{
54163898Smarcel
55163898Smarcel	return (0);
5677943Sdfr}
5777943Sdfr
5877943Sdfrvm_object_t
5977943Sdfrvmm_mmio_alloc(struct vmspace *vmspace, vm_paddr_t gpa, size_t len,
6077943Sdfr	       vm_paddr_t hpa)
6177943Sdfr{
6277943Sdfr	int error;
6377943Sdfr	vm_object_t obj;
6477943Sdfr	struct sglist *sg;
6577943Sdfr
6677943Sdfr	sg = sglist_alloc(1, M_WAITOK);
6777943Sdfr	error = sglist_append_phys(sg, hpa, len);
6877943Sdfr	KASSERT(error == 0, ("error %d appending physaddr to sglist", error));
6977943Sdfr
7077943Sdfr	obj = vm_pager_allocate(OBJT_SG, sg, len, VM_PROT_RW, 0, NULL);
7177943Sdfr	if (obj != NULL) {
7277943Sdfr		/*
7377943Sdfr		 * VT-x ignores the MTRR settings when figuring out the
7477943Sdfr		 * memory type for translations obtained through EPT.
7577943Sdfr		 *
76163898Smarcel		 * Therefore we explicitly force the pages provided by
77163898Smarcel		 * this object to be mapped as uncacheable.
78163898Smarcel		 */
79163898Smarcel		VM_OBJECT_WLOCK(obj);
80163898Smarcel		error = vm_object_set_memattr(obj, VM_MEMATTR_UNCACHEABLE);
8177943Sdfr		VM_OBJECT_WUNLOCK(obj);
8277943Sdfr		if (error != KERN_SUCCESS) {
8377943Sdfr			panic("vmm_mmio_alloc: vm_object_set_memattr error %d",
84163898Smarcel				error);
8577943Sdfr		}
8677943Sdfr		error = vm_map_find(&vmspace->vm_map, obj, 0, &gpa, len, 0,
8777943Sdfr				    VMFS_NO_SPACE, VM_PROT_RW, VM_PROT_RW, 0);
8877943Sdfr		if (error != KERN_SUCCESS) {
8977943Sdfr			vm_object_deallocate(obj);
9077943Sdfr			obj = NULL;
9177943Sdfr		}
9277943Sdfr	}
9377943Sdfr
9477943Sdfr	/*
9577943Sdfr	 * Drop the reference on the sglist.
9677943Sdfr	 *
9777943Sdfr	 * If the scatter/gather object was successfully allocated then it
9877943Sdfr	 * has incremented the reference count on the sglist. Dropping the
9977943Sdfr	 * initial reference count ensures that the sglist will be freed
10077943Sdfr	 * when the object is deallocated.
10177943Sdfr	 *
10277943Sdfr	 * If the object could not be allocated then we end up freeing the
10377943Sdfr	 * sglist.
10477943Sdfr	 */
10577943Sdfr	sglist_free(sg);
10677943Sdfr
10777943Sdfr	return (obj);
108163898Smarcel}
109163898Smarcel
110163898Smarcelvoid
11177943Sdfrvmm_mmio_free(struct vmspace *vmspace, vm_paddr_t gpa, size_t len)
11277943Sdfr{
11377943Sdfr
11477943Sdfr	vm_map_remove(&vmspace->vm_map, gpa, gpa + len);
11577943Sdfr}
11677943Sdfr
11777943Sdfrvm_paddr_t
11877943Sdfrvmm_mem_maxaddr(void)
11977943Sdfr{
12077943Sdfr
12177943Sdfr	return (ptoa(Maxmem));
12277943Sdfr}
12377943Sdfr