2 * Copyright (c) 2012 Marcel Moolenaar
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
31 #include <sys/systm.h>
33 #include <machine/md_var.h>
34 #include <machine/vmparam.h>
36 static u_int phys_avail_segs;
38 vm_paddr_t phys_avail[2 * VM_PHYSSEG_MAX + 2];
45 ia64_physmem_find(vm_paddr_t base, vm_paddr_t lim)
49 for (idx = 0; phys_avail[idx + 1] != 0; idx += 2) {
50 if (phys_avail[idx] >= lim ||
51 phys_avail[idx + 1] > base)
58 ia64_physmem_insert(u_int idx, vm_paddr_t base, vm_paddr_t lim)
62 if (phys_avail_segs == VM_PHYSSEG_MAX)
65 ridx = phys_avail_segs * 2;
67 phys_avail[ridx + 1] = phys_avail[ridx - 1];
68 phys_avail[ridx] = phys_avail[ridx - 2];
71 phys_avail[idx] = base;
72 phys_avail[idx + 1] = lim;
78 ia64_physmem_remove(u_int idx)
81 if (phys_avail_segs == 0)
84 phys_avail[idx] = phys_avail[idx + 2];
85 phys_avail[idx + 1] = phys_avail[idx + 3];
87 } while (phys_avail[idx + 1] != 0);
93 ia64_physmem_add(vm_paddr_t base, vm_size_t len)
101 idx = ia64_physmem_find(base, lim);
102 if (phys_avail[idx] == lim) {
103 phys_avail[idx] = base;
106 if (idx > 0 && phys_avail[idx - 1] == base) {
107 phys_avail[idx - 1] = lim;
110 return (ia64_physmem_insert(idx, base, lim));
114 ia64_physmem_delete(vm_paddr_t base, vm_size_t len)
120 idx = ia64_physmem_find(base, lim);
121 if (phys_avail[idx] >= lim || phys_avail[idx + 1] == 0)
123 if (phys_avail[idx] < base && phys_avail[idx + 1] > lim) {
124 len = phys_avail[idx + 1] - lim;
125 phys_avail[idx + 1] = base;
128 return (ia64_physmem_insert(idx + 2, base, lim));
130 if (phys_avail[idx] == base)
131 phys_avail[idx] = lim;
132 if (phys_avail[idx + 1] == lim)
133 phys_avail[idx + 1] = base;
134 if (phys_avail[idx] >= phys_avail[idx + 1])
135 return (ia64_physmem_remove(idx));
141 ia64_physmem_fini(void)
143 vm_paddr_t base, lim, size;
147 while (phys_avail[idx + 1] != 0) {
148 base = round_page(phys_avail[idx]);
149 lim = trunc_page(phys_avail[idx + 1]);
151 phys_avail[idx] = base;
152 phys_avail[idx + 1] = lim;
154 physmem += atop(size);
158 ia64_physmem_remove(idx);
162 * Round realmem to a multple of 128MB. Hopefully that compensates
163 * for any loss of DRAM that isn't accounted for in the memory map.
164 * I'm thinking legacy BIOS or VGA here. In any case, it's ok if
165 * we got it wrong, because we don't actually use realmem. It's
169 realmem = (realmem + size - 1) & ~(size - 1);
170 realmem = atop(realmem);
175 ia64_physmem_init(void)
178 /* Nothing to do just yet. */
183 ia64_physmem_track(vm_paddr_t base, vm_size_t len)
191 ia64_physmem_alloc(vm_size_t len, vm_size_t align)
193 vm_paddr_t base, lim, pa;
197 if (phys_avail_segs == 0)
200 len = round_page(len);
203 * Try and allocate with least effort.
205 idx = phys_avail_segs * 2;
208 base = phys_avail[idx];
209 lim = phys_avail[idx + 1];
211 if (lim - base < len)
214 /* First try from the end. */
216 if ((pa & (align - 1)) == 0) {
218 ia64_physmem_remove(idx);
220 phys_avail[idx + 1] = pa;
224 /* Try from the start next. */
226 if ((pa & (align - 1)) == 0) {
228 ia64_physmem_remove(idx);
230 phys_avail[idx] += len;
236 * Find a good segment and split it up.
238 idx = phys_avail_segs * 2;
241 base = phys_avail[idx];
242 lim = phys_avail[idx + 1];
244 pa = (base + align - 1) & ~(align - 1);
245 if (pa + len <= lim) {
246 ia64_physmem_delete(pa, len);
255 ptr = (void *)IA64_PHYS_TO_RR7(pa);