| @@ -1,1948 +1,1944 @@ | | | @@ -1,1948 +1,1944 @@ |
1 | /* $NetBSD: machdep.c,v 1.725 2012/03/04 15:56:09 bouyer Exp $ */ | | 1 | /* $NetBSD: machdep.c,v 1.726 2012/03/04 20:44:17 bouyer Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008, 2009 | | 4 | * Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006, 2008, 2009 |
5 | * The NetBSD Foundation, Inc. | | 5 | * The NetBSD Foundation, Inc. |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * This code is derived from software contributed to The NetBSD Foundation | | 8 | * This code is derived from software contributed to The NetBSD Foundation |
9 | * by Charles M. Hannum, by Jason R. Thorpe of the Numerical Aerospace | | 9 | * by Charles M. Hannum, by Jason R. Thorpe of the Numerical Aerospace |
10 | * Simulation Facility NASA Ames Research Center, by Julio M. Merino Vidal, | | 10 | * Simulation Facility NASA Ames Research Center, by Julio M. Merino Vidal, |
11 | * and by Andrew Doran. | | 11 | * and by Andrew Doran. |
12 | * | | 12 | * |
13 | * Redistribution and use in source and binary forms, with or without | | 13 | * Redistribution and use in source and binary forms, with or without |
14 | * modification, are permitted provided that the following conditions | | 14 | * modification, are permitted provided that the following conditions |
15 | * are met: | | 15 | * are met: |
16 | * 1. Redistributions of source code must retain the above copyright | | 16 | * 1. Redistributions of source code must retain the above copyright |
17 | * notice, this list of conditions and the following disclaimer. | | 17 | * notice, this list of conditions and the following disclaimer. |
18 | * 2. Redistributions in binary form must reproduce the above copyright | | 18 | * 2. Redistributions in binary form must reproduce the above copyright |
19 | * notice, this list of conditions and the following disclaimer in the | | 19 | * notice, this list of conditions and the following disclaimer in the |
20 | * documentation and/or other materials provided with the distribution. | | 20 | * documentation and/or other materials provided with the distribution. |
21 | * | | 21 | * |
22 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 22 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
23 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 23 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
24 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 24 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
25 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 25 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
26 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 26 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
32 | * POSSIBILITY OF SUCH DAMAGE. | | 32 | * POSSIBILITY OF SUCH DAMAGE. |
33 | */ | | 33 | */ |
34 | | | 34 | |
35 | /*- | | 35 | /*- |
36 | * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. | | 36 | * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. |
37 | * All rights reserved. | | 37 | * All rights reserved. |
38 | * | | 38 | * |
39 | * This code is derived from software contributed to Berkeley by | | 39 | * This code is derived from software contributed to Berkeley by |
40 | * William Jolitz. | | 40 | * William Jolitz. |
41 | * | | 41 | * |
42 | * Redistribution and use in source and binary forms, with or without | | 42 | * Redistribution and use in source and binary forms, with or without |
43 | * modification, are permitted provided that the following conditions | | 43 | * modification, are permitted provided that the following conditions |
44 | * are met: | | 44 | * are met: |
45 | * 1. Redistributions of source code must retain the above copyright | | 45 | * 1. Redistributions of source code must retain the above copyright |
46 | * notice, this list of conditions and the following disclaimer. | | 46 | * notice, this list of conditions and the following disclaimer. |
47 | * 2. Redistributions in binary form must reproduce the above copyright | | 47 | * 2. Redistributions in binary form must reproduce the above copyright |
48 | * notice, this list of conditions and the following disclaimer in the | | 48 | * notice, this list of conditions and the following disclaimer in the |
49 | * documentation and/or other materials provided with the distribution. | | 49 | * documentation and/or other materials provided with the distribution. |
50 | * 3. Neither the name of the University nor the names of its contributors | | 50 | * 3. Neither the name of the University nor the names of its contributors |
51 | * may be used to endorse or promote products derived from this software | | 51 | * may be used to endorse or promote products derived from this software |
52 | * without specific prior written permission. | | 52 | * without specific prior written permission. |
53 | * | | 53 | * |
54 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 54 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
55 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 55 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
56 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 56 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
57 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 57 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
58 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 58 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
59 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 59 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
60 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 60 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
61 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 61 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
62 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 62 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
63 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 63 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
64 | * SUCH DAMAGE. | | 64 | * SUCH DAMAGE. |
65 | * | | 65 | * |
66 | * @(#)machdep.c 7.4 (Berkeley) 6/3/91 | | 66 | * @(#)machdep.c 7.4 (Berkeley) 6/3/91 |
67 | */ | | 67 | */ |
68 | | | 68 | |
69 | #include <sys/cdefs.h> | | 69 | #include <sys/cdefs.h> |
70 | __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.725 2012/03/04 15:56:09 bouyer Exp $"); | | 70 | __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.726 2012/03/04 20:44:17 bouyer Exp $"); |
71 | | | 71 | |
72 | #include "opt_beep.h" | | 72 | #include "opt_beep.h" |
73 | #include "opt_compat_ibcs2.h" | | 73 | #include "opt_compat_ibcs2.h" |
74 | #include "opt_compat_freebsd.h" | | 74 | #include "opt_compat_freebsd.h" |
75 | #include "opt_compat_netbsd.h" | | 75 | #include "opt_compat_netbsd.h" |
76 | #include "opt_compat_svr4.h" | | 76 | #include "opt_compat_svr4.h" |
77 | #include "opt_cpureset_delay.h" | | 77 | #include "opt_cpureset_delay.h" |
78 | #include "opt_ddb.h" | | 78 | #include "opt_ddb.h" |
79 | #include "opt_ipkdb.h" | | 79 | #include "opt_ipkdb.h" |
80 | #include "opt_kgdb.h" | | 80 | #include "opt_kgdb.h" |
81 | #include "opt_mtrr.h" | | 81 | #include "opt_mtrr.h" |
82 | #include "opt_modular.h" | | 82 | #include "opt_modular.h" |
83 | #include "opt_multiboot.h" | | 83 | #include "opt_multiboot.h" |
84 | #include "opt_multiprocessor.h" | | 84 | #include "opt_multiprocessor.h" |
85 | #include "opt_physmem.h" | | 85 | #include "opt_physmem.h" |
86 | #include "opt_realmem.h" | | 86 | #include "opt_realmem.h" |
87 | #include "opt_user_ldt.h" | | 87 | #include "opt_user_ldt.h" |
88 | #include "opt_vm86.h" | | 88 | #include "opt_vm86.h" |
89 | #include "opt_xen.h" | | 89 | #include "opt_xen.h" |
90 | #include "isa.h" | | 90 | #include "isa.h" |
91 | #include "pci.h" | | 91 | #include "pci.h" |
92 | | | 92 | |
93 | #include <sys/param.h> | | 93 | #include <sys/param.h> |
94 | #include <sys/systm.h> | | 94 | #include <sys/systm.h> |
95 | #include <sys/signal.h> | | 95 | #include <sys/signal.h> |
96 | #include <sys/signalvar.h> | | 96 | #include <sys/signalvar.h> |
97 | #include <sys/kernel.h> | | 97 | #include <sys/kernel.h> |
98 | #include <sys/cpu.h> | | 98 | #include <sys/cpu.h> |
99 | #include <sys/exec.h> | | 99 | #include <sys/exec.h> |
100 | #include <sys/fcntl.h> | | 100 | #include <sys/fcntl.h> |
101 | #include <sys/reboot.h> | | 101 | #include <sys/reboot.h> |
102 | #include <sys/conf.h> | | 102 | #include <sys/conf.h> |
103 | #include <sys/kauth.h> | | 103 | #include <sys/kauth.h> |
104 | #include <sys/mbuf.h> | | 104 | #include <sys/mbuf.h> |
105 | #include <sys/msgbuf.h> | | 105 | #include <sys/msgbuf.h> |
106 | #include <sys/mount.h> | | 106 | #include <sys/mount.h> |
107 | #include <sys/syscallargs.h> | | 107 | #include <sys/syscallargs.h> |
108 | #include <sys/core.h> | | 108 | #include <sys/core.h> |
109 | #include <sys/kcore.h> | | 109 | #include <sys/kcore.h> |
110 | #include <sys/ucontext.h> | | 110 | #include <sys/ucontext.h> |
111 | #include <sys/ras.h> | | 111 | #include <sys/ras.h> |
112 | #include <sys/ksyms.h> | | 112 | #include <sys/ksyms.h> |
113 | #include <sys/device.h> | | 113 | #include <sys/device.h> |
114 | | | 114 | |
115 | #ifdef IPKDB | | 115 | #ifdef IPKDB |
116 | #include <ipkdb/ipkdb.h> | | 116 | #include <ipkdb/ipkdb.h> |
117 | #endif | | 117 | #endif |
118 | | | 118 | |
119 | #ifdef KGDB | | 119 | #ifdef KGDB |
120 | #include <sys/kgdb.h> | | 120 | #include <sys/kgdb.h> |
121 | #endif | | 121 | #endif |
122 | | | 122 | |
123 | #include <dev/cons.h> | | 123 | #include <dev/cons.h> |
124 | #include <dev/mm.h> | | 124 | #include <dev/mm.h> |
125 | | | 125 | |
126 | #include <uvm/uvm.h> | | 126 | #include <uvm/uvm.h> |
127 | #include <uvm/uvm_page.h> | | 127 | #include <uvm/uvm_page.h> |
128 | | | 128 | |
129 | #include <sys/sysctl.h> | | 129 | #include <sys/sysctl.h> |
130 | | | 130 | |
131 | #include <machine/cpu.h> | | 131 | #include <machine/cpu.h> |
132 | #include <machine/cpufunc.h> | | 132 | #include <machine/cpufunc.h> |
133 | #include <machine/cpuvar.h> | | 133 | #include <machine/cpuvar.h> |
134 | #include <machine/gdt.h> | | 134 | #include <machine/gdt.h> |
135 | #include <machine/intr.h> | | 135 | #include <machine/intr.h> |
136 | #include <machine/kcore.h> | | 136 | #include <machine/kcore.h> |
137 | #include <machine/pio.h> | | 137 | #include <machine/pio.h> |
138 | #include <machine/psl.h> | | 138 | #include <machine/psl.h> |
139 | #include <machine/reg.h> | | 139 | #include <machine/reg.h> |
140 | #include <machine/specialreg.h> | | 140 | #include <machine/specialreg.h> |
141 | #include <machine/bootinfo.h> | | 141 | #include <machine/bootinfo.h> |
142 | #include <machine/mtrr.h> | | 142 | #include <machine/mtrr.h> |
143 | #include <x86/x86/tsc.h> | | 143 | #include <x86/x86/tsc.h> |
144 | | | 144 | |
145 | #include <x86/machdep.h> | | 145 | #include <x86/machdep.h> |
146 | | | 146 | |
147 | #include <machine/multiboot.h> | | 147 | #include <machine/multiboot.h> |
148 | #ifdef XEN | | 148 | #ifdef XEN |
149 | #include <xen/evtchn.h> | | 149 | #include <xen/evtchn.h> |
150 | #include <xen/xen.h> | | 150 | #include <xen/xen.h> |
151 | #include <xen/hypervisor.h> | | 151 | #include <xen/hypervisor.h> |
152 | | | 152 | |
153 | /* #define XENDEBUG */ | | 153 | /* #define XENDEBUG */ |
154 | /* #define XENDEBUG_LOW */ | | 154 | /* #define XENDEBUG_LOW */ |
155 | | | 155 | |
156 | #ifdef XENDEBUG | | 156 | #ifdef XENDEBUG |
157 | #define XENPRINTF(x) printf x | | 157 | #define XENPRINTF(x) printf x |
158 | #define XENPRINTK(x) printk x | | 158 | #define XENPRINTK(x) printk x |
159 | #else | | 159 | #else |
160 | #define XENPRINTF(x) | | 160 | #define XENPRINTF(x) |
161 | #define XENPRINTK(x) | | 161 | #define XENPRINTK(x) |
162 | #endif | | 162 | #endif |
163 | #define PRINTK(x) printf x | | 163 | #define PRINTK(x) printf x |
164 | #endif /* XEN */ | | 164 | #endif /* XEN */ |
165 | | | 165 | |
166 | #include <dev/isa/isareg.h> | | 166 | #include <dev/isa/isareg.h> |
167 | #include <machine/isa_machdep.h> | | 167 | #include <machine/isa_machdep.h> |
168 | #include <dev/ic/i8042reg.h> | | 168 | #include <dev/ic/i8042reg.h> |
169 | | | 169 | |
170 | #ifdef DDB | | 170 | #ifdef DDB |
171 | #include <machine/db_machdep.h> | | 171 | #include <machine/db_machdep.h> |
172 | #include <ddb/db_extern.h> | | 172 | #include <ddb/db_extern.h> |
173 | #endif | | 173 | #endif |
174 | | | 174 | |
175 | #ifdef VM86 | | 175 | #ifdef VM86 |
176 | #include <machine/vm86.h> | | 176 | #include <machine/vm86.h> |
177 | #endif | | 177 | #endif |
178 | | | 178 | |
179 | #include "acpica.h" | | 179 | #include "acpica.h" |
180 | #include "apmbios.h" | | 180 | #include "apmbios.h" |
181 | #include "bioscall.h" | | 181 | #include "bioscall.h" |
182 | | | 182 | |
183 | #if NBIOSCALL > 0 | | 183 | #if NBIOSCALL > 0 |
184 | #include <machine/bioscall.h> | | 184 | #include <machine/bioscall.h> |
185 | #endif | | 185 | #endif |
186 | | | 186 | |
187 | #if NACPICA > 0 | | 187 | #if NACPICA > 0 |
188 | #include <dev/acpi/acpivar.h> | | 188 | #include <dev/acpi/acpivar.h> |
189 | #define ACPI_MACHDEP_PRIVATE | | 189 | #define ACPI_MACHDEP_PRIVATE |
190 | #include <machine/acpi_machdep.h> | | 190 | #include <machine/acpi_machdep.h> |
191 | #endif | | 191 | #endif |
192 | | | 192 | |
193 | #if NAPMBIOS > 0 | | 193 | #if NAPMBIOS > 0 |
194 | #include <machine/apmvar.h> | | 194 | #include <machine/apmvar.h> |
195 | #endif | | 195 | #endif |
196 | | | 196 | |
197 | #include "isa.h" | | 197 | #include "isa.h" |
198 | #include "isadma.h" | | 198 | #include "isadma.h" |
199 | #include "npx.h" | | 199 | #include "npx.h" |
200 | #include "ksyms.h" | | 200 | #include "ksyms.h" |
201 | | | 201 | |
202 | #include "cardbus.h" | | 202 | #include "cardbus.h" |
203 | #if NCARDBUS > 0 | | 203 | #if NCARDBUS > 0 |
204 | /* For rbus_min_start hint. */ | | 204 | /* For rbus_min_start hint. */ |
205 | #include <sys/bus.h> | | 205 | #include <sys/bus.h> |
206 | #include <dev/cardbus/rbus.h> | | 206 | #include <dev/cardbus/rbus.h> |
207 | #include <machine/rbus_machdep.h> | | 207 | #include <machine/rbus_machdep.h> |
208 | #endif | | 208 | #endif |
209 | | | 209 | |
210 | #include "mca.h" | | 210 | #include "mca.h" |
211 | #if NMCA > 0 | | 211 | #if NMCA > 0 |
212 | #include <machine/mca_machdep.h> /* for mca_busprobe() */ | | 212 | #include <machine/mca_machdep.h> /* for mca_busprobe() */ |
213 | #endif | | 213 | #endif |
214 | | | 214 | |
215 | #ifdef MULTIPROCESSOR /* XXX */ | | 215 | #ifdef MULTIPROCESSOR /* XXX */ |
216 | #include <machine/mpbiosvar.h> /* XXX */ | | 216 | #include <machine/mpbiosvar.h> /* XXX */ |
217 | #endif /* XXX */ | | 217 | #endif /* XXX */ |
218 | | | 218 | |
219 | /* the following is used externally (sysctl_hw) */ | | 219 | /* the following is used externally (sysctl_hw) */ |
220 | char machine[] = "i386"; /* CPU "architecture" */ | | 220 | char machine[] = "i386"; /* CPU "architecture" */ |
221 | char machine_arch[] = "i386"; /* machine == machine_arch */ | | 221 | char machine_arch[] = "i386"; /* machine == machine_arch */ |
222 | | | 222 | |
223 | extern struct bi_devmatch *x86_alldisks; | | 223 | extern struct bi_devmatch *x86_alldisks; |
224 | extern int x86_ndisks; | | 224 | extern int x86_ndisks; |
225 | | | 225 | |
226 | #ifdef CPURESET_DELAY | | 226 | #ifdef CPURESET_DELAY |
227 | int cpureset_delay = CPURESET_DELAY; | | 227 | int cpureset_delay = CPURESET_DELAY; |
228 | #else | | 228 | #else |
229 | int cpureset_delay = 2000; /* default to 2s */ | | 229 | int cpureset_delay = 2000; /* default to 2s */ |
230 | #endif | | 230 | #endif |
231 | | | 231 | |
232 | #ifdef MTRR | | 232 | #ifdef MTRR |
233 | struct mtrr_funcs *mtrr_funcs; | | 233 | struct mtrr_funcs *mtrr_funcs; |
234 | #endif | | 234 | #endif |
235 | | | 235 | |
236 | int physmem; | | 236 | int physmem; |
237 | | | 237 | |
238 | int cpu_class; | | 238 | int cpu_class; |
239 | int use_pae; | | 239 | int use_pae; |
240 | int i386_fpu_present; | | 240 | int i386_fpu_present; |
241 | int i386_fpu_exception; | | 241 | int i386_fpu_exception; |
242 | int i386_fpu_fdivbug; | | 242 | int i386_fpu_fdivbug; |
243 | | | 243 | |
244 | int i386_use_fxsave; | | 244 | int i386_use_fxsave; |
245 | int i386_has_sse; | | 245 | int i386_has_sse; |
246 | int i386_has_sse2; | | 246 | int i386_has_sse2; |
247 | | | 247 | |
248 | vaddr_t msgbuf_vaddr; | | 248 | vaddr_t msgbuf_vaddr; |
249 | struct { | | 249 | struct { |
250 | paddr_t paddr; | | 250 | paddr_t paddr; |
251 | psize_t sz; | | 251 | psize_t sz; |
252 | } msgbuf_p_seg[VM_PHYSSEG_MAX]; | | 252 | } msgbuf_p_seg[VM_PHYSSEG_MAX]; |
253 | unsigned int msgbuf_p_cnt = 0; | | 253 | unsigned int msgbuf_p_cnt = 0; |
254 | | | 254 | |
255 | vaddr_t idt_vaddr; | | 255 | vaddr_t idt_vaddr; |
256 | paddr_t idt_paddr; | | 256 | paddr_t idt_paddr; |
257 | vaddr_t pentium_idt_vaddr; | | 257 | vaddr_t pentium_idt_vaddr; |
258 | | | 258 | |
259 | struct vm_map *phys_map = NULL; | | 259 | struct vm_map *phys_map = NULL; |
260 | | | 260 | |
261 | extern paddr_t avail_start, avail_end; | | 261 | extern paddr_t avail_start, avail_end; |
262 | #ifdef XEN | | 262 | #ifdef XEN |
263 | extern paddr_t pmap_pa_start, pmap_pa_end; | | 263 | extern paddr_t pmap_pa_start, pmap_pa_end; |
264 | void hypervisor_callback(void); | | 264 | void hypervisor_callback(void); |
265 | void failsafe_callback(void); | | 265 | void failsafe_callback(void); |
266 | #endif | | 266 | #endif |
267 | | | 267 | |
268 | #ifdef XEN | | 268 | #ifdef XEN |
269 | void (*delay_func)(unsigned int) = xen_delay; | | 269 | void (*delay_func)(unsigned int) = xen_delay; |
270 | void (*initclock_func)(void) = xen_initclocks; | | 270 | void (*initclock_func)(void) = xen_initclocks; |
271 | #else | | 271 | #else |
272 | void (*delay_func)(unsigned int) = i8254_delay; | | 272 | void (*delay_func)(unsigned int) = i8254_delay; |
273 | void (*initclock_func)(void) = i8254_initclocks; | | 273 | void (*initclock_func)(void) = i8254_initclocks; |
274 | #endif | | 274 | #endif |
275 | | | 275 | |
276 | | | 276 | |
277 | /* | | 277 | /* |
278 | * Size of memory segments, before any memory is stolen. | | 278 | * Size of memory segments, before any memory is stolen. |
279 | */ | | 279 | */ |
280 | phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; | | 280 | phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; |
281 | int mem_cluster_cnt = 0; | | 281 | int mem_cluster_cnt = 0; |
282 | | | 282 | |
283 | void init386(paddr_t); | | 283 | void init386(paddr_t); |
284 | void initgdt(union descriptor *); | | 284 | void initgdt(union descriptor *); |
285 | | | 285 | |
286 | extern int time_adjusted; | | 286 | extern int time_adjusted; |
287 | | | 287 | |
288 | int *esym; | | 288 | int *esym; |
289 | int *eblob; | | 289 | int *eblob; |
290 | extern int boothowto; | | 290 | extern int boothowto; |
291 | | | 291 | |
292 | #ifndef XEN | | 292 | #ifndef XEN |
293 | | | 293 | |
294 | /* Base memory reported by BIOS. */ | | 294 | /* Base memory reported by BIOS. */ |
295 | #ifndef REALBASEMEM | | 295 | #ifndef REALBASEMEM |
296 | int biosbasemem = 0; | | 296 | int biosbasemem = 0; |
297 | #else | | 297 | #else |
298 | int biosbasemem = REALBASEMEM; | | 298 | int biosbasemem = REALBASEMEM; |
299 | #endif | | 299 | #endif |
300 | | | 300 | |
301 | /* Extended memory reported by BIOS. */ | | 301 | /* Extended memory reported by BIOS. */ |
302 | #ifndef REALEXTMEM | | 302 | #ifndef REALEXTMEM |
303 | int biosextmem = 0; | | 303 | int biosextmem = 0; |
304 | #else | | 304 | #else |
305 | int biosextmem = REALEXTMEM; | | 305 | int biosextmem = REALEXTMEM; |
306 | #endif | | 306 | #endif |
307 | | | 307 | |
308 | /* Set if any boot-loader set biosbasemem/biosextmem. */ | | 308 | /* Set if any boot-loader set biosbasemem/biosextmem. */ |
309 | int biosmem_implicit; | | 309 | int biosmem_implicit; |
310 | | | 310 | |
311 | /* Representation of the bootinfo structure constructed by a NetBSD native | | 311 | /* Representation of the bootinfo structure constructed by a NetBSD native |
312 | * boot loader. Only be used by native_loader(). */ | | 312 | * boot loader. Only be used by native_loader(). */ |
313 | struct bootinfo_source { | | 313 | struct bootinfo_source { |
314 | uint32_t bs_naddrs; | | 314 | uint32_t bs_naddrs; |
315 | void *bs_addrs[1]; /* Actually longer. */ | | 315 | void *bs_addrs[1]; /* Actually longer. */ |
316 | }; | | 316 | }; |
317 | | | 317 | |
318 | /* Only called by locore.h; no need to be in a header file. */ | | 318 | /* Only called by locore.h; no need to be in a header file. */ |
319 | void native_loader(int, int, struct bootinfo_source *, paddr_t, int, int); | | 319 | void native_loader(int, int, struct bootinfo_source *, paddr_t, int, int); |
320 | | | 320 | |
321 | /* | | 321 | /* |
322 | * Called as one of the very first things during system startup (just after | | 322 | * Called as one of the very first things during system startup (just after |
323 | * the boot loader gave control to the kernel image), this routine is in | | 323 | * the boot loader gave control to the kernel image), this routine is in |
324 | * charge of retrieving the parameters passed in by the boot loader and | | 324 | * charge of retrieving the parameters passed in by the boot loader and |
325 | * storing them in the appropriate kernel variables. | | 325 | * storing them in the appropriate kernel variables. |
326 | * | | 326 | * |
327 | * WARNING: Because the kernel has not yet relocated itself to KERNBASE, | | 327 | * WARNING: Because the kernel has not yet relocated itself to KERNBASE, |
328 | * special care has to be taken when accessing memory because absolute | | 328 | * special care has to be taken when accessing memory because absolute |
329 | * addresses (referring to kernel symbols) do not work. So: | | 329 | * addresses (referring to kernel symbols) do not work. So: |
330 | * | | 330 | * |
331 | * 1) Avoid jumps to absolute addresses (such as gotos and switches). | | 331 | * 1) Avoid jumps to absolute addresses (such as gotos and switches). |
332 | * 2) To access global variables use their physical address, which | | 332 | * 2) To access global variables use their physical address, which |
333 | * can be obtained using the RELOC macro. | | 333 | * can be obtained using the RELOC macro. |
334 | */ | | 334 | */ |
335 | void | | 335 | void |
336 | native_loader(int bl_boothowto, int bl_bootdev, | | 336 | native_loader(int bl_boothowto, int bl_bootdev, |
337 | struct bootinfo_source *bl_bootinfo, paddr_t bl_esym, | | 337 | struct bootinfo_source *bl_bootinfo, paddr_t bl_esym, |
338 | int bl_biosextmem, int bl_biosbasemem) | | 338 | int bl_biosextmem, int bl_biosbasemem) |
339 | { | | 339 | { |
340 | #define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE)) | | 340 | #define RELOC(type, x) ((type)((vaddr_t)(x) - KERNBASE)) |
341 | | | 341 | |
342 | *RELOC(int *, &boothowto) = bl_boothowto; | | 342 | *RELOC(int *, &boothowto) = bl_boothowto; |
343 | | | 343 | |
344 | #ifdef COMPAT_OLDBOOT | | 344 | #ifdef COMPAT_OLDBOOT |
345 | /* | | 345 | /* |
346 | * Pre-1.3 boot loaders gave the boot device as a parameter | | 346 | * Pre-1.3 boot loaders gave the boot device as a parameter |
347 | * (instead of a bootinfo entry). | | 347 | * (instead of a bootinfo entry). |
348 | */ | | 348 | */ |
349 | *RELOC(int *, &bootdev) = bl_bootdev; | | 349 | *RELOC(int *, &bootdev) = bl_bootdev; |
350 | #endif | | 350 | #endif |
351 | | | 351 | |
352 | /* | | 352 | /* |
353 | * The boot loader provides a physical, non-relocated address | | 353 | * The boot loader provides a physical, non-relocated address |
354 | * for the symbols table's end. We need to convert it to a | | 354 | * for the symbols table's end. We need to convert it to a |
355 | * virtual address. | | 355 | * virtual address. |
356 | */ | | 356 | */ |
357 | if (bl_esym != 0) | | 357 | if (bl_esym != 0) |
358 | *RELOC(int **, &esym) = (int *)((vaddr_t)bl_esym + KERNBASE); | | 358 | *RELOC(int **, &esym) = (int *)((vaddr_t)bl_esym + KERNBASE); |
359 | else | | 359 | else |
360 | *RELOC(int **, &esym) = 0; | | 360 | *RELOC(int **, &esym) = 0; |
361 | | | 361 | |
362 | /* | | 362 | /* |
363 | * Copy bootinfo entries (if any) from the boot loader's | | 363 | * Copy bootinfo entries (if any) from the boot loader's |
364 | * representation to the kernel's bootinfo space. | | 364 | * representation to the kernel's bootinfo space. |
365 | */ | | 365 | */ |
366 | if (bl_bootinfo != NULL) { | | 366 | if (bl_bootinfo != NULL) { |
367 | size_t i; | | 367 | size_t i; |
368 | uint8_t *data; | | 368 | uint8_t *data; |
369 | struct bootinfo *bidest; | | 369 | struct bootinfo *bidest; |
370 | struct btinfo_modulelist *bi; | | 370 | struct btinfo_modulelist *bi; |
371 | | | 371 | |
372 | bidest = RELOC(struct bootinfo *, &bootinfo); | | 372 | bidest = RELOC(struct bootinfo *, &bootinfo); |
373 | | | 373 | |
374 | data = &bidest->bi_data[0]; | | 374 | data = &bidest->bi_data[0]; |
375 | | | 375 | |
376 | for (i = 0; i < bl_bootinfo->bs_naddrs; i++) { | | 376 | for (i = 0; i < bl_bootinfo->bs_naddrs; i++) { |
377 | struct btinfo_common *bc; | | 377 | struct btinfo_common *bc; |
378 | | | 378 | |
379 | bc = bl_bootinfo->bs_addrs[i]; | | 379 | bc = bl_bootinfo->bs_addrs[i]; |
380 | | | 380 | |
381 | if ((data + bc->len) > | | 381 | if ((data + bc->len) > |
382 | (&bidest->bi_data[0] + BOOTINFO_MAXSIZE)) | | 382 | (&bidest->bi_data[0] + BOOTINFO_MAXSIZE)) |
383 | break; | | 383 | break; |
384 | | | 384 | |
385 | memcpy(data, bc, bc->len); | | 385 | memcpy(data, bc, bc->len); |
386 | /* | | 386 | /* |
387 | * If any modules were loaded, record where they | | 387 | * If any modules were loaded, record where they |
388 | * end. We'll need to skip over them. | | 388 | * end. We'll need to skip over them. |
389 | */ | | 389 | */ |
390 | bi = (struct btinfo_modulelist *)data; | | 390 | bi = (struct btinfo_modulelist *)data; |
391 | if (bi->common.type == BTINFO_MODULELIST) { | | 391 | if (bi->common.type == BTINFO_MODULELIST) { |
392 | *RELOC(int **, &eblob) = | | 392 | *RELOC(int **, &eblob) = |
393 | (int *)(bi->endpa + KERNBASE); | | 393 | (int *)(bi->endpa + KERNBASE); |
394 | } | | 394 | } |
395 | data += bc->len; | | 395 | data += bc->len; |
396 | } | | 396 | } |
397 | bidest->bi_nentries = i; | | 397 | bidest->bi_nentries = i; |
398 | } | | 398 | } |
399 | | | 399 | |
400 | /* | | 400 | /* |
401 | * Configure biosbasemem and biosextmem only if they were not | | 401 | * Configure biosbasemem and biosextmem only if they were not |
402 | * explicitly given during the kernel's build. | | 402 | * explicitly given during the kernel's build. |
403 | */ | | 403 | */ |
404 | if (*RELOC(int *, &biosbasemem) == 0) { | | 404 | if (*RELOC(int *, &biosbasemem) == 0) { |
405 | *RELOC(int *, &biosbasemem) = bl_biosbasemem; | | 405 | *RELOC(int *, &biosbasemem) = bl_biosbasemem; |
406 | *RELOC(int *, &biosmem_implicit) = 1; | | 406 | *RELOC(int *, &biosmem_implicit) = 1; |
407 | } | | 407 | } |
408 | if (*RELOC(int *, &biosextmem) == 0) { | | 408 | if (*RELOC(int *, &biosextmem) == 0) { |
409 | *RELOC(int *, &biosextmem) = bl_biosextmem; | | 409 | *RELOC(int *, &biosextmem) = bl_biosextmem; |
410 | *RELOC(int *, &biosmem_implicit) = 1; | | 410 | *RELOC(int *, &biosmem_implicit) = 1; |
411 | } | | 411 | } |
412 | #undef RELOC | | 412 | #undef RELOC |
413 | } | | 413 | } |
414 | | | 414 | |
415 | #endif /* XEN */ | | 415 | #endif /* XEN */ |
416 | | | 416 | |
417 | /* | | 417 | /* |
418 | * Machine-dependent startup code | | 418 | * Machine-dependent startup code |
419 | */ | | 419 | */ |
420 | void | | 420 | void |
421 | cpu_startup(void) | | 421 | cpu_startup(void) |
422 | { | | 422 | { |
423 | int x, y; | | 423 | int x, y; |
424 | vaddr_t minaddr, maxaddr; | | 424 | vaddr_t minaddr, maxaddr; |
425 | psize_t sz; | | 425 | psize_t sz; |
426 | | | 426 | |
427 | /* | | 427 | /* |
428 | * For console drivers that require uvm and pmap to be initialized, | | 428 | * For console drivers that require uvm and pmap to be initialized, |
429 | * we'll give them one more chance here... | | 429 | * we'll give them one more chance here... |
430 | */ | | 430 | */ |
431 | consinit(); | | 431 | consinit(); |
432 | | | 432 | |
433 | /* | | 433 | /* |
434 | * Initialize error message buffer (et end of core). | | 434 | * Initialize error message buffer (et end of core). |
435 | */ | | 435 | */ |
436 | if (msgbuf_p_cnt == 0) | | 436 | if (msgbuf_p_cnt == 0) |
437 | panic("msgbuf paddr map has not been set up"); | | 437 | panic("msgbuf paddr map has not been set up"); |
438 | for (x = 0, sz = 0; x < msgbuf_p_cnt; sz += msgbuf_p_seg[x++].sz) | | 438 | for (x = 0, sz = 0; x < msgbuf_p_cnt; sz += msgbuf_p_seg[x++].sz) |
439 | continue; | | 439 | continue; |
440 | msgbuf_vaddr = uvm_km_alloc(kernel_map, sz, 0, UVM_KMF_VAONLY); | | 440 | msgbuf_vaddr = uvm_km_alloc(kernel_map, sz, 0, UVM_KMF_VAONLY); |
441 | if (msgbuf_vaddr == 0) | | 441 | if (msgbuf_vaddr == 0) |
442 | panic("failed to valloc msgbuf_vaddr"); | | 442 | panic("failed to valloc msgbuf_vaddr"); |
443 | | | 443 | |
444 | /* msgbuf_paddr was init'd in pmap */ | | 444 | /* msgbuf_paddr was init'd in pmap */ |
445 | for (y = 0, sz = 0; y < msgbuf_p_cnt; y++) { | | 445 | for (y = 0, sz = 0; y < msgbuf_p_cnt; y++) { |
446 | for (x = 0; x < btoc(msgbuf_p_seg[y].sz); x++, sz += PAGE_SIZE) | | 446 | for (x = 0; x < btoc(msgbuf_p_seg[y].sz); x++, sz += PAGE_SIZE) |
447 | pmap_kenter_pa((vaddr_t)msgbuf_vaddr + sz, | | 447 | pmap_kenter_pa((vaddr_t)msgbuf_vaddr + sz, |
448 | msgbuf_p_seg[y].paddr + x * PAGE_SIZE, | | 448 | msgbuf_p_seg[y].paddr + x * PAGE_SIZE, |
449 | VM_PROT_READ|VM_PROT_WRITE, 0); | | 449 | VM_PROT_READ|VM_PROT_WRITE, 0); |
450 | } | | 450 | } |
451 | pmap_update(pmap_kernel()); | | 451 | pmap_update(pmap_kernel()); |
452 | | | 452 | |
453 | initmsgbuf((void *)msgbuf_vaddr, sz); | | 453 | initmsgbuf((void *)msgbuf_vaddr, sz); |
454 | | | 454 | |
455 | #ifdef MULTIBOOT | | 455 | #ifdef MULTIBOOT |
456 | multiboot_print_info(); | | 456 | multiboot_print_info(); |
457 | #endif | | 457 | #endif |
458 | | | 458 | |
459 | #ifdef TRAPLOG | | 459 | #ifdef TRAPLOG |
460 | /* | | 460 | /* |
461 | * Enable recording of branch from/to in MSR's | | 461 | * Enable recording of branch from/to in MSR's |
462 | */ | | 462 | */ |
463 | wrmsr(MSR_DEBUGCTLMSR, 0x1); | | 463 | wrmsr(MSR_DEBUGCTLMSR, 0x1); |
464 | #endif | | 464 | #endif |
465 | | | 465 | |
466 | #if NCARDBUS > 0 | | 466 | #if NCARDBUS > 0 |
467 | /* Tell RBUS how much RAM we have, so it can use heuristics. */ | | 467 | /* Tell RBUS how much RAM we have, so it can use heuristics. */ |
468 | rbus_min_start_hint(ctob((psize_t)physmem)); | | 468 | rbus_min_start_hint(ctob((psize_t)physmem)); |
469 | #endif | | 469 | #endif |
470 | | | 470 | |
471 | minaddr = 0; | | 471 | minaddr = 0; |
472 | | | 472 | |
473 | /* | | 473 | /* |
474 | * Allocate a submap for physio | | 474 | * Allocate a submap for physio |
475 | */ | | 475 | */ |
476 | phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, | | 476 | phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, |
477 | VM_PHYS_SIZE, 0, false, NULL); | | 477 | VM_PHYS_SIZE, 0, false, NULL); |
478 | | | 478 | |
479 | /* Say hello. */ | | 479 | /* Say hello. */ |
480 | banner(); | | 480 | banner(); |
481 | | | 481 | |
482 | /* Safe for i/o port / memory space allocation to use malloc now. */ | | 482 | /* Safe for i/o port / memory space allocation to use malloc now. */ |
483 | #if NISA > 0 || NPCI > 0 | | 483 | #if NISA > 0 || NPCI > 0 |
484 | x86_bus_space_mallocok(); | | 484 | x86_bus_space_mallocok(); |
485 | #endif | | 485 | #endif |
486 | | | 486 | |
487 | gdt_init(); | | 487 | gdt_init(); |
488 | i386_proc0_tss_ldt_init(); | | 488 | i386_proc0_tss_ldt_init(); |
489 | | | 489 | |
490 | #ifndef XEN | | 490 | #ifndef XEN |
491 | cpu_init_tss(&cpu_info_primary); | | 491 | cpu_init_tss(&cpu_info_primary); |
492 | ltr(cpu_info_primary.ci_tss_sel); | | 492 | ltr(cpu_info_primary.ci_tss_sel); |
493 | #endif | | 493 | #endif |
494 | | | 494 | |
495 | x86_startup(); | | 495 | x86_startup(); |
496 | } | | 496 | } |
497 | | | 497 | |
498 | /* | | 498 | /* |
499 | * Set up proc0's TSS and LDT. | | 499 | * Set up proc0's TSS and LDT. |
500 | */ | | 500 | */ |
501 | void | | 501 | void |
502 | i386_proc0_tss_ldt_init(void) | | 502 | i386_proc0_tss_ldt_init(void) |
503 | { | | 503 | { |
504 | struct lwp *l = &lwp0; | | 504 | struct lwp *l = &lwp0; |
505 | struct pcb *pcb = lwp_getpcb(l); | | 505 | struct pcb *pcb = lwp_getpcb(l); |
506 | | | 506 | |
507 | pmap_kernel()->pm_ldt_sel = GSEL(GLDT_SEL, SEL_KPL); | | 507 | pmap_kernel()->pm_ldt_sel = GSEL(GLDT_SEL, SEL_KPL); |
508 | pcb->pcb_cr0 = rcr0() & ~CR0_TS; | | 508 | pcb->pcb_cr0 = rcr0() & ~CR0_TS; |
509 | pcb->pcb_esp0 = uvm_lwp_getuarea(l) + KSTACK_SIZE - 16; | | 509 | pcb->pcb_esp0 = uvm_lwp_getuarea(l) + KSTACK_SIZE - 16; |
510 | pcb->pcb_iopl = SEL_KPL; | | 510 | pcb->pcb_iopl = SEL_KPL; |
511 | l->l_md.md_regs = (struct trapframe *)pcb->pcb_esp0 - 1; | | 511 | l->l_md.md_regs = (struct trapframe *)pcb->pcb_esp0 - 1; |
512 | memcpy(&pcb->pcb_fsd, &gdt[GUDATA_SEL], sizeof(pcb->pcb_fsd)); | | 512 | memcpy(&pcb->pcb_fsd, &gdt[GUDATA_SEL], sizeof(pcb->pcb_fsd)); |
513 | memcpy(&pcb->pcb_gsd, &gdt[GUDATA_SEL], sizeof(pcb->pcb_gsd)); | | 513 | memcpy(&pcb->pcb_gsd, &gdt[GUDATA_SEL], sizeof(pcb->pcb_gsd)); |
514 | | | 514 | |
515 | #ifndef XEN | | 515 | #ifndef XEN |
516 | lldt(pmap_kernel()->pm_ldt_sel); | | 516 | lldt(pmap_kernel()->pm_ldt_sel); |
517 | #else | | 517 | #else |
518 | HYPERVISOR_fpu_taskswitch(1); | | 518 | HYPERVISOR_fpu_taskswitch(1); |
519 | XENPRINTF(("lwp tss sp %p ss %04x/%04x\n", | | 519 | XENPRINTF(("lwp tss sp %p ss %04x/%04x\n", |
520 | (void *)pcb->pcb_esp0, | | 520 | (void *)pcb->pcb_esp0, |
521 | GSEL(GDATA_SEL, SEL_KPL), | | 521 | GSEL(GDATA_SEL, SEL_KPL), |
522 | IDXSEL(GSEL(GDATA_SEL, SEL_KPL)))); | | 522 | IDXSEL(GSEL(GDATA_SEL, SEL_KPL)))); |
523 | HYPERVISOR_stack_switch(GSEL(GDATA_SEL, SEL_KPL), pcb->pcb_esp0); | | 523 | HYPERVISOR_stack_switch(GSEL(GDATA_SEL, SEL_KPL), pcb->pcb_esp0); |
524 | #endif | | 524 | #endif |
525 | } | | 525 | } |
526 | | | 526 | |
527 | #ifdef XEN | | 527 | #ifdef XEN |
528 | /* used in assembly */ | | 528 | /* used in assembly */ |
529 | void i386_switch_context(lwp_t *); | | 529 | void i386_switch_context(lwp_t *); |
530 | void i386_tls_switch(lwp_t *); | | 530 | void i386_tls_switch(lwp_t *); |
531 | | | 531 | |
532 | /* | | 532 | /* |
533 | * Switch context: | | 533 | * Switch context: |
534 | * - switch stack pointer for user->kernel transition | | 534 | * - switch stack pointer for user->kernel transition |
535 | */ | | 535 | */ |
536 | void | | 536 | void |
537 | i386_switch_context(lwp_t *l) | | 537 | i386_switch_context(lwp_t *l) |
538 | { | | 538 | { |
539 | struct cpu_info *ci; | | 539 | struct cpu_info *ci; |
540 | struct pcb *pcb; | | 540 | struct pcb *pcb; |
541 | struct physdev_op physop; | | 541 | struct physdev_op physop; |
542 | | | 542 | |
543 | pcb = lwp_getpcb(l); | | 543 | pcb = lwp_getpcb(l); |
544 | ci = curcpu(); | | 544 | ci = curcpu(); |
545 | | | 545 | |
546 | HYPERVISOR_stack_switch(GSEL(GDATA_SEL, SEL_KPL), pcb->pcb_esp0); | | 546 | HYPERVISOR_stack_switch(GSEL(GDATA_SEL, SEL_KPL), pcb->pcb_esp0); |
547 | | | 547 | |
548 | physop.cmd = PHYSDEVOP_SET_IOPL; | | 548 | physop.cmd = PHYSDEVOP_SET_IOPL; |
549 | physop.u.set_iopl.iopl = pcb->pcb_iopl; | | 549 | physop.u.set_iopl.iopl = pcb->pcb_iopl; |
550 | HYPERVISOR_physdev_op(&physop); | | 550 | HYPERVISOR_physdev_op(&physop); |
551 | } | | 551 | } |
552 | | | 552 | |
553 | void | | 553 | void |
554 | i386_tls_switch(lwp_t *l) | | 554 | i386_tls_switch(lwp_t *l) |
555 | { | | 555 | { |
556 | struct cpu_info *ci = curcpu(); | | 556 | struct cpu_info *ci = curcpu(); |
557 | struct pcb *pcb = lwp_getpcb(l); | | 557 | struct pcb *pcb = lwp_getpcb(l); |
558 | /* | | 558 | /* |
559 | * Raise the IPL to IPL_HIGH. | | 559 | * Raise the IPL to IPL_HIGH. |
560 | * FPU IPIs can alter the LWP's saved cr0. Dropping the priority | | 560 | * FPU IPIs can alter the LWP's saved cr0. Dropping the priority |
561 | * is deferred until mi_switch(), when cpu_switchto() returns. | | 561 | * is deferred until mi_switch(), when cpu_switchto() returns. |
562 | */ | | 562 | */ |
563 | (void)splhigh(); | | 563 | (void)splhigh(); |
564 | | | 564 | |
565 | /* | | 565 | /* |
566 | * If our floating point registers are on a different CPU, | | 566 | * If our floating point registers are on a different CPU, |
567 | * set CR0_TS so we'll trap rather than reuse bogus state. | | 567 | * set CR0_TS so we'll trap rather than reuse bogus state. |
568 | */ | | 568 | */ |
569 | | | 569 | |
570 | if (l != ci->ci_fpcurlwp) { | | 570 | if (l != ci->ci_fpcurlwp) { |
571 | HYPERVISOR_fpu_taskswitch(1); | | 571 | HYPERVISOR_fpu_taskswitch(1); |
572 | } | | 572 | } |
573 | | | 573 | |
574 | /* Update TLS segment pointers */ | | 574 | /* Update TLS segment pointers */ |
575 | update_descriptor(&ci->ci_gdt[GUFS_SEL], | | 575 | update_descriptor(&ci->ci_gdt[GUFS_SEL], |
576 | (union descriptor *) &pcb->pcb_fsd); | | 576 | (union descriptor *) &pcb->pcb_fsd); |
577 | update_descriptor(&ci->ci_gdt[GUGS_SEL], | | 577 | update_descriptor(&ci->ci_gdt[GUGS_SEL], |
578 | (union descriptor *) &pcb->pcb_gsd); | | 578 | (union descriptor *) &pcb->pcb_gsd); |
579 | | | 579 | |
580 | } | | 580 | } |
581 | #endif /* XEN */ | | 581 | #endif /* XEN */ |
582 | | | 582 | |
583 | #ifndef XEN | | 583 | #ifndef XEN |
584 | /* | | 584 | /* |
585 | * Set up TSS and I/O bitmap. | | 585 | * Set up TSS and I/O bitmap. |
586 | */ | | 586 | */ |
587 | void | | 587 | void |
588 | cpu_init_tss(struct cpu_info *ci) | | 588 | cpu_init_tss(struct cpu_info *ci) |
589 | { | | 589 | { |
590 | struct i386tss *tss = &ci->ci_tss; | | 590 | struct i386tss *tss = &ci->ci_tss; |
591 | | | 591 | |
592 | tss->tss_iobase = IOMAP_INVALOFF << 16; | | 592 | tss->tss_iobase = IOMAP_INVALOFF << 16; |
593 | tss->tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); | | 593 | tss->tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); |
594 | tss->tss_ldt = GSEL(GLDT_SEL, SEL_KPL); | | 594 | tss->tss_ldt = GSEL(GLDT_SEL, SEL_KPL); |
595 | tss->tss_cr3 = rcr3(); | | 595 | tss->tss_cr3 = rcr3(); |
596 | ci->ci_tss_sel = tss_alloc(tss); | | 596 | ci->ci_tss_sel = tss_alloc(tss); |
597 | } | | 597 | } |
598 | #endif /* XEN */ | | 598 | #endif /* XEN */ |
599 | | | 599 | |
600 | /* | | 600 | /* |
601 | * sysctl helper routine for machdep.booted_kernel | | 601 | * sysctl helper routine for machdep.booted_kernel |
602 | */ | | 602 | */ |
603 | static int | | 603 | static int |
604 | sysctl_machdep_booted_kernel(SYSCTLFN_ARGS) | | 604 | sysctl_machdep_booted_kernel(SYSCTLFN_ARGS) |
605 | { | | 605 | { |
606 | struct btinfo_bootpath *bibp; | | 606 | struct btinfo_bootpath *bibp; |
607 | struct sysctlnode node; | | 607 | struct sysctlnode node; |
608 | | | 608 | |
609 | bibp = lookup_bootinfo(BTINFO_BOOTPATH); | | 609 | bibp = lookup_bootinfo(BTINFO_BOOTPATH); |
610 | if(!bibp) | | 610 | if(!bibp) |
611 | return(ENOENT); /* ??? */ | | 611 | return(ENOENT); /* ??? */ |
612 | | | 612 | |
613 | node = *rnode; | | 613 | node = *rnode; |
614 | node.sysctl_data = bibp->bootpath; | | 614 | node.sysctl_data = bibp->bootpath; |
615 | node.sysctl_size = sizeof(bibp->bootpath); | | 615 | node.sysctl_size = sizeof(bibp->bootpath); |
616 | return (sysctl_lookup(SYSCTLFN_CALL(&node))); | | 616 | return (sysctl_lookup(SYSCTLFN_CALL(&node))); |
617 | } | | 617 | } |
618 | | | 618 | |
619 | /* | | 619 | /* |
620 | * sysctl helper routine for machdep.diskinfo | | 620 | * sysctl helper routine for machdep.diskinfo |
621 | */ | | 621 | */ |
622 | static int | | 622 | static int |
623 | sysctl_machdep_diskinfo(SYSCTLFN_ARGS) | | 623 | sysctl_machdep_diskinfo(SYSCTLFN_ARGS) |
624 | { | | 624 | { |
625 | struct sysctlnode node; | | 625 | struct sysctlnode node; |
626 | | | 626 | |
627 | node = *rnode; | | 627 | node = *rnode; |
628 | if (x86_alldisks == NULL) | | 628 | if (x86_alldisks == NULL) |
629 | return(EOPNOTSUPP); | | 629 | return(EOPNOTSUPP); |
630 | node.sysctl_data = x86_alldisks; | | 630 | node.sysctl_data = x86_alldisks; |
631 | node.sysctl_size = sizeof(struct disklist) + | | 631 | node.sysctl_size = sizeof(struct disklist) + |
632 | (x86_ndisks - 1) * sizeof(struct nativedisk_info); | | 632 | (x86_ndisks - 1) * sizeof(struct nativedisk_info); |
633 | return (sysctl_lookup(SYSCTLFN_CALL(&node))); | | 633 | return (sysctl_lookup(SYSCTLFN_CALL(&node))); |
634 | } | | 634 | } |
635 | | | 635 | |
636 | /* | | 636 | /* |
637 | * machine dependent system variables. | | 637 | * machine dependent system variables. |
638 | */ | | 638 | */ |
639 | SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") | | 639 | SYSCTL_SETUP(sysctl_machdep_setup, "sysctl machdep subtree setup") |
640 | { | | 640 | { |
641 | extern uint64_t tsc_freq; | | 641 | extern uint64_t tsc_freq; |
642 | | | 642 | |
643 | sysctl_createv(clog, 0, NULL, NULL, | | 643 | sysctl_createv(clog, 0, NULL, NULL, |
644 | CTLFLAG_PERMANENT, | | 644 | CTLFLAG_PERMANENT, |
645 | CTLTYPE_NODE, "machdep", NULL, | | 645 | CTLTYPE_NODE, "machdep", NULL, |
646 | NULL, 0, NULL, 0, | | 646 | NULL, 0, NULL, 0, |
647 | CTL_MACHDEP, CTL_EOL); | | 647 | CTL_MACHDEP, CTL_EOL); |
648 | | | 648 | |
649 | sysctl_createv(clog, 0, NULL, NULL, | | 649 | sysctl_createv(clog, 0, NULL, NULL, |
650 | CTLFLAG_PERMANENT, | | 650 | CTLFLAG_PERMANENT, |
651 | CTLTYPE_STRUCT, "console_device", NULL, | | 651 | CTLTYPE_STRUCT, "console_device", NULL, |
652 | sysctl_consdev, 0, NULL, sizeof(dev_t), | | 652 | sysctl_consdev, 0, NULL, sizeof(dev_t), |
653 | CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); | | 653 | CTL_MACHDEP, CPU_CONSDEV, CTL_EOL); |
654 | #ifndef XEN | | 654 | #ifndef XEN |
655 | sysctl_createv(clog, 0, NULL, NULL, | | 655 | sysctl_createv(clog, 0, NULL, NULL, |
656 | CTLFLAG_PERMANENT, | | 656 | CTLFLAG_PERMANENT, |
657 | CTLTYPE_INT, "biosbasemem", NULL, | | 657 | CTLTYPE_INT, "biosbasemem", NULL, |
658 | NULL, 0, &biosbasemem, 0, | | 658 | NULL, 0, &biosbasemem, 0, |
659 | CTL_MACHDEP, CPU_BIOSBASEMEM, CTL_EOL); | | 659 | CTL_MACHDEP, CPU_BIOSBASEMEM, CTL_EOL); |
660 | sysctl_createv(clog, 0, NULL, NULL, | | 660 | sysctl_createv(clog, 0, NULL, NULL, |
661 | CTLFLAG_PERMANENT, | | 661 | CTLFLAG_PERMANENT, |
662 | CTLTYPE_INT, "biosextmem", NULL, | | 662 | CTLTYPE_INT, "biosextmem", NULL, |
663 | NULL, 0, &biosextmem, 0, | | 663 | NULL, 0, &biosextmem, 0, |
664 | CTL_MACHDEP, CPU_BIOSEXTMEM, CTL_EOL); | | 664 | CTL_MACHDEP, CPU_BIOSEXTMEM, CTL_EOL); |
665 | #endif /* XEN */ | | 665 | #endif /* XEN */ |
666 | sysctl_createv(clog, 0, NULL, NULL, | | 666 | sysctl_createv(clog, 0, NULL, NULL, |
667 | CTLFLAG_PERMANENT, | | 667 | CTLFLAG_PERMANENT, |
668 | CTLTYPE_STRING, "booted_kernel", NULL, | | 668 | CTLTYPE_STRING, "booted_kernel", NULL, |
669 | sysctl_machdep_booted_kernel, 0, NULL, 0, | | 669 | sysctl_machdep_booted_kernel, 0, NULL, 0, |
670 | CTL_MACHDEP, CPU_BOOTED_KERNEL, CTL_EOL); | | 670 | CTL_MACHDEP, CPU_BOOTED_KERNEL, CTL_EOL); |
671 | sysctl_createv(clog, 0, NULL, NULL, | | 671 | sysctl_createv(clog, 0, NULL, NULL, |
672 | CTLFLAG_PERMANENT, | | 672 | CTLFLAG_PERMANENT, |
673 | CTLTYPE_STRUCT, "diskinfo", NULL, | | 673 | CTLTYPE_STRUCT, "diskinfo", NULL, |
674 | sysctl_machdep_diskinfo, 0, NULL, 0, | | 674 | sysctl_machdep_diskinfo, 0, NULL, 0, |
675 | CTL_MACHDEP, CPU_DISKINFO, CTL_EOL); | | 675 | CTL_MACHDEP, CPU_DISKINFO, CTL_EOL); |
676 | sysctl_createv(clog, 0, NULL, NULL, | | 676 | sysctl_createv(clog, 0, NULL, NULL, |
677 | CTLFLAG_PERMANENT, | | 677 | CTLFLAG_PERMANENT, |
678 | CTLTYPE_INT, "fpu_present", NULL, | | 678 | CTLTYPE_INT, "fpu_present", NULL, |
679 | NULL, 0, &i386_fpu_present, 0, | | 679 | NULL, 0, &i386_fpu_present, 0, |
680 | CTL_MACHDEP, CPU_FPU_PRESENT, CTL_EOL); | | 680 | CTL_MACHDEP, CPU_FPU_PRESENT, CTL_EOL); |
681 | sysctl_createv(clog, 0, NULL, NULL, | | 681 | sysctl_createv(clog, 0, NULL, NULL, |
682 | CTLFLAG_PERMANENT, | | 682 | CTLFLAG_PERMANENT, |
683 | CTLTYPE_INT, "osfxsr", NULL, | | 683 | CTLTYPE_INT, "osfxsr", NULL, |
684 | NULL, 0, &i386_use_fxsave, 0, | | 684 | NULL, 0, &i386_use_fxsave, 0, |
685 | CTL_MACHDEP, CPU_OSFXSR, CTL_EOL); | | 685 | CTL_MACHDEP, CPU_OSFXSR, CTL_EOL); |
686 | sysctl_createv(clog, 0, NULL, NULL, | | 686 | sysctl_createv(clog, 0, NULL, NULL, |
687 | CTLFLAG_PERMANENT, | | 687 | CTLFLAG_PERMANENT, |
688 | CTLTYPE_INT, "sse", NULL, | | 688 | CTLTYPE_INT, "sse", NULL, |
689 | NULL, 0, &i386_has_sse, 0, | | 689 | NULL, 0, &i386_has_sse, 0, |
690 | CTL_MACHDEP, CPU_SSE, CTL_EOL); | | 690 | CTL_MACHDEP, CPU_SSE, CTL_EOL); |
691 | sysctl_createv(clog, 0, NULL, NULL, | | 691 | sysctl_createv(clog, 0, NULL, NULL, |
692 | CTLFLAG_PERMANENT, | | 692 | CTLFLAG_PERMANENT, |
693 | CTLTYPE_INT, "sse2", NULL, | | 693 | CTLTYPE_INT, "sse2", NULL, |
694 | NULL, 0, &i386_has_sse2, 0, | | 694 | NULL, 0, &i386_has_sse2, 0, |
695 | CTL_MACHDEP, CPU_SSE2, CTL_EOL); | | 695 | CTL_MACHDEP, CPU_SSE2, CTL_EOL); |
696 | sysctl_createv(clog, 0, NULL, NULL, | | 696 | sysctl_createv(clog, 0, NULL, NULL, |
697 | CTLFLAG_PERMANENT, | | 697 | CTLFLAG_PERMANENT, |
698 | CTLTYPE_STRING, "cpu_brand", NULL, | | 698 | CTLTYPE_STRING, "cpu_brand", NULL, |
699 | NULL, 0, &cpu_brand_string, 0, | | 699 | NULL, 0, &cpu_brand_string, 0, |
700 | CTL_MACHDEP, CTL_CREATE, CTL_EOL); | | 700 | CTL_MACHDEP, CTL_CREATE, CTL_EOL); |
701 | sysctl_createv(clog, 0, NULL, NULL, | | 701 | sysctl_createv(clog, 0, NULL, NULL, |
702 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 702 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
703 | CTLTYPE_INT, "sparse_dump", NULL, | | 703 | CTLTYPE_INT, "sparse_dump", NULL, |
704 | NULL, 0, &sparse_dump, 0, | | 704 | NULL, 0, &sparse_dump, 0, |
705 | CTL_MACHDEP, CTL_CREATE, CTL_EOL); | | 705 | CTL_MACHDEP, CTL_CREATE, CTL_EOL); |
706 | sysctl_createv(clog, 0, NULL, NULL, | | 706 | sysctl_createv(clog, 0, NULL, NULL, |
707 | CTLFLAG_PERMANENT, | | 707 | CTLFLAG_PERMANENT, |
708 | CTLTYPE_QUAD, "tsc_freq", NULL, | | 708 | CTLTYPE_QUAD, "tsc_freq", NULL, |
709 | NULL, 0, &tsc_freq, 0, | | 709 | NULL, 0, &tsc_freq, 0, |
710 | CTL_MACHDEP, CTL_CREATE, CTL_EOL); | | 710 | CTL_MACHDEP, CTL_CREATE, CTL_EOL); |
711 | sysctl_createv(clog, 0, NULL, NULL, | | 711 | sysctl_createv(clog, 0, NULL, NULL, |
712 | CTLFLAG_PERMANENT, | | 712 | CTLFLAG_PERMANENT, |
713 | CTLTYPE_INT, "pae", | | 713 | CTLTYPE_INT, "pae", |
714 | SYSCTL_DESCR("Whether the kernel uses PAE"), | | 714 | SYSCTL_DESCR("Whether the kernel uses PAE"), |
715 | NULL, 0, &use_pae, 0, | | 715 | NULL, 0, &use_pae, 0, |
716 | CTL_MACHDEP, CTL_CREATE, CTL_EOL); | | 716 | CTL_MACHDEP, CTL_CREATE, CTL_EOL); |
717 | } | | 717 | } |
718 | | | 718 | |
719 | void * | | 719 | void * |
720 | getframe(struct lwp *l, int sig, int *onstack) | | 720 | getframe(struct lwp *l, int sig, int *onstack) |
721 | { | | 721 | { |
722 | struct proc *p = l->l_proc; | | 722 | struct proc *p = l->l_proc; |
723 | struct trapframe *tf = l->l_md.md_regs; | | 723 | struct trapframe *tf = l->l_md.md_regs; |
724 | | | 724 | |
725 | /* Do we need to jump onto the signal stack? */ | | 725 | /* Do we need to jump onto the signal stack? */ |
726 | *onstack = (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 | | 726 | *onstack = (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 |
727 | && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; | | 727 | && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; |
728 | if (*onstack) | | 728 | if (*onstack) |
729 | return (char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size; | | 729 | return (char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size; |
730 | #ifdef VM86 | | 730 | #ifdef VM86 |
731 | if (tf->tf_eflags & PSL_VM) | | 731 | if (tf->tf_eflags & PSL_VM) |
732 | return (void *)(tf->tf_esp + (tf->tf_ss << 4)); | | 732 | return (void *)(tf->tf_esp + (tf->tf_ss << 4)); |
733 | else | | 733 | else |
734 | #endif | | 734 | #endif |
735 | return (void *)tf->tf_esp; | | 735 | return (void *)tf->tf_esp; |
736 | } | | 736 | } |
737 | | | 737 | |
738 | /* | | 738 | /* |
739 | * Build context to run handler in. We invoke the handler | | 739 | * Build context to run handler in. We invoke the handler |
740 | * directly, only returning via the trampoline. Note the | | 740 | * directly, only returning via the trampoline. Note the |
741 | * trampoline version numbers are coordinated with machine- | | 741 | * trampoline version numbers are coordinated with machine- |
742 | * dependent code in libc. | | 742 | * dependent code in libc. |
743 | */ | | 743 | */ |
744 | void | | 744 | void |
745 | buildcontext(struct lwp *l, int sel, void *catcher, void *fp) | | 745 | buildcontext(struct lwp *l, int sel, void *catcher, void *fp) |
746 | { | | 746 | { |
747 | struct trapframe *tf = l->l_md.md_regs; | | 747 | struct trapframe *tf = l->l_md.md_regs; |
748 | | | 748 | |
749 | tf->tf_gs = GSEL(GUGS_SEL, SEL_UPL); | | 749 | tf->tf_gs = GSEL(GUGS_SEL, SEL_UPL); |
750 | tf->tf_fs = GSEL(GUFS_SEL, SEL_UPL); | | 750 | tf->tf_fs = GSEL(GUFS_SEL, SEL_UPL); |
751 | tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL); | | 751 | tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL); |
752 | tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); | | 752 | tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); |
753 | tf->tf_eip = (int)catcher; | | 753 | tf->tf_eip = (int)catcher; |
754 | tf->tf_cs = GSEL(sel, SEL_UPL); | | 754 | tf->tf_cs = GSEL(sel, SEL_UPL); |
755 | tf->tf_eflags &= ~PSL_CLEARSIG; | | 755 | tf->tf_eflags &= ~PSL_CLEARSIG; |
756 | tf->tf_esp = (int)fp; | | 756 | tf->tf_esp = (int)fp; |
757 | tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); | | 757 | tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); |
758 | | | 758 | |
759 | /* Ensure FP state is reset, if FP is used. */ | | 759 | /* Ensure FP state is reset, if FP is used. */ |
760 | l->l_md.md_flags &= ~MDL_USEDFPU; | | 760 | l->l_md.md_flags &= ~MDL_USEDFPU; |
761 | } | | 761 | } |
762 | | | 762 | |
763 | void | | 763 | void |
764 | sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) | | 764 | sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) |
765 | { | | 765 | { |
766 | struct lwp *l = curlwp; | | 766 | struct lwp *l = curlwp; |
767 | struct proc *p = l->l_proc; | | 767 | struct proc *p = l->l_proc; |
768 | struct pmap *pmap = vm_map_pmap(&p->p_vmspace->vm_map); | | 768 | struct pmap *pmap = vm_map_pmap(&p->p_vmspace->vm_map); |
769 | int sel = pmap->pm_hiexec > I386_MAX_EXE_ADDR ? | | 769 | int sel = pmap->pm_hiexec > I386_MAX_EXE_ADDR ? |
770 | GUCODEBIG_SEL : GUCODE_SEL; | | 770 | GUCODEBIG_SEL : GUCODE_SEL; |
771 | struct sigacts *ps = p->p_sigacts; | | 771 | struct sigacts *ps = p->p_sigacts; |
772 | int onstack, error; | | 772 | int onstack, error; |
773 | int sig = ksi->ksi_signo; | | 773 | int sig = ksi->ksi_signo; |
774 | struct sigframe_siginfo *fp = getframe(l, sig, &onstack), frame; | | 774 | struct sigframe_siginfo *fp = getframe(l, sig, &onstack), frame; |
775 | sig_t catcher = SIGACTION(p, sig).sa_handler; | | 775 | sig_t catcher = SIGACTION(p, sig).sa_handler; |
776 | struct trapframe *tf = l->l_md.md_regs; | | 776 | struct trapframe *tf = l->l_md.md_regs; |
777 | | | 777 | |
778 | KASSERT(mutex_owned(p->p_lock)); | | 778 | KASSERT(mutex_owned(p->p_lock)); |
779 | | | 779 | |
780 | fp--; | | 780 | fp--; |
781 | | | 781 | |
782 | frame.sf_ra = (int)ps->sa_sigdesc[sig].sd_tramp; | | 782 | frame.sf_ra = (int)ps->sa_sigdesc[sig].sd_tramp; |
783 | frame.sf_signum = sig; | | 783 | frame.sf_signum = sig; |
784 | frame.sf_sip = &fp->sf_si; | | 784 | frame.sf_sip = &fp->sf_si; |
785 | frame.sf_ucp = &fp->sf_uc; | | 785 | frame.sf_ucp = &fp->sf_uc; |
786 | frame.sf_si._info = ksi->ksi_info; | | 786 | frame.sf_si._info = ksi->ksi_info; |
787 | frame.sf_uc.uc_flags = _UC_SIGMASK|_UC_VM; | | 787 | frame.sf_uc.uc_flags = _UC_SIGMASK|_UC_VM; |
788 | frame.sf_uc.uc_sigmask = *mask; | | 788 | frame.sf_uc.uc_sigmask = *mask; |
789 | frame.sf_uc.uc_link = l->l_ctxlink; | | 789 | frame.sf_uc.uc_link = l->l_ctxlink; |
790 | frame.sf_uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK) | | 790 | frame.sf_uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK) |
791 | ? _UC_SETSTACK : _UC_CLRSTACK; | | 791 | ? _UC_SETSTACK : _UC_CLRSTACK; |
792 | memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack)); | | 792 | memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack)); |
793 | | | 793 | |
794 | if (tf->tf_eflags & PSL_VM) | | 794 | if (tf->tf_eflags & PSL_VM) |
795 | (*p->p_emul->e_syscall_intern)(p); | | 795 | (*p->p_emul->e_syscall_intern)(p); |
796 | sendsig_reset(l, sig); | | 796 | sendsig_reset(l, sig); |
797 | | | 797 | |
798 | mutex_exit(p->p_lock); | | 798 | mutex_exit(p->p_lock); |
799 | cpu_getmcontext(l, &frame.sf_uc.uc_mcontext, &frame.sf_uc.uc_flags); | | 799 | cpu_getmcontext(l, &frame.sf_uc.uc_mcontext, &frame.sf_uc.uc_flags); |
800 | error = copyout(&frame, fp, sizeof(frame)); | | 800 | error = copyout(&frame, fp, sizeof(frame)); |
801 | mutex_enter(p->p_lock); | | 801 | mutex_enter(p->p_lock); |
802 | | | 802 | |
803 | if (error != 0) { | | 803 | if (error != 0) { |
804 | /* | | 804 | /* |
805 | * Process has trashed its stack; give it an illegal | | 805 | * Process has trashed its stack; give it an illegal |
806 | * instruction to halt it in its tracks. | | 806 | * instruction to halt it in its tracks. |
807 | */ | | 807 | */ |
808 | sigexit(l, SIGILL); | | 808 | sigexit(l, SIGILL); |
809 | /* NOTREACHED */ | | 809 | /* NOTREACHED */ |
810 | } | | 810 | } |
811 | | | 811 | |
812 | buildcontext(l, sel, catcher, fp); | | 812 | buildcontext(l, sel, catcher, fp); |
813 | | | 813 | |
814 | /* Remember that we're now on the signal stack. */ | | 814 | /* Remember that we're now on the signal stack. */ |
815 | if (onstack) | | 815 | if (onstack) |
816 | l->l_sigstk.ss_flags |= SS_ONSTACK; | | 816 | l->l_sigstk.ss_flags |= SS_ONSTACK; |
817 | } | | 817 | } |
818 | | | 818 | |
819 | static void | | 819 | static void |
820 | maybe_dump(int howto) | | 820 | maybe_dump(int howto) |
821 | { | | 821 | { |
822 | int s; | | 822 | int s; |
823 | | | 823 | |
824 | /* Disable interrupts. */ | | 824 | /* Disable interrupts. */ |
825 | s = splhigh(); | | 825 | s = splhigh(); |
826 | | | 826 | |
827 | /* Do a dump if requested. */ | | 827 | /* Do a dump if requested. */ |
828 | if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) | | 828 | if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) |
829 | dumpsys(); | | 829 | dumpsys(); |
830 | | | 830 | |
831 | splx(s); | | 831 | splx(s); |
832 | } | | 832 | } |
833 | | | 833 | |
834 | void | | 834 | void |
835 | cpu_reboot(int howto, char *bootstr) | | 835 | cpu_reboot(int howto, char *bootstr) |
836 | { | | 836 | { |
837 | static bool syncdone = false; | | 837 | static bool syncdone = false; |
838 | int s = IPL_NONE; | | 838 | int s = IPL_NONE; |
839 | | | 839 | |
840 | if (cold) { | | 840 | if (cold) { |
841 | howto |= RB_HALT; | | 841 | howto |= RB_HALT; |
842 | goto haltsys; | | 842 | goto haltsys; |
843 | } | | 843 | } |
844 | | | 844 | |
845 | boothowto = howto; | | 845 | boothowto = howto; |
846 | | | 846 | |
847 | /* XXX used to dump after vfs_shutdown() and before | | 847 | /* XXX used to dump after vfs_shutdown() and before |
848 | * detaching devices / shutdown hooks / pmf_system_shutdown(). | | 848 | * detaching devices / shutdown hooks / pmf_system_shutdown(). |
849 | */ | | 849 | */ |
850 | maybe_dump(howto); | | 850 | maybe_dump(howto); |
851 | | | 851 | |
852 | /* | | 852 | /* |
853 | * If we've panic'd, don't make the situation potentially | | 853 | * If we've panic'd, don't make the situation potentially |
854 | * worse by syncing or unmounting the file systems. | | 854 | * worse by syncing or unmounting the file systems. |
855 | */ | | 855 | */ |
856 | if ((howto & RB_NOSYNC) == 0 && panicstr == NULL) { | | 856 | if ((howto & RB_NOSYNC) == 0 && panicstr == NULL) { |
857 | if (!syncdone) { | | 857 | if (!syncdone) { |
858 | syncdone = true; | | 858 | syncdone = true; |
859 | /* XXX used to force unmount as well, here */ | | 859 | /* XXX used to force unmount as well, here */ |
860 | vfs_sync_all(curlwp); | | 860 | vfs_sync_all(curlwp); |
861 | /* | | 861 | /* |
862 | * If we've been adjusting the clock, the todr | | 862 | * If we've been adjusting the clock, the todr |
863 | * will be out of synch; adjust it now. | | 863 | * will be out of synch; adjust it now. |
864 | * | | 864 | * |
865 | * XXX used to do this after unmounting all | | 865 | * XXX used to do this after unmounting all |
866 | * filesystems with vfs_shutdown(). | | 866 | * filesystems with vfs_shutdown(). |
867 | */ | | 867 | */ |
868 | if (time_adjusted != 0) | | 868 | if (time_adjusted != 0) |
869 | resettodr(); | | 869 | resettodr(); |
870 | } | | 870 | } |
871 | | | 871 | |
872 | while (vfs_unmountall1(curlwp, false, false) || | | 872 | while (vfs_unmountall1(curlwp, false, false) || |
873 | config_detach_all(boothowto) || | | 873 | config_detach_all(boothowto) || |
874 | vfs_unmount_forceone(curlwp)) | | 874 | vfs_unmount_forceone(curlwp)) |
875 | ; /* do nothing */ | | 875 | ; /* do nothing */ |
876 | } else | | 876 | } else |
877 | suspendsched(); | | 877 | suspendsched(); |
878 | | | 878 | |
879 | pmf_system_shutdown(boothowto); | | 879 | pmf_system_shutdown(boothowto); |
880 | | | 880 | |
881 | s = splhigh(); | | 881 | s = splhigh(); |
882 | | | 882 | |
883 | /* amd64 maybe_dump() */ | | 883 | /* amd64 maybe_dump() */ |
884 | | | 884 | |
885 | haltsys: | | 885 | haltsys: |
886 | doshutdownhooks(); | | 886 | doshutdownhooks(); |
887 | | | 887 | |
888 | if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { | | 888 | if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { |
889 | #ifdef XEN | | 889 | #ifdef XEN |
890 | HYPERVISOR_shutdown(); | | 890 | HYPERVISOR_shutdown(); |
891 | for (;;); | | 891 | for (;;); |
892 | #endif | | 892 | #endif |
893 | #if NACPICA > 0 | | 893 | #if NACPICA > 0 |
894 | if (s != IPL_NONE) | | 894 | if (s != IPL_NONE) |
895 | splx(s); | | 895 | splx(s); |
896 | | | 896 | |
897 | acpi_enter_sleep_state(ACPI_STATE_S5); | | 897 | acpi_enter_sleep_state(ACPI_STATE_S5); |
898 | #endif | | 898 | #endif |
899 | #if NAPMBIOS > 0 && !defined(APM_NO_POWEROFF) | | 899 | #if NAPMBIOS > 0 && !defined(APM_NO_POWEROFF) |
900 | /* turn off, if we can. But try to turn disk off and | | 900 | /* turn off, if we can. But try to turn disk off and |
901 | * wait a bit first--some disk drives are slow to clean up | | 901 | * wait a bit first--some disk drives are slow to clean up |
902 | * and users have reported disk corruption. | | 902 | * and users have reported disk corruption. |
903 | */ | | 903 | */ |
904 | delay(500000); | | 904 | delay(500000); |
905 | apm_set_powstate(NULL, APM_DEV_DISK(APM_DEV_ALLUNITS), | | 905 | apm_set_powstate(NULL, APM_DEV_DISK(APM_DEV_ALLUNITS), |
906 | APM_SYS_OFF); | | 906 | APM_SYS_OFF); |
907 | delay(500000); | | 907 | delay(500000); |
908 | apm_set_powstate(NULL, APM_DEV_ALLDEVS, APM_SYS_OFF); | | 908 | apm_set_powstate(NULL, APM_DEV_ALLDEVS, APM_SYS_OFF); |
909 | printf("WARNING: APM powerdown failed!\n"); | | 909 | printf("WARNING: APM powerdown failed!\n"); |
910 | /* | | 910 | /* |
911 | * RB_POWERDOWN implies RB_HALT... fall into it... | | 911 | * RB_POWERDOWN implies RB_HALT... fall into it... |
912 | */ | | 912 | */ |
913 | #endif | | 913 | #endif |
914 | } | | 914 | } |
915 | | | 915 | |
916 | #ifdef MULTIPROCESSOR | | 916 | #ifdef MULTIPROCESSOR |
917 | cpu_broadcast_halt(); | | 917 | cpu_broadcast_halt(); |
918 | #endif /* MULTIPROCESSOR */ | | 918 | #endif /* MULTIPROCESSOR */ |
919 | | | 919 | |
920 | if (howto & RB_HALT) { | | 920 | if (howto & RB_HALT) { |
921 | #if NACPICA > 0 | | 921 | #if NACPICA > 0 |
922 | acpi_disable(); | | 922 | acpi_disable(); |
923 | #endif | | 923 | #endif |
924 | | | 924 | |
925 | printf("\n"); | | 925 | printf("\n"); |
926 | printf("The operating system has halted.\n"); | | 926 | printf("The operating system has halted.\n"); |
927 | printf("Please press any key to reboot.\n\n"); | | 927 | printf("Please press any key to reboot.\n\n"); |
928 | | | 928 | |
929 | #ifdef BEEP_ONHALT | | 929 | #ifdef BEEP_ONHALT |
930 | { | | 930 | { |
931 | int c; | | 931 | int c; |
932 | for (c = BEEP_ONHALT_COUNT; c > 0; c--) { | | 932 | for (c = BEEP_ONHALT_COUNT; c > 0; c--) { |
933 | sysbeep(BEEP_ONHALT_PITCH, | | 933 | sysbeep(BEEP_ONHALT_PITCH, |
934 | BEEP_ONHALT_PERIOD * hz / 1000); | | 934 | BEEP_ONHALT_PERIOD * hz / 1000); |
935 | delay(BEEP_ONHALT_PERIOD * 1000); | | 935 | delay(BEEP_ONHALT_PERIOD * 1000); |
936 | sysbeep(0, BEEP_ONHALT_PERIOD * hz / 1000); | | 936 | sysbeep(0, BEEP_ONHALT_PERIOD * hz / 1000); |
937 | delay(BEEP_ONHALT_PERIOD * 1000); | | 937 | delay(BEEP_ONHALT_PERIOD * 1000); |
938 | } | | 938 | } |
939 | } | | 939 | } |
940 | #endif | | 940 | #endif |
941 | | | 941 | |
942 | cnpollc(1); /* for proper keyboard command handling */ | | 942 | cnpollc(1); /* for proper keyboard command handling */ |
943 | if (cngetc() == 0) { | | 943 | if (cngetc() == 0) { |
944 | /* no console attached, so just hlt */ | | 944 | /* no console attached, so just hlt */ |
945 | for(;;) { | | 945 | for(;;) { |
946 | x86_hlt(); | | 946 | x86_hlt(); |
947 | } | | 947 | } |
948 | } | | 948 | } |
949 | cnpollc(0); | | 949 | cnpollc(0); |
950 | } | | 950 | } |
951 | | | 951 | |
952 | printf("rebooting...\n"); | | 952 | printf("rebooting...\n"); |
953 | if (cpureset_delay > 0) | | 953 | if (cpureset_delay > 0) |
954 | delay(cpureset_delay * 1000); | | 954 | delay(cpureset_delay * 1000); |
955 | cpu_reset(); | | 955 | cpu_reset(); |
956 | for(;;) ; | | 956 | for(;;) ; |
957 | /*NOTREACHED*/ | | 957 | /*NOTREACHED*/ |
958 | } | | 958 | } |
959 | | | 959 | |
960 | /* | | 960 | /* |
961 | * Clear registers on exec | | 961 | * Clear registers on exec |
962 | */ | | 962 | */ |
963 | void | | 963 | void |
964 | setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) | | 964 | setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) |
965 | { | | 965 | { |
966 | struct pmap *pmap = vm_map_pmap(&l->l_proc->p_vmspace->vm_map); | | 966 | struct pmap *pmap = vm_map_pmap(&l->l_proc->p_vmspace->vm_map); |
967 | struct pcb *pcb = lwp_getpcb(l); | | 967 | struct pcb *pcb = lwp_getpcb(l); |
968 | struct trapframe *tf; | | 968 | struct trapframe *tf; |
969 | | | 969 | |
970 | #if NNPX > 0 | | 970 | #if NNPX > 0 |
971 | /* If we were using the FPU, forget about it. */ | | 971 | /* If we were using the FPU, forget about it. */ |
972 | if (pcb->pcb_fpcpu != NULL) { | | 972 | if (pcb->pcb_fpcpu != NULL) { |
973 | npxsave_lwp(l, false); | | 973 | npxsave_lwp(l, false); |
974 | } | | 974 | } |
975 | #endif | | 975 | #endif |
976 | | | 976 | |
977 | #ifdef USER_LDT | | 977 | #ifdef USER_LDT |
978 | pmap_ldt_cleanup(l); | | 978 | pmap_ldt_cleanup(l); |
979 | #endif | | 979 | #endif |
980 | | | 980 | |
981 | l->l_md.md_flags &= ~MDL_USEDFPU; | | 981 | l->l_md.md_flags &= ~MDL_USEDFPU; |
982 | if (i386_use_fxsave) { | | 982 | if (i386_use_fxsave) { |
983 | pcb->pcb_savefpu.sv_xmm.sv_env.en_cw = __NetBSD_NPXCW__; | | 983 | pcb->pcb_savefpu.sv_xmm.sv_env.en_cw = __NetBSD_NPXCW__; |
984 | pcb->pcb_savefpu.sv_xmm.sv_env.en_mxcsr = __INITIAL_MXCSR__; | | 984 | pcb->pcb_savefpu.sv_xmm.sv_env.en_mxcsr = __INITIAL_MXCSR__; |
985 | } else | | 985 | } else |
986 | pcb->pcb_savefpu.sv_87.sv_env.en_cw = __NetBSD_NPXCW__; | | 986 | pcb->pcb_savefpu.sv_87.sv_env.en_cw = __NetBSD_NPXCW__; |
987 | memcpy(&pcb->pcb_fsd, &gdt[GUDATA_SEL], sizeof(pcb->pcb_fsd)); | | 987 | memcpy(&pcb->pcb_fsd, &gdt[GUDATA_SEL], sizeof(pcb->pcb_fsd)); |
988 | memcpy(&pcb->pcb_gsd, &gdt[GUDATA_SEL], sizeof(pcb->pcb_gsd)); | | 988 | memcpy(&pcb->pcb_gsd, &gdt[GUDATA_SEL], sizeof(pcb->pcb_gsd)); |
989 | | | 989 | |
990 | tf = l->l_md.md_regs; | | 990 | tf = l->l_md.md_regs; |
991 | tf->tf_gs = GSEL(GUGS_SEL, SEL_UPL); | | 991 | tf->tf_gs = GSEL(GUGS_SEL, SEL_UPL); |
992 | tf->tf_fs = GSEL(GUFS_SEL, SEL_UPL); | | 992 | tf->tf_fs = GSEL(GUFS_SEL, SEL_UPL); |
993 | tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL); | | 993 | tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL); |
994 | tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL); | | 994 | tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL); |
995 | tf->tf_edi = 0; | | 995 | tf->tf_edi = 0; |
996 | tf->tf_esi = 0; | | 996 | tf->tf_esi = 0; |
997 | tf->tf_ebp = 0; | | 997 | tf->tf_ebp = 0; |
998 | tf->tf_ebx = l->l_proc->p_psstrp; | | 998 | tf->tf_ebx = l->l_proc->p_psstrp; |
999 | tf->tf_edx = 0; | | 999 | tf->tf_edx = 0; |
1000 | tf->tf_ecx = 0; | | 1000 | tf->tf_ecx = 0; |
1001 | tf->tf_eax = 0; | | 1001 | tf->tf_eax = 0; |
1002 | tf->tf_eip = pack->ep_entry; | | 1002 | tf->tf_eip = pack->ep_entry; |
1003 | tf->tf_cs = pmap->pm_hiexec > I386_MAX_EXE_ADDR ? | | 1003 | tf->tf_cs = pmap->pm_hiexec > I386_MAX_EXE_ADDR ? |
1004 | LSEL(LUCODEBIG_SEL, SEL_UPL) : LSEL(LUCODE_SEL, SEL_UPL); | | 1004 | LSEL(LUCODEBIG_SEL, SEL_UPL) : LSEL(LUCODE_SEL, SEL_UPL); |
1005 | tf->tf_eflags = PSL_USERSET; | | 1005 | tf->tf_eflags = PSL_USERSET; |
1006 | tf->tf_esp = stack; | | 1006 | tf->tf_esp = stack; |
1007 | tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL); | | 1007 | tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL); |
1008 | } | | 1008 | } |
1009 | | | 1009 | |
1010 | /* | | 1010 | /* |
1011 | * Initialize segments and descriptor tables | | 1011 | * Initialize segments and descriptor tables |
1012 | */ | | 1012 | */ |
1013 | | | 1013 | |
1014 | union descriptor *gdt, *ldt; | | 1014 | union descriptor *gdt, *ldt; |
1015 | union descriptor *pentium_idt; | | 1015 | union descriptor *pentium_idt; |
1016 | extern vaddr_t lwp0uarea; | | 1016 | extern vaddr_t lwp0uarea; |
1017 | | | 1017 | |
1018 | void | | 1018 | void |
1019 | setgate(struct gate_descriptor *gd, void *func, int args, int type, int dpl, | | 1019 | setgate(struct gate_descriptor *gd, void *func, int args, int type, int dpl, |
1020 | int sel) | | 1020 | int sel) |
1021 | { | | 1021 | { |
1022 | | | 1022 | |
1023 | gd->gd_looffset = (int)func; | | 1023 | gd->gd_looffset = (int)func; |
1024 | gd->gd_selector = sel; | | 1024 | gd->gd_selector = sel; |
1025 | gd->gd_stkcpy = args; | | 1025 | gd->gd_stkcpy = args; |
1026 | gd->gd_xx = 0; | | 1026 | gd->gd_xx = 0; |
1027 | gd->gd_type = type; | | 1027 | gd->gd_type = type; |
1028 | gd->gd_dpl = dpl; | | 1028 | gd->gd_dpl = dpl; |
1029 | gd->gd_p = 1; | | 1029 | gd->gd_p = 1; |
1030 | gd->gd_hioffset = (int)func >> 16; | | 1030 | gd->gd_hioffset = (int)func >> 16; |
1031 | } | | 1031 | } |
1032 | | | 1032 | |
1033 | void | | 1033 | void |
1034 | unsetgate(struct gate_descriptor *gd) | | 1034 | unsetgate(struct gate_descriptor *gd) |
1035 | { | | 1035 | { |
1036 | gd->gd_p = 0; | | 1036 | gd->gd_p = 0; |
1037 | gd->gd_hioffset = 0; | | 1037 | gd->gd_hioffset = 0; |
1038 | gd->gd_looffset = 0; | | 1038 | gd->gd_looffset = 0; |
1039 | gd->gd_selector = 0; | | 1039 | gd->gd_selector = 0; |
1040 | gd->gd_xx = 0; | | 1040 | gd->gd_xx = 0; |
1041 | gd->gd_stkcpy = 0; | | 1041 | gd->gd_stkcpy = 0; |
1042 | gd->gd_type = 0; | | 1042 | gd->gd_type = 0; |
1043 | gd->gd_dpl = 0; | | 1043 | gd->gd_dpl = 0; |
1044 | } | | 1044 | } |
1045 | | | 1045 | |
1046 | | | 1046 | |
1047 | void | | 1047 | void |
1048 | setregion(struct region_descriptor *rd, void *base, size_t limit) | | 1048 | setregion(struct region_descriptor *rd, void *base, size_t limit) |
1049 | { | | 1049 | { |
1050 | | | 1050 | |
1051 | rd->rd_limit = (int)limit; | | 1051 | rd->rd_limit = (int)limit; |
1052 | rd->rd_base = (int)base; | | 1052 | rd->rd_base = (int)base; |
1053 | } | | 1053 | } |
1054 | | | 1054 | |
1055 | void | | 1055 | void |
1056 | setsegment(struct segment_descriptor *sd, const void *base, size_t limit, | | 1056 | setsegment(struct segment_descriptor *sd, const void *base, size_t limit, |
1057 | int type, int dpl, int def32, int gran) | | 1057 | int type, int dpl, int def32, int gran) |
1058 | { | | 1058 | { |
1059 | | | 1059 | |
1060 | sd->sd_lolimit = (int)limit; | | 1060 | sd->sd_lolimit = (int)limit; |
1061 | sd->sd_lobase = (int)base; | | 1061 | sd->sd_lobase = (int)base; |
1062 | sd->sd_type = type; | | 1062 | sd->sd_type = type; |
1063 | sd->sd_dpl = dpl; | | 1063 | sd->sd_dpl = dpl; |
1064 | sd->sd_p = 1; | | 1064 | sd->sd_p = 1; |
1065 | sd->sd_hilimit = (int)limit >> 16; | | 1065 | sd->sd_hilimit = (int)limit >> 16; |
1066 | sd->sd_xx = 0; | | 1066 | sd->sd_xx = 0; |
1067 | sd->sd_def32 = def32; | | 1067 | sd->sd_def32 = def32; |
1068 | sd->sd_gran = gran; | | 1068 | sd->sd_gran = gran; |
1069 | sd->sd_hibase = (int)base >> 24; | | 1069 | sd->sd_hibase = (int)base >> 24; |
1070 | } | | 1070 | } |
1071 | | | 1071 | |
1072 | #define IDTVEC(name) __CONCAT(X, name) | | 1072 | #define IDTVEC(name) __CONCAT(X, name) |
1073 | typedef void (vector)(void); | | 1073 | typedef void (vector)(void); |
1074 | extern vector IDTVEC(syscall); | | 1074 | extern vector IDTVEC(syscall); |
1075 | extern vector IDTVEC(osyscall); | | 1075 | extern vector IDTVEC(osyscall); |
1076 | extern vector *IDTVEC(exceptions)[]; | | 1076 | extern vector *IDTVEC(exceptions)[]; |
1077 | extern vector IDTVEC(svr4_fasttrap); | | 1077 | extern vector IDTVEC(svr4_fasttrap); |
1078 | void (*svr4_fasttrap_vec)(void) = (void (*)(void))nullop; | | 1078 | void (*svr4_fasttrap_vec)(void) = (void (*)(void))nullop; |
1079 | krwlock_t svr4_fasttrap_lock; | | 1079 | krwlock_t svr4_fasttrap_lock; |
1080 | #ifdef XEN | | 1080 | #ifdef XEN |
1081 | #define MAX_XEN_IDT 128 | | 1081 | #define MAX_XEN_IDT 128 |
1082 | trap_info_t xen_idt[MAX_XEN_IDT]; | | 1082 | trap_info_t xen_idt[MAX_XEN_IDT]; |
1083 | int xen_idt_idx; | | 1083 | int xen_idt_idx; |
1084 | extern union descriptor tmpgdt[]; | | 1084 | extern union descriptor tmpgdt[]; |
1085 | #endif | | 1085 | #endif |
1086 | | | 1086 | |
1087 | void cpu_init_idt(void) | | 1087 | void cpu_init_idt(void) |
1088 | { | | 1088 | { |
1089 | #ifndef XEN | | 1089 | #ifndef XEN |
1090 | struct region_descriptor region; | | 1090 | struct region_descriptor region; |
1091 | setregion(®ion, pentium_idt, NIDT * sizeof(idt[0]) - 1); | | 1091 | setregion(®ion, pentium_idt, NIDT * sizeof(idt[0]) - 1); |
1092 | lidt(®ion); | | 1092 | lidt(®ion); |
1093 | #else /* XEN */ | | 1093 | #else /* XEN */ |
1094 | XENPRINTF(("HYPERVISOR_set_trap_table %p\n", xen_idt)); | | 1094 | XENPRINTF(("HYPERVISOR_set_trap_table %p\n", xen_idt)); |
1095 | if (HYPERVISOR_set_trap_table(xen_idt)) | | 1095 | if (HYPERVISOR_set_trap_table(xen_idt)) |
1096 | panic("HYPERVISOR_set_trap_table %p failed\n", xen_idt); | | 1096 | panic("HYPERVISOR_set_trap_table %p failed\n", xen_idt); |
1097 | #endif /* !XEN */ | | 1097 | #endif /* !XEN */ |
1098 | } | | 1098 | } |
1099 | | | 1099 | |
1100 | void | | 1100 | void |
1101 | initgdt(union descriptor *tgdt) | | 1101 | initgdt(union descriptor *tgdt) |
1102 | { | | 1102 | { |
1103 | KASSERT(tgdt != NULL); | | 1103 | KASSERT(tgdt != NULL); |
1104 | | | 1104 | |
1105 | gdt = tgdt; | | 1105 | gdt = tgdt; |
1106 | #ifdef XEN | | 1106 | #ifdef XEN |
1107 | u_long frames[16]; | | 1107 | u_long frames[16]; |
1108 | #else | | 1108 | #else |
1109 | struct region_descriptor region; | | 1109 | struct region_descriptor region; |
1110 | memset(gdt, 0, NGDT*sizeof(*gdt)); | | 1110 | memset(gdt, 0, NGDT*sizeof(*gdt)); |
1111 | #endif /* XEN */ | | 1111 | #endif /* XEN */ |
1112 | /* make gdt gates and memory segments */ | | 1112 | /* make gdt gates and memory segments */ |
1113 | setsegment(&gdt[GCODE_SEL].sd, 0, 0xfffff, SDT_MEMERA, SEL_KPL, 1, 1); | | 1113 | setsegment(&gdt[GCODE_SEL].sd, 0, 0xfffff, SDT_MEMERA, SEL_KPL, 1, 1); |
1114 | setsegment(&gdt[GDATA_SEL].sd, 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 1, 1); | | 1114 | setsegment(&gdt[GDATA_SEL].sd, 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 1, 1); |
1115 | setsegment(&gdt[GUCODE_SEL].sd, 0, x86_btop(I386_MAX_EXE_ADDR) - 1, | | 1115 | setsegment(&gdt[GUCODE_SEL].sd, 0, x86_btop(I386_MAX_EXE_ADDR) - 1, |
1116 | SDT_MEMERA, SEL_UPL, 1, 1); | | 1116 | SDT_MEMERA, SEL_UPL, 1, 1); |
1117 | setsegment(&gdt[GUCODEBIG_SEL].sd, 0, 0xfffff, | | 1117 | setsegment(&gdt[GUCODEBIG_SEL].sd, 0, 0xfffff, |
1118 | SDT_MEMERA, SEL_UPL, 1, 1); | | 1118 | SDT_MEMERA, SEL_UPL, 1, 1); |
1119 | setsegment(&gdt[GUDATA_SEL].sd, 0, 0xfffff, | | 1119 | setsegment(&gdt[GUDATA_SEL].sd, 0, 0xfffff, |
1120 | SDT_MEMRWA, SEL_UPL, 1, 1); | | 1120 | SDT_MEMRWA, SEL_UPL, 1, 1); |
1121 | #if NBIOSCALL > 0 | | 1121 | #if NBIOSCALL > 0 |
1122 | /* bios trampoline GDT entries */ | | 1122 | /* bios trampoline GDT entries */ |
1123 | setsegment(&gdt[GBIOSCODE_SEL].sd, 0, 0xfffff, SDT_MEMERA, SEL_KPL, 0, | | 1123 | setsegment(&gdt[GBIOSCODE_SEL].sd, 0, 0xfffff, SDT_MEMERA, SEL_KPL, 0, |
1124 | 0); | | 1124 | 0); |
1125 | setsegment(&gdt[GBIOSDATA_SEL].sd, 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 0, | | 1125 | setsegment(&gdt[GBIOSDATA_SEL].sd, 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 0, |
1126 | 0); | | 1126 | 0); |
1127 | #endif | | 1127 | #endif |
1128 | setsegment(&gdt[GCPU_SEL].sd, &cpu_info_primary, 0xfffff, | | 1128 | setsegment(&gdt[GCPU_SEL].sd, &cpu_info_primary, 0xfffff, |
1129 | SDT_MEMRWA, SEL_KPL, 1, 1); | | 1129 | SDT_MEMRWA, SEL_KPL, 1, 1); |
1130 | | | 1130 | |
1131 | #ifndef XEN | | 1131 | #ifndef XEN |
1132 | setregion(®ion, gdt, NGDT * sizeof(gdt[0]) - 1); | | 1132 | setregion(®ion, gdt, NGDT * sizeof(gdt[0]) - 1); |
1133 | lgdt(®ion); | | 1133 | lgdt(®ion); |
1134 | #else /* !XEN */ | | 1134 | #else /* !XEN */ |
1135 | /* | | 1135 | /* |
1136 | * We jumpstart the bootstrap process a bit so we can update | | 1136 | * We jumpstart the bootstrap process a bit so we can update |
1137 | * page permissions. This is done redundantly later from | | 1137 | * page permissions. This is done redundantly later from |
1138 | * x86_xpmap.c:xen_pmap_bootstrap() - harmless. | | 1138 | * x86_xpmap.c:xen_pmap_bootstrap() - harmless. |
1139 | */ | | 1139 | */ |
1140 | xpmap_phys_to_machine_mapping = | | 1140 | xpmap_phys_to_machine_mapping = |
1141 | (unsigned long *)xen_start_info.mfn_list; | | 1141 | (unsigned long *)xen_start_info.mfn_list; |
1142 | | | 1142 | |
1143 | frames[0] = xpmap_ptom((uint32_t)gdt - KERNBASE) >> PAGE_SHIFT; | | 1143 | frames[0] = xpmap_ptom((uint32_t)gdt - KERNBASE) >> PAGE_SHIFT; |
1144 | { /* | | 1144 | { /* |
1145 | * Enter the gdt page RO into the kernel map. We can't | | 1145 | * Enter the gdt page RO into the kernel map. We can't |
1146 | * use pmap_kenter_pa() here, because %fs is not | | 1146 | * use pmap_kenter_pa() here, because %fs is not |
1147 | * usable until the gdt is loaded, and %fs is used as | | 1147 | * usable until the gdt is loaded, and %fs is used as |
1148 | * the base pointer for curcpu() and curlwp(), both of | | 1148 | * the base pointer for curcpu() and curlwp(), both of |
1149 | * which are in the callpath of pmap_kenter_pa(). | | 1149 | * which are in the callpath of pmap_kenter_pa(). |
1150 | * So we mash up our own - this is MD code anyway. | | 1150 | * So we mash up our own - this is MD code anyway. |
1151 | */ | | 1151 | */ |
1152 | pt_entry_t pte; | | 1152 | pt_entry_t pte; |
1153 | pt_entry_t pg_nx = (cpu_feature[2] & CPUID_NOX ? PG_NX : 0); | | 1153 | pt_entry_t pg_nx = (cpu_feature[2] & CPUID_NOX ? PG_NX : 0); |
1154 | | | 1154 | |
1155 | pte = pmap_pa2pte((vaddr_t)gdt - KERNBASE); | | 1155 | pte = pmap_pa2pte((vaddr_t)gdt - KERNBASE); |
1156 | pte |= PG_k | PG_RO | pg_nx | PG_V; | | 1156 | pte |= PG_k | PG_RO | pg_nx | PG_V; |
1157 | | | 1157 | |
1158 | if (HYPERVISOR_update_va_mapping((vaddr_t)gdt, pte, UVMF_INVLPG) < 0) { | | 1158 | if (HYPERVISOR_update_va_mapping((vaddr_t)gdt, pte, UVMF_INVLPG) < 0) { |
1159 | panic("gdt page RO update failed.\n"); | | 1159 | panic("gdt page RO update failed.\n"); |
1160 | } | | 1160 | } |
1161 | | | 1161 | |
1162 | } | | 1162 | } |
1163 | | | 1163 | |
1164 | XENPRINTK(("loading gdt %lx, %d entries\n", frames[0] << PAGE_SHIFT, | | 1164 | XENPRINTK(("loading gdt %lx, %d entries\n", frames[0] << PAGE_SHIFT, |
1165 | NGDT)); | | 1165 | NGDT)); |
1166 | if (HYPERVISOR_set_gdt(frames, NGDT /* XXX is it right ? */)) | | 1166 | if (HYPERVISOR_set_gdt(frames, NGDT /* XXX is it right ? */)) |
1167 | panic("HYPERVISOR_set_gdt failed!\n"); | | 1167 | panic("HYPERVISOR_set_gdt failed!\n"); |
1168 | | | 1168 | |
1169 | lgdt_finish(); | | 1169 | lgdt_finish(); |
1170 | #endif /* !XEN */ | | 1170 | #endif /* !XEN */ |
1171 | } | | 1171 | } |
1172 | | | 1172 | |
1173 | static void | | 1173 | static void |
1174 | init386_msgbuf(void) | | 1174 | init386_msgbuf(void) |
1175 | { | | 1175 | { |
1176 | /* Message buffer is located at end of core. */ | | 1176 | /* Message buffer is located at end of core. */ |
1177 | struct vm_physseg *vps; | | 1177 | struct vm_physseg *vps; |
1178 | psize_t sz = round_page(MSGBUFSIZE); | | 1178 | psize_t sz = round_page(MSGBUFSIZE); |
1179 | psize_t reqsz = sz; | | 1179 | psize_t reqsz = sz; |
1180 | unsigned int x; | | 1180 | unsigned int x; |
1181 | | | 1181 | |
1182 | search_again: | | 1182 | search_again: |
1183 | vps = NULL; | | 1183 | vps = NULL; |
1184 | for (x = 0; x < vm_nphysseg; ++x) { | | 1184 | for (x = 0; x < vm_nphysseg; ++x) { |
1185 | vps = VM_PHYSMEM_PTR(x); | | 1185 | vps = VM_PHYSMEM_PTR(x); |
1186 | if (ctob(vps->avail_end) == avail_end) { | | 1186 | if (ctob(vps->avail_end) == avail_end) { |
1187 | break; | | 1187 | break; |
1188 | } | | 1188 | } |
1189 | } | | 1189 | } |
1190 | if (x == vm_nphysseg) | | 1190 | if (x == vm_nphysseg) |
1191 | panic("init386: can't find end of memory"); | | 1191 | panic("init386: can't find end of memory"); |
1192 | | | 1192 | |
1193 | /* Shrink so it'll fit in the last segment. */ | | 1193 | /* Shrink so it'll fit in the last segment. */ |
1194 | if (vps->avail_end - vps->avail_start < atop(sz)) | | 1194 | if (vps->avail_end - vps->avail_start < atop(sz)) |
1195 | sz = ctob(vps->avail_end - vps->avail_start); | | 1195 | sz = ctob(vps->avail_end - vps->avail_start); |
1196 | | | 1196 | |
1197 | vps->avail_end -= atop(sz); | | 1197 | vps->avail_end -= atop(sz); |
1198 | vps->end -= atop(sz); | | 1198 | vps->end -= atop(sz); |
1199 | msgbuf_p_seg[msgbuf_p_cnt].sz = sz; | | 1199 | msgbuf_p_seg[msgbuf_p_cnt].sz = sz; |
1200 | msgbuf_p_seg[msgbuf_p_cnt++].paddr = ctob(vps->avail_end); | | 1200 | msgbuf_p_seg[msgbuf_p_cnt++].paddr = ctob(vps->avail_end); |
1201 | | | 1201 | |
1202 | /* Remove the last segment if it now has no pages. */ | | 1202 | /* Remove the last segment if it now has no pages. */ |
1203 | if (vps->start == vps->end) { | | 1203 | if (vps->start == vps->end) { |
1204 | for (--vm_nphysseg; x < vm_nphysseg; x++) | | 1204 | for (--vm_nphysseg; x < vm_nphysseg; x++) |
1205 | VM_PHYSMEM_PTR_SWAP(x, x + 1); | | 1205 | VM_PHYSMEM_PTR_SWAP(x, x + 1); |
1206 | } | | 1206 | } |
1207 | | | 1207 | |
1208 | /* Now find where the new avail_end is. */ | | 1208 | /* Now find where the new avail_end is. */ |
1209 | for (avail_end = 0, x = 0; x < vm_nphysseg; x++) | | 1209 | for (avail_end = 0, x = 0; x < vm_nphysseg; x++) |
1210 | if (VM_PHYSMEM_PTR(x)->avail_end > avail_end) | | 1210 | if (VM_PHYSMEM_PTR(x)->avail_end > avail_end) |
1211 | avail_end = VM_PHYSMEM_PTR(x)->avail_end; | | 1211 | avail_end = VM_PHYSMEM_PTR(x)->avail_end; |
1212 | avail_end = ctob(avail_end); | | 1212 | avail_end = ctob(avail_end); |
1213 | | | 1213 | |
1214 | if (sz == reqsz) | | 1214 | if (sz == reqsz) |
1215 | return; | | 1215 | return; |
1216 | | | 1216 | |
1217 | reqsz -= sz; | | 1217 | reqsz -= sz; |
1218 | if (msgbuf_p_cnt == VM_PHYSSEG_MAX) { | | 1218 | if (msgbuf_p_cnt == VM_PHYSSEG_MAX) { |
1219 | /* No more segments available, bail out. */ | | 1219 | /* No more segments available, bail out. */ |
1220 | printf("WARNING: MSGBUFSIZE (%zu) too large, using %zu.\n", | | 1220 | printf("WARNING: MSGBUFSIZE (%zu) too large, using %zu.\n", |
1221 | (size_t)MSGBUFSIZE, (size_t)(MSGBUFSIZE - reqsz)); | | 1221 | (size_t)MSGBUFSIZE, (size_t)(MSGBUFSIZE - reqsz)); |
1222 | return; | | 1222 | return; |
1223 | } | | 1223 | } |
1224 | | | 1224 | |
1225 | sz = reqsz; | | 1225 | sz = reqsz; |
1226 | goto search_again; | | 1226 | goto search_again; |
1227 | } | | 1227 | } |
1228 | | | 1228 | |
1229 | #ifndef XEN | | 1229 | #ifndef XEN |
1230 | static void | | 1230 | static void |
1231 | init386_pte0(void) | | 1231 | init386_pte0(void) |
1232 | { | | 1232 | { |
1233 | paddr_t paddr; | | 1233 | paddr_t paddr; |
1234 | vaddr_t vaddr; | | 1234 | vaddr_t vaddr; |
1235 | | | 1235 | |
1236 | paddr = 4 * PAGE_SIZE; | | 1236 | paddr = 4 * PAGE_SIZE; |
1237 | vaddr = (vaddr_t)vtopte(0); | | 1237 | vaddr = (vaddr_t)vtopte(0); |
1238 | pmap_kenter_pa(vaddr, paddr, VM_PROT_ALL, 0); | | 1238 | pmap_kenter_pa(vaddr, paddr, VM_PROT_ALL, 0); |
1239 | pmap_update(pmap_kernel()); | | 1239 | pmap_update(pmap_kernel()); |
1240 | /* make sure it is clean before using */ | | 1240 | /* make sure it is clean before using */ |
1241 | memset((void *)vaddr, 0, PAGE_SIZE); | | 1241 | memset((void *)vaddr, 0, PAGE_SIZE); |
1242 | } | | 1242 | } |
1243 | #endif /* !XEN */ | | 1243 | #endif /* !XEN */ |
1244 | | | 1244 | |
1245 | static void | | 1245 | static void |
1246 | init386_ksyms(void) | | 1246 | init386_ksyms(void) |
1247 | { | | 1247 | { |
1248 | #if NKSYMS || defined(DDB) || defined(MODULAR) | | 1248 | #if NKSYMS || defined(DDB) || defined(MODULAR) |
1249 | extern int end; | | 1249 | extern int end; |
1250 | struct btinfo_symtab *symtab; | | 1250 | struct btinfo_symtab *symtab; |
1251 | | | 1251 | |
1252 | #ifdef DDB | | 1252 | #ifdef DDB |
1253 | db_machine_init(); | | 1253 | db_machine_init(); |
1254 | #endif | | 1254 | #endif |
1255 | | | 1255 | |
1256 | #if defined(MULTIBOOT) | | 1256 | #if defined(MULTIBOOT) |
1257 | if (multiboot_ksyms_addsyms_elf()) | | 1257 | if (multiboot_ksyms_addsyms_elf()) |
1258 | return; | | 1258 | return; |
1259 | #endif | | 1259 | #endif |
1260 | | | 1260 | |
1261 | if ((symtab = lookup_bootinfo(BTINFO_SYMTAB)) == NULL) { | | 1261 | if ((symtab = lookup_bootinfo(BTINFO_SYMTAB)) == NULL) { |
1262 | ksyms_addsyms_elf(*(int *)&end, ((int *)&end) + 1, esym); | | 1262 | ksyms_addsyms_elf(*(int *)&end, ((int *)&end) + 1, esym); |
1263 | return; | | 1263 | return; |
1264 | } | | 1264 | } |
1265 | | | 1265 | |
1266 | symtab->ssym += KERNBASE; | | 1266 | symtab->ssym += KERNBASE; |
1267 | symtab->esym += KERNBASE; | | 1267 | symtab->esym += KERNBASE; |
1268 | ksyms_addsyms_elf(symtab->nsym, (int *)symtab->ssym, (int *)symtab->esym); | | 1268 | ksyms_addsyms_elf(symtab->nsym, (int *)symtab->ssym, (int *)symtab->esym); |
1269 | #endif | | 1269 | #endif |
1270 | } | | 1270 | } |
1271 | | | 1271 | |
1272 | void | | 1272 | void |
1273 | init386(paddr_t first_avail) | | 1273 | init386(paddr_t first_avail) |
1274 | { | | 1274 | { |
1275 | extern void consinit(void); | | 1275 | extern void consinit(void); |
1276 | struct pcb *pcb; | | 1276 | struct pcb *pcb; |
1277 | int x; | | 1277 | int x; |
1278 | #ifndef XEN | | 1278 | #ifndef XEN |
1279 | union descriptor *tgdt; | | 1279 | union descriptor *tgdt; |
1280 | extern struct extent *iomem_ex; | | 1280 | extern struct extent *iomem_ex; |
1281 | struct region_descriptor region; | | 1281 | struct region_descriptor region; |
1282 | struct btinfo_memmap *bim; | | 1282 | struct btinfo_memmap *bim; |
1283 | #endif | | 1283 | #endif |
1284 | #if NBIOSCALL > 0 | | 1284 | #if NBIOSCALL > 0 |
1285 | extern int biostramp_image_size; | | 1285 | extern int biostramp_image_size; |
1286 | extern u_char biostramp_image[]; | | 1286 | extern u_char biostramp_image[]; |
1287 | #endif | | 1287 | #endif |
1288 | | | 1288 | |
1289 | #ifdef XEN | | 1289 | #ifdef XEN |
1290 | XENPRINTK(("HYPERVISOR_shared_info %p (%x)\n", HYPERVISOR_shared_info, | | 1290 | XENPRINTK(("HYPERVISOR_shared_info %p (%x)\n", HYPERVISOR_shared_info, |
1291 | xen_start_info.shared_info)); | | 1291 | xen_start_info.shared_info)); |
1292 | KASSERT(HYPERVISOR_shared_info != NULL); | | 1292 | KASSERT(HYPERVISOR_shared_info != NULL); |
1293 | cpu_info_primary.ci_vcpu = &HYPERVISOR_shared_info->vcpu_info[0]; | | 1293 | cpu_info_primary.ci_vcpu = &HYPERVISOR_shared_info->vcpu_info[0]; |
1294 | #endif | | 1294 | #endif |
1295 | cpu_probe(&cpu_info_primary); | | 1295 | cpu_probe(&cpu_info_primary); |
1296 | | | 1296 | |
1297 | uvm_lwp_setuarea(&lwp0, lwp0uarea); | | 1297 | uvm_lwp_setuarea(&lwp0, lwp0uarea); |
1298 | pcb = lwp_getpcb(&lwp0); | | 1298 | pcb = lwp_getpcb(&lwp0); |
1299 | | | 1299 | |
1300 | cpu_init_msrs(&cpu_info_primary, true); | | 1300 | cpu_init_msrs(&cpu_info_primary, true); |
1301 | | | 1301 | |
1302 | #ifdef PAE | | 1302 | #ifdef PAE |
1303 | use_pae = 1; | | 1303 | use_pae = 1; |
1304 | #else | | 1304 | #else |
1305 | use_pae = 0; | | 1305 | use_pae = 0; |
1306 | #endif | | 1306 | #endif |
1307 | | | 1307 | |
1308 | #ifdef XEN | | 1308 | #ifdef XEN |
1309 | pcb->pcb_cr3 = PDPpaddr; | | 1309 | pcb->pcb_cr3 = PDPpaddr; |
1310 | __PRINTK(("pcb_cr3 0x%lx cr3 0x%lx\n", | | 1310 | __PRINTK(("pcb_cr3 0x%lx cr3 0x%lx\n", |
1311 | PDPpaddr, xpmap_ptom(PDPpaddr))); | | 1311 | PDPpaddr, xpmap_ptom(PDPpaddr))); |
1312 | XENPRINTK(("lwp0uarea %p first_avail %p\n", | | 1312 | XENPRINTK(("lwp0uarea %p first_avail %p\n", |
1313 | lwp0uarea, (void *)(long)first_avail)); | | 1313 | lwp0uarea, (void *)(long)first_avail)); |
1314 | XENPRINTK(("ptdpaddr %p atdevbase %p\n", (void *)PDPpaddr, | | 1314 | XENPRINTK(("ptdpaddr %p atdevbase %p\n", (void *)PDPpaddr, |
1315 | (void *)atdevbase)); | | 1315 | (void *)atdevbase)); |
1316 | #endif | | 1316 | #endif |
1317 | | | 1317 | |
1318 | #if defined(PAE) && !defined(XEN) | | 1318 | #if defined(PAE) && !defined(XEN) |
1319 | /* | | 1319 | /* |
1320 | * Save VA and PA of L3 PD of boot processor (for Xen, this is done | | 1320 | * Save VA and PA of L3 PD of boot processor (for Xen, this is done |
1321 | * in xen_pmap_bootstrap()) | | 1321 | * in xen_pmap_bootstrap()) |
1322 | */ | | 1322 | */ |
1323 | cpu_info_primary.ci_pae_l3_pdirpa = rcr3(); | | 1323 | cpu_info_primary.ci_pae_l3_pdirpa = rcr3(); |
1324 | cpu_info_primary.ci_pae_l3_pdir = (pd_entry_t *)(rcr3() + KERNBASE); | | 1324 | cpu_info_primary.ci_pae_l3_pdir = (pd_entry_t *)(rcr3() + KERNBASE); |
1325 | #endif /* PAE && !XEN */ | | 1325 | #endif /* PAE && !XEN */ |
1326 | | | 1326 | |
1327 | #ifdef XEN | | 1327 | #ifdef XEN |
1328 | xen_parse_cmdline(XEN_PARSE_BOOTFLAGS, NULL); | | 1328 | xen_parse_cmdline(XEN_PARSE_BOOTFLAGS, NULL); |
1329 | #endif | | 1329 | #endif |
1330 | | | 1330 | |
1331 | /* | | 1331 | /* |
1332 | * Initialize PAGE_SIZE-dependent variables. | | 1332 | * Initialize PAGE_SIZE-dependent variables. |
1333 | */ | | 1333 | */ |
1334 | uvm_setpagesize(); | | 1334 | uvm_setpagesize(); |
1335 | | | 1335 | |
1336 | /* | | 1336 | /* |
1337 | * Saving SSE registers won't work if the save area isn't | | 1337 | * Saving SSE registers won't work if the save area isn't |
1338 | * 16-byte aligned. | | 1338 | * 16-byte aligned. |
1339 | */ | | 1339 | */ |
1340 | KASSERT((offsetof(struct pcb, pcb_savefpu) & 0xf) == 0); | | 1340 | KASSERT((offsetof(struct pcb, pcb_savefpu) & 0xf) == 0); |
1341 | | | 1341 | |
1342 | /* | | 1342 | /* |
1343 | * Start with 2 color bins -- this is just a guess to get us | | 1343 | * Start with 2 color bins -- this is just a guess to get us |
1344 | * started. We'll recolor when we determine the largest cache | | 1344 | * started. We'll recolor when we determine the largest cache |
1345 | * sizes on the system. | | 1345 | * sizes on the system. |
1346 | */ | | 1346 | */ |
1347 | uvmexp.ncolors = 2; | | 1347 | uvmexp.ncolors = 2; |
1348 | | | 1348 | |
1349 | #ifndef XEN | | 1349 | #ifndef XEN |
1350 | /* | | 1350 | /* |
1351 | * Low memory reservations: | | 1351 | * Low memory reservations: |
1352 | * Page 0: BIOS data | | 1352 | * Page 0: BIOS data |
1353 | * Page 1: BIOS callback | | 1353 | * Page 1: BIOS callback |
1354 | * Page 2: MP bootstrap | | 1354 | * Page 2: MP bootstrap |
1355 | * Page 3: ACPI wakeup code | | 1355 | * Page 3: ACPI wakeup code |
1356 | * Page 4: Temporary page table for 0MB-4MB | | 1356 | * Page 4: Temporary page table for 0MB-4MB |
1357 | * Page 5: Temporary page directory | | 1357 | * Page 5: Temporary page directory |
1358 | */ | | 1358 | */ |
1359 | avail_start = 6 * PAGE_SIZE; | | 1359 | avail_start = 6 * PAGE_SIZE; |
1360 | #else /* !XEN */ | | 1360 | #else /* !XEN */ |
1361 | /* steal one page for gdt */ | | 1361 | /* steal one page for gdt */ |
1362 | gdt = (void *)((u_long)first_avail + KERNBASE); | | 1362 | gdt = (void *)((u_long)first_avail + KERNBASE); |
1363 | first_avail += PAGE_SIZE; | | 1363 | first_avail += PAGE_SIZE; |
1364 | /* Make sure the end of the space used by the kernel is rounded. */ | | 1364 | /* Make sure the end of the space used by the kernel is rounded. */ |
1365 | first_avail = round_page(first_avail); | | 1365 | first_avail = round_page(first_avail); |
1366 | avail_start = first_avail; | | 1366 | avail_start = first_avail; |
1367 | avail_end = ctob((paddr_t)xen_start_info.nr_pages) + XPMAP_OFFSET; | | 1367 | avail_end = ctob((paddr_t)xen_start_info.nr_pages) + XPMAP_OFFSET; |
1368 | pmap_pa_start = (KERNTEXTOFF - KERNBASE); | | 1368 | pmap_pa_start = (KERNTEXTOFF - KERNBASE); |
1369 | pmap_pa_end = pmap_pa_start + ctob((paddr_t)xen_start_info.nr_pages); | | 1369 | pmap_pa_end = pmap_pa_start + ctob((paddr_t)xen_start_info.nr_pages); |
1370 | mem_clusters[0].start = avail_start; | | 1370 | mem_clusters[0].start = avail_start; |
1371 | mem_clusters[0].size = avail_end - avail_start; | | 1371 | mem_clusters[0].size = avail_end - avail_start; |
1372 | mem_cluster_cnt++; | | 1372 | mem_cluster_cnt++; |
1373 | physmem += xen_start_info.nr_pages; | | 1373 | physmem += xen_start_info.nr_pages; |
1374 | uvmexp.wired += atop(avail_start); | | 1374 | uvmexp.wired += atop(avail_start); |
1375 | /* | | 1375 | /* |
1376 | * initgdt() has to be done before consinit(), so that %fs is properly | | 1376 | * initgdt() has to be done before consinit(), so that %fs is properly |
1377 | * initialised. initgdt() uses pmap_kenter_pa so it can't be called | | 1377 | * initialised. initgdt() uses pmap_kenter_pa so it can't be called |
1378 | * before the above variables are set. | | 1378 | * before the above variables are set. |
1379 | */ | | 1379 | */ |
1380 | | | 1380 | |
1381 | initgdt(gdt); | | 1381 | initgdt(gdt); |
1382 | | | 1382 | |
1383 | mutex_init(&pte_lock, MUTEX_DEFAULT, IPL_VM); | | 1383 | mutex_init(&pte_lock, MUTEX_DEFAULT, IPL_VM); |
1384 | #endif /* XEN */ | | 1384 | #endif /* XEN */ |
1385 | | | 1385 | |
1386 | #if NISA > 0 || NPCI > 0 | | 1386 | #if NISA > 0 || NPCI > 0 |
1387 | x86_bus_space_init(); | | 1387 | x86_bus_space_init(); |
1388 | #endif /* NISA > 0 || NPCI > 0 */ | | 1388 | #endif /* NISA > 0 || NPCI > 0 */ |
1389 | | | 1389 | |
1390 | consinit(); /* XXX SHOULD NOT BE DONE HERE */ | | 1390 | consinit(); /* XXX SHOULD NOT BE DONE HERE */ |
1391 | | | 1391 | |
1392 | #ifdef DEBUG_MEMLOAD | | 1392 | #ifdef DEBUG_MEMLOAD |
1393 | printf("mem_cluster_count: %d\n", mem_cluster_cnt); | | 1393 | printf("mem_cluster_count: %d\n", mem_cluster_cnt); |
1394 | #endif | | 1394 | #endif |
1395 | | | 1395 | |
1396 | /* | | 1396 | /* |
1397 | * Call pmap initialization to make new kernel address space. | | 1397 | * Call pmap initialization to make new kernel address space. |
1398 | * We must do this before loading pages into the VM system. | | 1398 | * We must do this before loading pages into the VM system. |
1399 | */ | | 1399 | */ |
1400 | pmap_bootstrap((vaddr_t)atdevbase + IOM_SIZE); | | 1400 | pmap_bootstrap((vaddr_t)atdevbase + IOM_SIZE); |
1401 | | | 1401 | |
1402 | #ifndef XEN | | 1402 | #ifndef XEN |
1403 | /* | | 1403 | /* |
1404 | * Check to see if we have a memory map from the BIOS (passed | | 1404 | * Check to see if we have a memory map from the BIOS (passed |
1405 | * to us by the boot program. | | 1405 | * to us by the boot program. |
1406 | */ | | 1406 | */ |
1407 | bim = lookup_bootinfo(BTINFO_MEMMAP); | | 1407 | bim = lookup_bootinfo(BTINFO_MEMMAP); |
1408 | if ((biosmem_implicit || (biosbasemem == 0 && biosextmem == 0)) && | | 1408 | if ((biosmem_implicit || (biosbasemem == 0 && biosextmem == 0)) && |
1409 | bim != NULL && bim->num > 0) | | 1409 | bim != NULL && bim->num > 0) |
1410 | initx86_parse_memmap(bim, iomem_ex); | | 1410 | initx86_parse_memmap(bim, iomem_ex); |
1411 | | | 1411 | |
1412 | /* | | 1412 | /* |
1413 | * If the loop above didn't find any valid segment, fall back to | | 1413 | * If the loop above didn't find any valid segment, fall back to |
1414 | * former code. | | 1414 | * former code. |
1415 | */ | | 1415 | */ |
1416 | if (mem_cluster_cnt == 0) | | 1416 | if (mem_cluster_cnt == 0) |
1417 | initx86_fake_memmap(iomem_ex); | | 1417 | initx86_fake_memmap(iomem_ex); |
1418 | | | 1418 | |
1419 | initx86_load_memmap(first_avail); | | 1419 | initx86_load_memmap(first_avail); |
1420 | | | 1420 | |
1421 | #else /* !XEN */ | | 1421 | #else /* !XEN */ |
1422 | XENPRINTK(("load the memory cluster 0x%" PRIx64 " (%" PRId64 ") - " | | 1422 | XENPRINTK(("load the memory cluster 0x%" PRIx64 " (%" PRId64 ") - " |
1423 | "0x%" PRIx64 " (%" PRId64 ")\n", | | 1423 | "0x%" PRIx64 " (%" PRId64 ")\n", |
1424 | (uint64_t)avail_start, (uint64_t)atop(avail_start), | | 1424 | (uint64_t)avail_start, (uint64_t)atop(avail_start), |
1425 | (uint64_t)avail_end, (uint64_t)atop(avail_end))); | | 1425 | (uint64_t)avail_end, (uint64_t)atop(avail_end))); |
1426 | uvm_page_physload(atop(avail_start), atop(avail_end), | | 1426 | uvm_page_physload(atop(avail_start), atop(avail_end), |
1427 | atop(avail_start), atop(avail_end), | | 1427 | atop(avail_start), atop(avail_end), |
1428 | VM_FREELIST_DEFAULT); | | 1428 | VM_FREELIST_DEFAULT); |
1429 | | | 1429 | |
1430 | /* Reclaim the boot gdt page - see locore.s */ | | 1430 | /* Reclaim the boot gdt page - see locore.s */ |
1431 | { | | 1431 | { |
1432 | pt_entry_t pte; | | 1432 | pt_entry_t pte; |
1433 | pt_entry_t pg_nx = (cpu_feature[2] & CPUID_NOX ? PG_NX : 0); | | 1433 | pt_entry_t pg_nx = (cpu_feature[2] & CPUID_NOX ? PG_NX : 0); |
1434 | | | 1434 | |
1435 | pte = pmap_pa2pte((vaddr_t)tmpgdt - KERNBASE); | | 1435 | pte = pmap_pa2pte((vaddr_t)tmpgdt - KERNBASE); |
1436 | pte |= PG_k | PG_RW | pg_nx | PG_V; | | 1436 | pte |= PG_k | PG_RW | pg_nx | PG_V; |
1437 | | | 1437 | |
1438 | if (HYPERVISOR_update_va_mapping((vaddr_t)tmpgdt, pte, UVMF_INVLPG) < 0) { | | 1438 | if (HYPERVISOR_update_va_mapping((vaddr_t)tmpgdt, pte, UVMF_INVLPG) < 0) { |
1439 | panic("tmpgdt page relaim RW update failed.\n"); | | 1439 | panic("tmpgdt page relaim RW update failed.\n"); |
1440 | } | | 1440 | } |
1441 | } | | 1441 | } |
1442 | | | 1442 | |
1443 | uvm_page_physload(atop((vaddr_t)tmpgdt), atop((vaddr_t)tmpgdt + PAGE_SIZE), | | | |
1444 | atop((vaddr_t)tmpgdt), atop((vaddr_t)tmpgdt + PAGE_SIZE), | | | |
1445 | VM_FREELIST_DEFAULT); | | | |
1446 | | | | |
1447 | #endif /* !XEN */ | | 1443 | #endif /* !XEN */ |
1448 | | | 1444 | |
1449 | init386_msgbuf(); | | 1445 | init386_msgbuf(); |
1450 | | | 1446 | |
1451 | #ifndef XEN | | 1447 | #ifndef XEN |
1452 | /* | | 1448 | /* |
1453 | * XXX Remove this | | 1449 | * XXX Remove this |
1454 | * | | 1450 | * |
1455 | * Setup a temporary Page Table Entry to allow identity mappings of | | 1451 | * Setup a temporary Page Table Entry to allow identity mappings of |
1456 | * the real mode address. This is required by: | | 1452 | * the real mode address. This is required by: |
1457 | * - bioscall | | 1453 | * - bioscall |
1458 | * - MP bootstrap | | 1454 | * - MP bootstrap |
1459 | * - ACPI wakecode | | 1455 | * - ACPI wakecode |
1460 | */ | | 1456 | */ |
1461 | init386_pte0(); | | 1457 | init386_pte0(); |
1462 | | | 1458 | |
1463 | #if NBIOSCALL > 0 | | 1459 | #if NBIOSCALL > 0 |
1464 | KASSERT(biostramp_image_size <= PAGE_SIZE); | | 1460 | KASSERT(biostramp_image_size <= PAGE_SIZE); |
1465 | pmap_kenter_pa((vaddr_t)BIOSTRAMP_BASE, /* virtual */ | | 1461 | pmap_kenter_pa((vaddr_t)BIOSTRAMP_BASE, /* virtual */ |
1466 | (paddr_t)BIOSTRAMP_BASE, /* physical */ | | 1462 | (paddr_t)BIOSTRAMP_BASE, /* physical */ |
1467 | VM_PROT_ALL, 0); /* protection */ | | 1463 | VM_PROT_ALL, 0); /* protection */ |
1468 | pmap_update(pmap_kernel()); | | 1464 | pmap_update(pmap_kernel()); |
1469 | memcpy((void *)BIOSTRAMP_BASE, biostramp_image, biostramp_image_size); | | 1465 | memcpy((void *)BIOSTRAMP_BASE, biostramp_image, biostramp_image_size); |
1470 | | | 1466 | |
1471 | /* Needed early, for bioscall() and kvm86_call() */ | | 1467 | /* Needed early, for bioscall() and kvm86_call() */ |
1472 | cpu_info_primary.ci_pmap = pmap_kernel(); | | 1468 | cpu_info_primary.ci_pmap = pmap_kernel(); |
1473 | #endif | | 1469 | #endif |
1474 | #endif /* !XEN */ | | 1470 | #endif /* !XEN */ |
1475 | | | 1471 | |
1476 | pmap_kenter_pa(idt_vaddr, idt_paddr, VM_PROT_READ|VM_PROT_WRITE, 0); | | 1472 | pmap_kenter_pa(idt_vaddr, idt_paddr, VM_PROT_READ|VM_PROT_WRITE, 0); |
1477 | pmap_update(pmap_kernel()); | | 1473 | pmap_update(pmap_kernel()); |
1478 | memset((void *)idt_vaddr, 0, PAGE_SIZE); | | 1474 | memset((void *)idt_vaddr, 0, PAGE_SIZE); |
1479 | | | 1475 | |
1480 | | | 1476 | |
1481 | #ifndef XEN | | 1477 | #ifndef XEN |
1482 | idt_init(); | | 1478 | idt_init(); |
1483 | | | 1479 | |
1484 | idt = (struct gate_descriptor *)idt_vaddr; | | 1480 | idt = (struct gate_descriptor *)idt_vaddr; |
1485 | pmap_kenter_pa(pentium_idt_vaddr, idt_paddr, VM_PROT_READ, 0); | | 1481 | pmap_kenter_pa(pentium_idt_vaddr, idt_paddr, VM_PROT_READ, 0); |
1486 | pmap_update(pmap_kernel()); | | 1482 | pmap_update(pmap_kernel()); |
1487 | pentium_idt = (union descriptor *)pentium_idt_vaddr; | | 1483 | pentium_idt = (union descriptor *)pentium_idt_vaddr; |
1488 | | | 1484 | |
1489 | tgdt = gdt; | | 1485 | tgdt = gdt; |
1490 | gdt = (union descriptor *) | | 1486 | gdt = (union descriptor *) |
1491 | ((char *)idt + NIDT * sizeof (struct gate_descriptor)); | | 1487 | ((char *)idt + NIDT * sizeof (struct gate_descriptor)); |
1492 | ldt = gdt + NGDT; | | 1488 | ldt = gdt + NGDT; |
1493 | | | 1489 | |
1494 | memcpy(gdt, tgdt, NGDT*sizeof(*gdt)); | | 1490 | memcpy(gdt, tgdt, NGDT*sizeof(*gdt)); |
1495 | | | 1491 | |
1496 | setsegment(&gdt[GLDT_SEL].sd, ldt, NLDT * sizeof(ldt[0]) - 1, | | 1492 | setsegment(&gdt[GLDT_SEL].sd, ldt, NLDT * sizeof(ldt[0]) - 1, |
1497 | SDT_SYSLDT, SEL_KPL, 0, 0); | | 1493 | SDT_SYSLDT, SEL_KPL, 0, 0); |
1498 | #else | | 1494 | #else |
1499 | HYPERVISOR_set_callbacks( | | 1495 | HYPERVISOR_set_callbacks( |
1500 | GSEL(GCODE_SEL, SEL_KPL), (unsigned long)hypervisor_callback, | | 1496 | GSEL(GCODE_SEL, SEL_KPL), (unsigned long)hypervisor_callback, |
1501 | GSEL(GCODE_SEL, SEL_KPL), (unsigned long)failsafe_callback); | | 1497 | GSEL(GCODE_SEL, SEL_KPL), (unsigned long)failsafe_callback); |
1502 | | | 1498 | |
1503 | ldt = (union descriptor *)idt_vaddr; | | 1499 | ldt = (union descriptor *)idt_vaddr; |
1504 | #endif /* XEN */ | | 1500 | #endif /* XEN */ |
1505 | | | 1501 | |
1506 | /* make ldt gates and memory segments */ | | 1502 | /* make ldt gates and memory segments */ |
1507 | setgate(&ldt[LSYS5CALLS_SEL].gd, &IDTVEC(osyscall), 1, | | 1503 | setgate(&ldt[LSYS5CALLS_SEL].gd, &IDTVEC(osyscall), 1, |
1508 | SDT_SYS386CGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); | | 1504 | SDT_SYS386CGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); |
1509 | | | 1505 | |
1510 | ldt[LUCODE_SEL] = gdt[GUCODE_SEL]; | | 1506 | ldt[LUCODE_SEL] = gdt[GUCODE_SEL]; |
1511 | ldt[LUCODEBIG_SEL] = gdt[GUCODEBIG_SEL]; | | 1507 | ldt[LUCODEBIG_SEL] = gdt[GUCODEBIG_SEL]; |
1512 | ldt[LUDATA_SEL] = gdt[GUDATA_SEL]; | | 1508 | ldt[LUDATA_SEL] = gdt[GUDATA_SEL]; |
1513 | ldt[LSOL26CALLS_SEL] = ldt[LBSDICALLS_SEL] = ldt[LSYS5CALLS_SEL]; | | 1509 | ldt[LSOL26CALLS_SEL] = ldt[LBSDICALLS_SEL] = ldt[LSYS5CALLS_SEL]; |
1514 | | | 1510 | |
1515 | #ifndef XEN | | 1511 | #ifndef XEN |
1516 | /* exceptions */ | | 1512 | /* exceptions */ |
1517 | for (x = 0; x < 32; x++) { | | 1513 | for (x = 0; x < 32; x++) { |
1518 | idt_vec_reserve(x); | | 1514 | idt_vec_reserve(x); |
1519 | setgate(&idt[x], IDTVEC(exceptions)[x], 0, SDT_SYS386IGT, | | 1515 | setgate(&idt[x], IDTVEC(exceptions)[x], 0, SDT_SYS386IGT, |
1520 | (x == 3 || x == 4) ? SEL_UPL : SEL_KPL, | | 1516 | (x == 3 || x == 4) ? SEL_UPL : SEL_KPL, |
1521 | GSEL(GCODE_SEL, SEL_KPL)); | | 1517 | GSEL(GCODE_SEL, SEL_KPL)); |
1522 | } | | 1518 | } |
1523 | | | 1519 | |
1524 | /* new-style interrupt gate for syscalls */ | | 1520 | /* new-style interrupt gate for syscalls */ |
1525 | idt_vec_reserve(128); | | 1521 | idt_vec_reserve(128); |
1526 | setgate(&idt[128], &IDTVEC(syscall), 0, SDT_SYS386IGT, SEL_UPL, | | 1522 | setgate(&idt[128], &IDTVEC(syscall), 0, SDT_SYS386IGT, SEL_UPL, |
1527 | GSEL(GCODE_SEL, SEL_KPL)); | | 1523 | GSEL(GCODE_SEL, SEL_KPL)); |
1528 | idt_vec_reserve(0xd2); | | 1524 | idt_vec_reserve(0xd2); |
1529 | setgate(&idt[0xd2], &IDTVEC(svr4_fasttrap), 0, SDT_SYS386IGT, | | 1525 | setgate(&idt[0xd2], &IDTVEC(svr4_fasttrap), 0, SDT_SYS386IGT, |
1530 | SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); | | 1526 | SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); |
1531 | | | 1527 | |
1532 | setregion(®ion, gdt, NGDT * sizeof(gdt[0]) - 1); | | 1528 | setregion(®ion, gdt, NGDT * sizeof(gdt[0]) - 1); |
1533 | lgdt(®ion); | | 1529 | lgdt(®ion); |
1534 | | | 1530 | |
1535 | cpu_init_idt(); | | 1531 | cpu_init_idt(); |
1536 | #else /* !XEN */ | | 1532 | #else /* !XEN */ |
1537 | memset(xen_idt, 0, sizeof(trap_info_t) * MAX_XEN_IDT); | | 1533 | memset(xen_idt, 0, sizeof(trap_info_t) * MAX_XEN_IDT); |
1538 | xen_idt_idx = 0; | | 1534 | xen_idt_idx = 0; |
1539 | for (x = 0; x < 32; x++) { | | 1535 | for (x = 0; x < 32; x++) { |
1540 | KASSERT(xen_idt_idx < MAX_XEN_IDT); | | 1536 | KASSERT(xen_idt_idx < MAX_XEN_IDT); |
1541 | xen_idt[xen_idt_idx].vector = x; | | 1537 | xen_idt[xen_idt_idx].vector = x; |
1542 | | | 1538 | |
1543 | switch (x) { | | 1539 | switch (x) { |
1544 | case 2: /* NMI */ | | 1540 | case 2: /* NMI */ |
1545 | case 18: /* MCA */ | | 1541 | case 18: /* MCA */ |
1546 | TI_SET_IF(&(xen_idt[xen_idt_idx]), 2); | | 1542 | TI_SET_IF(&(xen_idt[xen_idt_idx]), 2); |
1547 | break; | | 1543 | break; |
1548 | case 3: | | 1544 | case 3: |
1549 | case 4: | | 1545 | case 4: |
1550 | xen_idt[xen_idt_idx].flags = SEL_UPL; | | 1546 | xen_idt[xen_idt_idx].flags = SEL_UPL; |
1551 | break; | | 1547 | break; |
1552 | default: | | 1548 | default: |
1553 | xen_idt[xen_idt_idx].flags = SEL_XEN; | | 1549 | xen_idt[xen_idt_idx].flags = SEL_XEN; |
1554 | break; | | 1550 | break; |
1555 | } | | 1551 | } |
1556 | | | 1552 | |
1557 | xen_idt[xen_idt_idx].cs = GSEL(GCODE_SEL, SEL_KPL); | | 1553 | xen_idt[xen_idt_idx].cs = GSEL(GCODE_SEL, SEL_KPL); |
1558 | xen_idt[xen_idt_idx].address = | | 1554 | xen_idt[xen_idt_idx].address = |
1559 | (uint32_t)IDTVEC(exceptions)[x]; | | 1555 | (uint32_t)IDTVEC(exceptions)[x]; |
1560 | xen_idt_idx++; | | 1556 | xen_idt_idx++; |
1561 | } | | 1557 | } |
1562 | KASSERT(xen_idt_idx < MAX_XEN_IDT); | | 1558 | KASSERT(xen_idt_idx < MAX_XEN_IDT); |
1563 | xen_idt[xen_idt_idx].vector = 128; | | 1559 | xen_idt[xen_idt_idx].vector = 128; |
1564 | xen_idt[xen_idt_idx].flags = SEL_UPL; | | 1560 | xen_idt[xen_idt_idx].flags = SEL_UPL; |
1565 | xen_idt[xen_idt_idx].cs = GSEL(GCODE_SEL, SEL_KPL); | | 1561 | xen_idt[xen_idt_idx].cs = GSEL(GCODE_SEL, SEL_KPL); |
1566 | xen_idt[xen_idt_idx].address = (uint32_t)&IDTVEC(syscall); | | 1562 | xen_idt[xen_idt_idx].address = (uint32_t)&IDTVEC(syscall); |
1567 | xen_idt_idx++; | | 1563 | xen_idt_idx++; |
1568 | KASSERT(xen_idt_idx < MAX_XEN_IDT); | | 1564 | KASSERT(xen_idt_idx < MAX_XEN_IDT); |
1569 | xen_idt[xen_idt_idx].vector = 0xd2; | | 1565 | xen_idt[xen_idt_idx].vector = 0xd2; |
1570 | xen_idt[xen_idt_idx].flags = SEL_UPL; | | 1566 | xen_idt[xen_idt_idx].flags = SEL_UPL; |
1571 | xen_idt[xen_idt_idx].cs = GSEL(GCODE_SEL, SEL_KPL); | | 1567 | xen_idt[xen_idt_idx].cs = GSEL(GCODE_SEL, SEL_KPL); |
1572 | xen_idt[xen_idt_idx].address = (uint32_t)&IDTVEC(svr4_fasttrap); | | 1568 | xen_idt[xen_idt_idx].address = (uint32_t)&IDTVEC(svr4_fasttrap); |
1573 | xen_idt_idx++; | | 1569 | xen_idt_idx++; |
1574 | lldt(GSEL(GLDT_SEL, SEL_KPL)); | | 1570 | lldt(GSEL(GLDT_SEL, SEL_KPL)); |
1575 | cpu_init_idt(); | | 1571 | cpu_init_idt(); |
1576 | #endif /* XEN */ | | 1572 | #endif /* XEN */ |
1577 | | | 1573 | |
1578 | init386_ksyms(); | | 1574 | init386_ksyms(); |
1579 | | | 1575 | |
1580 | #if NMCA > 0 | | 1576 | #if NMCA > 0 |
1581 | /* check for MCA bus, needed to be done before ISA stuff - if | | 1577 | /* check for MCA bus, needed to be done before ISA stuff - if |
1582 | * MCA is detected, ISA needs to use level triggered interrupts | | 1578 | * MCA is detected, ISA needs to use level triggered interrupts |
1583 | * by default */ | | 1579 | * by default */ |
1584 | mca_busprobe(); | | 1580 | mca_busprobe(); |
1585 | #endif | | 1581 | #endif |
1586 | | | 1582 | |
1587 | #ifdef XEN | | 1583 | #ifdef XEN |
1588 | XENPRINTF(("events_default_setup\n")); | | 1584 | XENPRINTF(("events_default_setup\n")); |
1589 | events_default_setup(); | | 1585 | events_default_setup(); |
1590 | #else | | 1586 | #else |
1591 | intr_default_setup(); | | 1587 | intr_default_setup(); |
1592 | #endif | | 1588 | #endif |
1593 | | | 1589 | |
1594 | splraise(IPL_HIGH); | | 1590 | splraise(IPL_HIGH); |
1595 | x86_enable_intr(); | | 1591 | x86_enable_intr(); |
1596 | | | 1592 | |
1597 | #ifdef DDB | | 1593 | #ifdef DDB |
1598 | if (boothowto & RB_KDB) | | 1594 | if (boothowto & RB_KDB) |
1599 | Debugger(); | | 1595 | Debugger(); |
1600 | #endif | | 1596 | #endif |
1601 | #ifdef IPKDB | | 1597 | #ifdef IPKDB |
1602 | ipkdb_init(); | | 1598 | ipkdb_init(); |
1603 | if (boothowto & RB_KDB) | | 1599 | if (boothowto & RB_KDB) |
1604 | ipkdb_connect(0); | | 1600 | ipkdb_connect(0); |
1605 | #endif | | 1601 | #endif |
1606 | #ifdef KGDB | | 1602 | #ifdef KGDB |
1607 | kgdb_port_init(); | | 1603 | kgdb_port_init(); |
1608 | if (boothowto & RB_KDB) { | | 1604 | if (boothowto & RB_KDB) { |
1609 | kgdb_debug_init = 1; | | 1605 | kgdb_debug_init = 1; |
1610 | kgdb_connect(1); | | 1606 | kgdb_connect(1); |
1611 | } | | 1607 | } |
1612 | #endif | | 1608 | #endif |
1613 | | | 1609 | |
1614 | if (physmem < btoc(2 * 1024 * 1024)) { | | 1610 | if (physmem < btoc(2 * 1024 * 1024)) { |
1615 | printf("warning: too little memory available; " | | 1611 | printf("warning: too little memory available; " |
1616 | "have %lu bytes, want %lu bytes\n" | | 1612 | "have %lu bytes, want %lu bytes\n" |
1617 | "running in degraded mode\n" | | 1613 | "running in degraded mode\n" |
1618 | "press a key to confirm\n\n", | | 1614 | "press a key to confirm\n\n", |
1619 | (unsigned long)ptoa(physmem), 2*1024*1024UL); | | 1615 | (unsigned long)ptoa(physmem), 2*1024*1024UL); |
1620 | cngetc(); | | 1616 | cngetc(); |
1621 | } | | 1617 | } |
1622 | | | 1618 | |
1623 | rw_init(&svr4_fasttrap_lock); | | 1619 | rw_init(&svr4_fasttrap_lock); |
1624 | } | | 1620 | } |
1625 | | | 1621 | |
1626 | #include <dev/ic/mc146818reg.h> /* for NVRAM POST */ | | 1622 | #include <dev/ic/mc146818reg.h> /* for NVRAM POST */ |
1627 | #include <i386/isa/nvram.h> /* for NVRAM POST */ | | 1623 | #include <i386/isa/nvram.h> /* for NVRAM POST */ |
1628 | | | 1624 | |
1629 | void | | 1625 | void |
1630 | cpu_reset(void) | | 1626 | cpu_reset(void) |
1631 | { | | 1627 | { |
1632 | #ifdef XEN | | 1628 | #ifdef XEN |
1633 | HYPERVISOR_reboot(); | | 1629 | HYPERVISOR_reboot(); |
1634 | for (;;); | | 1630 | for (;;); |
1635 | #else /* XEN */ | | 1631 | #else /* XEN */ |
1636 | struct region_descriptor region; | | 1632 | struct region_descriptor region; |
1637 | | | 1633 | |
1638 | x86_disable_intr(); | | 1634 | x86_disable_intr(); |
1639 | | | 1635 | |
1640 | /* | | 1636 | /* |
1641 | * Ensure the NVRAM reset byte contains something vaguely sane. | | 1637 | * Ensure the NVRAM reset byte contains something vaguely sane. |
1642 | */ | | 1638 | */ |
1643 | | | 1639 | |
1644 | outb(IO_RTC, NVRAM_RESET); | | 1640 | outb(IO_RTC, NVRAM_RESET); |
1645 | outb(IO_RTC+1, NVRAM_RESET_RST); | | 1641 | outb(IO_RTC+1, NVRAM_RESET_RST); |
1646 | | | 1642 | |
1647 | /* | | 1643 | /* |
1648 | * Reset AMD Geode SC1100. | | 1644 | * Reset AMD Geode SC1100. |
1649 | * | | 1645 | * |
1650 | * 1) Write PCI Configuration Address Register (0xcf8) to | | 1646 | * 1) Write PCI Configuration Address Register (0xcf8) to |
1651 | * select Function 0, Register 0x44: Bridge Configuration, | | 1647 | * select Function 0, Register 0x44: Bridge Configuration, |
1652 | * GPIO and LPC Configuration Register Space, Reset | | 1648 | * GPIO and LPC Configuration Register Space, Reset |
1653 | * Control Register. | | 1649 | * Control Register. |
1654 | * | | 1650 | * |
1655 | * 2) Write 0xf to PCI Configuration Data Register (0xcfc) | | 1651 | * 2) Write 0xf to PCI Configuration Data Register (0xcfc) |
1656 | * to reset IDE controller, IDE bus, and PCI bus, and | | 1652 | * to reset IDE controller, IDE bus, and PCI bus, and |
1657 | * to trigger a system-wide reset. | | 1653 | * to trigger a system-wide reset. |
1658 | * | | 1654 | * |
1659 | * See AMD Geode SC1100 Processor Data Book, Revision 2.0, | | 1655 | * See AMD Geode SC1100 Processor Data Book, Revision 2.0, |
1660 | * sections 6.3.1, 6.3.2, and 6.4.1. | | 1656 | * sections 6.3.1, 6.3.2, and 6.4.1. |
1661 | */ | | 1657 | */ |
1662 | if (cpu_info_primary.ci_signature == 0x540) { | | 1658 | if (cpu_info_primary.ci_signature == 0x540) { |
1663 | outl(0xcf8, 0x80009044); | | 1659 | outl(0xcf8, 0x80009044); |
1664 | outl(0xcfc, 0xf); | | 1660 | outl(0xcfc, 0xf); |
1665 | } | | 1661 | } |
1666 | | | 1662 | |
1667 | x86_reset(); | | 1663 | x86_reset(); |
1668 | | | 1664 | |
1669 | /* | | 1665 | /* |
1670 | * Try to cause a triple fault and watchdog reset by making the IDT | | 1666 | * Try to cause a triple fault and watchdog reset by making the IDT |
1671 | * invalid and causing a fault. | | 1667 | * invalid and causing a fault. |
1672 | */ | | 1668 | */ |
1673 | memset((void *)idt, 0, NIDT * sizeof(idt[0])); | | 1669 | memset((void *)idt, 0, NIDT * sizeof(idt[0])); |
1674 | setregion(®ion, idt, NIDT * sizeof(idt[0]) - 1); | | 1670 | setregion(®ion, idt, NIDT * sizeof(idt[0]) - 1); |
1675 | lidt(®ion); | | 1671 | lidt(®ion); |
1676 | breakpoint(); | | 1672 | breakpoint(); |
1677 | | | 1673 | |
1678 | #if 0 | | 1674 | #if 0 |
1679 | /* | | 1675 | /* |
1680 | * Try to cause a triple fault and watchdog reset by unmapping the | | 1676 | * Try to cause a triple fault and watchdog reset by unmapping the |
1681 | * entire address space and doing a TLB flush. | | 1677 | * entire address space and doing a TLB flush. |
1682 | */ | | 1678 | */ |
1683 | memset((void *)PTD, 0, PAGE_SIZE); | | 1679 | memset((void *)PTD, 0, PAGE_SIZE); |
1684 | tlbflush(); | | 1680 | tlbflush(); |
1685 | #endif | | 1681 | #endif |
1686 | | | 1682 | |
1687 | for (;;); | | 1683 | for (;;); |
1688 | #endif /* XEN */ | | 1684 | #endif /* XEN */ |
1689 | } | | 1685 | } |
1690 | | | 1686 | |
1691 | void | | 1687 | void |
1692 | cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags) | | 1688 | cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags) |
1693 | { | | 1689 | { |
1694 | const struct trapframe *tf = l->l_md.md_regs; | | 1690 | const struct trapframe *tf = l->l_md.md_regs; |
1695 | __greg_t *gr = mcp->__gregs; | | 1691 | __greg_t *gr = mcp->__gregs; |
1696 | __greg_t ras_eip; | | 1692 | __greg_t ras_eip; |
1697 | | | 1693 | |
1698 | /* Save register context. */ | | 1694 | /* Save register context. */ |
1699 | #ifdef VM86 | | 1695 | #ifdef VM86 |
1700 | if (tf->tf_eflags & PSL_VM) { | | 1696 | if (tf->tf_eflags & PSL_VM) { |
1701 | gr[_REG_GS] = tf->tf_vm86_gs; | | 1697 | gr[_REG_GS] = tf->tf_vm86_gs; |
1702 | gr[_REG_FS] = tf->tf_vm86_fs; | | 1698 | gr[_REG_FS] = tf->tf_vm86_fs; |
1703 | gr[_REG_ES] = tf->tf_vm86_es; | | 1699 | gr[_REG_ES] = tf->tf_vm86_es; |
1704 | gr[_REG_DS] = tf->tf_vm86_ds; | | 1700 | gr[_REG_DS] = tf->tf_vm86_ds; |
1705 | gr[_REG_EFL] = get_vflags(l); | | 1701 | gr[_REG_EFL] = get_vflags(l); |
1706 | } else | | 1702 | } else |
1707 | #endif | | 1703 | #endif |
1708 | { | | 1704 | { |
1709 | gr[_REG_GS] = tf->tf_gs; | | 1705 | gr[_REG_GS] = tf->tf_gs; |
1710 | gr[_REG_FS] = tf->tf_fs; | | 1706 | gr[_REG_FS] = tf->tf_fs; |
1711 | gr[_REG_ES] = tf->tf_es; | | 1707 | gr[_REG_ES] = tf->tf_es; |
1712 | gr[_REG_DS] = tf->tf_ds; | | 1708 | gr[_REG_DS] = tf->tf_ds; |
1713 | gr[_REG_EFL] = tf->tf_eflags; | | 1709 | gr[_REG_EFL] = tf->tf_eflags; |
1714 | } | | 1710 | } |
1715 | gr[_REG_EDI] = tf->tf_edi; | | 1711 | gr[_REG_EDI] = tf->tf_edi; |
1716 | gr[_REG_ESI] = tf->tf_esi; | | 1712 | gr[_REG_ESI] = tf->tf_esi; |
1717 | gr[_REG_EBP] = tf->tf_ebp; | | 1713 | gr[_REG_EBP] = tf->tf_ebp; |
1718 | gr[_REG_EBX] = tf->tf_ebx; | | 1714 | gr[_REG_EBX] = tf->tf_ebx; |
1719 | gr[_REG_EDX] = tf->tf_edx; | | 1715 | gr[_REG_EDX] = tf->tf_edx; |
1720 | gr[_REG_ECX] = tf->tf_ecx; | | 1716 | gr[_REG_ECX] = tf->tf_ecx; |
1721 | gr[_REG_EAX] = tf->tf_eax; | | 1717 | gr[_REG_EAX] = tf->tf_eax; |
1722 | gr[_REG_EIP] = tf->tf_eip; | | 1718 | gr[_REG_EIP] = tf->tf_eip; |
1723 | gr[_REG_CS] = tf->tf_cs; | | 1719 | gr[_REG_CS] = tf->tf_cs; |
1724 | gr[_REG_ESP] = tf->tf_esp; | | 1720 | gr[_REG_ESP] = tf->tf_esp; |
1725 | gr[_REG_UESP] = tf->tf_esp; | | 1721 | gr[_REG_UESP] = tf->tf_esp; |
1726 | gr[_REG_SS] = tf->tf_ss; | | 1722 | gr[_REG_SS] = tf->tf_ss; |
1727 | gr[_REG_TRAPNO] = tf->tf_trapno; | | 1723 | gr[_REG_TRAPNO] = tf->tf_trapno; |
1728 | gr[_REG_ERR] = tf->tf_err; | | 1724 | gr[_REG_ERR] = tf->tf_err; |
1729 | | | 1725 | |
1730 | if ((ras_eip = (__greg_t)ras_lookup(l->l_proc, | | 1726 | if ((ras_eip = (__greg_t)ras_lookup(l->l_proc, |
1731 | (void *) gr[_REG_EIP])) != -1) | | 1727 | (void *) gr[_REG_EIP])) != -1) |
1732 | gr[_REG_EIP] = ras_eip; | | 1728 | gr[_REG_EIP] = ras_eip; |
1733 | | | 1729 | |
1734 | *flags |= _UC_CPU; | | 1730 | *flags |= _UC_CPU; |
1735 | | | 1731 | |
1736 | mcp->_mc_tlsbase = (uintptr_t)l->l_private; | | 1732 | mcp->_mc_tlsbase = (uintptr_t)l->l_private; |
1737 | *flags |= _UC_TLSBASE; | | 1733 | *flags |= _UC_TLSBASE; |
1738 | | | 1734 | |
1739 | /* Save floating point register context, if any. */ | | 1735 | /* Save floating point register context, if any. */ |
1740 | if ((l->l_md.md_flags & MDL_USEDFPU) != 0) { | | 1736 | if ((l->l_md.md_flags & MDL_USEDFPU) != 0) { |
1741 | struct pcb *pcb = lwp_getpcb(l); | | 1737 | struct pcb *pcb = lwp_getpcb(l); |
1742 | #if NNPX > 0 | | 1738 | #if NNPX > 0 |
1743 | | | 1739 | |
1744 | /* | | 1740 | /* |
1745 | * If this process is the current FP owner, dump its | | 1741 | * If this process is the current FP owner, dump its |
1746 | * context to the PCB first. | | 1742 | * context to the PCB first. |
1747 | */ | | 1743 | */ |
1748 | if (pcb->pcb_fpcpu) { | | 1744 | if (pcb->pcb_fpcpu) { |
1749 | npxsave_lwp(l, true); | | 1745 | npxsave_lwp(l, true); |
1750 | } | | 1746 | } |
1751 | #endif | | 1747 | #endif |
1752 | if (i386_use_fxsave) { | | 1748 | if (i386_use_fxsave) { |
1753 | memcpy(&mcp->__fpregs.__fp_reg_set.__fp_xmm_state.__fp_xmm, | | 1749 | memcpy(&mcp->__fpregs.__fp_reg_set.__fp_xmm_state.__fp_xmm, |
1754 | &pcb->pcb_savefpu.sv_xmm, | | 1750 | &pcb->pcb_savefpu.sv_xmm, |
1755 | sizeof (mcp->__fpregs.__fp_reg_set.__fp_xmm_state.__fp_xmm)); | | 1751 | sizeof (mcp->__fpregs.__fp_reg_set.__fp_xmm_state.__fp_xmm)); |
1756 | *flags |= _UC_FXSAVE; | | 1752 | *flags |= _UC_FXSAVE; |
1757 | } else { | | 1753 | } else { |
1758 | memcpy(&mcp->__fpregs.__fp_reg_set.__fpchip_state.__fp_state, | | 1754 | memcpy(&mcp->__fpregs.__fp_reg_set.__fpchip_state.__fp_state, |
1759 | &pcb->pcb_savefpu.sv_87, | | 1755 | &pcb->pcb_savefpu.sv_87, |
1760 | sizeof (mcp->__fpregs.__fp_reg_set.__fpchip_state.__fp_state)); | | 1756 | sizeof (mcp->__fpregs.__fp_reg_set.__fpchip_state.__fp_state)); |
1761 | } | | 1757 | } |
1762 | #if 0 | | 1758 | #if 0 |
1763 | /* Apparently nothing ever touches this. */ | | 1759 | /* Apparently nothing ever touches this. */ |
1764 | ucp->mcp.mc_fp.fp_emcsts = pcb->pcb_saveemc; | | 1760 | ucp->mcp.mc_fp.fp_emcsts = pcb->pcb_saveemc; |
1765 | #endif | | 1761 | #endif |
1766 | *flags |= _UC_FPU; | | 1762 | *flags |= _UC_FPU; |
1767 | } | | 1763 | } |
1768 | } | | 1764 | } |
1769 | | | 1765 | |
1770 | int | | 1766 | int |
1771 | cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) | | 1767 | cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) |
1772 | { | | 1768 | { |
1773 | struct trapframe *tf = l->l_md.md_regs; | | 1769 | struct trapframe *tf = l->l_md.md_regs; |
1774 | const __greg_t *gr = mcp->__gregs; | | 1770 | const __greg_t *gr = mcp->__gregs; |
1775 | struct pcb *pcb = lwp_getpcb(l); | | 1771 | struct pcb *pcb = lwp_getpcb(l); |
1776 | struct proc *p = l->l_proc; | | 1772 | struct proc *p = l->l_proc; |
1777 | | | 1773 | |
1778 | /* Restore register context, if any. */ | | 1774 | /* Restore register context, if any. */ |
1779 | if ((flags & _UC_CPU) != 0) { | | 1775 | if ((flags & _UC_CPU) != 0) { |
1780 | #ifdef VM86 | | 1776 | #ifdef VM86 |
1781 | if (gr[_REG_EFL] & PSL_VM) { | | 1777 | if (gr[_REG_EFL] & PSL_VM) { |
1782 | tf->tf_vm86_gs = gr[_REG_GS]; | | 1778 | tf->tf_vm86_gs = gr[_REG_GS]; |
1783 | tf->tf_vm86_fs = gr[_REG_FS]; | | 1779 | tf->tf_vm86_fs = gr[_REG_FS]; |
1784 | tf->tf_vm86_es = gr[_REG_ES]; | | 1780 | tf->tf_vm86_es = gr[_REG_ES]; |
1785 | tf->tf_vm86_ds = gr[_REG_DS]; | | 1781 | tf->tf_vm86_ds = gr[_REG_DS]; |
1786 | set_vflags(l, gr[_REG_EFL]); | | 1782 | set_vflags(l, gr[_REG_EFL]); |
1787 | if (flags & _UC_VM) { | | 1783 | if (flags & _UC_VM) { |
1788 | void syscall_vm86(struct trapframe *); | | 1784 | void syscall_vm86(struct trapframe *); |
1789 | l->l_proc->p_md.md_syscall = syscall_vm86; | | 1785 | l->l_proc->p_md.md_syscall = syscall_vm86; |
1790 | } | | 1786 | } |
1791 | } else | | 1787 | } else |
1792 | #endif | | 1788 | #endif |
1793 | { | | 1789 | { |
1794 | /* | | 1790 | /* |
1795 | * Check for security violations. If we're returning | | 1791 | * Check for security violations. If we're returning |
1796 | * to protected mode, the CPU will validate the segment | | 1792 | * to protected mode, the CPU will validate the segment |
1797 | * registers automatically and generate a trap on | | 1793 | * registers automatically and generate a trap on |
1798 | * violations. We handle the trap, rather than doing | | 1794 | * violations. We handle the trap, rather than doing |
1799 | * all of the checking here. | | 1795 | * all of the checking here. |
1800 | */ | | 1796 | */ |
1801 | if (((gr[_REG_EFL] ^ tf->tf_eflags) & PSL_USERSTATIC) || | | 1797 | if (((gr[_REG_EFL] ^ tf->tf_eflags) & PSL_USERSTATIC) || |
1802 | !USERMODE(gr[_REG_CS], gr[_REG_EFL])) { | | 1798 | !USERMODE(gr[_REG_CS], gr[_REG_EFL])) { |
1803 | printf("cpu_setmcontext error: uc EFL: 0x%08x" | | 1799 | printf("cpu_setmcontext error: uc EFL: 0x%08x" |
1804 | " tf EFL: 0x%08x uc CS: 0x%x\n", | | 1800 | " tf EFL: 0x%08x uc CS: 0x%x\n", |
1805 | gr[_REG_EFL], tf->tf_eflags, gr[_REG_CS]); | | 1801 | gr[_REG_EFL], tf->tf_eflags, gr[_REG_CS]); |
1806 | return (EINVAL); | | 1802 | return (EINVAL); |
1807 | } | | 1803 | } |
1808 | tf->tf_gs = gr[_REG_GS]; | | 1804 | tf->tf_gs = gr[_REG_GS]; |
1809 | tf->tf_fs = gr[_REG_FS]; | | 1805 | tf->tf_fs = gr[_REG_FS]; |
1810 | tf->tf_es = gr[_REG_ES]; | | 1806 | tf->tf_es = gr[_REG_ES]; |
1811 | tf->tf_ds = gr[_REG_DS]; | | 1807 | tf->tf_ds = gr[_REG_DS]; |
1812 | /* Only change the user-alterable part of eflags */ | | 1808 | /* Only change the user-alterable part of eflags */ |
1813 | tf->tf_eflags &= ~PSL_USER; | | 1809 | tf->tf_eflags &= ~PSL_USER; |
1814 | tf->tf_eflags |= (gr[_REG_EFL] & PSL_USER); | | 1810 | tf->tf_eflags |= (gr[_REG_EFL] & PSL_USER); |
1815 | } | | 1811 | } |
1816 | tf->tf_edi = gr[_REG_EDI]; | | 1812 | tf->tf_edi = gr[_REG_EDI]; |
1817 | tf->tf_esi = gr[_REG_ESI]; | | 1813 | tf->tf_esi = gr[_REG_ESI]; |
1818 | tf->tf_ebp = gr[_REG_EBP]; | | 1814 | tf->tf_ebp = gr[_REG_EBP]; |
1819 | tf->tf_ebx = gr[_REG_EBX]; | | 1815 | tf->tf_ebx = gr[_REG_EBX]; |
1820 | tf->tf_edx = gr[_REG_EDX]; | | 1816 | tf->tf_edx = gr[_REG_EDX]; |
1821 | tf->tf_ecx = gr[_REG_ECX]; | | 1817 | tf->tf_ecx = gr[_REG_ECX]; |
1822 | tf->tf_eax = gr[_REG_EAX]; | | 1818 | tf->tf_eax = gr[_REG_EAX]; |
1823 | tf->tf_eip = gr[_REG_EIP]; | | 1819 | tf->tf_eip = gr[_REG_EIP]; |
1824 | tf->tf_cs = gr[_REG_CS]; | | 1820 | tf->tf_cs = gr[_REG_CS]; |
1825 | tf->tf_esp = gr[_REG_UESP]; | | 1821 | tf->tf_esp = gr[_REG_UESP]; |
1826 | tf->tf_ss = gr[_REG_SS]; | | 1822 | tf->tf_ss = gr[_REG_SS]; |
1827 | } | | 1823 | } |
1828 | | | 1824 | |
1829 | if ((flags & _UC_TLSBASE) != 0) | | 1825 | if ((flags & _UC_TLSBASE) != 0) |
1830 | lwp_setprivate(l, (void *)(uintptr_t)mcp->_mc_tlsbase); | | 1826 | lwp_setprivate(l, (void *)(uintptr_t)mcp->_mc_tlsbase); |
1831 | | | 1827 | |
1832 | #if NNPX > 0 | | 1828 | #if NNPX > 0 |
1833 | /* | | 1829 | /* |
1834 | * If we were using the FPU, forget that we were. | | 1830 | * If we were using the FPU, forget that we were. |
1835 | */ | | 1831 | */ |
1836 | if (pcb->pcb_fpcpu != NULL) { | | 1832 | if (pcb->pcb_fpcpu != NULL) { |
1837 | npxsave_lwp(l, false); | | 1833 | npxsave_lwp(l, false); |
1838 | } | | 1834 | } |
1839 | #endif | | 1835 | #endif |
1840 | | | 1836 | |
1841 | /* Restore floating point register context, if any. */ | | 1837 | /* Restore floating point register context, if any. */ |
1842 | if ((flags & _UC_FPU) != 0) { | | 1838 | if ((flags & _UC_FPU) != 0) { |
1843 | if (flags & _UC_FXSAVE) { | | 1839 | if (flags & _UC_FXSAVE) { |
1844 | if (i386_use_fxsave) { | | 1840 | if (i386_use_fxsave) { |
1845 | memcpy( | | 1841 | memcpy( |
1846 | &pcb->pcb_savefpu.sv_xmm, | | 1842 | &pcb->pcb_savefpu.sv_xmm, |
1847 | &mcp->__fpregs.__fp_reg_set.__fp_xmm_state.__fp_xmm, | | 1843 | &mcp->__fpregs.__fp_reg_set.__fp_xmm_state.__fp_xmm, |
1848 | sizeof (pcb->pcb_savefpu.sv_xmm)); | | 1844 | sizeof (pcb->pcb_savefpu.sv_xmm)); |
1849 | } else { | | 1845 | } else { |
1850 | /* This is a weird corner case */ | | 1846 | /* This is a weird corner case */ |
1851 | process_xmm_to_s87((struct savexmm *) | | 1847 | process_xmm_to_s87((struct savexmm *) |
1852 | &mcp->__fpregs.__fp_reg_set.__fp_xmm_state.__fp_xmm, | | 1848 | &mcp->__fpregs.__fp_reg_set.__fp_xmm_state.__fp_xmm, |
1853 | &pcb->pcb_savefpu.sv_87); | | 1849 | &pcb->pcb_savefpu.sv_87); |
1854 | } | | 1850 | } |
1855 | } else { | | 1851 | } else { |
1856 | if (i386_use_fxsave) { | | 1852 | if (i386_use_fxsave) { |
1857 | process_s87_to_xmm((struct save87 *) | | 1853 | process_s87_to_xmm((struct save87 *) |
1858 | &mcp->__fpregs.__fp_reg_set.__fpchip_state.__fp_state, | | 1854 | &mcp->__fpregs.__fp_reg_set.__fpchip_state.__fp_state, |
1859 | &pcb->pcb_savefpu.sv_xmm); | | 1855 | &pcb->pcb_savefpu.sv_xmm); |
1860 | } else { | | 1856 | } else { |
1861 | memcpy(&pcb->pcb_savefpu.sv_87, | | 1857 | memcpy(&pcb->pcb_savefpu.sv_87, |
1862 | &mcp->__fpregs.__fp_reg_set.__fpchip_state.__fp_state, | | 1858 | &mcp->__fpregs.__fp_reg_set.__fpchip_state.__fp_state, |
1863 | sizeof (pcb->pcb_savefpu.sv_87)); | | 1859 | sizeof (pcb->pcb_savefpu.sv_87)); |
1864 | } | | 1860 | } |
1865 | } | | 1861 | } |
1866 | l->l_md.md_flags |= MDL_USEDFPU; | | 1862 | l->l_md.md_flags |= MDL_USEDFPU; |
1867 | } | | 1863 | } |
1868 | mutex_enter(p->p_lock); | | 1864 | mutex_enter(p->p_lock); |
1869 | if (flags & _UC_SETSTACK) | | 1865 | if (flags & _UC_SETSTACK) |
1870 | l->l_sigstk.ss_flags |= SS_ONSTACK; | | 1866 | l->l_sigstk.ss_flags |= SS_ONSTACK; |
1871 | if (flags & _UC_CLRSTACK) | | 1867 | if (flags & _UC_CLRSTACK) |
1872 | l->l_sigstk.ss_flags &= ~SS_ONSTACK; | | 1868 | l->l_sigstk.ss_flags &= ~SS_ONSTACK; |
1873 | mutex_exit(p->p_lock); | | 1869 | mutex_exit(p->p_lock); |
1874 | return (0); | | 1870 | return (0); |
1875 | } | | 1871 | } |
1876 | | | 1872 | |
1877 | void | | 1873 | void |
1878 | cpu_initclocks(void) | | 1874 | cpu_initclocks(void) |
1879 | { | | 1875 | { |
1880 | | | 1876 | |
1881 | (*initclock_func)(); | | 1877 | (*initclock_func)(); |
1882 | } | | 1878 | } |
1883 | | | 1879 | |
1884 | #define DEV_IO 14 /* iopl for compat_10 */ | | 1880 | #define DEV_IO 14 /* iopl for compat_10 */ |
1885 | | | 1881 | |
1886 | int | | 1882 | int |
1887 | mm_md_open(dev_t dev, int flag, int mode, struct lwp *l) | | 1883 | mm_md_open(dev_t dev, int flag, int mode, struct lwp *l) |
1888 | { | | 1884 | { |
1889 | | | 1885 | |
1890 | switch (minor(dev)) { | | 1886 | switch (minor(dev)) { |
1891 | case DEV_IO: | | 1887 | case DEV_IO: |
1892 | /* | | 1888 | /* |
1893 | * This is done by i386_iopl(3) now. | | 1889 | * This is done by i386_iopl(3) now. |
1894 | * | | 1890 | * |
1895 | * #if defined(COMPAT_10) || defined(COMPAT_FREEBSD) | | 1891 | * #if defined(COMPAT_10) || defined(COMPAT_FREEBSD) |
1896 | */ | | 1892 | */ |
1897 | if (flag & FWRITE) { | | 1893 | if (flag & FWRITE) { |
1898 | struct trapframe *fp; | | 1894 | struct trapframe *fp; |
1899 | int error; | | 1895 | int error; |
1900 | | | 1896 | |
1901 | error = kauth_authorize_machdep(l->l_cred, | | 1897 | error = kauth_authorize_machdep(l->l_cred, |
1902 | KAUTH_MACHDEP_IOPL, NULL, NULL, NULL, NULL); | | 1898 | KAUTH_MACHDEP_IOPL, NULL, NULL, NULL, NULL); |
1903 | if (error) | | 1899 | if (error) |
1904 | return (error); | | 1900 | return (error); |
1905 | fp = curlwp->l_md.md_regs; | | 1901 | fp = curlwp->l_md.md_regs; |
1906 | fp->tf_eflags |= PSL_IOPL; | | 1902 | fp->tf_eflags |= PSL_IOPL; |
1907 | } | | 1903 | } |
1908 | break; | | 1904 | break; |
1909 | default: | | 1905 | default: |
1910 | break; | | 1906 | break; |
1911 | } | | 1907 | } |
1912 | return 0; | | 1908 | return 0; |
1913 | } | | 1909 | } |
1914 | | | 1910 | |
1915 | #ifdef PAE | | 1911 | #ifdef PAE |
1916 | void | | 1912 | void |
1917 | cpu_alloc_l3_page(struct cpu_info *ci) | | 1913 | cpu_alloc_l3_page(struct cpu_info *ci) |
1918 | { | | 1914 | { |
1919 | int ret; | | 1915 | int ret; |
1920 | struct pglist pg; | | 1916 | struct pglist pg; |
1921 | struct vm_page *vmap; | | 1917 | struct vm_page *vmap; |
1922 | | | 1918 | |
1923 | KASSERT(ci != NULL); | | 1919 | KASSERT(ci != NULL); |
1924 | /* | | 1920 | /* |
1925 | * Allocate a page for the per-CPU L3 PD. cr3 being 32 bits, PA musts | | 1921 | * Allocate a page for the per-CPU L3 PD. cr3 being 32 bits, PA musts |
1926 | * resides below the 4GB boundary. | | 1922 | * resides below the 4GB boundary. |
1927 | */ | | 1923 | */ |
1928 | ret = uvm_pglistalloc(PAGE_SIZE, 0, 0x100000000ULL, 32, 0, &pg, 1, 0); | | 1924 | ret = uvm_pglistalloc(PAGE_SIZE, 0, 0x100000000ULL, 32, 0, &pg, 1, 0); |
1929 | vmap = TAILQ_FIRST(&pg); | | 1925 | vmap = TAILQ_FIRST(&pg); |
1930 | | | 1926 | |
1931 | if (ret != 0 || vmap == NULL) | | 1927 | if (ret != 0 || vmap == NULL) |
1932 | panic("%s: failed to allocate L3 pglist for CPU %d (ret %d)\n", | | 1928 | panic("%s: failed to allocate L3 pglist for CPU %d (ret %d)\n", |
1933 | __func__, cpu_index(ci), ret); | | 1929 | __func__, cpu_index(ci), ret); |
1934 | | | 1930 | |
1935 | ci->ci_pae_l3_pdirpa = vmap->phys_addr; | | 1931 | ci->ci_pae_l3_pdirpa = vmap->phys_addr; |
1936 | | | 1932 | |
1937 | ci->ci_pae_l3_pdir = (paddr_t *)uvm_km_alloc(kernel_map, PAGE_SIZE, 0, | | 1933 | ci->ci_pae_l3_pdir = (paddr_t *)uvm_km_alloc(kernel_map, PAGE_SIZE, 0, |
1938 | UVM_KMF_VAONLY | UVM_KMF_NOWAIT); | | 1934 | UVM_KMF_VAONLY | UVM_KMF_NOWAIT); |
1939 | if (ci->ci_pae_l3_pdir == NULL) | | 1935 | if (ci->ci_pae_l3_pdir == NULL) |
1940 | panic("%s: failed to allocate L3 PD for CPU %d\n", | | 1936 | panic("%s: failed to allocate L3 PD for CPU %d\n", |
1941 | __func__, cpu_index(ci)); | | 1937 | __func__, cpu_index(ci)); |
1942 | | | 1938 | |
1943 | pmap_kenter_pa((vaddr_t)ci->ci_pae_l3_pdir, ci->ci_pae_l3_pdirpa, | | 1939 | pmap_kenter_pa((vaddr_t)ci->ci_pae_l3_pdir, ci->ci_pae_l3_pdirpa, |
1944 | VM_PROT_READ | VM_PROT_WRITE, 0); | | 1940 | VM_PROT_READ | VM_PROT_WRITE, 0); |
1945 | | | 1941 | |
1946 | pmap_update(pmap_kernel()); | | 1942 | pmap_update(pmap_kernel()); |
1947 | } | | 1943 | } |
1948 | #endif /* PAE */ | | 1944 | #endif /* PAE */ |