Sun Sep 16 22:09:34 2012 UTC ()
Rename kcpuset_copybits() to kcpuset_export_u32() and thus be more specific
about the interface.


(rmind)
diff -r1.83 -r1.84 src/sys/arch/arm/arm32/arm32_machdep.c
diff -r1.2 -r1.3 src/sys/arch/arm/cortex/gic.c
diff -r1.48 -r1.49 src/sys/arch/xen/x86/x86_xpmap.c
diff -r1.7 -r1.8 src/sys/kern/subr_kcpuset.c
diff -r1.7 -r1.8 src/sys/sys/kcpuset.h

cvs diff -r1.83 -r1.84 src/sys/arch/arm/arm32/arm32_machdep.c (switch to unified diff)

--- src/sys/arch/arm/arm32/arm32_machdep.c 2012/08/31 23:59:51 1.83
+++ src/sys/arch/arm/arm32/arm32_machdep.c 2012/09/16 22:09:33 1.84
@@ -1,563 +1,563 @@ @@ -1,563 +1,563 @@
1/* $NetBSD: arm32_machdep.c,v 1.83 2012/08/31 23:59:51 matt Exp $ */ 1/* $NetBSD: arm32_machdep.c,v 1.84 2012/09/16 22:09:33 rmind Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1994-1998 Mark Brinicombe. 4 * Copyright (c) 1994-1998 Mark Brinicombe.
5 * Copyright (c) 1994 Brini. 5 * Copyright (c) 1994 Brini.
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * This code is derived from software written for Brini by Mark Brinicombe 8 * This code is derived from software written for Brini by Mark Brinicombe
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software 18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement: 19 * must display the following acknowledgement:
20 * This product includes software developed by Mark Brinicombe 20 * This product includes software developed by Mark Brinicombe
21 * for the NetBSD Project. 21 * for the NetBSD Project.
22 * 4. The name of the company nor the name of the author may be used to 22 * 4. The name of the company nor the name of the author may be used to
23 * endorse or promote products derived from this software without specific 23 * endorse or promote products derived from this software without specific
24 * prior written permission. 24 * prior written permission.
25 * 25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 27 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 29 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 30 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE. 36 * SUCH DAMAGE.
37 * 37 *
38 * Machine dependent functions for kernel setup 38 * Machine dependent functions for kernel setup
39 * 39 *
40 * Created : 17/09/94 40 * Created : 17/09/94
41 * Updated : 18/04/01 updated for new wscons 41 * Updated : 18/04/01 updated for new wscons
42 */ 42 */
43 43
44#include <sys/cdefs.h> 44#include <sys/cdefs.h>
45__KERNEL_RCSID(0, "$NetBSD: arm32_machdep.c,v 1.83 2012/08/31 23:59:51 matt Exp $"); 45__KERNEL_RCSID(0, "$NetBSD: arm32_machdep.c,v 1.84 2012/09/16 22:09:33 rmind Exp $");
46 46
47#include "opt_modular.h" 47#include "opt_modular.h"
48#include "opt_md.h" 48#include "opt_md.h"
49#include "opt_pmap_debug.h" 49#include "opt_pmap_debug.h"
50 50
51#include <sys/param.h> 51#include <sys/param.h>
52#include <sys/systm.h> 52#include <sys/systm.h>
53#include <sys/reboot.h> 53#include <sys/reboot.h>
54#include <sys/proc.h> 54#include <sys/proc.h>
55#include <sys/kauth.h> 55#include <sys/kauth.h>
56#include <sys/kernel.h> 56#include <sys/kernel.h>
57#include <sys/mbuf.h> 57#include <sys/mbuf.h>
58#include <sys/mount.h> 58#include <sys/mount.h>
59#include <sys/buf.h> 59#include <sys/buf.h>
60#include <sys/msgbuf.h> 60#include <sys/msgbuf.h>
61#include <sys/device.h> 61#include <sys/device.h>
62#include <sys/sysctl.h> 62#include <sys/sysctl.h>
63#include <sys/cpu.h> 63#include <sys/cpu.h>
64#include <sys/intr.h> 64#include <sys/intr.h>
65#include <sys/module.h> 65#include <sys/module.h>
66#include <sys/atomic.h> 66#include <sys/atomic.h>
67#include <sys/xcall.h> 67#include <sys/xcall.h>
68 68
69#include <uvm/uvm_extern.h> 69#include <uvm/uvm_extern.h>
70 70
71#include <dev/cons.h> 71#include <dev/cons.h>
72#include <dev/mm.h> 72#include <dev/mm.h>
73 73
74#include <arm/arm32/katelib.h> 74#include <arm/arm32/katelib.h>
75#include <arm/arm32/machdep.h> 75#include <arm/arm32/machdep.h>
76 76
77#include <machine/bootconfig.h> 77#include <machine/bootconfig.h>
78#include <machine/pcb.h> 78#include <machine/pcb.h>
79 79
80void (*cpu_reset_address)(void); /* Used by locore */ 80void (*cpu_reset_address)(void); /* Used by locore */
81paddr_t cpu_reset_address_paddr; /* Used by locore */ 81paddr_t cpu_reset_address_paddr; /* Used by locore */
82 82
83struct vm_map *phys_map = NULL; 83struct vm_map *phys_map = NULL;
84 84
85#if defined(MEMORY_DISK_HOOKS) && !defined(MEMORY_DISK_ROOT_SIZE) 85#if defined(MEMORY_DISK_HOOKS) && !defined(MEMORY_DISK_ROOT_SIZE)
86extern size_t md_root_size; /* Memory disc size */ 86extern size_t md_root_size; /* Memory disc size */
87#endif /* MEMORY_DISK_HOOKS && !MEMORY_DISK_ROOT_SIZE */ 87#endif /* MEMORY_DISK_HOOKS && !MEMORY_DISK_ROOT_SIZE */
88 88
89pv_addr_t kernelstack; 89pv_addr_t kernelstack;
90pv_addr_t abtstack; 90pv_addr_t abtstack;
91pv_addr_t fiqstack; 91pv_addr_t fiqstack;
92pv_addr_t irqstack; 92pv_addr_t irqstack;
93pv_addr_t undstack; 93pv_addr_t undstack;
94pv_addr_t idlestack; 94pv_addr_t idlestack;
95 95
96void * msgbufaddr; 96void * msgbufaddr;
97extern paddr_t msgbufphys; 97extern paddr_t msgbufphys;
98 98
99int kernel_debug = 0; 99int kernel_debug = 0;
100 100
101/* exported variable to be filled in by the bootloaders */ 101/* exported variable to be filled in by the bootloaders */
102char *booted_kernel; 102char *booted_kernel;
103 103
104/* Prototypes */ 104/* Prototypes */
105 105
106void data_abort_handler(trapframe_t *frame); 106void data_abort_handler(trapframe_t *frame);
107void prefetch_abort_handler(trapframe_t *frame); 107void prefetch_abort_handler(trapframe_t *frame);
108extern void configure(void); 108extern void configure(void);
109 109
110/* 110/*
111 * arm32_vector_init: 111 * arm32_vector_init:
112 * 112 *
113 * Initialize the vector page, and select whether or not to 113 * Initialize the vector page, and select whether or not to
114 * relocate the vectors. 114 * relocate the vectors.
115 * 115 *
116 * NOTE: We expect the vector page to be mapped at its expected 116 * NOTE: We expect the vector page to be mapped at its expected
117 * destination. 117 * destination.
118 */ 118 */
119void 119void
120arm32_vector_init(vaddr_t va, int which) 120arm32_vector_init(vaddr_t va, int which)
121{ 121{
122 if (CPU_IS_PRIMARY(curcpu())) { 122 if (CPU_IS_PRIMARY(curcpu())) {
123 extern unsigned int page0[], page0_data[]; 123 extern unsigned int page0[], page0_data[];
124 unsigned int *vectors = (int *) va; 124 unsigned int *vectors = (int *) va;
125 unsigned int *vectors_data = vectors + (page0_data - page0); 125 unsigned int *vectors_data = vectors + (page0_data - page0);
126 int vec; 126 int vec;
127 127
128 /* 128 /*
129 * Loop through the vectors we're taking over, and copy the 129 * Loop through the vectors we're taking over, and copy the
130 * vector's insn and data word. 130 * vector's insn and data word.
131 */ 131 */
132 for (vec = 0; vec < ARM_NVEC; vec++) { 132 for (vec = 0; vec < ARM_NVEC; vec++) {
133 if ((which & (1 << vec)) == 0) { 133 if ((which & (1 << vec)) == 0) {
134 /* Don't want to take over this vector. */ 134 /* Don't want to take over this vector. */
135 continue; 135 continue;
136 } 136 }
137 vectors[vec] = page0[vec]; 137 vectors[vec] = page0[vec];
138 vectors_data[vec] = page0_data[vec]; 138 vectors_data[vec] = page0_data[vec];
139 } 139 }
140 140
141 /* Now sync the vectors. */ 141 /* Now sync the vectors. */
142 cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int)); 142 cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int));
143 143
144 vector_page = va; 144 vector_page = va;
145 } 145 }
146 146
147 if (va == ARM_VECTORS_HIGH) { 147 if (va == ARM_VECTORS_HIGH) {
148 /* 148 /*
149 * Assume the MD caller knows what it's doing here, and 149 * Assume the MD caller knows what it's doing here, and
150 * really does want the vector page relocated. 150 * really does want the vector page relocated.
151 * 151 *
152 * Note: This has to be done here (and not just in 152 * Note: This has to be done here (and not just in
153 * cpu_setup()) because the vector page needs to be 153 * cpu_setup()) because the vector page needs to be
154 * accessible *before* cpu_startup() is called. 154 * accessible *before* cpu_startup() is called.
155 * Think ddb(9) ... 155 * Think ddb(9) ...
156 * 156 *
157 * NOTE: If the CPU control register is not readable, 157 * NOTE: If the CPU control register is not readable,
158 * this will totally fail! We'll just assume that 158 * this will totally fail! We'll just assume that
159 * any system that has high vector support has a 159 * any system that has high vector support has a
160 * readable CPU control register, for now. If we 160 * readable CPU control register, for now. If we
161 * ever encounter one that does not, we'll have to 161 * ever encounter one that does not, we'll have to
162 * rethink this. 162 * rethink this.
163 */ 163 */
164 cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC); 164 cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC);
165 } 165 }
166} 166}
167 167
168/* 168/*
169 * Debug function just to park the CPU 169 * Debug function just to park the CPU
170 */ 170 */
171 171
172void 172void
173halt(void) 173halt(void)
174{ 174{
175 while (1) 175 while (1)
176 cpu_sleep(0); 176 cpu_sleep(0);
177} 177}
178 178
179 179
180/* Sync the discs and unmount the filesystems */ 180/* Sync the discs and unmount the filesystems */
181 181
182void 182void
183bootsync(void) 183bootsync(void)
184{ 184{
185 static bool bootsyncdone = false; 185 static bool bootsyncdone = false;
186 186
187 if (bootsyncdone) return; 187 if (bootsyncdone) return;
188 188
189 bootsyncdone = true; 189 bootsyncdone = true;
190 190
191 /* Make sure we can still manage to do things */ 191 /* Make sure we can still manage to do things */
192 if (GetCPSR() & I32_bit) { 192 if (GetCPSR() & I32_bit) {
193 /* 193 /*
194 * If we get here then boot has been called without RB_NOSYNC 194 * If we get here then boot has been called without RB_NOSYNC
195 * and interrupts were disabled. This means the boot() call 195 * and interrupts were disabled. This means the boot() call
196 * did not come from a user process e.g. shutdown, but must 196 * did not come from a user process e.g. shutdown, but must
197 * have come from somewhere in the kernel. 197 * have come from somewhere in the kernel.
198 */ 198 */
199 IRQenable; 199 IRQenable;
200 printf("Warning IRQ's disabled during boot()\n"); 200 printf("Warning IRQ's disabled during boot()\n");
201 } 201 }
202 202
203 vfs_shutdown(); 203 vfs_shutdown();
204} 204}
205 205
206/* 206/*
207 * void cpu_startup(void) 207 * void cpu_startup(void)
208 * 208 *
209 * Machine dependent startup code.  209 * Machine dependent startup code.
210 * 210 *
211 */ 211 */
212void 212void
213cpu_startup(void) 213cpu_startup(void)
214{ 214{
215 vaddr_t minaddr; 215 vaddr_t minaddr;
216 vaddr_t maxaddr; 216 vaddr_t maxaddr;
217 u_int loop; 217 u_int loop;
218 char pbuf[9]; 218 char pbuf[9];
219 219
220 /* 220 /*
221 * Until we better locking, we have to live under the kernel lock. 221 * Until we better locking, we have to live under the kernel lock.
222 */ 222 */
223 //KERNEL_LOCK(1, NULL); 223 //KERNEL_LOCK(1, NULL);
224 224
225 /* Set the CPU control register */ 225 /* Set the CPU control register */
226 cpu_setup(boot_args); 226 cpu_setup(boot_args);
227 227
228 /* Lock down zero page */ 228 /* Lock down zero page */
229 vector_page_setprot(VM_PROT_READ); 229 vector_page_setprot(VM_PROT_READ);
230 230
231 /* 231 /*
232 * Give pmap a chance to set up a few more things now the vm 232 * Give pmap a chance to set up a few more things now the vm
233 * is initialised 233 * is initialised
234 */ 234 */
235 pmap_postinit(); 235 pmap_postinit();
236 236
237 /* 237 /*
238 * Initialize error message buffer (at end of core). 238 * Initialize error message buffer (at end of core).
239 */ 239 */
240 240
241 /* msgbufphys was setup during the secondary boot strap */ 241 /* msgbufphys was setup during the secondary boot strap */
242 for (loop = 0; loop < btoc(MSGBUFSIZE); ++loop) 242 for (loop = 0; loop < btoc(MSGBUFSIZE); ++loop)
243 pmap_kenter_pa((vaddr_t)msgbufaddr + loop * PAGE_SIZE, 243 pmap_kenter_pa((vaddr_t)msgbufaddr + loop * PAGE_SIZE,
244 msgbufphys + loop * PAGE_SIZE, 244 msgbufphys + loop * PAGE_SIZE,
245 VM_PROT_READ|VM_PROT_WRITE, 0); 245 VM_PROT_READ|VM_PROT_WRITE, 0);
246 pmap_update(pmap_kernel()); 246 pmap_update(pmap_kernel());
247 initmsgbuf(msgbufaddr, round_page(MSGBUFSIZE)); 247 initmsgbuf(msgbufaddr, round_page(MSGBUFSIZE));
248 248
249 /* 249 /*
250 * Identify ourselves for the msgbuf (everything printed earlier will 250 * Identify ourselves for the msgbuf (everything printed earlier will
251 * not be buffered). 251 * not be buffered).
252 */ 252 */
253 printf("%s%s", copyright, version); 253 printf("%s%s", copyright, version);
254 254
255 format_bytes(pbuf, sizeof(pbuf), arm_ptob(physmem)); 255 format_bytes(pbuf, sizeof(pbuf), arm_ptob(physmem));
256 printf("total memory = %s\n", pbuf); 256 printf("total memory = %s\n", pbuf);
257 257
258 minaddr = 0; 258 minaddr = 0;
259 259
260 /* 260 /*
261 * Allocate a submap for physio 261 * Allocate a submap for physio
262 */ 262 */
263 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 263 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
264 VM_PHYS_SIZE, 0, false, NULL); 264 VM_PHYS_SIZE, 0, false, NULL);
265 265
266 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 266 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free));
267 printf("avail memory = %s\n", pbuf); 267 printf("avail memory = %s\n", pbuf);
268 268
269 struct lwp * const l = &lwp0; 269 struct lwp * const l = &lwp0;
270 struct pcb * const pcb = lwp_getpcb(l); 270 struct pcb * const pcb = lwp_getpcb(l);
271 pcb->pcb_sp = uvm_lwp_getuarea(l) + USPACE_SVC_STACK_TOP; 271 pcb->pcb_sp = uvm_lwp_getuarea(l) + USPACE_SVC_STACK_TOP;
272 lwp_settrapframe(l, (struct trapframe *)pcb->pcb_sp - 1); 272 lwp_settrapframe(l, (struct trapframe *)pcb->pcb_sp - 1);
273} 273}
274 274
275/* 275/*
276 * machine dependent system variables. 276 * machine dependent system variables.
277 */ 277 */
278static int 278static int
279sysctl_machdep_booted_device(SYSCTLFN_ARGS) 279sysctl_machdep_booted_device(SYSCTLFN_ARGS)
280{ 280{
281 struct sysctlnode node; 281 struct sysctlnode node;
282 282
283 if (booted_device == NULL) 283 if (booted_device == NULL)
284 return (EOPNOTSUPP); 284 return (EOPNOTSUPP);
285 285
286 node = *rnode; 286 node = *rnode;
287 node.sysctl_data = booted_device->dv_xname; 287 node.sysctl_data = booted_device->dv_xname;
288 node.sysctl_size = strlen(booted_device->dv_xname) + 1; 288 node.sysctl_size = strlen(booted_device->dv_xname) + 1;
289 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 289 return (sysctl_lookup(SYSCTLFN_CALL(&node)));
290} 290}
291 291
292static int 292static int
293sysctl_machdep_booted_kernel(SYSCTLFN_ARGS) 293sysctl_machdep_booted_kernel(SYSCTLFN_ARGS)
294{ 294{
295 struct sysctlnode node; 295 struct sysctlnode node;
296 296
297 if (booted_kernel == NULL || booted_kernel[0] == '\0') 297 if (booted_kernel == NULL || booted_kernel[0] == '\0')
298 return (EOPNOTSUPP); 298 return (EOPNOTSUPP);
299 299
300 node = *rnode; 300 node = *rnode;
301 node.sysctl_data = booted_kernel; 301 node.sysctl_data = booted_kernel;
302 node.sysctl_size = strlen(booted_kernel) + 1; 302 node.sysctl_size = strlen(booted_kernel) + 1;
303 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 303 return (sysctl_lookup(SYSCTLFN_CALL(&node)));
304} 304}
305 305
306static int 306static int
307sysctl_machdep_powersave(SYSCTLFN_ARGS) 307sysctl_machdep_powersave(SYSCTLFN_ARGS)
308{ 308{
309 struct sysctlnode node = *rnode; 309 struct sysctlnode node = *rnode;
310 int error, newval; 310 int error, newval;
311 311
312 newval = cpu_do_powersave; 312 newval = cpu_do_powersave;
313 node.sysctl_data = &newval; 313 node.sysctl_data = &newval;
314 if (cpufuncs.cf_sleep == (void *) cpufunc_nullop) 314 if (cpufuncs.cf_sleep == (void *) cpufunc_nullop)
315 node.sysctl_flags &= ~CTLFLAG_READWRITE; 315 node.sysctl_flags &= ~CTLFLAG_READWRITE;
316 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 316 error = sysctl_lookup(SYSCTLFN_CALL(&node));
317 if (error || newp == NULL || newval == cpu_do_powersave) 317 if (error || newp == NULL || newval == cpu_do_powersave)
318 return (error); 318 return (error);
319 319
320 if (newval < 0 || newval > 1) 320 if (newval < 0 || newval > 1)
321 return (EINVAL); 321 return (EINVAL);
322 cpu_do_powersave = newval; 322 cpu_do_powersave = newval;
323 323
324 return (0); 324 return (0);
325} 325}
326 326
327SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") 327SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup")
328{ 328{
329 329
330 sysctl_createv(clog, 0, NULL, NULL, 330 sysctl_createv(clog, 0, NULL, NULL,
331 CTLFLAG_PERMANENT, 331 CTLFLAG_PERMANENT,
332 CTLTYPE_NODE, "machdep", NULL, 332 CTLTYPE_NODE, "machdep", NULL,
333 NULL, 0, NULL, 0, 333 NULL, 0, NULL, 0,
334 CTL_MACHDEP, CTL_EOL); 334 CTL_MACHDEP, CTL_EOL);
335 335
336 sysctl_createv(clog, 0, NULL, NULL, 336 sysctl_createv(clog, 0, NULL, NULL,
337 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 337 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
338 CTLTYPE_INT, "debug", NULL, 338 CTLTYPE_INT, "debug", NULL,
339 NULL, 0, &kernel_debug, 0, 339 NULL, 0, &kernel_debug, 0,
340 CTL_MACHDEP, CPU_DEBUG, CTL_EOL); 340 CTL_MACHDEP, CPU_DEBUG, CTL_EOL);
341 sysctl_createv(clog, 0, NULL, NULL, 341 sysctl_createv(clog, 0, NULL, NULL,
342 CTLFLAG_PERMANENT, 342 CTLFLAG_PERMANENT,
343 CTLTYPE_STRING, "booted_device", NULL, 343 CTLTYPE_STRING, "booted_device", NULL,
344 sysctl_machdep_booted_device, 0, NULL, 0, 344 sysctl_machdep_booted_device, 0, NULL, 0,
345 CTL_MACHDEP, CPU_BOOTED_DEVICE, CTL_EOL); 345 CTL_MACHDEP, CPU_BOOTED_DEVICE, CTL_EOL);
346 sysctl_createv(clog, 0, NULL, NULL, 346 sysctl_createv(clog, 0, NULL, NULL,
347 CTLFLAG_PERMANENT, 347 CTLFLAG_PERMANENT,
348 CTLTYPE_STRING, "booted_kernel", NULL, 348 CTLTYPE_STRING, "booted_kernel", NULL,
349 sysctl_machdep_booted_kernel, 0, NULL, 0, 349 sysctl_machdep_booted_kernel, 0, NULL, 0,
350 CTL_MACHDEP, CPU_BOOTED_KERNEL, CTL_EOL); 350 CTL_MACHDEP, CPU_BOOTED_KERNEL, CTL_EOL);
351 sysctl_createv(clog, 0, NULL, NULL, 351 sysctl_createv(clog, 0, NULL, NULL,
352 CTLFLAG_PERMANENT, 352 CTLFLAG_PERMANENT,
353 CTLTYPE_STRUCT, "console_device", NULL, 353 CTLTYPE_STRUCT, "console_device", NULL,
354 sysctl_consdev, 0, NULL, sizeof(dev_t), 354 sysctl_consdev, 0, NULL, sizeof(dev_t),
355 CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); 355 CTL_MACHDEP, CPU_CONSDEV, CTL_EOL);
356 sysctl_createv(clog, 0, NULL, NULL, 356 sysctl_createv(clog, 0, NULL, NULL,
357 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 357 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
358 CTLTYPE_INT, "powersave", NULL, 358 CTLTYPE_INT, "powersave", NULL,
359 sysctl_machdep_powersave, 0, &cpu_do_powersave, 0, 359 sysctl_machdep_powersave, 0, &cpu_do_powersave, 0,
360 CTL_MACHDEP, CPU_POWERSAVE, CTL_EOL); 360 CTL_MACHDEP, CPU_POWERSAVE, CTL_EOL);
361} 361}
362 362
363void 363void
364parse_mi_bootargs(char *args) 364parse_mi_bootargs(char *args)
365{ 365{
366 int integer; 366 int integer;
367 367
368 if (get_bootconf_option(args, "single", BOOTOPT_TYPE_BOOLEAN, &integer) 368 if (get_bootconf_option(args, "single", BOOTOPT_TYPE_BOOLEAN, &integer)
369 || get_bootconf_option(args, "-s", BOOTOPT_TYPE_BOOLEAN, &integer)) 369 || get_bootconf_option(args, "-s", BOOTOPT_TYPE_BOOLEAN, &integer))
370 if (integer) 370 if (integer)
371 boothowto |= RB_SINGLE; 371 boothowto |= RB_SINGLE;
372 if (get_bootconf_option(args, "kdb", BOOTOPT_TYPE_BOOLEAN, &integer) 372 if (get_bootconf_option(args, "kdb", BOOTOPT_TYPE_BOOLEAN, &integer)
373 || get_bootconf_option(args, "-k", BOOTOPT_TYPE_BOOLEAN, &integer)) 373 || get_bootconf_option(args, "-k", BOOTOPT_TYPE_BOOLEAN, &integer))
374 if (integer) 374 if (integer)
375 boothowto |= RB_KDB; 375 boothowto |= RB_KDB;
376 if (get_bootconf_option(args, "ask", BOOTOPT_TYPE_BOOLEAN, &integer) 376 if (get_bootconf_option(args, "ask", BOOTOPT_TYPE_BOOLEAN, &integer)
377 || get_bootconf_option(args, "-a", BOOTOPT_TYPE_BOOLEAN, &integer)) 377 || get_bootconf_option(args, "-a", BOOTOPT_TYPE_BOOLEAN, &integer))
378 if (integer) 378 if (integer)
379 boothowto |= RB_ASKNAME; 379 boothowto |= RB_ASKNAME;
380 380
381#ifdef PMAP_DEBUG 381#ifdef PMAP_DEBUG
382 if (get_bootconf_option(args, "pmapdebug", BOOTOPT_TYPE_INT, &integer)) { 382 if (get_bootconf_option(args, "pmapdebug", BOOTOPT_TYPE_INT, &integer)) {
383 pmap_debug_level = integer; 383 pmap_debug_level = integer;
384 pmap_debug(pmap_debug_level); 384 pmap_debug(pmap_debug_level);
385 } 385 }
386#endif /* PMAP_DEBUG */ 386#endif /* PMAP_DEBUG */
387 387
388/* if (get_bootconf_option(args, "nbuf", BOOTOPT_TYPE_INT, &integer)) 388/* if (get_bootconf_option(args, "nbuf", BOOTOPT_TYPE_INT, &integer))
389 bufpages = integer;*/ 389 bufpages = integer;*/
390 390
391#if defined(MEMORY_DISK_HOOKS) && !defined(MEMORY_DISK_ROOT_SIZE) 391#if defined(MEMORY_DISK_HOOKS) && !defined(MEMORY_DISK_ROOT_SIZE)
392 if (get_bootconf_option(args, "memorydisc", BOOTOPT_TYPE_INT, &integer) 392 if (get_bootconf_option(args, "memorydisc", BOOTOPT_TYPE_INT, &integer)
393 || get_bootconf_option(args, "memorydisk", BOOTOPT_TYPE_INT, &integer)) { 393 || get_bootconf_option(args, "memorydisk", BOOTOPT_TYPE_INT, &integer)) {
394 md_root_size = integer; 394 md_root_size = integer;
395 md_root_size *= 1024; 395 md_root_size *= 1024;
396 if (md_root_size < 32*1024) 396 if (md_root_size < 32*1024)
397 md_root_size = 32*1024; 397 md_root_size = 32*1024;
398 if (md_root_size > 2048*1024) 398 if (md_root_size > 2048*1024)
399 md_root_size = 2048*1024; 399 md_root_size = 2048*1024;
400 } 400 }
401#endif /* MEMORY_DISK_HOOKS && !MEMORY_DISK_ROOT_SIZE */ 401#endif /* MEMORY_DISK_HOOKS && !MEMORY_DISK_ROOT_SIZE */
402 402
403 if (get_bootconf_option(args, "quiet", BOOTOPT_TYPE_BOOLEAN, &integer) 403 if (get_bootconf_option(args, "quiet", BOOTOPT_TYPE_BOOLEAN, &integer)
404 || get_bootconf_option(args, "-q", BOOTOPT_TYPE_BOOLEAN, &integer)) 404 || get_bootconf_option(args, "-q", BOOTOPT_TYPE_BOOLEAN, &integer))
405 if (integer) 405 if (integer)
406 boothowto |= AB_QUIET; 406 boothowto |= AB_QUIET;
407 if (get_bootconf_option(args, "verbose", BOOTOPT_TYPE_BOOLEAN, &integer) 407 if (get_bootconf_option(args, "verbose", BOOTOPT_TYPE_BOOLEAN, &integer)
408 || get_bootconf_option(args, "-v", BOOTOPT_TYPE_BOOLEAN, &integer)) 408 || get_bootconf_option(args, "-v", BOOTOPT_TYPE_BOOLEAN, &integer))
409 if (integer) 409 if (integer)
410 boothowto |= AB_VERBOSE; 410 boothowto |= AB_VERBOSE;
411} 411}
412 412
413#ifdef __HAVE_FAST_SOFTINTS 413#ifdef __HAVE_FAST_SOFTINTS
414#if IPL_SOFTSERIAL != IPL_SOFTNET + 1 414#if IPL_SOFTSERIAL != IPL_SOFTNET + 1
415#error IPLs are screwed up 415#error IPLs are screwed up
416#elif IPL_SOFTNET != IPL_SOFTBIO + 1 416#elif IPL_SOFTNET != IPL_SOFTBIO + 1
417#error IPLs are screwed up 417#error IPLs are screwed up
418#elif IPL_SOFTBIO != IPL_SOFTCLOCK + 1 418#elif IPL_SOFTBIO != IPL_SOFTCLOCK + 1
419#error IPLs are screwed up 419#error IPLs are screwed up
420#elif !(IPL_SOFTCLOCK > IPL_NONE) 420#elif !(IPL_SOFTCLOCK > IPL_NONE)
421#error IPLs are screwed up 421#error IPLs are screwed up
422#elif (IPL_NONE != 0) 422#elif (IPL_NONE != 0)
423#error IPLs are screwed up 423#error IPLs are screwed up
424#endif 424#endif
425 425
426#ifndef __HAVE_PIC_FAST_SOFTINTS 426#ifndef __HAVE_PIC_FAST_SOFTINTS
427#define SOFTINT2IPLMAP \ 427#define SOFTINT2IPLMAP \
428 (((IPL_SOFTSERIAL - IPL_SOFTCLOCK) << (SOFTINT_SERIAL * 4)) | \ 428 (((IPL_SOFTSERIAL - IPL_SOFTCLOCK) << (SOFTINT_SERIAL * 4)) | \
429 ((IPL_SOFTNET - IPL_SOFTCLOCK) << (SOFTINT_NET * 4)) | \ 429 ((IPL_SOFTNET - IPL_SOFTCLOCK) << (SOFTINT_NET * 4)) | \
430 ((IPL_SOFTBIO - IPL_SOFTCLOCK) << (SOFTINT_BIO * 4)) | \ 430 ((IPL_SOFTBIO - IPL_SOFTCLOCK) << (SOFTINT_BIO * 4)) | \
431 ((IPL_SOFTCLOCK - IPL_SOFTCLOCK) << (SOFTINT_CLOCK * 4))) 431 ((IPL_SOFTCLOCK - IPL_SOFTCLOCK) << (SOFTINT_CLOCK * 4)))
432#define SOFTINT2IPL(l) ((SOFTINT2IPLMAP >> ((l) * 4)) & 0x0f) 432#define SOFTINT2IPL(l) ((SOFTINT2IPLMAP >> ((l) * 4)) & 0x0f)
433 433
434/* 434/*
435 * This returns a mask of softint IPLs that be dispatch at <ipl> 435 * This returns a mask of softint IPLs that be dispatch at <ipl>
436 * SOFTIPLMASK(IPL_NONE) = 0x0000000f 436 * SOFTIPLMASK(IPL_NONE) = 0x0000000f
437 * SOFTIPLMASK(IPL_SOFTCLOCK) = 0x0000000e 437 * SOFTIPLMASK(IPL_SOFTCLOCK) = 0x0000000e
438 * SOFTIPLMASK(IPL_SOFTBIO) = 0x0000000c 438 * SOFTIPLMASK(IPL_SOFTBIO) = 0x0000000c
439 * SOFTIPLMASK(IPL_SOFTNET) = 0x00000008 439 * SOFTIPLMASK(IPL_SOFTNET) = 0x00000008
440 * SOFTIPLMASK(IPL_SOFTSERIAL) = 0x00000000 440 * SOFTIPLMASK(IPL_SOFTSERIAL) = 0x00000000
441 */ 441 */
442#define SOFTIPLMASK(ipl) ((0x0f << (ipl)) & 0x0f) 442#define SOFTIPLMASK(ipl) ((0x0f << (ipl)) & 0x0f)
443 443
444void softint_switch(lwp_t *, int); 444void softint_switch(lwp_t *, int);
445 445
446void 446void
447softint_trigger(uintptr_t mask) 447softint_trigger(uintptr_t mask)
448{ 448{
449 curcpu()->ci_softints |= mask; 449 curcpu()->ci_softints |= mask;
450} 450}
451 451
452void 452void
453softint_init_md(lwp_t *l, u_int level, uintptr_t *machdep) 453softint_init_md(lwp_t *l, u_int level, uintptr_t *machdep)
454{ 454{
455 lwp_t ** lp = &l->l_cpu->ci_softlwps[level]; 455 lwp_t ** lp = &l->l_cpu->ci_softlwps[level];
456 KASSERT(*lp == NULL || *lp == l); 456 KASSERT(*lp == NULL || *lp == l);
457 *lp = l; 457 *lp = l;
458 *machdep = 1 << SOFTINT2IPL(level); 458 *machdep = 1 << SOFTINT2IPL(level);
459 KASSERT(level != SOFTINT_CLOCK || *machdep == (1 << (IPL_SOFTCLOCK - IPL_SOFTCLOCK))); 459 KASSERT(level != SOFTINT_CLOCK || *machdep == (1 << (IPL_SOFTCLOCK - IPL_SOFTCLOCK)));
460 KASSERT(level != SOFTINT_BIO || *machdep == (1 << (IPL_SOFTBIO - IPL_SOFTCLOCK))); 460 KASSERT(level != SOFTINT_BIO || *machdep == (1 << (IPL_SOFTBIO - IPL_SOFTCLOCK)));
461 KASSERT(level != SOFTINT_NET || *machdep == (1 << (IPL_SOFTNET - IPL_SOFTCLOCK))); 461 KASSERT(level != SOFTINT_NET || *machdep == (1 << (IPL_SOFTNET - IPL_SOFTCLOCK)));
462 KASSERT(level != SOFTINT_SERIAL || *machdep == (1 << (IPL_SOFTSERIAL - IPL_SOFTCLOCK))); 462 KASSERT(level != SOFTINT_SERIAL || *machdep == (1 << (IPL_SOFTSERIAL - IPL_SOFTCLOCK)));
463} 463}
464 464
465void 465void
466dosoftints(void) 466dosoftints(void)
467{ 467{
468 struct cpu_info * const ci = curcpu(); 468 struct cpu_info * const ci = curcpu();
469 const int opl = ci->ci_cpl; 469 const int opl = ci->ci_cpl;
470 const uint32_t softiplmask = SOFTIPLMASK(opl); 470 const uint32_t softiplmask = SOFTIPLMASK(opl);
471 471
472 splhigh(); 472 splhigh();
473 for (;;) { 473 for (;;) {
474 u_int softints = ci->ci_softints & softiplmask; 474 u_int softints = ci->ci_softints & softiplmask;
475 KASSERT((softints != 0) == ((ci->ci_softints >> opl) != 0)); 475 KASSERT((softints != 0) == ((ci->ci_softints >> opl) != 0));
476 KASSERT(opl == IPL_NONE || (softints & (1 << (opl - IPL_SOFTCLOCK))) == 0); 476 KASSERT(opl == IPL_NONE || (softints & (1 << (opl - IPL_SOFTCLOCK))) == 0);
477 if (softints == 0) { 477 if (softints == 0) {
478 splx(opl); 478 splx(opl);
479 return; 479 return;
480 } 480 }
481#define DOSOFTINT(n) \ 481#define DOSOFTINT(n) \
482 if (ci->ci_softints & (1 << (IPL_SOFT ## n - IPL_SOFTCLOCK))) { \ 482 if (ci->ci_softints & (1 << (IPL_SOFT ## n - IPL_SOFTCLOCK))) { \
483 ci->ci_softints &= \ 483 ci->ci_softints &= \
484 ~(1 << (IPL_SOFT ## n - IPL_SOFTCLOCK)); \ 484 ~(1 << (IPL_SOFT ## n - IPL_SOFTCLOCK)); \
485 softint_switch(ci->ci_softlwps[SOFTINT_ ## n], \ 485 softint_switch(ci->ci_softlwps[SOFTINT_ ## n], \
486 IPL_SOFT ## n); \ 486 IPL_SOFT ## n); \
487 continue; \ 487 continue; \
488 } 488 }
489 DOSOFTINT(SERIAL); 489 DOSOFTINT(SERIAL);
490 DOSOFTINT(NET); 490 DOSOFTINT(NET);
491 DOSOFTINT(BIO); 491 DOSOFTINT(BIO);
492 DOSOFTINT(CLOCK); 492 DOSOFTINT(CLOCK);
493 panic("dosoftints wtf (softints=%u?, ipl=%d)", softints, opl); 493 panic("dosoftints wtf (softints=%u?, ipl=%d)", softints, opl);
494 } 494 }
495} 495}
496#endif /* !__HAVE_PIC_FAST_SOFTINTS */ 496#endif /* !__HAVE_PIC_FAST_SOFTINTS */
497#endif /* __HAVE_FAST_SOFTINTS */ 497#endif /* __HAVE_FAST_SOFTINTS */
498 498
499#ifdef MODULAR 499#ifdef MODULAR
500/* 500/*
501 * Push any modules loaded by the boot loader. 501 * Push any modules loaded by the boot loader.
502 */ 502 */
503void 503void
504module_init_md(void) 504module_init_md(void)
505{ 505{
506} 506}
507#endif /* MODULAR */ 507#endif /* MODULAR */
508 508
509int 509int
510mm_md_physacc(paddr_t pa, vm_prot_t prot) 510mm_md_physacc(paddr_t pa, vm_prot_t prot)
511{ 511{
512 512
513 return (pa < ctob(physmem)) ? 0 : EFAULT; 513 return (pa < ctob(physmem)) ? 0 : EFAULT;
514} 514}
515 515
516#ifdef __HAVE_CPU_UAREA_ALLOC_IDLELWP 516#ifdef __HAVE_CPU_UAREA_ALLOC_IDLELWP
517vaddr_t 517vaddr_t
518cpu_uarea_alloc_idlelwp(struct cpu_info *ci) 518cpu_uarea_alloc_idlelwp(struct cpu_info *ci)
519{ 519{
520 const vaddr_t va = idlestack.pv_va + ci->ci_cpuid * USPACE; 520 const vaddr_t va = idlestack.pv_va + ci->ci_cpuid * USPACE;
521 // printf("%s: %s: va=%lx\n", __func__, ci->ci_data.cpu_name, va); 521 // printf("%s: %s: va=%lx\n", __func__, ci->ci_data.cpu_name, va);
522 return va; 522 return va;
523} 523}
524#endif 524#endif
525 525
526#ifdef MULTIPROCESSOR 526#ifdef MULTIPROCESSOR
527void 527void
528cpu_boot_secondary_processors(void) 528cpu_boot_secondary_processors(void)
529{ 529{
530 uint32_t mbox; 530 uint32_t mbox;
531 kcpuset_copybits(kcpuset_attached, &mbox, sizeof(mbox)); 531 kcpuset_export_u32(kcpuset_attached, &mbox, sizeof(mbox));
532 atomic_swap_32(&arm_cpu_mbox, mbox); 532 atomic_swap_32(&arm_cpu_mbox, mbox);
533 membar_producer(); 533 membar_producer();
534#ifdef _ARM_ARCH_7 534#ifdef _ARM_ARCH_7
535 __asm __volatile("sev; sev; sev"); 535 __asm __volatile("sev; sev; sev");
536#endif 536#endif
537} 537}
538 538
539void 539void
540xc_send_ipi(struct cpu_info *ci) 540xc_send_ipi(struct cpu_info *ci)
541{ 541{
542 KASSERT(kpreempt_disabled()); 542 KASSERT(kpreempt_disabled());
543 KASSERT(curcpu() != ci); 543 KASSERT(curcpu() != ci);
544 544
545 545
546 if (ci) { 546 if (ci) {
547 /* Unicast, remote CPU */ 547 /* Unicast, remote CPU */
548 printf("%s: -> %s", __func__, ci->ci_data.cpu_name); 548 printf("%s: -> %s", __func__, ci->ci_data.cpu_name);
549 intr_ipi_send(ci->ci_kcpuset, IPI_XCALL); 549 intr_ipi_send(ci->ci_kcpuset, IPI_XCALL);
550 } else { 550 } else {
551 printf("%s: -> !%s", __func__, ci->ci_data.cpu_name); 551 printf("%s: -> !%s", __func__, ci->ci_data.cpu_name);
552 /* Broadcast to all but ourselves */ 552 /* Broadcast to all but ourselves */
553 kcpuset_t *kcp; 553 kcpuset_t *kcp;
554 kcpuset_create(&kcp, (ci != NULL)); 554 kcpuset_create(&kcp, (ci != NULL));
555 KASSERT(kcp != NULL); 555 KASSERT(kcp != NULL);
556 kcpuset_copy(kcp, kcpuset_running); 556 kcpuset_copy(kcp, kcpuset_running);
557 kcpuset_clear(kcp, cpu_index(ci)); 557 kcpuset_clear(kcp, cpu_index(ci));
558 intr_ipi_send(kcp, IPI_XCALL); 558 intr_ipi_send(kcp, IPI_XCALL);
559 kcpuset_destroy(kcp); 559 kcpuset_destroy(kcp);
560 } 560 }
561 printf("\n"); 561 printf("\n");
562} 562}
563#endif /* MULTIPROCESSOR */ 563#endif /* MULTIPROCESSOR */

cvs diff -r1.2 -r1.3 src/sys/arch/arm/cortex/gic.c (switch to unified diff)

--- src/sys/arch/arm/cortex/gic.c 2012/09/14 03:52:50 1.2
+++ src/sys/arch/arm/cortex/gic.c 2012/09/16 22:09:34 1.3
@@ -1,577 +1,577 @@ @@ -1,577 +1,577 @@
1/* $NetBSD: gic.c,v 1.2 2012/09/14 03:52:50 matt Exp $ */ 1/* $NetBSD: gic.c,v 1.3 2012/09/16 22:09:34 rmind Exp $ */
2/*- 2/*-
3 * Copyright (c) 2012 The NetBSD Foundation, Inc. 3 * Copyright (c) 2012 The NetBSD Foundation, Inc.
4 * All rights reserved. 4 * All rights reserved.
5 * 5 *
6 * This code is derived from software contributed to The NetBSD Foundation 6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Matt Thomas of 3am Software Foundry. 7 * by Matt Thomas of 3am Software Foundry.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE. 28 * POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31#define _INTR_PRIVATE 31#define _INTR_PRIVATE
32 32
33#include <sys/cdefs.h> 33#include <sys/cdefs.h>
34__KERNEL_RCSID(0, "$NetBSD: gic.c,v 1.2 2012/09/14 03:52:50 matt Exp $"); 34__KERNEL_RCSID(0, "$NetBSD: gic.c,v 1.3 2012/09/16 22:09:34 rmind Exp $");
35 35
36#include <sys/param.h> 36#include <sys/param.h>
37#include <sys/bus.h> 37#include <sys/bus.h>
38#include <sys/device.h> 38#include <sys/device.h>
39#include <sys/evcnt.h> 39#include <sys/evcnt.h>
40#include <sys/intr.h> 40#include <sys/intr.h>
41#include <sys/proc.h> 41#include <sys/proc.h>
42#include <sys/xcall.h> /* for xc_ipi_handler */ 42#include <sys/xcall.h> /* for xc_ipi_handler */
43 43
44#include <arm/armreg.h> 44#include <arm/armreg.h>
45#include <arm/cpufunc.h> 45#include <arm/cpufunc.h>
46#include <arm/atomic.h> 46#include <arm/atomic.h>
47 47
48#include <arm/cortex/gic_reg.h> 48#include <arm/cortex/gic_reg.h>
49#include <arm/cortex/mpcore_var.h> 49#include <arm/cortex/mpcore_var.h>
50 50
51#define ARMGIC_SGI_IPIBASE (16 - NIPI) 51#define ARMGIC_SGI_IPIBASE (16 - NIPI)
52 52
53static int armgic_match(device_t, cfdata_t, void *); 53static int armgic_match(device_t, cfdata_t, void *);
54static void armgic_attach(device_t, device_t, void *); 54static void armgic_attach(device_t, device_t, void *);
55 55
56static void armgic_set_priority(struct pic_softc *, int); 56static void armgic_set_priority(struct pic_softc *, int);
57static void armgic_unblock_irqs(struct pic_softc *, size_t, uint32_t); 57static void armgic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
58static void armgic_block_irqs(struct pic_softc *, size_t, uint32_t); 58static void armgic_block_irqs(struct pic_softc *, size_t, uint32_t);
59static void armgic_establish_irq(struct pic_softc *, struct intrsource *); 59static void armgic_establish_irq(struct pic_softc *, struct intrsource *);
60#if 0 60#if 0
61static void armgic_source_name(struct pic_softc *, int, char *, size_t); 61static void armgic_source_name(struct pic_softc *, int, char *, size_t);
62#endif 62#endif
63 63
64#ifdef MULTIPROCESSOR 64#ifdef MULTIPROCESSOR
65static void armgic_cpu_init(struct pic_softc *, struct cpu_info *); 65static void armgic_cpu_init(struct pic_softc *, struct cpu_info *);
66static void armgic_ipi_send(struct pic_softc *, const kcpuset_t *, u_long); 66static void armgic_ipi_send(struct pic_softc *, const kcpuset_t *, u_long);
67#endif 67#endif
68 68
69static const struct pic_ops armgic_picops = { 69static const struct pic_ops armgic_picops = {
70 .pic_unblock_irqs = armgic_unblock_irqs, 70 .pic_unblock_irqs = armgic_unblock_irqs,
71 .pic_block_irqs = armgic_block_irqs, 71 .pic_block_irqs = armgic_block_irqs,
72 .pic_establish_irq = armgic_establish_irq, 72 .pic_establish_irq = armgic_establish_irq,
73#if 0 73#if 0
74 .pic_source_name = armgic_source_name, 74 .pic_source_name = armgic_source_name,
75#endif 75#endif
76 .pic_set_priority = armgic_set_priority, 76 .pic_set_priority = armgic_set_priority,
77#ifdef MULTIPROCESSOR 77#ifdef MULTIPROCESSOR
78 .pic_cpu_init = armgic_cpu_init, 78 .pic_cpu_init = armgic_cpu_init,
79 .pic_ipi_send = armgic_ipi_send, 79 .pic_ipi_send = armgic_ipi_send,
80#endif 80#endif
81}; 81};
82 82
83#define PICTOSOFTC(pic) ((struct armgic_softc *)(pic)) 83#define PICTOSOFTC(pic) ((struct armgic_softc *)(pic))
84 84
85static struct armgic_softc { 85static struct armgic_softc {
86 struct pic_softc sc_pic; 86 struct pic_softc sc_pic;
87 device_t sc_dev; 87 device_t sc_dev;
88 bus_space_tag_t sc_memt; 88 bus_space_tag_t sc_memt;
89 bus_space_handle_t sc_memh; 89 bus_space_handle_t sc_memh;
90 size_t sc_gic_lines; 90 size_t sc_gic_lines;
91 uint32_t sc_gic_type; 91 uint32_t sc_gic_type;
92 uint32_t sc_gic_valid_lines[1024/32]; 92 uint32_t sc_gic_valid_lines[1024/32];
93 uint32_t sc_enabled_local; 93 uint32_t sc_enabled_local;
94} armgic_softc = { 94} armgic_softc = {
95 .sc_pic = { 95 .sc_pic = {
96 .pic_ops = &armgic_picops, 96 .pic_ops = &armgic_picops,
97 .pic_name = "armgic", 97 .pic_name = "armgic",
98 }, 98 },
99}; 99};
100 100
101static struct intrsource armgic_dummy_source; 101static struct intrsource armgic_dummy_source;
102 102
103__CTASSERT(NIPL == 8); 103__CTASSERT(NIPL == 8);
104 104
105/* 105/*
106 * GIC register are always in little-endian. 106 * GIC register are always in little-endian.
107 */ 107 */
108static inline uint32_t 108static inline uint32_t
109gicc_read(struct armgic_softc *sc, bus_size_t o) 109gicc_read(struct armgic_softc *sc, bus_size_t o)
110{ 110{
111 uint32_t v = bus_space_read_4(sc->sc_memt, sc->sc_memh, GICC_BASE + o); 111 uint32_t v = bus_space_read_4(sc->sc_memt, sc->sc_memh, GICC_BASE + o);
112 return le32toh(v); 112 return le32toh(v);
113} 113}
114 114
115static inline void 115static inline void
116gicc_write(struct armgic_softc *sc, bus_size_t o, uint32_t v) 116gicc_write(struct armgic_softc *sc, bus_size_t o, uint32_t v)
117{ 117{
118 v = htole32(v); 118 v = htole32(v);
119 bus_space_write_4(sc->sc_memt, sc->sc_memh, GICC_BASE + o, v); 119 bus_space_write_4(sc->sc_memt, sc->sc_memh, GICC_BASE + o, v);
120} 120}
121 121
122static inline uint32_t 122static inline uint32_t
123gicd_read(struct armgic_softc *sc, bus_size_t o) 123gicd_read(struct armgic_softc *sc, bus_size_t o)
124{ 124{
125 uint32_t v = bus_space_read_4(sc->sc_memt, sc->sc_memh, GICD_BASE + o); 125 uint32_t v = bus_space_read_4(sc->sc_memt, sc->sc_memh, GICD_BASE + o);
126 return le32toh(v); 126 return le32toh(v);
127} 127}
128 128
129static inline void 129static inline void
130gicd_write(struct armgic_softc *sc, bus_size_t o, uint32_t v) 130gicd_write(struct armgic_softc *sc, bus_size_t o, uint32_t v)
131{ 131{
132 v = htole32(v); 132 v = htole32(v);
133 bus_space_write_4(sc->sc_memt, sc->sc_memh, GICD_BASE + o, v); 133 bus_space_write_4(sc->sc_memt, sc->sc_memh, GICD_BASE + o, v);
134} 134}
135 135
136/* 136/*
137 * In the GIC prioritization scheme, lower numbers have higher priority. 137 * In the GIC prioritization scheme, lower numbers have higher priority.
138 */ 138 */
139static inline uint32_t 139static inline uint32_t
140armgic_ipl_to_priority(int ipl) 140armgic_ipl_to_priority(int ipl)
141{ 141{
142 return (IPL_HIGH - ipl) * GICC_PMR_PRIORITIES / NIPL; 142 return (IPL_HIGH - ipl) * GICC_PMR_PRIORITIES / NIPL;
143} 143}
144 144
145static inline int 145static inline int
146armgic_priority_to_ipl(uint32_t priority) 146armgic_priority_to_ipl(uint32_t priority)
147{ 147{
148 return IPL_HIGH - priority * NIPL / GICC_PMR_PRIORITIES; 148 return IPL_HIGH - priority * NIPL / GICC_PMR_PRIORITIES;
149} 149}
150 150
151static void 151static void
152armgic_unblock_irqs(struct pic_softc *pic, size_t irq_base, uint32_t irq_mask) 152armgic_unblock_irqs(struct pic_softc *pic, size_t irq_base, uint32_t irq_mask)
153{ 153{
154 struct armgic_softc * const sc = PICTOSOFTC(pic); 154 struct armgic_softc * const sc = PICTOSOFTC(pic);
155 const size_t group = irq_base / 32; 155 const size_t group = irq_base / 32;
156 156
157 if (group == 0) 157 if (group == 0)
158 sc->sc_enabled_local |= irq_mask; 158 sc->sc_enabled_local |= irq_mask;
159 159
160 gicd_write(sc, GICD_ISENABLERn(group), irq_mask); 160 gicd_write(sc, GICD_ISENABLERn(group), irq_mask);
161} 161}
162 162
163static void 163static void
164armgic_block_irqs(struct pic_softc *pic, size_t irq_base, uint32_t irq_mask) 164armgic_block_irqs(struct pic_softc *pic, size_t irq_base, uint32_t irq_mask)
165{ 165{
166 struct armgic_softc * const sc = PICTOSOFTC(pic); 166 struct armgic_softc * const sc = PICTOSOFTC(pic);
167 const size_t group = irq_base / 32; 167 const size_t group = irq_base / 32;
168 168
169 if (group == 0) 169 if (group == 0)
170 sc->sc_enabled_local &= ~irq_mask; 170 sc->sc_enabled_local &= ~irq_mask;
171 171
172 gicd_write(sc, GICD_ICENABLERn(group), irq_mask); 172 gicd_write(sc, GICD_ICENABLERn(group), irq_mask);
173} 173}
174 174
175static uint32_t armgic_last_priority; 175static uint32_t armgic_last_priority;
176 176
177static void 177static void
178armgic_set_priority(struct pic_softc *pic, int ipl) 178armgic_set_priority(struct pic_softc *pic, int ipl)
179{ 179{
180 struct armgic_softc * const sc = PICTOSOFTC(pic); 180 struct armgic_softc * const sc = PICTOSOFTC(pic);
181 181
182 const uint32_t priority = armgic_ipl_to_priority(ipl); 182 const uint32_t priority = armgic_ipl_to_priority(ipl);
183 gicc_write(sc, GICC_PMR, priority); 183 gicc_write(sc, GICC_PMR, priority);
184 armgic_last_priority = priority; 184 armgic_last_priority = priority;
185} 185}
186 186
187#ifdef __HAVE_PIC_FAST_SOFTINTS 187#ifdef __HAVE_PIC_FAST_SOFTINTS
188void 188void
189softint_init_md(lwp_t *l, u_int level, uintptr_t *machdep_p) 189softint_init_md(lwp_t *l, u_int level, uintptr_t *machdep_p)
190{ 190{
191 lwp_t **lp = &l->l_cpu->ci_softlwps[level]; 191 lwp_t **lp = &l->l_cpu->ci_softlwps[level];
192 KASSERT(*lp == NULL || *lp == l); 192 KASSERT(*lp == NULL || *lp == l);
193 *lp = l; 193 *lp = l;
194 /* 194 /*
195 * Really easy. Just tell it to trigger the local CPU. 195 * Really easy. Just tell it to trigger the local CPU.
196 */ 196 */
197 *machdep_p = GICD_SGIR_TargetListFilter_Me 197 *machdep_p = GICD_SGIR_TargetListFilter_Me
198 | __SHIFTIN(level, GICD_SGIR_SGIINTID); 198 | __SHIFTIN(level, GICD_SGIR_SGIINTID);
199} 199}
200 200
201void 201void
202softint_trigger(uintptr_t machdep) 202softint_trigger(uintptr_t machdep)
203{ 203{
204 204
205 gicd_write(&armgic_softc, GICD_SGIR, machdep); 205 gicd_write(&armgic_softc, GICD_SGIR, machdep);
206} 206}
207#endif 207#endif
208 208
209void 209void
210armgic_irq_handler(void *tf) 210armgic_irq_handler(void *tf)
211{ 211{
212 struct cpu_info * const ci = curcpu(); 212 struct cpu_info * const ci = curcpu();
213 struct armgic_softc * const sc = &armgic_softc; 213 struct armgic_softc * const sc = &armgic_softc;
214 const int old_ipl = ci->ci_cpl; 214 const int old_ipl = ci->ci_cpl;
215#ifdef DIAGNOSTIC 215#ifdef DIAGNOSTIC
216 const int old_mtx_count = ci->ci_mtx_count; 216 const int old_mtx_count = ci->ci_mtx_count;
217 const int old_l_biglocks = ci->ci_curlwp->l_biglocks; 217 const int old_l_biglocks = ci->ci_curlwp->l_biglocks;
218#endif 218#endif
219#ifdef DEBUG 219#ifdef DEBUG
220 size_t n = 0; 220 size_t n = 0;
221#endif 221#endif
222 222
223 ci->ci_data.cpu_nintr++; 223 ci->ci_data.cpu_nintr++;
224 224
225 KASSERTMSG(old_ipl != IPL_HIGH, "old_ipl %d pmr %#x hppir %#x", 225 KASSERTMSG(old_ipl != IPL_HIGH, "old_ipl %d pmr %#x hppir %#x",
226 old_ipl, gicc_read(sc, GICC_PMR), gicc_read(sc, GICC_HPPIR)); 226 old_ipl, gicc_read(sc, GICC_PMR), gicc_read(sc, GICC_HPPIR));
227#if 0 227#if 0
228 printf("%s(enter): %s: pmr=%u hppir=%u\n", 228 printf("%s(enter): %s: pmr=%u hppir=%u\n",
229 __func__, ci->ci_data.cpu_name, 229 __func__, ci->ci_data.cpu_name,
230 gicc_read(sc, GICC_PMR), 230 gicc_read(sc, GICC_PMR),
231 gicc_read(sc, GICC_HPPIR)); 231 gicc_read(sc, GICC_HPPIR));
232#elif 0 232#elif 0
233 printf("(%u:%d", ci->ci_index, old_ipl); 233 printf("(%u:%d", ci->ci_index, old_ipl);
234#endif 234#endif
235 235
236 for (;;) { 236 for (;;) {
237 uint32_t iar = gicc_read(sc, GICC_IAR); 237 uint32_t iar = gicc_read(sc, GICC_IAR);
238 uint32_t irq = __SHIFTOUT(iar, GICC_IAR_IRQ); 238 uint32_t irq = __SHIFTOUT(iar, GICC_IAR_IRQ);
239 //printf(".%u", irq); 239 //printf(".%u", irq);
240 if (irq == GICC_IAR_IRQ_SPURIOUS) { 240 if (irq == GICC_IAR_IRQ_SPURIOUS) {
241 iar = gicc_read(sc, GICC_IAR); 241 iar = gicc_read(sc, GICC_IAR);
242 irq = __SHIFTOUT(iar, GICC_IAR_IRQ); 242 irq = __SHIFTOUT(iar, GICC_IAR_IRQ);
243 if (irq == GICC_IAR_IRQ_SPURIOUS) 243 if (irq == GICC_IAR_IRQ_SPURIOUS)
244 break; 244 break;
245 //printf(".%u", irq); 245 //printf(".%u", irq);
246 } 246 }
247 247
248 //const uint32_t cpuid = __SHIFTOUT(iar, GICC_IAR_CPUID_MASK); 248 //const uint32_t cpuid = __SHIFTOUT(iar, GICC_IAR_CPUID_MASK);
249 struct intrsource * const is = sc->sc_pic.pic_sources[irq]; 249 struct intrsource * const is = sc->sc_pic.pic_sources[irq];
250 KASSERT(is != &armgic_dummy_source); 250 KASSERT(is != &armgic_dummy_source);
251 251
252 /* 252 /*
253 * GIC has asserted IPL for us so we can just update ci_cpl. 253 * GIC has asserted IPL for us so we can just update ci_cpl.
254 * 254 *
255 * But it's not that simple. We may have already bumped ci_cpl 255 * But it's not that simple. We may have already bumped ci_cpl
256 * due to a high priority interrupt and now we are about to 256 * due to a high priority interrupt and now we are about to
257 * dispatch one lower than the previous. It's possible for 257 * dispatch one lower than the previous. It's possible for
258 * that previous interrupt to have deferred some interrupts 258 * that previous interrupt to have deferred some interrupts
259 * so we need deal with those when lowering to the current 259 * so we need deal with those when lowering to the current
260 * interrupt's ipl. 260 * interrupt's ipl.
261 * 261 *
262 * However, if are just raising ipl, we can just update ci_cpl. 262 * However, if are just raising ipl, we can just update ci_cpl.
263 */ 263 */
264#if 0 264#if 0
265 const int ipl = armgic_priority_to_ipl(gicc_read(sc, GICC_RPR)); 265 const int ipl = armgic_priority_to_ipl(gicc_read(sc, GICC_RPR));
266 KASSERTMSG(panicstr != NULL || ipl == is->is_ipl, 266 KASSERTMSG(panicstr != NULL || ipl == is->is_ipl,
267 "%s: irq %d: running ipl %d != source ipl %u",  267 "%s: irq %d: running ipl %d != source ipl %u",
268 ci->ci_data.cpu_name, irq, ipl, is->is_ipl); 268 ci->ci_data.cpu_name, irq, ipl, is->is_ipl);
269#else 269#else
270 const int ipl = is->is_ipl; 270 const int ipl = is->is_ipl;
271#endif 271#endif
272 if (__predict_false(ipl < ci->ci_cpl)) { 272 if (__predict_false(ipl < ci->ci_cpl)) {
273 //printf("<"); 273 //printf("<");
274 pic_do_pending_ints(I32_bit, ipl, tf); 274 pic_do_pending_ints(I32_bit, ipl, tf);
275 KASSERT(ci->ci_cpl == ipl); 275 KASSERT(ci->ci_cpl == ipl);
276 } else { 276 } else {
277 KASSERTMSG(ipl > ci->ci_cpl, "ipl %d cpl %d hw-ipl %#x", 277 KASSERTMSG(ipl > ci->ci_cpl, "ipl %d cpl %d hw-ipl %#x",
278 ipl, ci->ci_cpl, 278 ipl, ci->ci_cpl,
279 gicc_read(sc, GICC_PMR)); 279 gicc_read(sc, GICC_PMR));
280 //printf(">"); 280 //printf(">");
281 gicc_write(sc, GICC_PMR, armgic_ipl_to_priority(ipl)); 281 gicc_write(sc, GICC_PMR, armgic_ipl_to_priority(ipl));
282 ci->ci_cpl = ipl; 282 ci->ci_cpl = ipl;
283 } 283 }
284 //printf("$"); 284 //printf("$");
285 cpsie(I32_bit); 285 cpsie(I32_bit);
286 pic_dispatch(is, tf); 286 pic_dispatch(is, tf);
287 cpsid(I32_bit); 287 cpsid(I32_bit);
288 gicc_write(sc, GICC_EOIR, iar); 288 gicc_write(sc, GICC_EOIR, iar);
289#ifdef DEBUG 289#ifdef DEBUG
290 n++; 290 n++;
291 KDASSERTMSG(n < 5, "%s: processed too many (%zu)", 291 KDASSERTMSG(n < 5, "%s: processed too many (%zu)",
292 ci->ci_data.cpu_name, n); 292 ci->ci_data.cpu_name, n);
293#endif 293#endif
294 } 294 }
295 295
296 // printf("%s(%p): exit (%zu dispatched)\n", __func__, tf, n); 296 // printf("%s(%p): exit (%zu dispatched)\n", __func__, tf, n);
297 /* 297 /*
298 * Now handle any pending ints. 298 * Now handle any pending ints.
299 */ 299 */
300 //printf("!"); 300 //printf("!");
301 KASSERT(old_ipl != IPL_HIGH); 301 KASSERT(old_ipl != IPL_HIGH);
302 pic_do_pending_ints(I32_bit, old_ipl, tf); 302 pic_do_pending_ints(I32_bit, old_ipl, tf);
303 KASSERTMSG(ci->ci_cpl == old_ipl, "ci_cpl %d old_ipl %d", ci->ci_cpl, old_ipl); 303 KASSERTMSG(ci->ci_cpl == old_ipl, "ci_cpl %d old_ipl %d", ci->ci_cpl, old_ipl);
304 KASSERT(old_mtx_count == ci->ci_mtx_count); 304 KASSERT(old_mtx_count == ci->ci_mtx_count);
305 KASSERT(old_l_biglocks == ci->ci_curlwp->l_biglocks); 305 KASSERT(old_l_biglocks == ci->ci_curlwp->l_biglocks);
306#if 0 306#if 0
307 printf("%s(exit): %s(%d): pmr=%u hppir=%u\n", 307 printf("%s(exit): %s(%d): pmr=%u hppir=%u\n",
308 __func__, ci->ci_data.cpu_name, ci->ci_cpl, 308 __func__, ci->ci_data.cpu_name, ci->ci_cpl,
309 gicc_read(sc, GICC_PMR), 309 gicc_read(sc, GICC_PMR),
310 gicc_read(sc, GICC_HPPIR)); 310 gicc_read(sc, GICC_HPPIR));
311#elif 0 311#elif 0
312 printf("->%#x)", ((struct trapframe *)tf)->tf_pc); 312 printf("->%#x)", ((struct trapframe *)tf)->tf_pc);
313#endif 313#endif
314} 314}
315 315
316void 316void
317armgic_establish_irq(struct pic_softc *pic, struct intrsource *is) 317armgic_establish_irq(struct pic_softc *pic, struct intrsource *is)
318{ 318{
319 struct armgic_softc * const sc = PICTOSOFTC(pic); 319 struct armgic_softc * const sc = PICTOSOFTC(pic);
320 const size_t group = is->is_irq / 32; 320 const size_t group = is->is_irq / 32;
321 const u_int irq = is->is_irq & 31; 321 const u_int irq = is->is_irq & 31;
322 const u_int byte_shift = 8 * (irq & 3); 322 const u_int byte_shift = 8 * (irq & 3);
323 const u_int twopair_shift = 2 * (irq & 15); 323 const u_int twopair_shift = 2 * (irq & 15);
324 324
325 KASSERTMSG(sc->sc_gic_valid_lines[group] & __BIT(irq), 325 KASSERTMSG(sc->sc_gic_valid_lines[group] & __BIT(irq),
326 "irq %u: not valid (group[%zu]=0x%08x [0x%08x])", 326 "irq %u: not valid (group[%zu]=0x%08x [0x%08x])",
327 is->is_irq, group, sc->sc_gic_valid_lines[group], 327 is->is_irq, group, sc->sc_gic_valid_lines[group],
328 (uint32_t)__BIT(irq)); 328 (uint32_t)__BIT(irq));
329  329
330 KASSERTMSG(is->is_type == IST_LEVEL || is->is_type == IST_EDGE, 330 KASSERTMSG(is->is_type == IST_LEVEL || is->is_type == IST_EDGE,
331 "irq %u: type %u unsupported", is->is_irq, is->is_type); 331 "irq %u: type %u unsupported", is->is_irq, is->is_type);
332 332
333 const bus_size_t targets_reg = GICD_ITARGETSRn(is->is_irq / 4); 333 const bus_size_t targets_reg = GICD_ITARGETSRn(is->is_irq / 4);
334 const bus_size_t cfg_reg = GICD_ICFGRn(is->is_irq / 16); 334 const bus_size_t cfg_reg = GICD_ICFGRn(is->is_irq / 16);
335 uint32_t targets = gicd_read(sc, targets_reg); 335 uint32_t targets = gicd_read(sc, targets_reg);
336 uint32_t cfg = gicd_read(sc, cfg_reg); 336 uint32_t cfg = gicd_read(sc, cfg_reg);
337 337
338 if (group > 0) { 338 if (group > 0) {
339 /*  339 /*
340 * There are 4 irqs per TARGETS register. For now bind 340 * There are 4 irqs per TARGETS register. For now bind
341 * to the primary cpu. 341 * to the primary cpu.
342 */ 342 */
343 targets &= ~(0xff << byte_shift); 343 targets &= ~(0xff << byte_shift);
344 targets |= 1 << byte_shift; 344 targets |= 1 << byte_shift;
345 gicd_write(sc, targets_reg, targets); 345 gicd_write(sc, targets_reg, targets);
346 346
347 /*  347 /*
348 * There are 16 irqs per CFG register. 10=EDGE 00=LEVEL 348 * There are 16 irqs per CFG register. 10=EDGE 00=LEVEL
349 */ 349 */
350 uint32_t new_cfg = cfg; 350 uint32_t new_cfg = cfg;
351 uint32_t old_cfg = (cfg >> twopair_shift) & 3; 351 uint32_t old_cfg = (cfg >> twopair_shift) & 3;
352 if (is->is_type == IST_LEVEL && (old_cfg & 2) != 0) { 352 if (is->is_type == IST_LEVEL && (old_cfg & 2) != 0) {
353 new_cfg &= ~(3 << twopair_shift); 353 new_cfg &= ~(3 << twopair_shift);
354 } else if (is->is_type == IST_EDGE && (old_cfg & 2) == 0) { 354 } else if (is->is_type == IST_EDGE && (old_cfg & 2) == 0) {
355 new_cfg |= 2 << twopair_shift; 355 new_cfg |= 2 << twopair_shift;
356 } 356 }
357 if (new_cfg != cfg) { 357 if (new_cfg != cfg) {
358 gicd_write(sc, cfg_reg, cfg); 358 gicd_write(sc, cfg_reg, cfg);
359#if 0 359#if 0
360 printf("%s: irq %u: cfg changed from %#x to %#x\n", 360 printf("%s: irq %u: cfg changed from %#x to %#x\n",
361 pic->pic_name, is->is_irq, cfg, new_cfg); 361 pic->pic_name, is->is_irq, cfg, new_cfg);
362#endif 362#endif
363 } 363 }
364 } 364 }
365 365
366 /*  366 /*
367 * There are 4 irqs per PRIORITY register. Map the IPL 367 * There are 4 irqs per PRIORITY register. Map the IPL
368 * to GIC priority. 368 * to GIC priority.
369 */ 369 */
370 const bus_size_t priority_reg = GICD_IPRIORITYRn(is->is_irq / 4); 370 const bus_size_t priority_reg = GICD_IPRIORITYRn(is->is_irq / 4);
371 uint32_t priority = gicd_read(sc, priority_reg); 371 uint32_t priority = gicd_read(sc, priority_reg);
372 priority &= ~(0xff << byte_shift); 372 priority &= ~(0xff << byte_shift);
373 priority |= armgic_ipl_to_priority(is->is_ipl) << byte_shift; 373 priority |= armgic_ipl_to_priority(is->is_ipl) << byte_shift;
374 gicd_write(sc, priority_reg, priority); 374 gicd_write(sc, priority_reg, priority);
375 375
376#if 0 376#if 0
377 printf("%s: irq %u: target %#x cfg %u priority %#x (%u)\n", 377 printf("%s: irq %u: target %#x cfg %u priority %#x (%u)\n",
378 pic->pic_name, is->is_irq, (targets >> byte_shift) & 0xff, 378 pic->pic_name, is->is_irq, (targets >> byte_shift) & 0xff,
379 (cfg >> twopair_shift) & 3, (priority >> byte_shift) & 0xff, 379 (cfg >> twopair_shift) & 3, (priority >> byte_shift) & 0xff,
380 is->is_ipl); 380 is->is_ipl);
381#endif 381#endif
382} 382}
383 383
384#ifdef MULTIPROCESSOR 384#ifdef MULTIPROCESSOR
385static void 385static void
386armgic_cpu_init_priorities(struct armgic_softc *sc) 386armgic_cpu_init_priorities(struct armgic_softc *sc)
387{ 387{
388 uint32_t enabled = sc->sc_enabled_local; 388 uint32_t enabled = sc->sc_enabled_local;
389 for (size_t i = 0; i < 32; i += 4, enabled >>= 4) { 389 for (size_t i = 0; i < 32; i += 4, enabled >>= 4) {
390 /* 390 /*
391 * If there are no enabled interrupts for the priority register, 391 * If there are no enabled interrupts for the priority register,
392 * don't bother changing it. 392 * don't bother changing it.
393 */ 393 */
394 if ((enabled & 0x0f) == 0) 394 if ((enabled & 0x0f) == 0)
395 continue; 395 continue;
396 /* 396 /*
397 * Since priorities are in 3210 order, it' 397 * Since priorities are in 3210 order, it'
398 */ 398 */
399 const bus_size_t priority_reg = GICD_IPRIORITYRn(i / 4); 399 const bus_size_t priority_reg = GICD_IPRIORITYRn(i / 4);
400 uint32_t priority = gicd_read(sc, priority_reg); 400 uint32_t priority = gicd_read(sc, priority_reg);
401 uint32_t byte_mask = 0xff; 401 uint32_t byte_mask = 0xff;
402 size_t byte_shift = 0; 402 size_t byte_shift = 0;
403 for (size_t j = 0; j < 4; j++, byte_mask <<= 8, byte_shift += 8) { 403 for (size_t j = 0; j < 4; j++, byte_mask <<= 8, byte_shift += 8) {
404 struct intrsource * const is = sc->sc_pic.pic_sources[i+j]; 404 struct intrsource * const is = sc->sc_pic.pic_sources[i+j];
405 if (is == NULL || is == &armgic_dummy_source) 405 if (is == NULL || is == &armgic_dummy_source)
406 continue; 406 continue;
407 priority &= ~byte_mask; 407 priority &= ~byte_mask;
408 priority |= armgic_ipl_to_priority(is->is_ipl) << byte_shift; 408 priority |= armgic_ipl_to_priority(is->is_ipl) << byte_shift;
409 } 409 }
410 gicd_write(sc, priority_reg, priority); 410 gicd_write(sc, priority_reg, priority);
411 } 411 }
412} 412}
413 413
414void 414void
415armgic_cpu_init(struct pic_softc *pic, struct cpu_info *ci) 415armgic_cpu_init(struct pic_softc *pic, struct cpu_info *ci)
416{ 416{
417 struct armgic_softc * const sc = PICTOSOFTC(pic); 417 struct armgic_softc * const sc = PICTOSOFTC(pic);
418 if (!CPU_IS_PRIMARY(ci) && sc->sc_enabled_local) { 418 if (!CPU_IS_PRIMARY(ci) && sc->sc_enabled_local) {
419 armgic_cpu_init_priorities(sc); 419 armgic_cpu_init_priorities(sc);
420 } 420 }
421 KASSERTMSG(ci->ci_cpl == IPL_HIGH, "ipl %d not IPL_HIGH", ci->ci_cpl); 421 KASSERTMSG(ci->ci_cpl == IPL_HIGH, "ipl %d not IPL_HIGH", ci->ci_cpl);
422 gicc_write(sc, GICC_PMR, armgic_ipl_to_priority(ci->ci_cpl)); // set PMR 422 gicc_write(sc, GICC_PMR, armgic_ipl_to_priority(ci->ci_cpl)); // set PMR
423 gicc_write(sc, GICC_CTRL, GICC_CTRL_V1_Enable); // enable interrupt 423 gicc_write(sc, GICC_CTRL, GICC_CTRL_V1_Enable); // enable interrupt
424 if (!CPU_IS_PRIMARY(ci) && sc->sc_enabled_local) 424 if (!CPU_IS_PRIMARY(ci) && sc->sc_enabled_local)
425 gicd_write(sc, GICD_ISENABLERn(0), sc->sc_enabled_local); 425 gicd_write(sc, GICD_ISENABLERn(0), sc->sc_enabled_local);
426 cpsie(I32_bit); // allow IRQ exceptions 426 cpsie(I32_bit); // allow IRQ exceptions
427} 427}
428 428
429void 429void
430armgic_ipi_send(struct pic_softc *pic, const kcpuset_t *kcp, u_long ipi) 430armgic_ipi_send(struct pic_softc *pic, const kcpuset_t *kcp, u_long ipi)
431{ 431{
432 struct armgic_softc * const sc = PICTOSOFTC(pic); 432 struct armgic_softc * const sc = PICTOSOFTC(pic);
433 433
434 if (ipi == IPI_NOP) { 434 if (ipi == IPI_NOP) {
435 __asm __volatile("sev"); 435 __asm __volatile("sev");
436 return; 436 return;
437 } 437 }
438 438
439 uint32_t targets; 439 uint32_t targets;
440 kcpuset_copybits(kcp, &targets, sizeof(targets)); 440 kcpuset_export_u32(kcp, &targets, sizeof(targets));
441 uint32_t sgir = __SHIFTOUT(ARMGIC_SGI_IPIBASE + ipi, GICD_SGIR_SGIINTID); 441 uint32_t sgir = __SHIFTOUT(ARMGIC_SGI_IPIBASE + ipi, GICD_SGIR_SGIINTID);
442 sgir |= __SHIFTOUT(targets, GICD_SGIR_TargetList); 442 sgir |= __SHIFTOUT(targets, GICD_SGIR_TargetList);
443 443
444 printf("%s: %s: %#x", __func__, curcpu()->ci_data.cpu_name, sgir); 444 printf("%s: %s: %#x", __func__, curcpu()->ci_data.cpu_name, sgir);
445 gicd_write(sc, GICD_SGIR, sgir); 445 gicd_write(sc, GICD_SGIR, sgir);
446 printf("\n"); 446 printf("\n");
447} 447}
448#endif 448#endif
449 449
450int 450int
451armgic_match(device_t parent, cfdata_t cf, void *aux) 451armgic_match(device_t parent, cfdata_t cf, void *aux)
452{ 452{
453 struct mpcore_attach_args * const mpcaa = aux; 453 struct mpcore_attach_args * const mpcaa = aux;
454 454
455 if (strcmp(cf->cf_name, mpcaa->mpcaa_name) != 0) 455 if (strcmp(cf->cf_name, mpcaa->mpcaa_name) != 0)
456 return 0; 456 return 0;
457 if (!CPU_ID_CORTEX_P(cputype)) 457 if (!CPU_ID_CORTEX_P(cputype))
458 return 0; 458 return 0;
459 if (CPU_ID_CORTEX_A8_P(cputype)) 459 if (CPU_ID_CORTEX_A8_P(cputype))
460 return 0; 460 return 0;
461 461
462 return 1; 462 return 1;
463} 463}
464 464
465void 465void
466armgic_attach(device_t parent, device_t self, void *aux) 466armgic_attach(device_t parent, device_t self, void *aux)
467{ 467{
468 struct armgic_softc * const sc = &armgic_softc; 468 struct armgic_softc * const sc = &armgic_softc;
469 struct mpcore_attach_args * const mpcaa = aux; 469 struct mpcore_attach_args * const mpcaa = aux;
470 470
471 sc->sc_dev = self; 471 sc->sc_dev = self;
472 self->dv_private = sc; 472 self->dv_private = sc;
473 473
474 sc->sc_memt = mpcaa->mpcaa_memt; /* provided for us */ 474 sc->sc_memt = mpcaa->mpcaa_memt; /* provided for us */
475 sc->sc_memh = mpcaa->mpcaa_memh; /* provided for us */ 475 sc->sc_memh = mpcaa->mpcaa_memh; /* provided for us */
476 476
477 sc->sc_gic_type = gicd_read(sc, GICD_TYPER); 477 sc->sc_gic_type = gicd_read(sc, GICD_TYPER);
478 sc->sc_pic.pic_maxsources = GICD_TYPER_LINES(sc->sc_gic_type); 478 sc->sc_pic.pic_maxsources = GICD_TYPER_LINES(sc->sc_gic_type);
479 479
480 gicc_write(sc, GICC_CTRL, 0); /* disable all interrupts */ 480 gicc_write(sc, GICC_CTRL, 0); /* disable all interrupts */
481 gicd_write(sc, GICD_CTRL, 0); /* disable all interrupts */ 481 gicd_write(sc, GICD_CTRL, 0); /* disable all interrupts */
482 482
483 gicc_write(sc, GICC_PMR, 0xff); 483 gicc_write(sc, GICC_PMR, 0xff);
484 uint32_t pmr = gicc_read(sc, GICC_PMR); 484 uint32_t pmr = gicc_read(sc, GICC_PMR);
485 u_int priorities = 1 << popcount32(pmr); 485 u_int priorities = 1 << popcount32(pmr);
486 486
487 /* 487 /*
488 * Let's find out how many real sources we have. 488 * Let's find out how many real sources we have.
489 */ 489 */
490 for (size_t i = 0, group = 0; 490 for (size_t i = 0, group = 0;
491 i < sc->sc_pic.pic_maxsources; 491 i < sc->sc_pic.pic_maxsources;
492 i += 32, group++) { 492 i += 32, group++) {
493 /* 493 /*
494 * To figure what sources are real, one enables all interrupts 494 * To figure what sources are real, one enables all interrupts
495 * and then reads back the enable mask so which ones really 495 * and then reads back the enable mask so which ones really
496 * got enabled. 496 * got enabled.
497 */ 497 */
498 gicd_write(sc, GICD_ISENABLERn(group), 0xffffffff); 498 gicd_write(sc, GICD_ISENABLERn(group), 0xffffffff);
499 uint32_t valid = gicd_read(sc, GICD_ISENABLERn(group)); 499 uint32_t valid = gicd_read(sc, GICD_ISENABLERn(group));
500 500
501 /* 501 /*
502 * Now disable (clear enable) them again. 502 * Now disable (clear enable) them again.
503 */ 503 */
504 gicd_write(sc, GICD_ICENABLERn(group), valid); 504 gicd_write(sc, GICD_ICENABLERn(group), valid);
505 505
506 /* 506 /*
507 * Count how many are valid. 507 * Count how many are valid.
508 */ 508 */
509 sc->sc_gic_lines += popcount32(valid); 509 sc->sc_gic_lines += popcount32(valid);
510 sc->sc_gic_valid_lines[group] = valid; 510 sc->sc_gic_valid_lines[group] = valid;
511 } 511 }
512 512
513 pic_add(&sc->sc_pic, 0); 513 pic_add(&sc->sc_pic, 0);
514 514
515 /* 515 /*
516 * Force the GICD to IPL_HIGH and then enable interrupts. 516 * Force the GICD to IPL_HIGH and then enable interrupts.
517 */ 517 */
518 struct cpu_info * const ci = curcpu(); 518 struct cpu_info * const ci = curcpu();
519 KASSERTMSG(ci->ci_cpl == IPL_HIGH, "ipl %d not IPL_HIGH", ci->ci_cpl); 519 KASSERTMSG(ci->ci_cpl == IPL_HIGH, "ipl %d not IPL_HIGH", ci->ci_cpl);
520 armgic_set_priority(&sc->sc_pic, ci->ci_cpl); // set PMR 520 armgic_set_priority(&sc->sc_pic, ci->ci_cpl); // set PMR
521 gicd_write(sc, GICD_CTRL, GICD_CTRL_Enable); // enable Distributer 521 gicd_write(sc, GICD_CTRL, GICD_CTRL_Enable); // enable Distributer
522 gicc_write(sc, GICC_CTRL, GICC_CTRL_V1_Enable); // enable CPU interrupts 522 gicc_write(sc, GICC_CTRL, GICC_CTRL_V1_Enable); // enable CPU interrupts
523 cpsie(I32_bit); // allow interrupt exceptions 523 cpsie(I32_bit); // allow interrupt exceptions
524 524
525 /* 525 /*
526 * For each line that isn't valid, we set the intrsource for it to 526 * For each line that isn't valid, we set the intrsource for it to
527 * point at a dummy source so that pic_intr_establish will fail for it. 527 * point at a dummy source so that pic_intr_establish will fail for it.
528 */ 528 */
529 for (size_t i = 0, group = 0; 529 for (size_t i = 0, group = 0;
530 i < sc->sc_pic.pic_maxsources; 530 i < sc->sc_pic.pic_maxsources;
531 i += 32, group++) { 531 i += 32, group++) {
532 uint32_t invalid = ~sc->sc_gic_valid_lines[group]; 532 uint32_t invalid = ~sc->sc_gic_valid_lines[group];
533 for (size_t j = 0; invalid && j < 32; j++, invalid >>= 1) { 533 for (size_t j = 0; invalid && j < 32; j++, invalid >>= 1) {
534 if (invalid & 1) { 534 if (invalid & 1) {
535 sc->sc_pic.pic_sources[i + j] = 535 sc->sc_pic.pic_sources[i + j] =
536 &armgic_dummy_source; 536 &armgic_dummy_source;
537 } 537 }
538 } 538 }
539 } 539 }
540#ifdef __HAVE_PIC_FAST_SOFTINTS 540#ifdef __HAVE_PIC_FAST_SOFTINTS
541 intr_establish(SOFTINT_BIO, IPL_SOFTBIO, IST_EDGE, 541 intr_establish(SOFTINT_BIO, IPL_SOFTBIO, IST_EDGE,
542 pic_handle_softint, (void *)SOFTINT_BIO); 542 pic_handle_softint, (void *)SOFTINT_BIO);
543 intr_establish(SOFTINT_CLOCK, IPL_SOFTCLOCK, IST_EDGE, 543 intr_establish(SOFTINT_CLOCK, IPL_SOFTCLOCK, IST_EDGE,
544 pic_handle_softint, (void *)SOFTINT_CLOCK); 544 pic_handle_softint, (void *)SOFTINT_CLOCK);
545 intr_establish(SOFTINT_NET, IPL_SOFTNET, IST_EDGE, 545 intr_establish(SOFTINT_NET, IPL_SOFTNET, IST_EDGE,
546 pic_handle_softint, (void *)SOFTINT_NET); 546 pic_handle_softint, (void *)SOFTINT_NET);
547 intr_establish(SOFTINT_SERIAL, IPL_SOFTSERIAL, IST_EDGE, 547 intr_establish(SOFTINT_SERIAL, IPL_SOFTSERIAL, IST_EDGE,
548 pic_handle_softint, (void *)SOFTINT_SERIAL); 548 pic_handle_softint, (void *)SOFTINT_SERIAL);
549#endif 549#endif
550#ifdef MULTIPROCESSOR 550#ifdef MULTIPROCESSOR
551 intr_establish(ARMGIC_SGI_IPIBASE + IPI_AST, IPL_VM, IST_EDGE, 551 intr_establish(ARMGIC_SGI_IPIBASE + IPI_AST, IPL_VM, IST_EDGE,
552 pic_ipi_nop, (void *)-1); 552 pic_ipi_nop, (void *)-1);
553 intr_establish(ARMGIC_SGI_IPIBASE + IPI_XCALL, IPL_VM, IST_EDGE, 553 intr_establish(ARMGIC_SGI_IPIBASE + IPI_XCALL, IPL_VM, IST_EDGE,
554 pic_ipi_xcall, (void *)-1); 554 pic_ipi_xcall, (void *)-1);
555#if 0 /* Not needed */ 555#if 0 /* Not needed */
556 intr_establish(ARMGIC_SGI_IPIBASE + IPI_NOP, IPL_VM, IST_EDGE, 556 intr_establish(ARMGIC_SGI_IPIBASE + IPI_NOP, IPL_VM, IST_EDGE,
557 pic_ipi_nop, (void *)-1); 557 pic_ipi_nop, (void *)-1);
558#endif 558#endif
559#ifdef __HAVE_PREEMPTION 559#ifdef __HAVE_PREEMPTION
560 intr_establish(ARMGIC_SGI_IPIBASE + IPI_KPREEMPT, IPL_VM, IST_EDGE, 560 intr_establish(ARMGIC_SGI_IPIBASE + IPI_KPREEMPT, IPL_VM, IST_EDGE,
561 pic_ipi_nop, (void *)-1); 561 pic_ipi_nop, (void *)-1);
562#endif 562#endif
563 armgic_cpu_init(&sc->sc_pic, curcpu()); 563 armgic_cpu_init(&sc->sc_pic, curcpu());
564#endif 564#endif
565 565
566 aprint_normal(": Generic Interrupt Controller, " 566 aprint_normal(": Generic Interrupt Controller, "
567 "%zu sources (%zu valid)\n", 567 "%zu sources (%zu valid)\n",
568 sc->sc_pic.pic_maxsources, sc->sc_gic_lines); 568 sc->sc_pic.pic_maxsources, sc->sc_gic_lines);
569 569
570 const u_int ppis = popcount32(sc->sc_gic_valid_lines[0] >> 16); 570 const u_int ppis = popcount32(sc->sc_gic_valid_lines[0] >> 16);
571 const u_int sgis = popcount32(sc->sc_gic_valid_lines[0] & 0xffff); 571 const u_int sgis = popcount32(sc->sc_gic_valid_lines[0] & 0xffff);
572 aprint_normal_dev(sc->sc_dev, "%u Priorities, %zu SPIs, %u PPIs, %u SGIs\n", 572 aprint_normal_dev(sc->sc_dev, "%u Priorities, %zu SPIs, %u PPIs, %u SGIs\n",
573 priorities, sc->sc_gic_lines - ppis - sgis, ppis, sgis); 573 priorities, sc->sc_gic_lines - ppis - sgis, ppis, sgis);
574} 574}
575 575
576CFATTACH_DECL_NEW(armgic, 0, 576CFATTACH_DECL_NEW(armgic, 0,
577 armgic_match, armgic_attach, NULL, NULL); 577 armgic_match, armgic_attach, NULL, NULL);

cvs diff -r1.48 -r1.49 src/sys/arch/xen/x86/x86_xpmap.c (switch to unified diff)

--- src/sys/arch/xen/x86/x86_xpmap.c 2012/08/21 09:06:02 1.48
+++ src/sys/arch/xen/x86/x86_xpmap.c 2012/09/16 22:09:34 1.49
@@ -1,1114 +1,1114 @@ @@ -1,1114 +1,1114 @@
1/* $NetBSD: x86_xpmap.c,v 1.48 2012/08/21 09:06:02 bouyer Exp $ */ 1/* $NetBSD: x86_xpmap.c,v 1.49 2012/09/16 22:09:34 rmind Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006 Mathieu Ropert <mro@adviseo.fr> 4 * Copyright (c) 2006 Mathieu Ropert <mro@adviseo.fr>
5 * 5 *
6 * Permission to use, copy, modify, and distribute this software for any 6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above 7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies. 8 * copyright notice and this permission notice appear in all copies.
9 * 9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */ 17 */
18 18
19/* 19/*
20 * Copyright (c) 2006, 2007 Manuel Bouyer. 20 * Copyright (c) 2006, 2007 Manuel Bouyer.
21 * 21 *
22 * Redistribution and use in source and binary forms, with or without 22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions 23 * modification, are permitted provided that the following conditions
24 * are met: 24 * are met:
25 * 1. Redistributions of source code must retain the above copyright 25 * 1. Redistributions of source code must retain the above copyright
26 * notice, this list of conditions and the following disclaimer. 26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright 27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the 28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution. 29 * documentation and/or other materials provided with the distribution.
30 * 30 *
31 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 31 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
32 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 32 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
33 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 33 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 34 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
40 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 * 41 *
42 */ 42 */
43 43
44/* 44/*
45 * 45 *
46 * Copyright (c) 2004 Christian Limpach. 46 * Copyright (c) 2004 Christian Limpach.
47 * All rights reserved. 47 * All rights reserved.
48 * 48 *
49 * Redistribution and use in source and binary forms, with or without 49 * Redistribution and use in source and binary forms, with or without
50 * modification, are permitted provided that the following conditions 50 * modification, are permitted provided that the following conditions
51 * are met: 51 * are met:
52 * 1. Redistributions of source code must retain the above copyright 52 * 1. Redistributions of source code must retain the above copyright
53 * notice, this list of conditions and the following disclaimer. 53 * notice, this list of conditions and the following disclaimer.
54 * 2. Redistributions in binary form must reproduce the above copyright 54 * 2. Redistributions in binary form must reproduce the above copyright
55 * notice, this list of conditions and the following disclaimer in the 55 * notice, this list of conditions and the following disclaimer in the
56 * documentation and/or other materials provided with the distribution. 56 * documentation and/or other materials provided with the distribution.
57 * 57 *
58 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 58 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
59 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 59 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
60 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 60 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
61 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 61 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
62 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 62 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
63 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 63 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
64 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 64 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
65 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 65 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
66 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 66 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
67 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 67 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
68 */ 68 */
69 69
70 70
71#include <sys/cdefs.h> 71#include <sys/cdefs.h>
72__KERNEL_RCSID(0, "$NetBSD: x86_xpmap.c,v 1.48 2012/08/21 09:06:02 bouyer Exp $"); 72__KERNEL_RCSID(0, "$NetBSD: x86_xpmap.c,v 1.49 2012/09/16 22:09:34 rmind Exp $");
73 73
74#include "opt_xen.h" 74#include "opt_xen.h"
75#include "opt_ddb.h" 75#include "opt_ddb.h"
76#include "ksyms.h" 76#include "ksyms.h"
77 77
78#include <sys/param.h> 78#include <sys/param.h>
79#include <sys/systm.h> 79#include <sys/systm.h>
80#include <sys/mutex.h> 80#include <sys/mutex.h>
81#include <sys/cpu.h> 81#include <sys/cpu.h>
82 82
83#include <uvm/uvm.h> 83#include <uvm/uvm.h>
84 84
85#include <x86/pmap.h> 85#include <x86/pmap.h>
86#include <machine/gdt.h> 86#include <machine/gdt.h>
87#include <xen/xenfunc.h> 87#include <xen/xenfunc.h>
88 88
89#include <dev/isa/isareg.h> 89#include <dev/isa/isareg.h>
90#include <machine/isa_machdep.h> 90#include <machine/isa_machdep.h>
91 91
92#undef XENDEBUG 92#undef XENDEBUG
93/* #define XENDEBUG_SYNC */ 93/* #define XENDEBUG_SYNC */
94/* #define XENDEBUG_LOW */ 94/* #define XENDEBUG_LOW */
95 95
96#ifdef XENDEBUG 96#ifdef XENDEBUG
97#define XENPRINTF(x) printf x 97#define XENPRINTF(x) printf x
98#define XENPRINTK(x) printk x 98#define XENPRINTK(x) printk x
99#define XENPRINTK2(x) /* printk x */ 99#define XENPRINTK2(x) /* printk x */
100 100
101static char XBUF[256]; 101static char XBUF[256];
102#else 102#else
103#define XENPRINTF(x) 103#define XENPRINTF(x)
104#define XENPRINTK(x) 104#define XENPRINTK(x)
105#define XENPRINTK2(x) 105#define XENPRINTK2(x)
106#endif 106#endif
107#define PRINTF(x) printf x 107#define PRINTF(x) printf x
108#define PRINTK(x) printk x 108#define PRINTK(x) printk x
109 109
110volatile shared_info_t *HYPERVISOR_shared_info; 110volatile shared_info_t *HYPERVISOR_shared_info;
111/* Xen requires the start_info struct to be page aligned */ 111/* Xen requires the start_info struct to be page aligned */
112union start_info_union start_info_union __aligned(PAGE_SIZE); 112union start_info_union start_info_union __aligned(PAGE_SIZE);
113unsigned long *xpmap_phys_to_machine_mapping; 113unsigned long *xpmap_phys_to_machine_mapping;
114kmutex_t pte_lock; 114kmutex_t pte_lock;
115 115
116void xen_failsafe_handler(void); 116void xen_failsafe_handler(void);
117 117
118#define HYPERVISOR_mmu_update_self(req, count, success_count) \ 118#define HYPERVISOR_mmu_update_self(req, count, success_count) \
119 HYPERVISOR_mmu_update((req), (count), (success_count), DOMID_SELF) 119 HYPERVISOR_mmu_update((req), (count), (success_count), DOMID_SELF)
120 120
121/* 121/*
122 * kcpuset internally uses an array of uint32_t while xen uses an array of 122 * kcpuset internally uses an array of uint32_t while xen uses an array of
123 * u_long. As we're little-endian we can cast one to the other. 123 * u_long. As we're little-endian we can cast one to the other.
124 */ 124 */
125typedef union { 125typedef union {
126#ifdef _LP64 126#ifdef _LP64
127 uint32_t xcpum_km[2]; 127 uint32_t xcpum_km[2];
128#else 128#else
129 uint32_t xcpum_km[1]; 129 uint32_t xcpum_km[1];
130#endif  130#endif
131 u_long xcpum_xm; 131 u_long xcpum_xm;
132} xcpumask_t; 132} xcpumask_t;
133 133
134void 134void
135xen_failsafe_handler(void) 135xen_failsafe_handler(void)
136{ 136{
137 137
138 panic("xen_failsafe_handler called!\n"); 138 panic("xen_failsafe_handler called!\n");
139} 139}
140 140
141 141
142void 142void
143xen_set_ldt(vaddr_t base, uint32_t entries) 143xen_set_ldt(vaddr_t base, uint32_t entries)
144{ 144{
145 vaddr_t va; 145 vaddr_t va;
146 vaddr_t end; 146 vaddr_t end;
147 pt_entry_t *ptp; 147 pt_entry_t *ptp;
148 int s; 148 int s;
149 149
150#ifdef __x86_64__ 150#ifdef __x86_64__
151 end = base + (entries << 3); 151 end = base + (entries << 3);
152#else 152#else
153 end = base + entries * sizeof(union descriptor); 153 end = base + entries * sizeof(union descriptor);
154#endif 154#endif
155 155
156 for (va = base; va < end; va += PAGE_SIZE) { 156 for (va = base; va < end; va += PAGE_SIZE) {
157 KASSERT(va >= VM_MIN_KERNEL_ADDRESS); 157 KASSERT(va >= VM_MIN_KERNEL_ADDRESS);
158 ptp = kvtopte(va); 158 ptp = kvtopte(va);
159 XENPRINTF(("xen_set_ldt %#" PRIxVADDR " %d %p\n", 159 XENPRINTF(("xen_set_ldt %#" PRIxVADDR " %d %p\n",
160 base, entries, ptp)); 160 base, entries, ptp));
161 pmap_pte_clearbits(ptp, PG_RW); 161 pmap_pte_clearbits(ptp, PG_RW);
162 } 162 }
163 s = splvm(); 163 s = splvm();
164 xpq_queue_set_ldt(base, entries); 164 xpq_queue_set_ldt(base, entries);
165 splx(s); 165 splx(s);
166} 166}
167 167
168#ifdef XENDEBUG 168#ifdef XENDEBUG
169void xpq_debug_dump(void); 169void xpq_debug_dump(void);
170#endif 170#endif
171 171
172#define XPQUEUE_SIZE 2048 172#define XPQUEUE_SIZE 2048
173static mmu_update_t xpq_queue_array[MAXCPUS][XPQUEUE_SIZE]; 173static mmu_update_t xpq_queue_array[MAXCPUS][XPQUEUE_SIZE];
174static int xpq_idx_array[MAXCPUS]; 174static int xpq_idx_array[MAXCPUS];
175 175
176#ifdef i386 176#ifdef i386
177extern union descriptor tmpgdt[]; 177extern union descriptor tmpgdt[];
178#endif /* i386 */ 178#endif /* i386 */
179void 179void
180xpq_flush_queue(void) 180xpq_flush_queue(void)
181{ 181{
182 int i, ok = 0, ret; 182 int i, ok = 0, ret;
183 183
184 mmu_update_t *xpq_queue = xpq_queue_array[curcpu()->ci_cpuid]; 184 mmu_update_t *xpq_queue = xpq_queue_array[curcpu()->ci_cpuid];
185 int xpq_idx = xpq_idx_array[curcpu()->ci_cpuid]; 185 int xpq_idx = xpq_idx_array[curcpu()->ci_cpuid];
186 186
187 XENPRINTK2(("flush queue %p entries %d\n", xpq_queue, xpq_idx)); 187 XENPRINTK2(("flush queue %p entries %d\n", xpq_queue, xpq_idx));
188 for (i = 0; i < xpq_idx; i++) 188 for (i = 0; i < xpq_idx; i++)
189 XENPRINTK2(("%d: 0x%08" PRIx64 " 0x%08" PRIx64 "\n", i, 189 XENPRINTK2(("%d: 0x%08" PRIx64 " 0x%08" PRIx64 "\n", i,
190 xpq_queue[i].ptr, xpq_queue[i].val)); 190 xpq_queue[i].ptr, xpq_queue[i].val));
191 191
192retry: 192retry:
193 ret = HYPERVISOR_mmu_update_self(xpq_queue, xpq_idx, &ok); 193 ret = HYPERVISOR_mmu_update_self(xpq_queue, xpq_idx, &ok);
194 194
195 if (xpq_idx != 0 && ret < 0) { 195 if (xpq_idx != 0 && ret < 0) {
196 struct cpu_info *ci; 196 struct cpu_info *ci;
197 CPU_INFO_ITERATOR cii; 197 CPU_INFO_ITERATOR cii;
198 198
199 printf("xpq_flush_queue: %d entries (%d successful) on " 199 printf("xpq_flush_queue: %d entries (%d successful) on "
200 "cpu%d (%ld)\n", 200 "cpu%d (%ld)\n",
201 xpq_idx, ok, curcpu()->ci_index, curcpu()->ci_cpuid); 201 xpq_idx, ok, curcpu()->ci_index, curcpu()->ci_cpuid);
202 202
203 if (ok != 0) { 203 if (ok != 0) {
204 xpq_queue += ok; 204 xpq_queue += ok;
205 xpq_idx -= ok; 205 xpq_idx -= ok;
206 ok = 0; 206 ok = 0;
207 goto retry; 207 goto retry;
208 } 208 }
209 209
210 for (CPU_INFO_FOREACH(cii, ci)) { 210 for (CPU_INFO_FOREACH(cii, ci)) {
211 xpq_queue = xpq_queue_array[ci->ci_cpuid]; 211 xpq_queue = xpq_queue_array[ci->ci_cpuid];
212 xpq_idx = xpq_idx_array[ci->ci_cpuid]; 212 xpq_idx = xpq_idx_array[ci->ci_cpuid];
213 printf("cpu%d (%ld):\n", ci->ci_index, ci->ci_cpuid); 213 printf("cpu%d (%ld):\n", ci->ci_index, ci->ci_cpuid);
214 for (i = 0; i < xpq_idx; i++) { 214 for (i = 0; i < xpq_idx; i++) {
215 printf(" 0x%016" PRIx64 ": 0x%016" PRIx64 "\n", 215 printf(" 0x%016" PRIx64 ": 0x%016" PRIx64 "\n",
216 xpq_queue[i].ptr, xpq_queue[i].val); 216 xpq_queue[i].ptr, xpq_queue[i].val);
217 } 217 }
218#ifdef __x86_64__ 218#ifdef __x86_64__
219 for (i = 0; i < PDIR_SLOT_PTE; i++) { 219 for (i = 0; i < PDIR_SLOT_PTE; i++) {
220 if (ci->ci_kpm_pdir[i] == 0) 220 if (ci->ci_kpm_pdir[i] == 0)
221 continue; 221 continue;
222 printf(" kpm_pdir[%d]: 0x%" PRIx64 "\n", 222 printf(" kpm_pdir[%d]: 0x%" PRIx64 "\n",
223 i, ci->ci_kpm_pdir[i]); 223 i, ci->ci_kpm_pdir[i]);
224 } 224 }
225#endif 225#endif
226 } 226 }
227 panic("HYPERVISOR_mmu_update failed, ret: %d\n", ret); 227 panic("HYPERVISOR_mmu_update failed, ret: %d\n", ret);
228 } 228 }
229 xpq_idx_array[curcpu()->ci_cpuid] = 0; 229 xpq_idx_array[curcpu()->ci_cpuid] = 0;
230} 230}
231 231
232static inline void 232static inline void
233xpq_increment_idx(void) 233xpq_increment_idx(void)
234{ 234{
235 235
236 if (__predict_false(++xpq_idx_array[curcpu()->ci_cpuid] == XPQUEUE_SIZE)) 236 if (__predict_false(++xpq_idx_array[curcpu()->ci_cpuid] == XPQUEUE_SIZE))
237 xpq_flush_queue(); 237 xpq_flush_queue();
238} 238}
239 239
240void 240void
241xpq_queue_machphys_update(paddr_t ma, paddr_t pa) 241xpq_queue_machphys_update(paddr_t ma, paddr_t pa)
242{ 242{
243 243
244 mmu_update_t *xpq_queue = xpq_queue_array[curcpu()->ci_cpuid]; 244 mmu_update_t *xpq_queue = xpq_queue_array[curcpu()->ci_cpuid];
245 int xpq_idx = xpq_idx_array[curcpu()->ci_cpuid]; 245 int xpq_idx = xpq_idx_array[curcpu()->ci_cpuid];
246 246
247 XENPRINTK2(("xpq_queue_machphys_update ma=0x%" PRIx64 " pa=0x%" PRIx64 247 XENPRINTK2(("xpq_queue_machphys_update ma=0x%" PRIx64 " pa=0x%" PRIx64
248 "\n", (int64_t)ma, (int64_t)pa)); 248 "\n", (int64_t)ma, (int64_t)pa));
249 249
250 xpq_queue[xpq_idx].ptr = ma | MMU_MACHPHYS_UPDATE; 250 xpq_queue[xpq_idx].ptr = ma | MMU_MACHPHYS_UPDATE;
251 xpq_queue[xpq_idx].val = pa >> PAGE_SHIFT; 251 xpq_queue[xpq_idx].val = pa >> PAGE_SHIFT;
252 xpq_increment_idx(); 252 xpq_increment_idx();
253#ifdef XENDEBUG_SYNC 253#ifdef XENDEBUG_SYNC
254 xpq_flush_queue(); 254 xpq_flush_queue();
255#endif 255#endif
256} 256}
257 257
258void 258void
259xpq_queue_pte_update(paddr_t ptr, pt_entry_t val) 259xpq_queue_pte_update(paddr_t ptr, pt_entry_t val)
260{ 260{
261 261
262 mmu_update_t *xpq_queue = xpq_queue_array[curcpu()->ci_cpuid]; 262 mmu_update_t *xpq_queue = xpq_queue_array[curcpu()->ci_cpuid];
263 int xpq_idx = xpq_idx_array[curcpu()->ci_cpuid]; 263 int xpq_idx = xpq_idx_array[curcpu()->ci_cpuid];
264 264
265 KASSERT((ptr & 3) == 0); 265 KASSERT((ptr & 3) == 0);
266 xpq_queue[xpq_idx].ptr = (paddr_t)ptr | MMU_NORMAL_PT_UPDATE; 266 xpq_queue[xpq_idx].ptr = (paddr_t)ptr | MMU_NORMAL_PT_UPDATE;
267 xpq_queue[xpq_idx].val = val; 267 xpq_queue[xpq_idx].val = val;
268 xpq_increment_idx(); 268 xpq_increment_idx();
269#ifdef XENDEBUG_SYNC 269#ifdef XENDEBUG_SYNC
270 xpq_flush_queue(); 270 xpq_flush_queue();
271#endif 271#endif
272} 272}
273 273
274void 274void
275xpq_queue_pt_switch(paddr_t pa) 275xpq_queue_pt_switch(paddr_t pa)
276{ 276{
277 struct mmuext_op op; 277 struct mmuext_op op;
278 xpq_flush_queue(); 278 xpq_flush_queue();
279 279
280 XENPRINTK2(("xpq_queue_pt_switch: 0x%" PRIx64 " 0x%" PRIx64 "\n", 280 XENPRINTK2(("xpq_queue_pt_switch: 0x%" PRIx64 " 0x%" PRIx64 "\n",
281 (int64_t)pa, (int64_t)pa)); 281 (int64_t)pa, (int64_t)pa));
282 op.cmd = MMUEXT_NEW_BASEPTR; 282 op.cmd = MMUEXT_NEW_BASEPTR;
283 op.arg1.mfn = pa >> PAGE_SHIFT; 283 op.arg1.mfn = pa >> PAGE_SHIFT;
284 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) 284 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0)
285 panic("xpq_queue_pt_switch"); 285 panic("xpq_queue_pt_switch");
286} 286}
287 287
288void 288void
289xpq_queue_pin_table(paddr_t pa, int lvl) 289xpq_queue_pin_table(paddr_t pa, int lvl)
290{ 290{
291 struct mmuext_op op; 291 struct mmuext_op op;
292 292
293 xpq_flush_queue(); 293 xpq_flush_queue();
294 294
295 XENPRINTK2(("xpq_queue_pin_l%d_table: %#" PRIxPADDR "\n", 295 XENPRINTK2(("xpq_queue_pin_l%d_table: %#" PRIxPADDR "\n",
296 lvl + 1, pa)); 296 lvl + 1, pa));
297 297
298 op.arg1.mfn = pa >> PAGE_SHIFT; 298 op.arg1.mfn = pa >> PAGE_SHIFT;
299 op.cmd = lvl; 299 op.cmd = lvl;
300 300
301 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) 301 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0)
302 panic("xpq_queue_pin_table"); 302 panic("xpq_queue_pin_table");
303} 303}
304 304
305void 305void
306xpq_queue_unpin_table(paddr_t pa) 306xpq_queue_unpin_table(paddr_t pa)
307{ 307{
308 struct mmuext_op op; 308 struct mmuext_op op;
309 309
310 xpq_flush_queue(); 310 xpq_flush_queue();
311 311
312 XENPRINTK2(("xpq_queue_unpin_table: %#" PRIxPADDR "\n", pa)); 312 XENPRINTK2(("xpq_queue_unpin_table: %#" PRIxPADDR "\n", pa));
313 op.arg1.mfn = pa >> PAGE_SHIFT; 313 op.arg1.mfn = pa >> PAGE_SHIFT;
314 op.cmd = MMUEXT_UNPIN_TABLE; 314 op.cmd = MMUEXT_UNPIN_TABLE;
315 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) 315 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0)
316 panic("xpq_queue_unpin_table"); 316 panic("xpq_queue_unpin_table");
317} 317}
318 318
319void 319void
320xpq_queue_set_ldt(vaddr_t va, uint32_t entries) 320xpq_queue_set_ldt(vaddr_t va, uint32_t entries)
321{ 321{
322 struct mmuext_op op; 322 struct mmuext_op op;
323 323
324 xpq_flush_queue(); 324 xpq_flush_queue();
325 325
326 XENPRINTK2(("xpq_queue_set_ldt\n")); 326 XENPRINTK2(("xpq_queue_set_ldt\n"));
327 KASSERT(va == (va & ~PAGE_MASK)); 327 KASSERT(va == (va & ~PAGE_MASK));
328 op.cmd = MMUEXT_SET_LDT; 328 op.cmd = MMUEXT_SET_LDT;
329 op.arg1.linear_addr = va; 329 op.arg1.linear_addr = va;
330 op.arg2.nr_ents = entries; 330 op.arg2.nr_ents = entries;
331 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) 331 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0)
332 panic("xpq_queue_set_ldt"); 332 panic("xpq_queue_set_ldt");
333} 333}
334 334
335void 335void
336xpq_queue_tlb_flush(void) 336xpq_queue_tlb_flush(void)
337{ 337{
338 struct mmuext_op op; 338 struct mmuext_op op;
339 339
340 xpq_flush_queue(); 340 xpq_flush_queue();
341 341
342 XENPRINTK2(("xpq_queue_tlb_flush\n")); 342 XENPRINTK2(("xpq_queue_tlb_flush\n"));
343 op.cmd = MMUEXT_TLB_FLUSH_LOCAL; 343 op.cmd = MMUEXT_TLB_FLUSH_LOCAL;
344 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) 344 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0)
345 panic("xpq_queue_tlb_flush"); 345 panic("xpq_queue_tlb_flush");
346} 346}
347 347
348void 348void
349xpq_flush_cache(void) 349xpq_flush_cache(void)
350{ 350{
351 struct mmuext_op op; 351 struct mmuext_op op;
352 int s = splvm(), err; 352 int s = splvm(), err;
353 353
354 xpq_flush_queue(); 354 xpq_flush_queue();
355 355
356 XENPRINTK2(("xpq_queue_flush_cache\n")); 356 XENPRINTK2(("xpq_queue_flush_cache\n"));
357 op.cmd = MMUEXT_FLUSH_CACHE; 357 op.cmd = MMUEXT_FLUSH_CACHE;
358 if ((err = HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF)) < 0) { 358 if ((err = HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF)) < 0) {
359 panic("xpq_flush_cache, err %d", err); 359 panic("xpq_flush_cache, err %d", err);
360 } 360 }
361 splx(s); /* XXX: removeme */ 361 splx(s); /* XXX: removeme */
362} 362}
363 363
364void 364void
365xpq_queue_invlpg(vaddr_t va) 365xpq_queue_invlpg(vaddr_t va)
366{ 366{
367 struct mmuext_op op; 367 struct mmuext_op op;
368 xpq_flush_queue(); 368 xpq_flush_queue();
369 369
370 XENPRINTK2(("xpq_queue_invlpg %#" PRIxVADDR "\n", va)); 370 XENPRINTK2(("xpq_queue_invlpg %#" PRIxVADDR "\n", va));
371 op.cmd = MMUEXT_INVLPG_LOCAL; 371 op.cmd = MMUEXT_INVLPG_LOCAL;
372 op.arg1.linear_addr = (va & ~PAGE_MASK); 372 op.arg1.linear_addr = (va & ~PAGE_MASK);
373 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) 373 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0)
374 panic("xpq_queue_invlpg"); 374 panic("xpq_queue_invlpg");
375} 375}
376 376
377void 377void
378xen_mcast_invlpg(vaddr_t va, kcpuset_t *kc) 378xen_mcast_invlpg(vaddr_t va, kcpuset_t *kc)
379{ 379{
380 xcpumask_t xcpumask; 380 xcpumask_t xcpumask;
381 mmuext_op_t op; 381 mmuext_op_t op;
382 382
383 kcpuset_copybits(kc, &xcpumask.xcpum_km[0], sizeof(xcpumask)); 383 kcpuset_export_u32(kc, &xcpumask.xcpum_km[0], sizeof(xcpumask));
384 384
385 /* Flush pending page updates */ 385 /* Flush pending page updates */
386 xpq_flush_queue(); 386 xpq_flush_queue();
387 387
388 op.cmd = MMUEXT_INVLPG_MULTI; 388 op.cmd = MMUEXT_INVLPG_MULTI;
389 op.arg1.linear_addr = va; 389 op.arg1.linear_addr = va;
390 op.arg2.vcpumask = &xcpumask.xcpum_xm; 390 op.arg2.vcpumask = &xcpumask.xcpum_xm;
391 391
392 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) { 392 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) {
393 panic("xpq_queue_invlpg_all"); 393 panic("xpq_queue_invlpg_all");
394 } 394 }
395 395
396 return; 396 return;
397} 397}
398 398
399void 399void
400xen_bcast_invlpg(vaddr_t va) 400xen_bcast_invlpg(vaddr_t va)
401{ 401{
402 mmuext_op_t op; 402 mmuext_op_t op;
403 403
404 /* Flush pending page updates */ 404 /* Flush pending page updates */
405 xpq_flush_queue(); 405 xpq_flush_queue();
406 406
407 op.cmd = MMUEXT_INVLPG_ALL; 407 op.cmd = MMUEXT_INVLPG_ALL;
408 op.arg1.linear_addr = va; 408 op.arg1.linear_addr = va;
409 409
410 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) { 410 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) {
411 panic("xpq_queue_invlpg_all"); 411 panic("xpq_queue_invlpg_all");
412 } 412 }
413 413
414 return; 414 return;
415} 415}
416 416
417/* This is a synchronous call. */ 417/* This is a synchronous call. */
418void 418void
419xen_mcast_tlbflush(kcpuset_t *kc) 419xen_mcast_tlbflush(kcpuset_t *kc)
420{ 420{
421 xcpumask_t xcpumask; 421 xcpumask_t xcpumask;
422 mmuext_op_t op; 422 mmuext_op_t op;
423 423
424 kcpuset_copybits(kc, &xcpumask.xcpum_km[0], sizeof(xcpumask)); 424 kcpuset_export_u32(kc, &xcpumask.xcpum_km[0], sizeof(xcpumask));
425 425
426 /* Flush pending page updates */ 426 /* Flush pending page updates */
427 xpq_flush_queue(); 427 xpq_flush_queue();
428 428
429 op.cmd = MMUEXT_TLB_FLUSH_MULTI; 429 op.cmd = MMUEXT_TLB_FLUSH_MULTI;
430 op.arg2.vcpumask = &xcpumask.xcpum_xm; 430 op.arg2.vcpumask = &xcpumask.xcpum_xm;
431 431
432 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) { 432 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) {
433 panic("xpq_queue_invlpg_all"); 433 panic("xpq_queue_invlpg_all");
434 } 434 }
435 435
436 return; 436 return;
437} 437}
438 438
439/* This is a synchronous call. */ 439/* This is a synchronous call. */
440void 440void
441xen_bcast_tlbflush(void) 441xen_bcast_tlbflush(void)
442{ 442{
443 mmuext_op_t op; 443 mmuext_op_t op;
444 444
445 /* Flush pending page updates */ 445 /* Flush pending page updates */
446 xpq_flush_queue(); 446 xpq_flush_queue();
447 447
448 op.cmd = MMUEXT_TLB_FLUSH_ALL; 448 op.cmd = MMUEXT_TLB_FLUSH_ALL;
449 449
450 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) { 450 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) {
451 panic("xpq_queue_invlpg_all"); 451 panic("xpq_queue_invlpg_all");
452 } 452 }
453 453
454 return; 454 return;
455} 455}
456 456
457/* This is a synchronous call. */ 457/* This is a synchronous call. */
458void 458void
459xen_vcpu_mcast_invlpg(vaddr_t sva, vaddr_t eva, kcpuset_t *kc) 459xen_vcpu_mcast_invlpg(vaddr_t sva, vaddr_t eva, kcpuset_t *kc)
460{ 460{
461 KASSERT(eva > sva); 461 KASSERT(eva > sva);
462 462
463 /* Flush pending page updates */ 463 /* Flush pending page updates */
464 xpq_flush_queue(); 464 xpq_flush_queue();
465 465
466 /* Align to nearest page boundary */ 466 /* Align to nearest page boundary */
467 sva &= ~PAGE_MASK; 467 sva &= ~PAGE_MASK;
468 eva &= ~PAGE_MASK; 468 eva &= ~PAGE_MASK;
469 469
470 for ( ; sva <= eva; sva += PAGE_SIZE) { 470 for ( ; sva <= eva; sva += PAGE_SIZE) {
471 xen_mcast_invlpg(sva, kc); 471 xen_mcast_invlpg(sva, kc);
472 } 472 }
473 473
474 return; 474 return;
475} 475}
476 476
477/* This is a synchronous call. */ 477/* This is a synchronous call. */
478void 478void
479xen_vcpu_bcast_invlpg(vaddr_t sva, vaddr_t eva) 479xen_vcpu_bcast_invlpg(vaddr_t sva, vaddr_t eva)
480{ 480{
481 KASSERT(eva > sva); 481 KASSERT(eva > sva);
482 482
483 /* Flush pending page updates */ 483 /* Flush pending page updates */
484 xpq_flush_queue(); 484 xpq_flush_queue();
485 485
486 /* Align to nearest page boundary */ 486 /* Align to nearest page boundary */
487 sva &= ~PAGE_MASK; 487 sva &= ~PAGE_MASK;
488 eva &= ~PAGE_MASK; 488 eva &= ~PAGE_MASK;
489 489
490 for ( ; sva <= eva; sva += PAGE_SIZE) { 490 for ( ; sva <= eva; sva += PAGE_SIZE) {
491 xen_bcast_invlpg(sva); 491 xen_bcast_invlpg(sva);
492 } 492 }
493 493
494 return; 494 return;
495} 495}
496 496
497int 497int
498xpq_update_foreign(paddr_t ptr, pt_entry_t val, int dom) 498xpq_update_foreign(paddr_t ptr, pt_entry_t val, int dom)
499{ 499{
500 mmu_update_t op; 500 mmu_update_t op;
501 int ok; 501 int ok;
502 502
503 xpq_flush_queue(); 503 xpq_flush_queue();
504 504
505 op.ptr = ptr; 505 op.ptr = ptr;
506 op.val = val; 506 op.val = val;
507 if (HYPERVISOR_mmu_update(&op, 1, &ok, dom) < 0) 507 if (HYPERVISOR_mmu_update(&op, 1, &ok, dom) < 0)
508 return EFAULT; 508 return EFAULT;
509 return (0); 509 return (0);
510} 510}
511 511
512#ifdef XENDEBUG 512#ifdef XENDEBUG
513void 513void
514xpq_debug_dump(void) 514xpq_debug_dump(void)
515{ 515{
516 int i; 516 int i;
517 517
518 mmu_update_t *xpq_queue = xpq_queue_array[curcpu()->ci_cpuid]; 518 mmu_update_t *xpq_queue = xpq_queue_array[curcpu()->ci_cpuid];
519 int xpq_idx = xpq_idx_array[curcpu()->ci_cpuid]; 519 int xpq_idx = xpq_idx_array[curcpu()->ci_cpuid];
520 520
521 XENPRINTK2(("idx: %d\n", xpq_idx)); 521 XENPRINTK2(("idx: %d\n", xpq_idx));
522 for (i = 0; i < xpq_idx; i++) { 522 for (i = 0; i < xpq_idx; i++) {
523 snprintf(XBUF, sizeof(XBUF), "%" PRIx64 " %08" PRIx64, 523 snprintf(XBUF, sizeof(XBUF), "%" PRIx64 " %08" PRIx64,
524 xpq_queue[i].ptr, xpq_queue[i].val); 524 xpq_queue[i].ptr, xpq_queue[i].val);
525 if (++i < xpq_idx) 525 if (++i < xpq_idx)
526 snprintf(XBUF + strlen(XBUF), 526 snprintf(XBUF + strlen(XBUF),
527 sizeof(XBUF) - strlen(XBUF), 527 sizeof(XBUF) - strlen(XBUF),
528 "%" PRIx64 " %08" PRIx64, 528 "%" PRIx64 " %08" PRIx64,
529 xpq_queue[i].ptr, xpq_queue[i].val); 529 xpq_queue[i].ptr, xpq_queue[i].val);
530 if (++i < xpq_idx) 530 if (++i < xpq_idx)
531 snprintf(XBUF + strlen(XBUF), 531 snprintf(XBUF + strlen(XBUF),
532 sizeof(XBUF) - strlen(XBUF), 532 sizeof(XBUF) - strlen(XBUF),
533 "%" PRIx64 " %08" PRIx64,  533 "%" PRIx64 " %08" PRIx64,
534 xpq_queue[i].ptr, xpq_queue[i].val); 534 xpq_queue[i].ptr, xpq_queue[i].val);
535 if (++i < xpq_idx) 535 if (++i < xpq_idx)
536 snprintf(XBUF + strlen(XBUF), 536 snprintf(XBUF + strlen(XBUF),
537 sizeof(XBUF) - strlen(XBUF), 537 sizeof(XBUF) - strlen(XBUF),
538 "%" PRIx64 " %08" PRIx64, 538 "%" PRIx64 " %08" PRIx64,
539 xpq_queue[i].ptr, xpq_queue[i].val); 539 xpq_queue[i].ptr, xpq_queue[i].val);
540 XENPRINTK2(("%d: %s\n", xpq_idx, XBUF)); 540 XENPRINTK2(("%d: %s\n", xpq_idx, XBUF));
541 } 541 }
542} 542}
543#endif 543#endif
544 544
545 545
546extern volatile struct xencons_interface *xencons_interface; /* XXX */ 546extern volatile struct xencons_interface *xencons_interface; /* XXX */
547extern struct xenstore_domain_interface *xenstore_interface; /* XXX */ 547extern struct xenstore_domain_interface *xenstore_interface; /* XXX */
548 548
549static void xen_bt_set_readonly (vaddr_t); 549static void xen_bt_set_readonly (vaddr_t);
550static void xen_bootstrap_tables (vaddr_t, vaddr_t, int, int, int); 550static void xen_bootstrap_tables (vaddr_t, vaddr_t, int, int, int);
551 551
552/* How many PDEs ? */ 552/* How many PDEs ? */
553#if L2_SLOT_KERNBASE > 0 553#if L2_SLOT_KERNBASE > 0
554#define TABLE_L2_ENTRIES (2 * (NKL2_KIMG_ENTRIES + 1)) 554#define TABLE_L2_ENTRIES (2 * (NKL2_KIMG_ENTRIES + 1))
555#else 555#else
556#define TABLE_L2_ENTRIES (NKL2_KIMG_ENTRIES + 1) 556#define TABLE_L2_ENTRIES (NKL2_KIMG_ENTRIES + 1)
557#endif 557#endif
558 558
559/*  559/*
560 * Construct and switch to new pagetables 560 * Construct and switch to new pagetables
561 * first_avail is the first vaddr we can use after 561 * first_avail is the first vaddr we can use after
562 * we get rid of Xen pagetables 562 * we get rid of Xen pagetables
563 */ 563 */
564 564
565vaddr_t xen_pmap_bootstrap (void); 565vaddr_t xen_pmap_bootstrap (void);
566 566
567/* 567/*
568 * Function to get rid of Xen bootstrap tables 568 * Function to get rid of Xen bootstrap tables
569 */ 569 */
570 570
571/* How many PDP do we need: */ 571/* How many PDP do we need: */
572#ifdef PAE 572#ifdef PAE
573/* 573/*
574 * For PAE, we consider a single contigous L2 "superpage" of 4 pages, 574 * For PAE, we consider a single contigous L2 "superpage" of 4 pages,
575 * all of them mapped by the L3 page. We also need a shadow page 575 * all of them mapped by the L3 page. We also need a shadow page
576 * for L3[3]. 576 * for L3[3].
577 */ 577 */
578static const int l2_4_count = 6; 578static const int l2_4_count = 6;
579#elif defined(__x86_64__) 579#elif defined(__x86_64__)
580static const int l2_4_count = PTP_LEVELS; 580static const int l2_4_count = PTP_LEVELS;
581#else 581#else
582static const int l2_4_count = PTP_LEVELS - 1; 582static const int l2_4_count = PTP_LEVELS - 1;
583#endif 583#endif
584 584
585vaddr_t 585vaddr_t
586xen_pmap_bootstrap(void) 586xen_pmap_bootstrap(void)
587{ 587{
588 int count, oldcount; 588 int count, oldcount;
589 long mapsize; 589 long mapsize;
590 vaddr_t bootstrap_tables, init_tables; 590 vaddr_t bootstrap_tables, init_tables;
591 591
592 memset(xpq_idx_array, 0, sizeof xpq_idx_array); 592 memset(xpq_idx_array, 0, sizeof xpq_idx_array);
593 593
594 xpmap_phys_to_machine_mapping = 594 xpmap_phys_to_machine_mapping =
595 (unsigned long *)xen_start_info.mfn_list; 595 (unsigned long *)xen_start_info.mfn_list;
596 init_tables = xen_start_info.pt_base; 596 init_tables = xen_start_info.pt_base;
597 __PRINTK(("xen_arch_pmap_bootstrap init_tables=0x%lx\n", init_tables)); 597 __PRINTK(("xen_arch_pmap_bootstrap init_tables=0x%lx\n", init_tables));
598 598
599 /* Space after Xen boostrap tables should be free */ 599 /* Space after Xen boostrap tables should be free */
600 bootstrap_tables = xen_start_info.pt_base + 600 bootstrap_tables = xen_start_info.pt_base +
601 (xen_start_info.nr_pt_frames * PAGE_SIZE); 601 (xen_start_info.nr_pt_frames * PAGE_SIZE);
602 602
603 /* 603 /*
604 * Calculate how many space we need 604 * Calculate how many space we need
605 * first everything mapped before the Xen bootstrap tables 605 * first everything mapped before the Xen bootstrap tables
606 */ 606 */
607 mapsize = init_tables - KERNTEXTOFF; 607 mapsize = init_tables - KERNTEXTOFF;
608 /* after the tables we'll have: 608 /* after the tables we'll have:
609 * - UAREA 609 * - UAREA
610 * - dummy user PGD (x86_64) 610 * - dummy user PGD (x86_64)
611 * - HYPERVISOR_shared_info 611 * - HYPERVISOR_shared_info
612 * - early_zerop 612 * - early_zerop
613 * - ISA I/O mem (if needed) 613 * - ISA I/O mem (if needed)
614 */ 614 */
615 mapsize += UPAGES * NBPG; 615 mapsize += UPAGES * NBPG;
616#ifdef __x86_64__ 616#ifdef __x86_64__
617 mapsize += NBPG; 617 mapsize += NBPG;
618#endif 618#endif
619 mapsize += NBPG; 619 mapsize += NBPG;
620 mapsize += NBPG; 620 mapsize += NBPG;
621 621
622#ifdef DOM0OPS 622#ifdef DOM0OPS
623 if (xendomain_is_dom0()) { 623 if (xendomain_is_dom0()) {
624 /* space for ISA I/O mem */ 624 /* space for ISA I/O mem */
625 mapsize += IOM_SIZE; 625 mapsize += IOM_SIZE;
626 } 626 }
627#endif 627#endif
628 /* at this point mapsize doens't include the table size */ 628 /* at this point mapsize doens't include the table size */
629 629
630#ifdef __x86_64__ 630#ifdef __x86_64__
631 count = TABLE_L2_ENTRIES; 631 count = TABLE_L2_ENTRIES;
632#else 632#else
633 count = (mapsize + (NBPD_L2 -1)) >> L2_SHIFT; 633 count = (mapsize + (NBPD_L2 -1)) >> L2_SHIFT;
634#endif /* __x86_64__ */ 634#endif /* __x86_64__ */
635  635
636 /* now compute how many L2 pages we need exactly */ 636 /* now compute how many L2 pages we need exactly */
637 XENPRINTK(("bootstrap_final mapsize 0x%lx count %d\n", mapsize, count)); 637 XENPRINTK(("bootstrap_final mapsize 0x%lx count %d\n", mapsize, count));
638 while (mapsize + (count + l2_4_count) * PAGE_SIZE + KERNTEXTOFF > 638 while (mapsize + (count + l2_4_count) * PAGE_SIZE + KERNTEXTOFF >
639 ((long)count << L2_SHIFT) + KERNBASE) { 639 ((long)count << L2_SHIFT) + KERNBASE) {
640 count++; 640 count++;
641 } 641 }
642#ifndef __x86_64__ 642#ifndef __x86_64__
643 /* 643 /*
644 * one more L2 page: we'll alocate several pages after kva_start 644 * one more L2 page: we'll alocate several pages after kva_start
645 * in pmap_bootstrap() before pmap_growkernel(), which have not been 645 * in pmap_bootstrap() before pmap_growkernel(), which have not been
646 * counted here. It's not a big issue to allocate one more L2 as 646 * counted here. It's not a big issue to allocate one more L2 as
647 * pmap_growkernel() will be called anyway. 647 * pmap_growkernel() will be called anyway.
648 */ 648 */
649 count++; 649 count++;
650 nkptp[1] = count; 650 nkptp[1] = count;
651#endif 651#endif
652 652
653 /* 653 /*
654 * install bootstrap pages. We may need more L2 pages than will 654 * install bootstrap pages. We may need more L2 pages than will
655 * have the final table here, as it's installed after the final table 655 * have the final table here, as it's installed after the final table
656 */ 656 */
657 oldcount = count; 657 oldcount = count;
658 658
659bootstrap_again: 659bootstrap_again:
660 XENPRINTK(("bootstrap_again oldcount %d\n", oldcount)); 660 XENPRINTK(("bootstrap_again oldcount %d\n", oldcount));
661 /*  661 /*
662 * Xen space we'll reclaim may not be enough for our new page tables, 662 * Xen space we'll reclaim may not be enough for our new page tables,
663 * move bootstrap tables if necessary 663 * move bootstrap tables if necessary
664 */ 664 */
665 if (bootstrap_tables < init_tables + ((count + l2_4_count) * PAGE_SIZE)) 665 if (bootstrap_tables < init_tables + ((count + l2_4_count) * PAGE_SIZE))
666 bootstrap_tables = init_tables + 666 bootstrap_tables = init_tables +
667 ((count + l2_4_count) * PAGE_SIZE); 667 ((count + l2_4_count) * PAGE_SIZE);
668 /* make sure we have enough to map the bootstrap_tables */ 668 /* make sure we have enough to map the bootstrap_tables */
669 if (bootstrap_tables + ((oldcount + l2_4_count) * PAGE_SIZE) >  669 if (bootstrap_tables + ((oldcount + l2_4_count) * PAGE_SIZE) >
670 ((long)oldcount << L2_SHIFT) + KERNBASE) { 670 ((long)oldcount << L2_SHIFT) + KERNBASE) {
671 oldcount++; 671 oldcount++;
672 goto bootstrap_again; 672 goto bootstrap_again;
673 } 673 }
674 674
675 /* Create temporary tables */ 675 /* Create temporary tables */
676 xen_bootstrap_tables(xen_start_info.pt_base, bootstrap_tables, 676 xen_bootstrap_tables(xen_start_info.pt_base, bootstrap_tables,
677 xen_start_info.nr_pt_frames, oldcount, 0); 677 xen_start_info.nr_pt_frames, oldcount, 0);
678 678
679 /* Create final tables */ 679 /* Create final tables */
680 xen_bootstrap_tables(bootstrap_tables, init_tables, 680 xen_bootstrap_tables(bootstrap_tables, init_tables,
681 oldcount + l2_4_count, count, 1); 681 oldcount + l2_4_count, count, 1);
682 682
683 /* zero out free space after tables */ 683 /* zero out free space after tables */
684 memset((void *)(init_tables + ((count + l2_4_count) * PAGE_SIZE)), 0, 684 memset((void *)(init_tables + ((count + l2_4_count) * PAGE_SIZE)), 0,
685 (UPAGES + 1) * NBPG); 685 (UPAGES + 1) * NBPG);
686 686
687 /* Finally, flush TLB. */ 687 /* Finally, flush TLB. */
688 xpq_queue_tlb_flush(); 688 xpq_queue_tlb_flush();
689 689
690 return (init_tables + ((count + l2_4_count) * PAGE_SIZE)); 690 return (init_tables + ((count + l2_4_count) * PAGE_SIZE));
691} 691}
692 692
693/* 693/*
694 * Build a new table and switch to it 694 * Build a new table and switch to it
695 * old_count is # of old tables (including PGD, PDTPE and PDE) 695 * old_count is # of old tables (including PGD, PDTPE and PDE)
696 * new_count is # of new tables (PTE only) 696 * new_count is # of new tables (PTE only)
697 * we assume areas don't overlap 697 * we assume areas don't overlap
698 */ 698 */
699static void 699static void
700xen_bootstrap_tables (vaddr_t old_pgd, vaddr_t new_pgd, 700xen_bootstrap_tables (vaddr_t old_pgd, vaddr_t new_pgd,
701 int old_count, int new_count, int final) 701 int old_count, int new_count, int final)
702{ 702{
703 pd_entry_t *pdtpe, *pde, *pte; 703 pd_entry_t *pdtpe, *pde, *pte;
704 pd_entry_t *cur_pgd, *bt_pgd; 704 pd_entry_t *cur_pgd, *bt_pgd;
705 paddr_t addr; 705 paddr_t addr;
706 vaddr_t page, avail, text_end, map_end; 706 vaddr_t page, avail, text_end, map_end;
707 int i; 707 int i;
708 extern char __data_start; 708 extern char __data_start;
709 extern char *early_zerop; /* from pmap.c */ 709 extern char *early_zerop; /* from pmap.c */
710 710
711 __PRINTK(("xen_bootstrap_tables(%#" PRIxVADDR ", %#" PRIxVADDR "," 711 __PRINTK(("xen_bootstrap_tables(%#" PRIxVADDR ", %#" PRIxVADDR ","
712 " %d, %d)\n", 712 " %d, %d)\n",
713 old_pgd, new_pgd, old_count, new_count)); 713 old_pgd, new_pgd, old_count, new_count));
714 text_end = ((vaddr_t)&__data_start) & ~PAGE_MASK; 714 text_end = ((vaddr_t)&__data_start) & ~PAGE_MASK;
715 /* 715 /*
716 * size of R/W area after kernel text: 716 * size of R/W area after kernel text:
717 * xencons_interface (if present) 717 * xencons_interface (if present)
718 * xenstore_interface (if present) 718 * xenstore_interface (if present)
719 * table pages (new_count + l2_4_count entries) 719 * table pages (new_count + l2_4_count entries)
720 * extra mappings (only when final is true): 720 * extra mappings (only when final is true):
721 * UAREA 721 * UAREA
722 * dummy user PGD (x86_64 only)/gdt page (i386 only) 722 * dummy user PGD (x86_64 only)/gdt page (i386 only)
723 * HYPERVISOR_shared_info 723 * HYPERVISOR_shared_info
724 * early_zerop 724 * early_zerop
725 * ISA I/O mem (if needed) 725 * ISA I/O mem (if needed)
726 */ 726 */
727 map_end = new_pgd + ((new_count + l2_4_count) * NBPG); 727 map_end = new_pgd + ((new_count + l2_4_count) * NBPG);
728 if (final) { 728 if (final) {
729 map_end += (UPAGES + 1) * NBPG; 729 map_end += (UPAGES + 1) * NBPG;
730 HYPERVISOR_shared_info = (shared_info_t *)map_end; 730 HYPERVISOR_shared_info = (shared_info_t *)map_end;
731 map_end += NBPG; 731 map_end += NBPG;
732 early_zerop = (char *)map_end; 732 early_zerop = (char *)map_end;
733 map_end += NBPG; 733 map_end += NBPG;
734 } 734 }
735 /* 735 /*
736 * we always set atdevbase, as it's used by init386 to find the first 736 * we always set atdevbase, as it's used by init386 to find the first
737 * available VA. map_end is updated only if we are dom0, so 737 * available VA. map_end is updated only if we are dom0, so
738 * atdevbase -> atdevbase + IOM_SIZE will be mapped only in 738 * atdevbase -> atdevbase + IOM_SIZE will be mapped only in
739 * this case. 739 * this case.
740 */ 740 */
741 if (final) 741 if (final)
742 atdevbase = map_end; 742 atdevbase = map_end;
743#ifdef DOM0OPS 743#ifdef DOM0OPS
744 if (final && xendomain_is_dom0()) { 744 if (final && xendomain_is_dom0()) {
745 /* ISA I/O mem */ 745 /* ISA I/O mem */
746 map_end += IOM_SIZE; 746 map_end += IOM_SIZE;
747 } 747 }
748#endif /* DOM0OPS */ 748#endif /* DOM0OPS */
749 749
750 __PRINTK(("xen_bootstrap_tables text_end 0x%lx map_end 0x%lx\n", 750 __PRINTK(("xen_bootstrap_tables text_end 0x%lx map_end 0x%lx\n",
751 text_end, map_end)); 751 text_end, map_end));
752 __PRINTK(("console %#lx ", xen_start_info.console_mfn)); 752 __PRINTK(("console %#lx ", xen_start_info.console_mfn));
753 __PRINTK(("xenstore %#" PRIx32 "\n", xen_start_info.store_mfn)); 753 __PRINTK(("xenstore %#" PRIx32 "\n", xen_start_info.store_mfn));
754 754
755 /*  755 /*
756 * Create bootstrap page tables 756 * Create bootstrap page tables
757 * What we need: 757 * What we need:
758 * - a PGD (level 4) 758 * - a PGD (level 4)
759 * - a PDTPE (level 3) 759 * - a PDTPE (level 3)
760 * - a PDE (level2) 760 * - a PDE (level2)
761 * - some PTEs (level 1) 761 * - some PTEs (level 1)
762 */ 762 */
763  763
764 cur_pgd = (pd_entry_t *) old_pgd; 764 cur_pgd = (pd_entry_t *) old_pgd;
765 bt_pgd = (pd_entry_t *) new_pgd; 765 bt_pgd = (pd_entry_t *) new_pgd;
766 memset (bt_pgd, 0, PAGE_SIZE); 766 memset (bt_pgd, 0, PAGE_SIZE);
767 avail = new_pgd + PAGE_SIZE; 767 avail = new_pgd + PAGE_SIZE;
768#if PTP_LEVELS > 3 768#if PTP_LEVELS > 3
769 /* per-cpu L4 PD */ 769 /* per-cpu L4 PD */
770 pd_entry_t *bt_cpu_pgd = bt_pgd; 770 pd_entry_t *bt_cpu_pgd = bt_pgd;
771 /* pmap_kernel() "shadow" L4 PD */ 771 /* pmap_kernel() "shadow" L4 PD */
772 bt_pgd = (pd_entry_t *) avail; 772 bt_pgd = (pd_entry_t *) avail;
773 memset(bt_pgd, 0, PAGE_SIZE); 773 memset(bt_pgd, 0, PAGE_SIZE);
774 avail += PAGE_SIZE; 774 avail += PAGE_SIZE;
775 775
776 /* Install level 3 */ 776 /* Install level 3 */
777 pdtpe = (pd_entry_t *) avail; 777 pdtpe = (pd_entry_t *) avail;
778 memset (pdtpe, 0, PAGE_SIZE); 778 memset (pdtpe, 0, PAGE_SIZE);
779 avail += PAGE_SIZE; 779 avail += PAGE_SIZE;
780 780
781 addr = ((u_long) pdtpe) - KERNBASE; 781 addr = ((u_long) pdtpe) - KERNBASE;
782 bt_pgd[pl4_pi(KERNTEXTOFF)] = bt_cpu_pgd[pl4_pi(KERNTEXTOFF)] = 782 bt_pgd[pl4_pi(KERNTEXTOFF)] = bt_cpu_pgd[pl4_pi(KERNTEXTOFF)] =
783 xpmap_ptom_masked(addr) | PG_k | PG_RW | PG_V; 783 xpmap_ptom_masked(addr) | PG_k | PG_RW | PG_V;
784 784
785 __PRINTK(("L3 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR 785 __PRINTK(("L3 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR
786 " -> L4[%#x]\n", 786 " -> L4[%#x]\n",
787 pdtpe, addr, bt_pgd[pl4_pi(KERNTEXTOFF)], pl4_pi(KERNTEXTOFF))); 787 pdtpe, addr, bt_pgd[pl4_pi(KERNTEXTOFF)], pl4_pi(KERNTEXTOFF)));
788#else 788#else
789 pdtpe = bt_pgd; 789 pdtpe = bt_pgd;
790#endif /* PTP_LEVELS > 3 */ 790#endif /* PTP_LEVELS > 3 */
791 791
792#if PTP_LEVELS > 2 792#if PTP_LEVELS > 2
793 /* Level 2 */ 793 /* Level 2 */
794 pde = (pd_entry_t *) avail; 794 pde = (pd_entry_t *) avail;
795 memset(pde, 0, PAGE_SIZE); 795 memset(pde, 0, PAGE_SIZE);
796 avail += PAGE_SIZE; 796 avail += PAGE_SIZE;
797 797
798 addr = ((u_long) pde) - KERNBASE; 798 addr = ((u_long) pde) - KERNBASE;
799 pdtpe[pl3_pi(KERNTEXTOFF)] = 799 pdtpe[pl3_pi(KERNTEXTOFF)] =
800 xpmap_ptom_masked(addr) | PG_k | PG_V | PG_RW; 800 xpmap_ptom_masked(addr) | PG_k | PG_V | PG_RW;
801 __PRINTK(("L2 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR 801 __PRINTK(("L2 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR
802 " -> L3[%#x]\n", 802 " -> L3[%#x]\n",
803 pde, addr, pdtpe[pl3_pi(KERNTEXTOFF)], pl3_pi(KERNTEXTOFF))); 803 pde, addr, pdtpe[pl3_pi(KERNTEXTOFF)], pl3_pi(KERNTEXTOFF)));
804#elif defined(PAE) 804#elif defined(PAE)
805 /* our PAE-style level 2: 5 contigous pages (4 L2 + 1 shadow) */ 805 /* our PAE-style level 2: 5 contigous pages (4 L2 + 1 shadow) */
806 pde = (pd_entry_t *) avail; 806 pde = (pd_entry_t *) avail;
807 memset(pde, 0, PAGE_SIZE * 5); 807 memset(pde, 0, PAGE_SIZE * 5);
808 avail += PAGE_SIZE * 5; 808 avail += PAGE_SIZE * 5;
809 addr = ((u_long) pde) - KERNBASE; 809 addr = ((u_long) pde) - KERNBASE;
810 /* 810 /*
811 * enter L2 pages in the L3. 811 * enter L2 pages in the L3.
812 * The real L2 kernel PD will be the last one (so that 812 * The real L2 kernel PD will be the last one (so that
813 * pde[L2_SLOT_KERN] always point to the shadow). 813 * pde[L2_SLOT_KERN] always point to the shadow).
814 */ 814 */
815 for (i = 0; i < 3; i++, addr += PAGE_SIZE) { 815 for (i = 0; i < 3; i++, addr += PAGE_SIZE) {
816 /* 816 /*
817 * Xen doesn't want R/W mappings in L3 entries, it'll add it 817 * Xen doesn't want R/W mappings in L3 entries, it'll add it
818 * itself. 818 * itself.
819 */ 819 */
820 pdtpe[i] = xpmap_ptom_masked(addr) | PG_k | PG_V; 820 pdtpe[i] = xpmap_ptom_masked(addr) | PG_k | PG_V;
821 __PRINTK(("L2 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR 821 __PRINTK(("L2 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR
822 " -> L3[%#x]\n", 822 " -> L3[%#x]\n",
823 (vaddr_t)pde + PAGE_SIZE * i, addr, pdtpe[i], i)); 823 (vaddr_t)pde + PAGE_SIZE * i, addr, pdtpe[i], i));
824 } 824 }
825 addr += PAGE_SIZE; 825 addr += PAGE_SIZE;
826 pdtpe[3] = xpmap_ptom_masked(addr) | PG_k | PG_V; 826 pdtpe[3] = xpmap_ptom_masked(addr) | PG_k | PG_V;
827 __PRINTK(("L2 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR 827 __PRINTK(("L2 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR
828 " -> L3[%#x]\n", 828 " -> L3[%#x]\n",
829 (vaddr_t)pde + PAGE_SIZE * 4, addr, pdtpe[3], 3)); 829 (vaddr_t)pde + PAGE_SIZE * 4, addr, pdtpe[3], 3));
830 830
831#else /* PAE */ 831#else /* PAE */
832 pde = bt_pgd; 832 pde = bt_pgd;
833#endif /* PTP_LEVELS > 2 */ 833#endif /* PTP_LEVELS > 2 */
834 834
835 /* Level 1 */ 835 /* Level 1 */
836 page = KERNTEXTOFF; 836 page = KERNTEXTOFF;
837 for (i = 0; i < new_count; i ++) { 837 for (i = 0; i < new_count; i ++) {
838 vaddr_t cur_page = page; 838 vaddr_t cur_page = page;
839 839
840 pte = (pd_entry_t *) avail; 840 pte = (pd_entry_t *) avail;
841 avail += PAGE_SIZE; 841 avail += PAGE_SIZE;
842 842
843 memset(pte, 0, PAGE_SIZE); 843 memset(pte, 0, PAGE_SIZE);
844 while (pl2_pi(page) == pl2_pi (cur_page)) { 844 while (pl2_pi(page) == pl2_pi (cur_page)) {
845 if (page >= map_end) { 845 if (page >= map_end) {
846 /* not mapped at all */ 846 /* not mapped at all */
847 pte[pl1_pi(page)] = 0; 847 pte[pl1_pi(page)] = 0;
848 page += PAGE_SIZE; 848 page += PAGE_SIZE;
849 continue; 849 continue;
850 } 850 }
851 pte[pl1_pi(page)] = xpmap_ptom_masked(page - KERNBASE); 851 pte[pl1_pi(page)] = xpmap_ptom_masked(page - KERNBASE);
852 if (page == (vaddr_t)HYPERVISOR_shared_info) { 852 if (page == (vaddr_t)HYPERVISOR_shared_info) {
853 pte[pl1_pi(page)] = xen_start_info.shared_info; 853 pte[pl1_pi(page)] = xen_start_info.shared_info;
854 __PRINTK(("HYPERVISOR_shared_info " 854 __PRINTK(("HYPERVISOR_shared_info "
855 "va %#lx pte %#" PRIxPADDR "\n", 855 "va %#lx pte %#" PRIxPADDR "\n",
856 HYPERVISOR_shared_info, pte[pl1_pi(page)])); 856 HYPERVISOR_shared_info, pte[pl1_pi(page)]));
857 } 857 }
858 if ((xpmap_ptom_masked(page - KERNBASE) >> PAGE_SHIFT) 858 if ((xpmap_ptom_masked(page - KERNBASE) >> PAGE_SHIFT)
859 == xen_start_info.console.domU.mfn) { 859 == xen_start_info.console.domU.mfn) {
860 xencons_interface = (void *)page; 860 xencons_interface = (void *)page;
861 pte[pl1_pi(page)] = xen_start_info.console_mfn; 861 pte[pl1_pi(page)] = xen_start_info.console_mfn;
862 pte[pl1_pi(page)] <<= PAGE_SHIFT; 862 pte[pl1_pi(page)] <<= PAGE_SHIFT;
863 __PRINTK(("xencons_interface " 863 __PRINTK(("xencons_interface "
864 "va %#lx pte %#" PRIxPADDR "\n", 864 "va %#lx pte %#" PRIxPADDR "\n",
865 xencons_interface, pte[pl1_pi(page)])); 865 xencons_interface, pte[pl1_pi(page)]));
866 } 866 }
867 if ((xpmap_ptom_masked(page - KERNBASE) >> PAGE_SHIFT) 867 if ((xpmap_ptom_masked(page - KERNBASE) >> PAGE_SHIFT)
868 == xen_start_info.store_mfn) { 868 == xen_start_info.store_mfn) {
869 xenstore_interface = (void *)page; 869 xenstore_interface = (void *)page;
870 pte[pl1_pi(page)] = xen_start_info.store_mfn; 870 pte[pl1_pi(page)] = xen_start_info.store_mfn;
871 pte[pl1_pi(page)] <<= PAGE_SHIFT; 871 pte[pl1_pi(page)] <<= PAGE_SHIFT;
872 __PRINTK(("xenstore_interface " 872 __PRINTK(("xenstore_interface "
873 "va %#lx pte %#" PRIxPADDR "\n", 873 "va %#lx pte %#" PRIxPADDR "\n",
874 xenstore_interface, pte[pl1_pi(page)])); 874 xenstore_interface, pte[pl1_pi(page)]));
875 } 875 }
876#ifdef DOM0OPS 876#ifdef DOM0OPS
877 if (page >= (vaddr_t)atdevbase && 877 if (page >= (vaddr_t)atdevbase &&
878 page < (vaddr_t)atdevbase + IOM_SIZE) { 878 page < (vaddr_t)atdevbase + IOM_SIZE) {
879 pte[pl1_pi(page)] = 879 pte[pl1_pi(page)] =
880 IOM_BEGIN + (page - (vaddr_t)atdevbase); 880 IOM_BEGIN + (page - (vaddr_t)atdevbase);
881 } 881 }
882#endif 882#endif
883 pte[pl1_pi(page)] |= PG_k | PG_V; 883 pte[pl1_pi(page)] |= PG_k | PG_V;
884 if (page < text_end) { 884 if (page < text_end) {
885 /* map kernel text RO */ 885 /* map kernel text RO */
886 pte[pl1_pi(page)] |= 0; 886 pte[pl1_pi(page)] |= 0;
887 } else if (page >= old_pgd 887 } else if (page >= old_pgd
888 && page < old_pgd + (old_count * PAGE_SIZE)) { 888 && page < old_pgd + (old_count * PAGE_SIZE)) {
889 /* map old page tables RO */ 889 /* map old page tables RO */
890 pte[pl1_pi(page)] |= 0; 890 pte[pl1_pi(page)] |= 0;
891 } else if (page >= new_pgd && 891 } else if (page >= new_pgd &&
892 page < new_pgd + ((new_count + l2_4_count) * PAGE_SIZE)) { 892 page < new_pgd + ((new_count + l2_4_count) * PAGE_SIZE)) {
893 /* map new page tables RO */ 893 /* map new page tables RO */
894 pte[pl1_pi(page)] |= 0; 894 pte[pl1_pi(page)] |= 0;
895#ifdef i386 895#ifdef i386
896 } else if (page == (vaddr_t)tmpgdt) { 896 } else if (page == (vaddr_t)tmpgdt) {
897 /* 897 /*
898 * Map bootstrap gdt R/O. Later, we 898 * Map bootstrap gdt R/O. Later, we
899 * will re-add this to page to uvm 899 * will re-add this to page to uvm
900 * after making it writable. 900 * after making it writable.
901 */ 901 */
902 902
903 pte[pl1_pi(page)] = 0; 903 pte[pl1_pi(page)] = 0;
904 page += PAGE_SIZE; 904 page += PAGE_SIZE;
905 continue; 905 continue;
906#endif /* i386 */ 906#endif /* i386 */
907 } else { 907 } else {
908 /* map page RW */ 908 /* map page RW */
909 pte[pl1_pi(page)] |= PG_RW; 909 pte[pl1_pi(page)] |= PG_RW;
910 } 910 }
911  911
912 if ((page >= old_pgd && page < old_pgd + (old_count * PAGE_SIZE)) 912 if ((page >= old_pgd && page < old_pgd + (old_count * PAGE_SIZE))
913 || page >= new_pgd) { 913 || page >= new_pgd) {
914 __PRINTK(("va %#lx pa %#lx " 914 __PRINTK(("va %#lx pa %#lx "
915 "entry 0x%" PRIxPADDR " -> L1[%#x]\n", 915 "entry 0x%" PRIxPADDR " -> L1[%#x]\n",
916 page, page - KERNBASE, 916 page, page - KERNBASE,
917 pte[pl1_pi(page)], pl1_pi(page))); 917 pte[pl1_pi(page)], pl1_pi(page)));
918 } 918 }
919 page += PAGE_SIZE; 919 page += PAGE_SIZE;
920 } 920 }
921 921
922 addr = ((u_long) pte) - KERNBASE; 922 addr = ((u_long) pte) - KERNBASE;
923 pde[pl2_pi(cur_page)] = 923 pde[pl2_pi(cur_page)] =
924 xpmap_ptom_masked(addr) | PG_k | PG_RW | PG_V; 924 xpmap_ptom_masked(addr) | PG_k | PG_RW | PG_V;
925 __PRINTK(("L1 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR 925 __PRINTK(("L1 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR
926 " -> L2[%#x]\n", 926 " -> L2[%#x]\n",
927 pte, addr, pde[pl2_pi(cur_page)], pl2_pi(cur_page))); 927 pte, addr, pde[pl2_pi(cur_page)], pl2_pi(cur_page)));
928 /* Mark readonly */ 928 /* Mark readonly */
929 xen_bt_set_readonly((vaddr_t) pte); 929 xen_bt_set_readonly((vaddr_t) pte);
930 } 930 }
931 931
932 /* Install recursive page tables mapping */ 932 /* Install recursive page tables mapping */
933#ifdef PAE 933#ifdef PAE
934 /* 934 /*
935 * we need a shadow page for the kernel's L2 page 935 * we need a shadow page for the kernel's L2 page
936 * The real L2 kernel PD will be the last one (so that 936 * The real L2 kernel PD will be the last one (so that
937 * pde[L2_SLOT_KERN] always point to the shadow. 937 * pde[L2_SLOT_KERN] always point to the shadow.
938 */ 938 */
939 memcpy(&pde[L2_SLOT_KERN + NPDPG], &pde[L2_SLOT_KERN], PAGE_SIZE); 939 memcpy(&pde[L2_SLOT_KERN + NPDPG], &pde[L2_SLOT_KERN], PAGE_SIZE);
940 cpu_info_primary.ci_kpm_pdir = &pde[L2_SLOT_KERN + NPDPG]; 940 cpu_info_primary.ci_kpm_pdir = &pde[L2_SLOT_KERN + NPDPG];
941 cpu_info_primary.ci_kpm_pdirpa = 941 cpu_info_primary.ci_kpm_pdirpa =
942 (vaddr_t) cpu_info_primary.ci_kpm_pdir - KERNBASE; 942 (vaddr_t) cpu_info_primary.ci_kpm_pdir - KERNBASE;
943 943
944 /* 944 /*
945 * We don't enter a recursive entry from the L3 PD. Instead, 945 * We don't enter a recursive entry from the L3 PD. Instead,
946 * we enter the first 4 L2 pages, which includes the kernel's L2 946 * we enter the first 4 L2 pages, which includes the kernel's L2
947 * shadow. But we have to entrer the shadow after switching 947 * shadow. But we have to entrer the shadow after switching
948 * %cr3, or Xen will refcount some PTE with the wrong type. 948 * %cr3, or Xen will refcount some PTE with the wrong type.
949 */ 949 */
950 addr = (u_long)pde - KERNBASE; 950 addr = (u_long)pde - KERNBASE;
951 for (i = 0; i < 3; i++, addr += PAGE_SIZE) { 951 for (i = 0; i < 3; i++, addr += PAGE_SIZE) {
952 pde[PDIR_SLOT_PTE + i] = xpmap_ptom_masked(addr) | PG_k | PG_V; 952 pde[PDIR_SLOT_PTE + i] = xpmap_ptom_masked(addr) | PG_k | PG_V;
953 __PRINTK(("pde[%d] va %#" PRIxVADDR " pa %#" PRIxPADDR 953 __PRINTK(("pde[%d] va %#" PRIxVADDR " pa %#" PRIxPADDR
954 " entry %#" PRIxPADDR "\n", 954 " entry %#" PRIxPADDR "\n",
955 (int)(PDIR_SLOT_PTE + i), pde + PAGE_SIZE * i, 955 (int)(PDIR_SLOT_PTE + i), pde + PAGE_SIZE * i,
956 addr, pde[PDIR_SLOT_PTE + i])); 956 addr, pde[PDIR_SLOT_PTE + i]));
957 } 957 }
958#if 0 958#if 0
959 addr += PAGE_SIZE; /* point to shadow L2 */ 959 addr += PAGE_SIZE; /* point to shadow L2 */
960 pde[PDIR_SLOT_PTE + 3] = xpmap_ptom_masked(addr) | PG_k | PG_V; 960 pde[PDIR_SLOT_PTE + 3] = xpmap_ptom_masked(addr) | PG_k | PG_V;
961 __PRINTK(("pde[%d] va 0x%lx pa 0x%lx entry 0x%" PRIx64 "\n", 961 __PRINTK(("pde[%d] va 0x%lx pa 0x%lx entry 0x%" PRIx64 "\n",
962 (int)(PDIR_SLOT_PTE + 3), pde + PAGE_SIZE * 4, (long)addr, 962 (int)(PDIR_SLOT_PTE + 3), pde + PAGE_SIZE * 4, (long)addr,
963 (int64_t)pde[PDIR_SLOT_PTE + 3])); 963 (int64_t)pde[PDIR_SLOT_PTE + 3]));
964#endif 964#endif
965 /* Mark tables RO, and pin the kernel's shadow as L2 */ 965 /* Mark tables RO, and pin the kernel's shadow as L2 */
966 addr = (u_long)pde - KERNBASE; 966 addr = (u_long)pde - KERNBASE;
967 for (i = 0; i < 5; i++, addr += PAGE_SIZE) { 967 for (i = 0; i < 5; i++, addr += PAGE_SIZE) {
968 xen_bt_set_readonly(((vaddr_t)pde) + PAGE_SIZE * i); 968 xen_bt_set_readonly(((vaddr_t)pde) + PAGE_SIZE * i);
969 if (i == 2 || i == 3) 969 if (i == 2 || i == 3)
970 continue; 970 continue;
971#if 0 971#if 0
972 __PRINTK(("pin L2 %d addr 0x%" PRIx64 "\n", i, (int64_t)addr)); 972 __PRINTK(("pin L2 %d addr 0x%" PRIx64 "\n", i, (int64_t)addr));
973 xpq_queue_pin_l2_table(xpmap_ptom_masked(addr)); 973 xpq_queue_pin_l2_table(xpmap_ptom_masked(addr));
974#endif 974#endif
975 } 975 }
976 if (final) { 976 if (final) {
977 addr = (u_long)pde - KERNBASE + 3 * PAGE_SIZE; 977 addr = (u_long)pde - KERNBASE + 3 * PAGE_SIZE;
978 __PRINTK(("pin L2 %d addr %#" PRIxPADDR "\n", 2, addr)); 978 __PRINTK(("pin L2 %d addr %#" PRIxPADDR "\n", 2, addr));
979 xpq_queue_pin_l2_table(xpmap_ptom_masked(addr)); 979 xpq_queue_pin_l2_table(xpmap_ptom_masked(addr));
980 } 980 }
981#if 0 981#if 0
982 addr = (u_long)pde - KERNBASE + 2 * PAGE_SIZE; 982 addr = (u_long)pde - KERNBASE + 2 * PAGE_SIZE;
983 __PRINTK(("pin L2 %d addr 0x%" PRIx64 "\n", 2, (int64_t)addr)); 983 __PRINTK(("pin L2 %d addr 0x%" PRIx64 "\n", 2, (int64_t)addr));
984 xpq_queue_pin_l2_table(xpmap_ptom_masked(addr)); 984 xpq_queue_pin_l2_table(xpmap_ptom_masked(addr));
985#endif 985#endif
986#else /* PAE */ 986#else /* PAE */
987 /* recursive entry in higher-level per-cpu PD and pmap_kernel() */ 987 /* recursive entry in higher-level per-cpu PD and pmap_kernel() */
988 bt_pgd[PDIR_SLOT_PTE] = xpmap_ptom_masked((paddr_t)bt_pgd - KERNBASE) | PG_k | PG_V; 988 bt_pgd[PDIR_SLOT_PTE] = xpmap_ptom_masked((paddr_t)bt_pgd - KERNBASE) | PG_k | PG_V;
989#ifdef __x86_64__ 989#ifdef __x86_64__
990 bt_cpu_pgd[PDIR_SLOT_PTE] = 990 bt_cpu_pgd[PDIR_SLOT_PTE] =
991 xpmap_ptom_masked((paddr_t)bt_cpu_pgd - KERNBASE) | PG_k | PG_V; 991 xpmap_ptom_masked((paddr_t)bt_cpu_pgd - KERNBASE) | PG_k | PG_V;
992#endif /* __x86_64__ */ 992#endif /* __x86_64__ */
993 __PRINTK(("bt_pgd[PDIR_SLOT_PTE] va %#" PRIxVADDR " pa %#" PRIxPADDR 993 __PRINTK(("bt_pgd[PDIR_SLOT_PTE] va %#" PRIxVADDR " pa %#" PRIxPADDR
994 " entry %#" PRIxPADDR "\n", new_pgd, (paddr_t)new_pgd - KERNBASE, 994 " entry %#" PRIxPADDR "\n", new_pgd, (paddr_t)new_pgd - KERNBASE,
995 bt_pgd[PDIR_SLOT_PTE])); 995 bt_pgd[PDIR_SLOT_PTE]));
996 /* Mark tables RO */ 996 /* Mark tables RO */
997 xen_bt_set_readonly((vaddr_t) pde); 997 xen_bt_set_readonly((vaddr_t) pde);
998#endif 998#endif
999#if PTP_LEVELS > 2 || defined(PAE) 999#if PTP_LEVELS > 2 || defined(PAE)
1000 xen_bt_set_readonly((vaddr_t) pdtpe); 1000 xen_bt_set_readonly((vaddr_t) pdtpe);
1001#endif 1001#endif
1002#if PTP_LEVELS > 3 1002#if PTP_LEVELS > 3
1003 xen_bt_set_readonly(new_pgd); 1003 xen_bt_set_readonly(new_pgd);
1004#endif 1004#endif
1005 /* Pin the PGD */ 1005 /* Pin the PGD */
1006 __PRINTK(("pin PGD: %"PRIxVADDR"\n", new_pgd - KERNBASE)); 1006 __PRINTK(("pin PGD: %"PRIxVADDR"\n", new_pgd - KERNBASE));
1007#ifdef __x86_64__ 1007#ifdef __x86_64__
1008 xpq_queue_pin_l4_table(xpmap_ptom_masked(new_pgd - KERNBASE)); 1008 xpq_queue_pin_l4_table(xpmap_ptom_masked(new_pgd - KERNBASE));
1009#elif PAE 1009#elif PAE
1010 xpq_queue_pin_l3_table(xpmap_ptom_masked(new_pgd - KERNBASE)); 1010 xpq_queue_pin_l3_table(xpmap_ptom_masked(new_pgd - KERNBASE));
1011#else 1011#else
1012 xpq_queue_pin_l2_table(xpmap_ptom_masked(new_pgd - KERNBASE)); 1012 xpq_queue_pin_l2_table(xpmap_ptom_masked(new_pgd - KERNBASE));
1013#endif 1013#endif
1014 1014
1015 /* Save phys. addr of PDP, for libkvm. */ 1015 /* Save phys. addr of PDP, for libkvm. */
1016#ifdef PAE 1016#ifdef PAE
1017 PDPpaddr = (u_long)pde - KERNBASE; /* PDP is the L2 with PAE */ 1017 PDPpaddr = (u_long)pde - KERNBASE; /* PDP is the L2 with PAE */
1018#else 1018#else
1019 PDPpaddr = (u_long)bt_pgd - KERNBASE; 1019 PDPpaddr = (u_long)bt_pgd - KERNBASE;
1020#endif 1020#endif
1021 1021
1022 /* Switch to new tables */ 1022 /* Switch to new tables */
1023 __PRINTK(("switch to PGD\n")); 1023 __PRINTK(("switch to PGD\n"));
1024 xpq_queue_pt_switch(xpmap_ptom_masked(new_pgd - KERNBASE)); 1024 xpq_queue_pt_switch(xpmap_ptom_masked(new_pgd - KERNBASE));
1025 __PRINTK(("bt_pgd[PDIR_SLOT_PTE] now entry %#" PRIxPADDR "\n", 1025 __PRINTK(("bt_pgd[PDIR_SLOT_PTE] now entry %#" PRIxPADDR "\n",
1026 bt_pgd[PDIR_SLOT_PTE])); 1026 bt_pgd[PDIR_SLOT_PTE]));
1027 1027
1028#ifdef PAE 1028#ifdef PAE
1029 if (final) { 1029 if (final) {
1030 /* save the address of the L3 page */ 1030 /* save the address of the L3 page */
1031 cpu_info_primary.ci_pae_l3_pdir = pdtpe; 1031 cpu_info_primary.ci_pae_l3_pdir = pdtpe;
1032 cpu_info_primary.ci_pae_l3_pdirpa = (new_pgd - KERNBASE); 1032 cpu_info_primary.ci_pae_l3_pdirpa = (new_pgd - KERNBASE);
1033 1033
1034 /* now enter kernel's PTE mappings */ 1034 /* now enter kernel's PTE mappings */
1035 addr = (u_long)pde - KERNBASE + PAGE_SIZE * 3; 1035 addr = (u_long)pde - KERNBASE + PAGE_SIZE * 3;
1036 xpq_queue_pte_update( 1036 xpq_queue_pte_update(
1037 xpmap_ptom(((vaddr_t)&pde[PDIR_SLOT_PTE + 3]) - KERNBASE),  1037 xpmap_ptom(((vaddr_t)&pde[PDIR_SLOT_PTE + 3]) - KERNBASE),
1038 xpmap_ptom_masked(addr) | PG_k | PG_V); 1038 xpmap_ptom_masked(addr) | PG_k | PG_V);
1039 xpq_flush_queue(); 1039 xpq_flush_queue();
1040 } 1040 }
1041#elif defined(__x86_64__) 1041#elif defined(__x86_64__)
1042 if (final) { 1042 if (final) {
1043 /* save the address of the real per-cpu L4 pgd page */ 1043 /* save the address of the real per-cpu L4 pgd page */
1044 cpu_info_primary.ci_kpm_pdir = bt_cpu_pgd; 1044 cpu_info_primary.ci_kpm_pdir = bt_cpu_pgd;
1045 cpu_info_primary.ci_kpm_pdirpa = ((paddr_t) bt_cpu_pgd - KERNBASE); 1045 cpu_info_primary.ci_kpm_pdirpa = ((paddr_t) bt_cpu_pgd - KERNBASE);
1046 } 1046 }
1047#endif 1047#endif
1048 1048
1049 /* Now we can safely reclaim space taken by old tables */ 1049 /* Now we can safely reclaim space taken by old tables */
1050  1050
1051 __PRINTK(("unpin old PGD\n")); 1051 __PRINTK(("unpin old PGD\n"));
1052 /* Unpin old PGD */ 1052 /* Unpin old PGD */
1053 xpq_queue_unpin_table(xpmap_ptom_masked(old_pgd - KERNBASE)); 1053 xpq_queue_unpin_table(xpmap_ptom_masked(old_pgd - KERNBASE));
1054 /* Mark old tables RW */ 1054 /* Mark old tables RW */
1055 page = old_pgd; 1055 page = old_pgd;
1056 addr = (paddr_t) pde[pl2_pi(page)] & PG_FRAME; 1056 addr = (paddr_t) pde[pl2_pi(page)] & PG_FRAME;
1057 addr = xpmap_mtop(addr); 1057 addr = xpmap_mtop(addr);
1058 pte = (pd_entry_t *) ((u_long)addr + KERNBASE); 1058 pte = (pd_entry_t *) ((u_long)addr + KERNBASE);
1059 pte += pl1_pi(page); 1059 pte += pl1_pi(page);
1060 __PRINTK(("*pde %#" PRIxPADDR " addr %#" PRIxPADDR " pte %#lx\n", 1060 __PRINTK(("*pde %#" PRIxPADDR " addr %#" PRIxPADDR " pte %#lx\n",
1061 pde[pl2_pi(page)], addr, (long)pte)); 1061 pde[pl2_pi(page)], addr, (long)pte));
1062 while (page < old_pgd + (old_count * PAGE_SIZE) && page < map_end) { 1062 while (page < old_pgd + (old_count * PAGE_SIZE) && page < map_end) {
1063 addr = xpmap_ptom(((u_long) pte) - KERNBASE); 1063 addr = xpmap_ptom(((u_long) pte) - KERNBASE);
1064 XENPRINTK(("addr %#" PRIxPADDR " pte %#lx " 1064 XENPRINTK(("addr %#" PRIxPADDR " pte %#lx "
1065 "*pte %#" PRIxPADDR "\n", 1065 "*pte %#" PRIxPADDR "\n",
1066 addr, (long)pte, *pte)); 1066 addr, (long)pte, *pte));
1067 xpq_queue_pte_update(addr, *pte | PG_RW); 1067 xpq_queue_pte_update(addr, *pte | PG_RW);
1068 page += PAGE_SIZE; 1068 page += PAGE_SIZE;
1069 /*  1069 /*
1070 * Our ptes are contiguous 1070 * Our ptes are contiguous
1071 * so it's safe to just "++" here 1071 * so it's safe to just "++" here
1072 */ 1072 */
1073 pte++; 1073 pte++;
1074 } 1074 }
1075 xpq_flush_queue(); 1075 xpq_flush_queue();
1076} 1076}
1077 1077
1078 1078
1079/* 1079/*
1080 * Bootstrap helper functions 1080 * Bootstrap helper functions
1081 */ 1081 */
1082 1082
1083/* 1083/*
1084 * Mark a page readonly 1084 * Mark a page readonly
1085 * XXX: assuming vaddr = paddr + KERNBASE 1085 * XXX: assuming vaddr = paddr + KERNBASE
1086 */ 1086 */
1087 1087
1088static void 1088static void
1089xen_bt_set_readonly (vaddr_t page) 1089xen_bt_set_readonly (vaddr_t page)
1090{ 1090{
1091 pt_entry_t entry; 1091 pt_entry_t entry;
1092 1092
1093 entry = xpmap_ptom_masked(page - KERNBASE); 1093 entry = xpmap_ptom_masked(page - KERNBASE);
1094 entry |= PG_k | PG_V; 1094 entry |= PG_k | PG_V;
1095 1095
1096 HYPERVISOR_update_va_mapping (page, entry, UVMF_INVLPG); 1096 HYPERVISOR_update_va_mapping (page, entry, UVMF_INVLPG);
1097} 1097}
1098 1098
1099#ifdef __x86_64__ 1099#ifdef __x86_64__
1100void 1100void
1101xen_set_user_pgd(paddr_t page) 1101xen_set_user_pgd(paddr_t page)
1102{ 1102{
1103 struct mmuext_op op; 1103 struct mmuext_op op;
1104 int s = splvm(); 1104 int s = splvm();
1105 1105
1106 xpq_flush_queue(); 1106 xpq_flush_queue();
1107 op.cmd = MMUEXT_NEW_USER_BASEPTR; 1107 op.cmd = MMUEXT_NEW_USER_BASEPTR;
1108 op.arg1.mfn = xpmap_ptom_masked(page) >> PAGE_SHIFT; 1108 op.arg1.mfn = xpmap_ptom_masked(page) >> PAGE_SHIFT;
1109 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) 1109 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0)
1110 panic("xen_set_user_pgd: failed to install new user page" 1110 panic("xen_set_user_pgd: failed to install new user page"
1111 " directory %#" PRIxPADDR, page); 1111 " directory %#" PRIxPADDR, page);
1112 splx(s); 1112 splx(s);
1113} 1113}
1114#endif /* __x86_64__ */ 1114#endif /* __x86_64__ */

