vmm_mem.c revision 241362
1221828Sgrehan/*-
2221828Sgrehan * Copyright (c) 2011 NetApp, Inc.
3221828Sgrehan * All rights reserved.
4221828Sgrehan *
5221828Sgrehan * Redistribution and use in source and binary forms, with or without
6221828Sgrehan * modification, are permitted provided that the following conditions
7221828Sgrehan * are met:
8221828Sgrehan * 1. Redistributions of source code must retain the above copyright
9221828Sgrehan *    notice, this list of conditions and the following disclaimer.
10221828Sgrehan * 2. Redistributions in binary form must reproduce the above copyright
11221828Sgrehan *    notice, this list of conditions and the following disclaimer in the
12221828Sgrehan *    documentation and/or other materials provided with the distribution.
13221828Sgrehan *
14221828Sgrehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
15221828Sgrehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16221828Sgrehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17221828Sgrehan * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
18221828Sgrehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19221828Sgrehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20221828Sgrehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21221828Sgrehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22221828Sgrehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23221828Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24221828Sgrehan * SUCH DAMAGE.
25221828Sgrehan *
26221828Sgrehan * $FreeBSD$
27221828Sgrehan */
28221828Sgrehan
29221828Sgrehan#include <sys/cdefs.h>
30221828Sgrehan__FBSDID("$FreeBSD$");
31221828Sgrehan
32221828Sgrehan#include <sys/param.h>
33221828Sgrehan#include <sys/lock.h>
34221828Sgrehan#include <sys/mutex.h>
35221828Sgrehan#include <sys/linker.h>
36221828Sgrehan#include <sys/systm.h>
37221828Sgrehan#include <sys/malloc.h>
38221828Sgrehan#include <sys/kernel.h>
39241362Sneel#include <sys/sysctl.h>
40221828Sgrehan
41221828Sgrehan#include <vm/vm.h>
42221828Sgrehan#include <vm/pmap.h>
43241362Sneel#include <vm/vm_page.h>
44241362Sneel#include <vm/vm_pageout.h>
45221828Sgrehan
46221828Sgrehan#include <machine/md_var.h>
47221828Sgrehan#include <machine/metadata.h>
48221828Sgrehan#include <machine/pc/bios.h>
49221828Sgrehan#include <machine/vmparam.h>
50221828Sgrehan#include <machine/pmap.h>
51221828Sgrehan
52221828Sgrehan#include "vmm_util.h"
53221828Sgrehan#include "vmm_mem.h"
54221828Sgrehan
55241362SneelSYSCTL_DECL(_hw_vmm);
56221828Sgrehan
57241362Sneelstatic u_long pages_allocated;
58241362SneelSYSCTL_ULONG(_hw_vmm, OID_AUTO, pages_allocated, CTLFLAG_RD,
59241362Sneel	     &pages_allocated, 0, "4KB pages allocated");
60221828Sgrehan
61221828Sgrehanstatic void
62241362Sneelupdate_pages_allocated(int howmany)
63221828Sgrehan{
64241362Sneel	pages_allocated += howmany;	/* XXX locking? */
65221828Sgrehan}
66221828Sgrehan
67221828Sgrehanint
68221828Sgrehanvmm_mem_init(void)
69221828Sgrehan{
70221828Sgrehan
71221828Sgrehan	return (0);
72221828Sgrehan}
73221828Sgrehan
74221828Sgrehanvm_paddr_t
75221828Sgrehanvmm_mem_alloc(size_t size)
76221828Sgrehan{
77241362Sneel	int flags;
78241362Sneel	vm_page_t m;
79241362Sneel	vm_paddr_t pa;
80221828Sgrehan
81241362Sneel	if (size != PAGE_SIZE)
82241362Sneel		panic("vmm_mem_alloc: invalid allocation size %lu", size);
83221828Sgrehan
84241362Sneel	flags = VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED |
85241362Sneel		VM_ALLOC_ZERO;
86221828Sgrehan
87241362Sneel	while (1) {
88241362Sneel		/*
89241362Sneel		 * XXX need policy to determine when to back off the allocation
90241362Sneel		 */
91241362Sneel		m = vm_page_alloc(NULL, 0, flags);
92241362Sneel		if (m == NULL)
93241362Sneel			VM_WAIT;
94241362Sneel		else
95221828Sgrehan			break;
96221828Sgrehan	}
97221828Sgrehan
98241362Sneel	pa = VM_PAGE_TO_PHYS(m);
99241362Sneel
100241362Sneel	if ((m->flags & PG_ZERO) == 0)
101241362Sneel		pagezero((void *)PHYS_TO_DMAP(pa));
102221828Sgrehan
103241362Sneel	update_pages_allocated(1);
104239700Sgrehan
105241362Sneel	return (pa);
106239700Sgrehan}
107239700Sgrehan
108221828Sgrehanvoid
109221828Sgrehanvmm_mem_free(vm_paddr_t base, size_t length)
110221828Sgrehan{
111241362Sneel	vm_page_t m;
112221828Sgrehan
113241362Sneel	if (base & PAGE_MASK) {
114241362Sneel		panic("vmm_mem_free: base 0x%0lx must be aligned on a "
115241362Sneel		      "0x%0x boundary\n", base, PAGE_SIZE);
116221828Sgrehan	}
117221828Sgrehan
118241362Sneel	if (length != PAGE_SIZE)
119241362Sneel		panic("vmm_mem_free: invalid length %lu", length);
120221828Sgrehan
121241362Sneel	m = PHYS_TO_VM_PAGE(base);
122241362Sneel	m->wire_count--;
123241362Sneel	vm_page_free(m);
124241362Sneel	atomic_subtract_int(&cnt.v_wire_count, 1);
125221828Sgrehan
126241362Sneel	update_pages_allocated(-1);
127221828Sgrehan}
128221828Sgrehan
129221828Sgrehanvm_paddr_t
130221828Sgrehanvmm_mem_maxaddr(void)
131221828Sgrehan{
132221828Sgrehan
133241362Sneel	return (ptoa(Maxmem));
134221828Sgrehan}
135