cvs diff -r1.7 -r1.8 src/sys/kern/subr_kcpuset.c (switch to unified diff)

--- src/sys/kern/subr_kcpuset.c 2012/08/20 22:01:29 1.7
+++ src/sys/kern/subr_kcpuset.c 2012/09/16 22:09:33 1.8
@@ -1,462 +1,462 @@ @@ -1,462 +1,462 @@
1/* $NetBSD: subr_kcpuset.c,v 1.7 2012/08/20 22:01:29 rmind Exp $ */ 1/* $NetBSD: subr_kcpuset.c,v 1.8 2012/09/16 22:09:33 rmind Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2011 The NetBSD Foundation, Inc. 4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Mindaugas Rasiukevicius. 8 * by Mindaugas Rasiukevicius.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * Kernel CPU set implementation. 33 * Kernel CPU set implementation.
34 * 34 *
35 * Interface can be used by kernel subsystems as a unified dynamic CPU 35 * Interface can be used by kernel subsystems as a unified dynamic CPU
36 * bitset implementation handling many CPUs. Facility also supports early 36 * bitset implementation handling many CPUs. Facility also supports early
37 * use by MD code on boot, as it fixups bitsets on further boot. 37 * use by MD code on boot, as it fixups bitsets on further boot.
38 * 38 *
39 * TODO: 39 * TODO:
40 * - Handle "reverse" bitset on fixup/grow. 40 * - Handle "reverse" bitset on fixup/grow.
41 */ 41 */
42 42
43#include <sys/cdefs.h> 43#include <sys/cdefs.h>
44__KERNEL_RCSID(0, "$NetBSD: subr_kcpuset.c,v 1.7 2012/08/20 22:01:29 rmind Exp $"); 44__KERNEL_RCSID(0, "$NetBSD: subr_kcpuset.c,v 1.8 2012/09/16 22:09:33 rmind Exp $");
45 45
46#include <sys/param.h> 46#include <sys/param.h>
47#include <sys/types.h> 47#include <sys/types.h>
48 48
49#include <sys/atomic.h> 49#include <sys/atomic.h>
50#include <sys/sched.h> 50#include <sys/sched.h>
51#include <sys/kcpuset.h> 51#include <sys/kcpuset.h>
52#include <sys/pool.h> 52#include <sys/pool.h>
53 53
54/* Number of CPUs to support. */ 54/* Number of CPUs to support. */
55#define KC_MAXCPUS roundup2(MAXCPUS, 32) 55#define KC_MAXCPUS roundup2(MAXCPUS, 32)
56 56
57/* 57/*
58 * Structure of dynamic CPU set in the kernel. 58 * Structure of dynamic CPU set in the kernel.
59 */ 59 */
60struct kcpuset { 60struct kcpuset {
61 uint32_t bits[0]; 61 uint32_t bits[0];
62}; 62};
63 63
64typedef struct kcpuset_impl { 64typedef struct kcpuset_impl {
65 /* Reference count. */ 65 /* Reference count. */
66 u_int kc_refcnt; 66 u_int kc_refcnt;
67 /* Next to free, if non-NULL (used when multiple references). */  67 /* Next to free, if non-NULL (used when multiple references). */
68 struct kcpuset * kc_next; 68 struct kcpuset * kc_next;
69 /* Actual variable-sized field of bits. */ 69 /* Actual variable-sized field of bits. */
70 struct kcpuset kc_field; 70 struct kcpuset kc_field;
71} kcpuset_impl_t; 71} kcpuset_impl_t;
72 72
73#define KC_BITS_OFF (offsetof(struct kcpuset_impl, kc_field)) 73#define KC_BITS_OFF (offsetof(struct kcpuset_impl, kc_field))
74#define KC_GETSTRUCT(b) ((kcpuset_impl_t *)((char *)(b) - KC_BITS_OFF)) 74#define KC_GETSTRUCT(b) ((kcpuset_impl_t *)((char *)(b) - KC_BITS_OFF))
75 75
76/* Sizes of a single bitset. */ 76/* Sizes of a single bitset. */
77#define KC_SHIFT 5 77#define KC_SHIFT 5
78#define KC_MASK 31 78#define KC_MASK 31
79 79
80/* An array of noted early kcpuset creations and data. */ 80/* An array of noted early kcpuset creations and data. */
81#define KC_SAVE_NITEMS 8 81#define KC_SAVE_NITEMS 8
82 82
83/* Structures for early boot mechanism (must be statically initialised). */ 83/* Structures for early boot mechanism (must be statically initialised). */
84static kcpuset_t ** kc_noted_early[KC_SAVE_NITEMS]; 84static kcpuset_t ** kc_noted_early[KC_SAVE_NITEMS];
85static uint32_t kc_bits_early[KC_SAVE_NITEMS]; 85static uint32_t kc_bits_early[KC_SAVE_NITEMS];
86static int kc_last_idx = 0; 86static int kc_last_idx = 0;
87static bool kc_initialised = false; 87static bool kc_initialised = false;
88 88
89#define KC_BITSIZE_EARLY sizeof(kc_bits_early[0]) 89#define KC_BITSIZE_EARLY sizeof(kc_bits_early[0])
90#define KC_NFIELDS_EARLY 1 90#define KC_NFIELDS_EARLY 1
91 91
92/* 92/*
93 * The size of whole bitset fields and amount of fields. 93 * The size of whole bitset fields and amount of fields.
94 * The whole size must statically initialise for early case. 94 * The whole size must statically initialise for early case.
95 */ 95 */
96static size_t kc_bitsize __read_mostly = KC_BITSIZE_EARLY; 96static size_t kc_bitsize __read_mostly = KC_BITSIZE_EARLY;
97static size_t kc_nfields __read_mostly = KC_NFIELDS_EARLY; 97static size_t kc_nfields __read_mostly = KC_NFIELDS_EARLY;
98 98
99static pool_cache_t kc_cache __read_mostly; 99static pool_cache_t kc_cache __read_mostly;
100 100
101static kcpuset_t * kcpuset_create_raw(bool); 101static kcpuset_t * kcpuset_create_raw(bool);
102 102
103/* 103/*
104 * kcpuset_sysinit: initialize the subsystem, transfer early boot cases 104 * kcpuset_sysinit: initialize the subsystem, transfer early boot cases
105 * to dynamically allocated sets. 105 * to dynamically allocated sets.
106 */ 106 */
107void 107void
108kcpuset_sysinit(void) 108kcpuset_sysinit(void)
109{ 109{
110 kcpuset_t *kc_dynamic[KC_SAVE_NITEMS], *kcp; 110 kcpuset_t *kc_dynamic[KC_SAVE_NITEMS], *kcp;
111 int i, s; 111 int i, s;
112 112
113 /* Set a kcpuset_t sizes. */ 113 /* Set a kcpuset_t sizes. */
114 kc_nfields = (KC_MAXCPUS >> KC_SHIFT); 114 kc_nfields = (KC_MAXCPUS >> KC_SHIFT);
115 kc_bitsize = sizeof(uint32_t) * kc_nfields; 115 kc_bitsize = sizeof(uint32_t) * kc_nfields;
116 KASSERT(kc_nfields != 0 && kc_bitsize != 0); 116 KASSERT(kc_nfields != 0 && kc_bitsize != 0);
117 117
118 kc_cache = pool_cache_init(sizeof(kcpuset_impl_t) + kc_bitsize, 118 kc_cache = pool_cache_init(sizeof(kcpuset_impl_t) + kc_bitsize,
119 coherency_unit, 0, 0, "kcpuset", NULL, IPL_NONE, NULL, NULL, NULL); 119 coherency_unit, 0, 0, "kcpuset", NULL, IPL_NONE, NULL, NULL, NULL);
120 120
121 /* First, pre-allocate kcpuset entries. */ 121 /* First, pre-allocate kcpuset entries. */
122 for (i = 0; i < kc_last_idx; i++) { 122 for (i = 0; i < kc_last_idx; i++) {
123 kcp = kcpuset_create_raw(true); 123 kcp = kcpuset_create_raw(true);
124 kc_dynamic[i] = kcp; 124 kc_dynamic[i] = kcp;
125 } 125 }
126 126
127 /* 127 /*
128 * Prepare to convert all early noted kcpuset uses to dynamic sets. 128 * Prepare to convert all early noted kcpuset uses to dynamic sets.
129 * All processors, except the one we are currently running (primary), 129 * All processors, except the one we are currently running (primary),
130 * must not be spinned yet. Since MD facilities can use kcpuset, 130 * must not be spinned yet. Since MD facilities can use kcpuset,
131 * raise the IPL to high. 131 * raise the IPL to high.
132 */ 132 */
133 KASSERT(mp_online == false); 133 KASSERT(mp_online == false);
134 134
135 s = splhigh(); 135 s = splhigh();
136 for (i = 0; i < kc_last_idx; i++) { 136 for (i = 0; i < kc_last_idx; i++) {
137 /* 137 /*
138 * Transfer the bits from early static storage to the kcpuset. 138 * Transfer the bits from early static storage to the kcpuset.
139 */ 139 */
140 KASSERT(kc_bitsize >= KC_BITSIZE_EARLY); 140 KASSERT(kc_bitsize >= KC_BITSIZE_EARLY);
141 memcpy(kc_dynamic[i], &kc_bits_early[i], KC_BITSIZE_EARLY); 141 memcpy(kc_dynamic[i], &kc_bits_early[i], KC_BITSIZE_EARLY);
142 142
143 /* 143 /*
144 * Store the new pointer, pointing to the allocated kcpuset. 144 * Store the new pointer, pointing to the allocated kcpuset.
145 * Note: we are not in an interrupt context and it is the only 145 * Note: we are not in an interrupt context and it is the only
146 * CPU running - thus store is safe (e.g. no need for pointer 146 * CPU running - thus store is safe (e.g. no need for pointer
147 * variable to be volatile). 147 * variable to be volatile).
148 */ 148 */
149 *kc_noted_early[i] = kc_dynamic[i]; 149 *kc_noted_early[i] = kc_dynamic[i];
150 } 150 }
151 kc_initialised = true; 151 kc_initialised = true;
152 kc_last_idx = 0; 152 kc_last_idx = 0;
153 splx(s); 153 splx(s);
154} 154}
155 155
156/* 156/*
157 * kcpuset_early_ptr: note an early boot use by saving the pointer and 157 * kcpuset_early_ptr: note an early boot use by saving the pointer and
158 * returning a pointer to a static, temporary bit field. 158 * returning a pointer to a static, temporary bit field.
159 */ 159 */
160static kcpuset_t * 160static kcpuset_t *
161kcpuset_early_ptr(kcpuset_t **kcptr) 161kcpuset_early_ptr(kcpuset_t **kcptr)
162{ 162{
163 kcpuset_t *kcp; 163 kcpuset_t *kcp;
164 int s; 164 int s;
165 165
166 s = splhigh(); 166 s = splhigh();
167 if (kc_last_idx < KC_SAVE_NITEMS) { 167 if (kc_last_idx < KC_SAVE_NITEMS) {
168 /* 168 /*
169 * Save the pointer, return pointer to static early field. 169 * Save the pointer, return pointer to static early field.
170 * Need to zero it out. 170 * Need to zero it out.
171 */ 171 */
172 kc_noted_early[kc_last_idx] = kcptr; 172 kc_noted_early[kc_last_idx] = kcptr;
173 kcp = (kcpuset_t *)&kc_bits_early[kc_last_idx]; 173 kcp = (kcpuset_t *)&kc_bits_early[kc_last_idx];
174 kc_last_idx++; 174 kc_last_idx++;
175 memset(kcp, 0, KC_BITSIZE_EARLY); 175 memset(kcp, 0, KC_BITSIZE_EARLY);
176 KASSERT(kc_bitsize == KC_BITSIZE_EARLY); 176 KASSERT(kc_bitsize == KC_BITSIZE_EARLY);
177 } else { 177 } else {
178 panic("kcpuset(9): all early-use entries exhausted; " 178 panic("kcpuset(9): all early-use entries exhausted; "
179 "increase KC_SAVE_NITEMS\n"); 179 "increase KC_SAVE_NITEMS\n");
180 } 180 }
181 splx(s); 181 splx(s);
182 182
183 return kcp; 183 return kcp;
184} 184}
185 185
186/* 186/*
187 * Routines to create or destroy the CPU set. 187 * Routines to create or destroy the CPU set.
188 * Early boot case is handled. 188 * Early boot case is handled.
189 */ 189 */
190 190
191static kcpuset_t * 191static kcpuset_t *
192kcpuset_create_raw(bool zero) 192kcpuset_create_raw(bool zero)
193{ 193{
194 kcpuset_impl_t *kc; 194 kcpuset_impl_t *kc;
195 195
196 kc = pool_cache_get(kc_cache, PR_WAITOK); 196 kc = pool_cache_get(kc_cache, PR_WAITOK);
197 kc->kc_refcnt = 1; 197 kc->kc_refcnt = 1;
198 kc->kc_next = NULL; 198 kc->kc_next = NULL;
199 199
200 if (zero) { 200 if (zero) {
201 memset(&kc->kc_field, 0, kc_bitsize); 201 memset(&kc->kc_field, 0, kc_bitsize);
202 } 202 }
203 203
204 /* Note: return pointer to the actual field of bits. */ 204 /* Note: return pointer to the actual field of bits. */
205 KASSERT((uint8_t *)kc + KC_BITS_OFF == (uint8_t *)&kc->kc_field); 205 KASSERT((uint8_t *)kc + KC_BITS_OFF == (uint8_t *)&kc->kc_field);
206 return &kc->kc_field; 206 return &kc->kc_field;
207} 207}
208 208
209void 209void
210kcpuset_create(kcpuset_t **retkcp, bool zero) 210kcpuset_create(kcpuset_t **retkcp, bool zero)
211{ 211{
212 if (__predict_false(!kc_initialised)) { 212 if (__predict_false(!kc_initialised)) {
213 /* Early boot use - special case. */ 213 /* Early boot use - special case. */
214 *retkcp = kcpuset_early_ptr(retkcp); 214 *retkcp = kcpuset_early_ptr(retkcp);
215 return; 215 return;
216 } 216 }
217 *retkcp = kcpuset_create_raw(zero); 217 *retkcp = kcpuset_create_raw(zero);
218} 218}
219 219
220void 220void
221kcpuset_destroy(kcpuset_t *kcp) 221kcpuset_destroy(kcpuset_t *kcp)
222{ 222{
223 kcpuset_impl_t *kc; 223 kcpuset_impl_t *kc;
224 224
225 KASSERT(kc_initialised); 225 KASSERT(kc_initialised);
226 KASSERT(kcp != NULL); 226 KASSERT(kcp != NULL);
227 227
228 do { 228 do {
229 kc = KC_GETSTRUCT(kcp); 229 kc = KC_GETSTRUCT(kcp);
230 kcp = kc->kc_next; 230 kcp = kc->kc_next;
231 pool_cache_put(kc_cache, kc); 231 pool_cache_put(kc_cache, kc);
232 } while (kcp); 232 } while (kcp);
233} 233}
234 234
235/* 235/*
236 * Routines to reference/unreference the CPU set. 236 * Routines to reference/unreference the CPU set.
237 * Note: early boot case is not supported by these routines. 237 * Note: early boot case is not supported by these routines.
238 */ 238 */
239 239
240void 240void
241kcpuset_use(kcpuset_t *kcp) 241kcpuset_use(kcpuset_t *kcp)
242{ 242{
243 kcpuset_impl_t *kc = KC_GETSTRUCT(kcp); 243 kcpuset_impl_t *kc = KC_GETSTRUCT(kcp);
244 244
245 KASSERT(kc_initialised); 245 KASSERT(kc_initialised);
246 atomic_inc_uint(&kc->kc_refcnt); 246 atomic_inc_uint(&kc->kc_refcnt);
247} 247}
248 248
249void 249void
250kcpuset_unuse(kcpuset_t *kcp, kcpuset_t **lst) 250kcpuset_unuse(kcpuset_t *kcp, kcpuset_t **lst)
251{ 251{
252 kcpuset_impl_t *kc = KC_GETSTRUCT(kcp); 252 kcpuset_impl_t *kc = KC_GETSTRUCT(kcp);
253 253
254 KASSERT(kc_initialised); 254 KASSERT(kc_initialised);
255 KASSERT(kc->kc_refcnt > 0); 255 KASSERT(kc->kc_refcnt > 0);
256 256
257 if (atomic_dec_uint_nv(&kc->kc_refcnt) != 0) { 257 if (atomic_dec_uint_nv(&kc->kc_refcnt) != 0) {
258 return; 258 return;
259 } 259 }
260 KASSERT(kc->kc_next == NULL); 260 KASSERT(kc->kc_next == NULL);
261 if (lst == NULL) { 261 if (lst == NULL) {
262 kcpuset_destroy(kcp); 262 kcpuset_destroy(kcp);
263 return; 263 return;
264 } 264 }
265 kc->kc_next = *lst; 265 kc->kc_next = *lst;
266 *lst = kcp; 266 *lst = kcp;
267} 267}
268 268
269/* 269/*
270 * Routines to transfer the CPU set from / to userspace. 270 * Routines to transfer the CPU set from / to userspace.
271 * Note: early boot case is not supported by these routines. 271 * Note: early boot case is not supported by these routines.
272 */ 272 */
273 273
274int 274int
275kcpuset_copyin(const cpuset_t *ucp, kcpuset_t *kcp, size_t len) 275kcpuset_copyin(const cpuset_t *ucp, kcpuset_t *kcp, size_t len)
276{ 276{
277 kcpuset_impl_t *kc __unused = KC_GETSTRUCT(kcp); 277 kcpuset_impl_t *kc __unused = KC_GETSTRUCT(kcp);
278 278
279 KASSERT(kc_initialised); 279 KASSERT(kc_initialised);
280 KASSERT(kc->kc_refcnt > 0); 280 KASSERT(kc->kc_refcnt > 0);
281 KASSERT(kc->kc_next == NULL); 281 KASSERT(kc->kc_next == NULL);
282 282
283 if (len > kc_bitsize) { /* XXX */ 283 if (len > kc_bitsize) { /* XXX */
284 return EINVAL; 284 return EINVAL;
285 } 285 }
286 return copyin(ucp, kcp, len); 286 return copyin(ucp, kcp, len);
287} 287}
288 288
289int 289int
290kcpuset_copyout(kcpuset_t *kcp, cpuset_t *ucp, size_t len) 290kcpuset_copyout(kcpuset_t *kcp, cpuset_t *ucp, size_t len)
291{ 291{
292 kcpuset_impl_t *kc __unused = KC_GETSTRUCT(kcp); 292 kcpuset_impl_t *kc __unused = KC_GETSTRUCT(kcp);
293 293
294 KASSERT(kc_initialised); 294 KASSERT(kc_initialised);
295 KASSERT(kc->kc_refcnt > 0); 295 KASSERT(kc->kc_refcnt > 0);
296 KASSERT(kc->kc_next == NULL); 296 KASSERT(kc->kc_next == NULL);
297 297
298 if (len > kc_bitsize) { /* XXX */ 298 if (len > kc_bitsize) { /* XXX */
299 return EINVAL; 299 return EINVAL;
300 } 300 }
301 return copyout(kcp, ucp, len); 301 return copyout(kcp, ucp, len);
302} 302}
303 303
304void 304void
305kcpuset_copybits(const kcpuset_t *kcp, uint32_t *bitfield, size_t len) 305kcpuset_export_u32(const kcpuset_t *kcp, uint32_t *bitfield, size_t len)
306{ 306{
307 size_t rlen = MIN(kc_bitsize, len); 307 size_t rlen = MIN(kc_bitsize, len);
308 308
309 KASSERT(kcp != NULL); 309 KASSERT(kcp != NULL);
310 memcpy(bitfield, kcp->bits, rlen); 310 memcpy(bitfield, kcp->bits, rlen);
311} 311}
312 312
313/* 313/*
314 * Routines to change bit field - zero, fill, copy, set, unset, etc. 314 * Routines to change bit field - zero, fill, copy, set, unset, etc.
315 */ 315 */
316 316
317void 317void
318kcpuset_zero(kcpuset_t *kcp) 318kcpuset_zero(kcpuset_t *kcp)
319{ 319{
320 320
321 KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_refcnt > 0); 321 KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_refcnt > 0);
322 KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL); 322 KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL);
323 memset(kcp, 0, kc_bitsize); 323 memset(kcp, 0, kc_bitsize);
324} 324}
325 325
326void 326void
327kcpuset_fill(kcpuset_t *kcp) 327kcpuset_fill(kcpuset_t *kcp)
328{ 328{
329 329
330 KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_refcnt > 0); 330 KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_refcnt > 0);
331 KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL); 331 KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL);
332 memset(kcp, ~0, kc_bitsize); 332 memset(kcp, ~0, kc_bitsize);
333} 333}
334 334
335void 335void
336kcpuset_copy(kcpuset_t *dkcp, kcpuset_t *skcp) 336kcpuset_copy(kcpuset_t *dkcp, kcpuset_t *skcp)
337{ 337{
338 338
339 KASSERT(!kc_initialised || KC_GETSTRUCT(dkcp)->kc_refcnt > 0); 339 KASSERT(!kc_initialised || KC_GETSTRUCT(dkcp)->kc_refcnt > 0);
340 KASSERT(!kc_initialised || KC_GETSTRUCT(dkcp)->kc_next == NULL); 340 KASSERT(!kc_initialised || KC_GETSTRUCT(dkcp)->kc_next == NULL);
341 memcpy(dkcp, skcp, kc_bitsize); 341 memcpy(dkcp, skcp, kc_bitsize);
342} 342}
343 343
344void 344void
345kcpuset_set(kcpuset_t *kcp, cpuid_t i) 345kcpuset_set(kcpuset_t *kcp, cpuid_t i)
346{ 346{
347 const size_t j = i >> KC_SHIFT; 347 const size_t j = i >> KC_SHIFT;
348 348
349 KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL); 349 KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL);
350 KASSERT(j < kc_nfields); 350 KASSERT(j < kc_nfields);
351 351
352 kcp->bits[j] |= 1 << (i & KC_MASK); 352 kcp->bits[j] |= 1 << (i & KC_MASK);
353} 353}
354 354
355void 355void
356kcpuset_clear(kcpuset_t *kcp, cpuid_t i) 356kcpuset_clear(kcpuset_t *kcp, cpuid_t i)
357{ 357{
358 const size_t j = i >> KC_SHIFT; 358 const size_t j = i >> KC_SHIFT;
359 359
360 KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL); 360 KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL);
361 KASSERT(j < kc_nfields); 361 KASSERT(j < kc_nfields);
362 362
363 kcp->bits[j] &= ~(1 << (i & KC_MASK)); 363 kcp->bits[j] &= ~(1 << (i & KC_MASK));
364} 364}
365 365
366bool 366bool
367kcpuset_isset(kcpuset_t *kcp, cpuid_t i) 367kcpuset_isset(kcpuset_t *kcp, cpuid_t i)
368{ 368{
369 const size_t j = i >> KC_SHIFT; 369 const size_t j = i >> KC_SHIFT;
370 370
371 KASSERT(kcp != NULL); 371 KASSERT(kcp != NULL);
372 KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_refcnt > 0); 372 KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_refcnt > 0);
373 KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL); 373 KASSERT(!kc_initialised || KC_GETSTRUCT(kcp)->kc_next == NULL);
374 KASSERT(j < kc_nfields); 374 KASSERT(j < kc_nfields);
375 375
376 return ((1 << (i & KC_MASK)) & kcp->bits[j]) != 0; 376 return ((1 << (i & KC_MASK)) & kcp->bits[j]) != 0;
377} 377}
378 378
379bool 379bool
380kcpuset_isotherset(kcpuset_t *kcp, cpuid_t i) 380kcpuset_isotherset(kcpuset_t *kcp, cpuid_t i)
381{ 381{
382 const size_t j2 = i >> KC_SHIFT; 382 const size_t j2 = i >> KC_SHIFT;
383 const uint32_t mask = ~(1 << (i & KC_MASK)); 383 const uint32_t mask = ~(1 << (i & KC_MASK));
384 384
385 for (size_t j = 0; j < kc_nfields; j++) { 385 for (size_t j = 0; j < kc_nfields; j++) {
386 const uint32_t bits = kcp->bits[j]; 386 const uint32_t bits = kcp->bits[j];
387 if (bits && (j != j2 || (bits & mask) != 0)) { 387 if (bits && (j != j2 || (bits & mask) != 0)) {
388 return true; 388 return true;
389 } 389 }
390 } 390 }
391 return false; 391 return false;
392} 392}
393 393
394bool 394bool
395kcpuset_iszero(kcpuset_t *kcp) 395kcpuset_iszero(kcpuset_t *kcp)
396{ 396{
397 397
398 for (size_t j = 0; j < kc_nfields; j++) { 398 for (size_t j = 0; j < kc_nfields; j++) {
399 if (kcp->bits[j] != 0) { 399 if (kcp->bits[j] != 0) {
400 return false; 400 return false;
401 } 401 }
402 } 402 }
403 return true; 403 return true;
404} 404}
405 405
406bool 406bool
407kcpuset_match(const kcpuset_t *kcp1, const kcpuset_t *kcp2) 407kcpuset_match(const kcpuset_t *kcp1, const kcpuset_t *kcp2)
408{ 408{
409 409
410 return memcmp(kcp1, kcp2, kc_bitsize) == 0; 410 return memcmp(kcp1, kcp2, kc_bitsize) == 0;
411} 411}
412 412
413void 413void
414kcpuset_merge(kcpuset_t *kcp1, kcpuset_t *kcp2) 414kcpuset_merge(kcpuset_t *kcp1, kcpuset_t *kcp2)
415{ 415{
416 416
417 for (size_t j = 0; j < kc_nfields; j++) { 417 for (size_t j = 0; j < kc_nfields; j++) {
418 kcp1->bits[j] |= kcp2->bits[j]; 418 kcp1->bits[j] |= kcp2->bits[j];
419 } 419 }
420} 420}
421 421
422void 422void
423kcpuset_intersect(kcpuset_t *kcp1, kcpuset_t *kcp2) 423kcpuset_intersect(kcpuset_t *kcp1, kcpuset_t *kcp2)
424{ 424{
425 425
426 for (size_t j = 0; j < kc_nfields; j++) { 426 for (size_t j = 0; j < kc_nfields; j++) {
427 kcp1->bits[j] &= kcp2->bits[j]; 427 kcp1->bits[j] &= kcp2->bits[j];
428 } 428 }
429} 429}
430 430
431int 431int
432kcpuset_countset(kcpuset_t *kcp) 432kcpuset_countset(kcpuset_t *kcp)
433{ 433{
434 int count = 0; 434 int count = 0;
435 435
436 for (size_t j = 0; j < kc_nfields; j++) { 436 for (size_t j = 0; j < kc_nfields; j++) {
437 count += popcount32(kcp->bits[j]); 437 count += popcount32(kcp->bits[j]);
438 } 438 }
439 return count; 439 return count;
440} 440}
441 441
442/* 442/*
443 * Routines to set/clear the flags atomically. 443 * Routines to set/clear the flags atomically.
444 */ 444 */
445 445
446void 446void
447kcpuset_atomic_set(kcpuset_t *kcp, cpuid_t i) 447kcpuset_atomic_set(kcpuset_t *kcp, cpuid_t i)
448{ 448{
449 const size_t j = i >> KC_SHIFT; 449 const size_t j = i >> KC_SHIFT;
450 450
451 KASSERT(j < kc_nfields); 451 KASSERT(j < kc_nfields);
452 atomic_or_32(&kcp->bits[j], 1 << (i & KC_MASK)); 452 atomic_or_32(&kcp->bits[j], 1 << (i & KC_MASK));
453} 453}
454 454
455void 455void
456kcpuset_atomic_clear(kcpuset_t *kcp, cpuid_t i) 456kcpuset_atomic_clear(kcpuset_t *kcp, cpuid_t i)
457{ 457{
458 const size_t j = i >> KC_SHIFT; 458 const size_t j = i >> KC_SHIFT;
459 459
460 KASSERT(j < kc_nfields); 460 KASSERT(j < kc_nfields);
461 atomic_and_32(&kcp->bits[j], ~(1 << (i & KC_MASK))); 461 atomic_and_32(&kcp->bits[j], ~(1 << (i & KC_MASK)));
462} 462}

cvs diff -r1.7 -r1.8 src/sys/sys/kcpuset.h (switch to unified diff)

--- src/sys/sys/kcpuset.h 2012/08/20 22:01:30 1.7
+++ src/sys/sys/kcpuset.h 2012/09/16 22:09:33 1.8
@@ -1,73 +1,74 @@ @@ -1,73 +1,74 @@
1/* $NetBSD: kcpuset.h,v 1.7 2012/08/20 22:01:30 rmind Exp $ */ 1/* $NetBSD: kcpuset.h,v 1.8 2012/09/16 22:09:33 rmind Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008, 2011 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008, 2011 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas and Mindaugas Rasiukevicius. 8 * by Christos Zoulas and Mindaugas Rasiukevicius.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#ifndef _SYS_KCPUSET_H_ 32#ifndef _SYS_KCPUSET_H_
33#define _SYS_KCPUSET_H_ 33#define _SYS_KCPUSET_H_
34 34
35struct kcpuset; 35struct kcpuset;
36typedef struct kcpuset kcpuset_t; 36typedef struct kcpuset kcpuset_t;
37 37
38#ifdef _KERNEL 38#ifdef _KERNEL
39 39
40#include <sys/sched.h> 40#include <sys/sched.h>
41 41
42void kcpuset_sysinit(void); 42void kcpuset_sysinit(void);
43 43
44void kcpuset_create(kcpuset_t **, bool); 44void kcpuset_create(kcpuset_t **, bool);
45void kcpuset_destroy(kcpuset_t *); 45void kcpuset_destroy(kcpuset_t *);
46void kcpuset_copy(kcpuset_t *, kcpuset_t *); 46void kcpuset_copy(kcpuset_t *, kcpuset_t *);
47 47
48void kcpuset_use(kcpuset_t *); 48void kcpuset_use(kcpuset_t *);
49void kcpuset_unuse(kcpuset_t *, kcpuset_t **); 49void kcpuset_unuse(kcpuset_t *, kcpuset_t **);
50 50
51int kcpuset_copyin(const cpuset_t *, kcpuset_t *, size_t); 51int kcpuset_copyin(const cpuset_t *, kcpuset_t *, size_t);
52int kcpuset_copyout(kcpuset_t *, cpuset_t *, size_t); 52int kcpuset_copyout(kcpuset_t *, cpuset_t *, size_t);
53void kcpuset_copybits(const kcpuset_t *, uint32_t *, size_t); 
54 53
55void kcpuset_zero(kcpuset_t *); 54void kcpuset_zero(kcpuset_t *);
56void kcpuset_fill(kcpuset_t *); 55void kcpuset_fill(kcpuset_t *);
57void kcpuset_set(kcpuset_t *, cpuid_t); 56void kcpuset_set(kcpuset_t *, cpuid_t);
58void kcpuset_clear(kcpuset_t *, cpuid_t); 57void kcpuset_clear(kcpuset_t *, cpuid_t);
59 58
60bool kcpuset_isset(kcpuset_t *, cpuid_t); 59bool kcpuset_isset(kcpuset_t *, cpuid_t);
61bool kcpuset_isotherset(kcpuset_t *, cpuid_t); 60bool kcpuset_isotherset(kcpuset_t *, cpuid_t);
62bool kcpuset_iszero(kcpuset_t *); 61bool kcpuset_iszero(kcpuset_t *);
63bool kcpuset_match(const kcpuset_t *, const kcpuset_t *); 62bool kcpuset_match(const kcpuset_t *, const kcpuset_t *);
64void kcpuset_merge(kcpuset_t *, kcpuset_t *); 63void kcpuset_merge(kcpuset_t *, kcpuset_t *);
65void kcpuset_intersect(kcpuset_t *, kcpuset_t *); 64void kcpuset_intersect(kcpuset_t *, kcpuset_t *);
66int kcpuset_countset(kcpuset_t *); 65int kcpuset_countset(kcpuset_t *);
67 66
68void kcpuset_atomic_set(kcpuset_t *, cpuid_t); 67void kcpuset_atomic_set(kcpuset_t *, cpuid_t);
69void kcpuset_atomic_clear(kcpuset_t *, cpuid_t); 68void kcpuset_atomic_clear(kcpuset_t *, cpuid_t);
70 69
 70void kcpuset_export_u32(const kcpuset_t *, uint32_t *, size_t);
 71
71#endif 72#endif
72 73
73#endif /* _SYS_KCPUSET_H_ */ 74#endif /* _SYS_KCPUSET_H_ */