| @@ -1,405 +1,398 @@ | | | @@ -1,405 +1,398 @@ |
1 | /* $NetBSD: db_interface.c,v 1.72 2017/05/23 08:54:38 nonaka Exp $ */ | | 1 | /* $NetBSD: db_interface.c,v 1.73 2017/08/15 06:57:53 maxv Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Mach Operating System | | 4 | * Mach Operating System |
5 | * Copyright (c) 1991,1990 Carnegie Mellon University | | 5 | * Copyright (c) 1991,1990 Carnegie Mellon University |
6 | * All Rights Reserved. | | 6 | * All Rights Reserved. |
7 | * | | 7 | * |
8 | * Permission to use, copy, modify and distribute this software and its | | 8 | * Permission to use, copy, modify and distribute this software and its |
9 | * documentation is hereby granted, provided that both the copyright | | 9 | * documentation is hereby granted, provided that both the copyright |
10 | * notice and this permission notice appear in all copies of the | | 10 | * notice and this permission notice appear in all copies of the |
11 | * software, derivative works or modified versions, and any portions | | 11 | * software, derivative works or modified versions, and any portions |
12 | * thereof, and that both notices appear in supporting documentation. | | 12 | * thereof, and that both notices appear in supporting documentation. |
13 | * | | 13 | * |
14 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | | 14 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" |
15 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | | 15 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR |
16 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | | 16 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. |
17 | * | | 17 | * |
18 | * Carnegie Mellon requests users of this software to return to | | 18 | * Carnegie Mellon requests users of this software to return to |
19 | * | | 19 | * |
20 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | | 20 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU |
21 | * School of Computer Science | | 21 | * School of Computer Science |
22 | * Carnegie Mellon University | | 22 | * Carnegie Mellon University |
23 | * Pittsburgh PA 15213-3890 | | 23 | * Pittsburgh PA 15213-3890 |
24 | * | | 24 | * |
25 | * any improvements or extensions that they make and grant Carnegie the | | 25 | * any improvements or extensions that they make and grant Carnegie the |
26 | * rights to redistribute these changes. | | 26 | * rights to redistribute these changes. |
27 | * | | 27 | * |
28 | * db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU) | | 28 | * db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU) |
29 | */ | | 29 | */ |
30 | | | 30 | |
31 | /* | | 31 | /* |
32 | * Interface to new debugger. | | 32 | * Interface to new debugger. |
33 | */ | | 33 | */ |
34 | | | 34 | |
35 | #include <sys/cdefs.h> | | 35 | #include <sys/cdefs.h> |
36 | __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.72 2017/05/23 08:54:38 nonaka Exp $"); | | 36 | __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.73 2017/08/15 06:57:53 maxv Exp $"); |
37 | | | 37 | |
38 | #include "opt_ddb.h" | | 38 | #include "opt_ddb.h" |
39 | #include "opt_multiprocessor.h" | | 39 | #include "opt_multiprocessor.h" |
40 | | | 40 | |
41 | #include "ioapic.h" | | 41 | #include "ioapic.h" |
42 | #include "lapic.h" | | 42 | #include "lapic.h" |
43 | | | 43 | |
44 | #include <sys/param.h> | | 44 | #include <sys/param.h> |
45 | #include <sys/proc.h> | | 45 | #include <sys/proc.h> |
46 | #include <sys/reboot.h> | | 46 | #include <sys/reboot.h> |
47 | #include <sys/systm.h> | | 47 | #include <sys/systm.h> |
48 | #include <sys/atomic.h> | | 48 | #include <sys/atomic.h> |
49 | #include <sys/cpu.h> | | 49 | #include <sys/cpu.h> |
50 | | | 50 | |
51 | #include <uvm/uvm_extern.h> | | | |
52 | | | | |
53 | #include <dev/cons.h> | | 51 | #include <dev/cons.h> |
54 | | | 52 | |
55 | #include <machine/cpufunc.h> | | 53 | #include <machine/cpufunc.h> |
56 | #include <machine/db_machdep.h> | | 54 | #include <machine/db_machdep.h> |
57 | #include <machine/cpuvar.h> | | 55 | #include <machine/cpuvar.h> |
58 | #if NIOAPIC > 0 | | 56 | #if NIOAPIC > 0 |
59 | #include <machine/i82093var.h> | | 57 | #include <machine/i82093var.h> |
60 | #endif | | 58 | #endif |
61 | #if NLAPIC > 0 | | 59 | #if NLAPIC > 0 |
62 | #include <machine/i82489reg.h> | | 60 | #include <machine/i82489reg.h> |
63 | #include <machine/i82489var.h> | | 61 | #include <machine/i82489var.h> |
64 | #endif | | 62 | #endif |
65 | | | 63 | |
66 | #include <ddb/db_sym.h> | | 64 | #include <ddb/db_sym.h> |
67 | #include <ddb/db_command.h> | | 65 | #include <ddb/db_command.h> |
68 | #include <ddb/db_extern.h> | | 66 | #include <ddb/db_extern.h> |
69 | #include <ddb/db_access.h> | | 67 | #include <ddb/db_access.h> |
70 | #include <ddb/db_output.h> | | 68 | #include <ddb/db_output.h> |
71 | #include <ddb/ddbvar.h> | | 69 | #include <ddb/ddbvar.h> |
72 | | | 70 | |
73 | extern const char *const trap_type[]; | | 71 | extern const char *const trap_type[]; |
74 | extern int trap_types; | | 72 | extern int trap_types; |
75 | | | 73 | |
76 | int db_active = 0; | | 74 | int db_active = 0; |
77 | db_regs_t ddb_regs; /* register state */ | | 75 | db_regs_t ddb_regs; /* register state */ |
| | | 76 | db_regs_t *ddb_regp = NULL; |
78 | | | 77 | |
79 | void db_mach_cpu (db_expr_t, bool, db_expr_t, const char *); | | 78 | void db_mach_cpu (db_expr_t, bool, db_expr_t, const char *); |
80 | | | 79 | |
81 | const struct db_command db_machine_command_table[] = { | | 80 | const struct db_command db_machine_command_table[] = { |
82 | #ifdef MULTIPROCESSOR | | 81 | #ifdef MULTIPROCESSOR |
83 | { DDB_ADD_CMD("cpu", db_mach_cpu, 0, | | 82 | { DDB_ADD_CMD("cpu", db_mach_cpu, 0, |
84 | "switch to another cpu", "cpu-no", NULL) }, | | 83 | "switch to another cpu", "cpu-no", NULL) }, |
85 | #endif | | 84 | #endif |
86 | | | 85 | { DDB_ADD_CMD(NULL, NULL, 0, NULL, NULL, NULL) }, |
87 | { DDB_ADD_CMD(NULL, NULL, 0, NULL,NULL,NULL) }, | | | |
88 | }; | | 86 | }; |
89 | | | 87 | |
90 | void kdbprinttrap(int, int); | | 88 | void kdbprinttrap(int, int); |
91 | #ifdef MULTIPROCESSOR | | 89 | #ifdef MULTIPROCESSOR |
92 | extern void ddb_ipi(int, struct trapframe); | | 90 | extern void ddb_ipi(int, struct trapframe); |
93 | extern void ddb_ipi_tss(struct i386tss *); | | 91 | extern void ddb_ipi_tss(struct i386tss *); |
94 | static void ddb_suspend(struct trapframe *); | | 92 | static void ddb_suspend(struct trapframe *); |
95 | #ifndef XEN | | 93 | #ifndef XEN |
96 | int ddb_vec; | | 94 | int ddb_vec; |
97 | #endif /* XEN */ | | 95 | #endif /* XEN */ |
98 | static bool ddb_mp_online; | | 96 | static bool ddb_mp_online; |
99 | #endif | | 97 | #endif |
100 | | | 98 | |
101 | db_regs_t *ddb_regp = 0; | | 99 | #define NOCPU -1 |
102 | | | | |
103 | #define NOCPU -1 | | | |
104 | | | 100 | |
105 | int ddb_cpu = NOCPU; | | 101 | int ddb_cpu = NOCPU; |
106 | | | 102 | |
107 | typedef void (vector)(void); | | 103 | typedef void (vector)(void); |
108 | extern vector Xintrddbipi, Xx2apic_intrddbipi; | | 104 | extern vector Xintrddbipi, Xx2apic_intrddbipi; |
109 | | | 105 | |
110 | void | | 106 | void |
111 | db_machine_init(void) | | 107 | db_machine_init(void) |
112 | { | | 108 | { |
113 | | | 109 | |
114 | #ifdef MULTIPROCESSOR | | 110 | #ifdef MULTIPROCESSOR |
115 | #ifndef XEN | | 111 | #ifndef XEN |
116 | vector *handler = &Xintrddbipi; | | 112 | vector *handler = &Xintrddbipi; |
117 | #if NLAPIC > 0 | | 113 | #if NLAPIC > 0 |
118 | if (lapic_is_x2apic()) | | 114 | if (lapic_is_x2apic()) |
119 | handler = &Xx2apic_intrddbipi; | | 115 | handler = &Xx2apic_intrddbipi; |
120 | #endif | | 116 | #endif |
121 | ddb_vec = idt_vec_alloc(0xf0, 0xff); | | 117 | ddb_vec = idt_vec_alloc(0xf0, 0xff); |
122 | idt_vec_set(ddb_vec, handler); | | 118 | idt_vec_set(ddb_vec, handler); |
123 | #else | | 119 | #else |
124 | /* Initialised as part of xen_ipi_init() */ | | 120 | /* Initialised as part of xen_ipi_init() */ |
125 | #endif /* XEN */ | | 121 | #endif /* XEN */ |
126 | #endif | | 122 | #endif |
127 | } | | 123 | } |
128 | | | 124 | |
129 | #ifdef MULTIPROCESSOR | | 125 | #ifdef MULTIPROCESSOR |
130 | | | 126 | |
131 | __cpu_simple_lock_t db_lock; | | 127 | __cpu_simple_lock_t db_lock; |
132 | | | 128 | |
133 | static int | | 129 | static int |
134 | db_suspend_others(void) | | 130 | db_suspend_others(void) |
135 | { | | 131 | { |
136 | int cpu_me = cpu_number(); | | 132 | int cpu_me = cpu_number(); |
137 | int win; | | 133 | int win; |
138 | | | 134 | |
139 | #ifndef XEN | | 135 | #ifndef XEN |
140 | if (ddb_vec == 0) | | 136 | if (ddb_vec == 0) |
141 | return 1; | | 137 | return 1; |
142 | #endif /* XEN */ | | 138 | #endif /* XEN */ |
143 | | | 139 | |
144 | __cpu_simple_lock(&db_lock); | | 140 | __cpu_simple_lock(&db_lock); |
145 | if (ddb_cpu == NOCPU) | | 141 | if (ddb_cpu == NOCPU) |
146 | ddb_cpu = cpu_me; | | 142 | ddb_cpu = cpu_me; |
147 | win = (ddb_cpu == cpu_me); | | 143 | win = (ddb_cpu == cpu_me); |
148 | __cpu_simple_unlock(&db_lock); | | 144 | __cpu_simple_unlock(&db_lock); |
149 | if (win) { | | 145 | if (win) { |
150 | #ifdef XEN | | 146 | #ifdef XEN |
151 | xen_broadcast_ipi(XEN_IPI_DDB); | | 147 | xen_broadcast_ipi(XEN_IPI_DDB); |
152 | #else | | 148 | #else |
153 | x86_ipi(ddb_vec, LAPIC_DEST_ALLEXCL, LAPIC_DLMODE_FIXED); | | 149 | x86_ipi(ddb_vec, LAPIC_DEST_ALLEXCL, LAPIC_DLMODE_FIXED); |
154 | #endif /* XEN */ | | 150 | #endif /* XEN */ |
155 | } | | 151 | } |
156 | ddb_mp_online = x86_mp_online; | | 152 | ddb_mp_online = x86_mp_online; |
157 | x86_mp_online = false; | | 153 | x86_mp_online = false; |
158 | return win; | | 154 | return win; |
159 | } | | 155 | } |
160 | | | 156 | |
161 | static void | | 157 | static void |
162 | db_resume_others(void) | | 158 | db_resume_others(void) |
163 | { | | 159 | { |
164 | CPU_INFO_ITERATOR cii; | | 160 | CPU_INFO_ITERATOR cii; |
165 | struct cpu_info *ci; | | 161 | struct cpu_info *ci; |
166 | | | 162 | |
167 | x86_mp_online = ddb_mp_online; | | 163 | x86_mp_online = ddb_mp_online; |
168 | __cpu_simple_lock(&db_lock); | | 164 | __cpu_simple_lock(&db_lock); |
169 | ddb_cpu = NOCPU; | | 165 | ddb_cpu = NOCPU; |
170 | __cpu_simple_unlock(&db_lock); | | 166 | __cpu_simple_unlock(&db_lock); |
171 | | | 167 | |
172 | for (CPU_INFO_FOREACH(cii, ci)) { | | 168 | for (CPU_INFO_FOREACH(cii, ci)) { |
173 | if (ci->ci_flags & CPUF_PAUSE) | | 169 | if (ci->ci_flags & CPUF_PAUSE) |
174 | atomic_and_32(&ci->ci_flags, ~CPUF_PAUSE); | | 170 | atomic_and_32(&ci->ci_flags, ~CPUF_PAUSE); |
175 | } | | 171 | } |
176 | } | | 172 | } |
177 | | | 173 | |
178 | #endif | | 174 | #endif |
179 | | | 175 | |
180 | /* | | 176 | /* |
181 | * Print trap reason. | | 177 | * Print trap reason. |
182 | */ | | 178 | */ |
183 | void | | 179 | void |
184 | kdbprinttrap(int type, int code) | | 180 | kdbprinttrap(int type, int code) |
185 | { | | 181 | { |
186 | db_printf("kernel: %s trap ", (type & T_USER) ? "user" : "supervisor"); | | 182 | db_printf("kernel: %s trap ", (type & T_USER) ? "user" : "supervisor"); |
187 | type &= ~T_USER; | | 183 | type &= ~T_USER; |
188 | if (type >= trap_types || type < 0) | | 184 | if (type >= trap_types || type < 0) |
189 | db_printf("type %d", type); | | 185 | db_printf("type %d", type); |
190 | else | | 186 | else |
191 | db_printf("%s", trap_type[type]); | | 187 | db_printf("%s", trap_type[type]); |
192 | db_printf(", code=%x\n", code); | | 188 | db_printf(", code=%x\n", code); |
193 | } | | 189 | } |
194 | | | 190 | |
195 | /* | | 191 | /* |
196 | * kdb_trap - field a TRACE or BPT trap | | 192 | * kdb_trap - field a TRACE or BPT trap |
197 | */ | | 193 | */ |
198 | int | | 194 | int |
199 | kdb_trap(int type, int code, db_regs_t *regs) | | 195 | kdb_trap(int type, int code, db_regs_t *regs) |
200 | { | | 196 | { |
201 | int s, flags; | | 197 | int s, flags; |
202 | db_regs_t dbreg; | | 198 | db_regs_t dbreg; |
203 | | | 199 | |
204 | flags = regs->tf_err & TC_FLAGMASK; | | 200 | flags = regs->tf_err & TC_FLAGMASK; |
205 | regs->tf_err &= ~TC_FLAGMASK; | | 201 | regs->tf_err &= ~TC_FLAGMASK; |
206 | | | 202 | |
207 | switch (type) { | | 203 | switch (type) { |
208 | case T_NMI: /* NMI */ | | 204 | case T_NMI: /* NMI */ |
209 | printf("NMI ... going to debugger\n"); | | 205 | printf("NMI ... going to debugger\n"); |
210 | /*FALLTHROUGH*/ | | 206 | /*FALLTHROUGH*/ |
211 | case T_BPTFLT: /* breakpoint */ | | 207 | case T_BPTFLT: /* breakpoint */ |
212 | case T_TRCTRAP: /* single_step */ | | 208 | case T_TRCTRAP: /* single_step */ |
213 | case -1: /* keyboard interrupt */ | | 209 | case -1: /* keyboard interrupt */ |
214 | break; | | 210 | break; |
215 | default: | | 211 | default: |
216 | if (!db_onpanic && db_recover == 0) | | 212 | if (!db_onpanic && db_recover == 0) |
217 | return (0); | | 213 | return (0); |
218 | | | 214 | |
219 | kdbprinttrap(type, code); | | 215 | kdbprinttrap(type, code); |
220 | if (db_recover != 0) { | | 216 | if (db_recover != 0) { |
221 | db_error("Faulted in DDB; continuing...\n"); | | 217 | db_error("Faulted in DDB; continuing...\n"); |
222 | /*NOTREACHED*/ | | 218 | /*NOTREACHED*/ |
223 | } | | 219 | } |
224 | } | | 220 | } |
225 | | | 221 | |
226 | #ifdef MULTIPROCESSOR | | 222 | #ifdef MULTIPROCESSOR |
227 | if (!db_suspend_others()) { | | 223 | if (!db_suspend_others()) { |
228 | ddb_suspend(regs); | | 224 | ddb_suspend(regs); |
229 | } else { | | 225 | } else { |
230 | curcpu()->ci_ddb_regs = &dbreg; | | 226 | curcpu()->ci_ddb_regs = &dbreg; |
231 | ddb_regp = &dbreg; | | 227 | ddb_regp = &dbreg; |
232 | #endif | | 228 | #endif |
233 | /* XXX Should switch to kdb's own stack here. */ | | 229 | /* XXX Should switch to kdb's own stack here. */ |
234 | ddb_regs = *regs; | | 230 | ddb_regs = *regs; |
235 | if (!(flags & TC_TSS) && KERNELMODE(regs->tf_cs, regs->tf_eflags)) { | | 231 | if (!(flags & TC_TSS) && KERNELMODE(regs->tf_cs, regs->tf_eflags)) { |
236 | /* | | 232 | /* |
237 | * Kernel mode - esp and ss not saved | | 233 | * Kernel mode - esp and ss not saved |
238 | */ | | 234 | */ |
239 | ddb_regs.tf_esp = (int)®s->tf_esp; /* kernel stack pointer */ | | 235 | ddb_regs.tf_esp = (int)®s->tf_esp; /* kernel stack pointer */ |
240 | ddb_regs.tf_ss = x86_getss(); | | 236 | ddb_regs.tf_ss = x86_getss(); |
241 | } | | 237 | } |
242 | | | 238 | |
243 | ddb_regs.tf_cs &= 0xffff; | | 239 | ddb_regs.tf_cs &= 0xffff; |
244 | ddb_regs.tf_ds &= 0xffff; | | 240 | ddb_regs.tf_ds &= 0xffff; |
245 | ddb_regs.tf_es &= 0xffff; | | 241 | ddb_regs.tf_es &= 0xffff; |
246 | ddb_regs.tf_fs &= 0xffff; | | 242 | ddb_regs.tf_fs &= 0xffff; |
247 | ddb_regs.tf_gs &= 0xffff; | | 243 | ddb_regs.tf_gs &= 0xffff; |
248 | ddb_regs.tf_ss &= 0xffff; | | 244 | ddb_regs.tf_ss &= 0xffff; |
| | | 245 | |
249 | s = splhigh(); | | 246 | s = splhigh(); |
250 | db_active++; | | 247 | db_active++; |
251 | cnpollc(true); | | 248 | cnpollc(true); |
252 | db_trap(type, code); | | 249 | db_trap(type, code); |
253 | cnpollc(false); | | 250 | cnpollc(false); |
254 | db_active--; | | 251 | db_active--; |
255 | splx(s); | | 252 | splx(s); |
256 | #ifdef MULTIPROCESSOR | | 253 | #ifdef MULTIPROCESSOR |
257 | db_resume_others(); | | 254 | db_resume_others(); |
258 | } | | 255 | } |
259 | #endif | | 256 | #endif |
260 | ddb_regp = &dbreg; | | 257 | ddb_regp = &dbreg; |
261 | | | 258 | |
262 | regs->tf_gs = ddb_regs.tf_gs; | | 259 | regs->tf_gs = ddb_regs.tf_gs; |
263 | regs->tf_fs = ddb_regs.tf_fs; | | 260 | regs->tf_fs = ddb_regs.tf_fs; |
264 | regs->tf_es = ddb_regs.tf_es; | | 261 | regs->tf_es = ddb_regs.tf_es; |
265 | regs->tf_ds = ddb_regs.tf_ds; | | 262 | regs->tf_ds = ddb_regs.tf_ds; |
266 | regs->tf_edi = ddb_regs.tf_edi; | | 263 | regs->tf_edi = ddb_regs.tf_edi; |
267 | regs->tf_esi = ddb_regs.tf_esi; | | 264 | regs->tf_esi = ddb_regs.tf_esi; |
268 | regs->tf_ebp = ddb_regs.tf_ebp; | | 265 | regs->tf_ebp = ddb_regs.tf_ebp; |
269 | regs->tf_ebx = ddb_regs.tf_ebx; | | 266 | regs->tf_ebx = ddb_regs.tf_ebx; |
270 | regs->tf_edx = ddb_regs.tf_edx; | | 267 | regs->tf_edx = ddb_regs.tf_edx; |
271 | regs->tf_ecx = ddb_regs.tf_ecx; | | 268 | regs->tf_ecx = ddb_regs.tf_ecx; |
272 | regs->tf_eax = ddb_regs.tf_eax; | | 269 | regs->tf_eax = ddb_regs.tf_eax; |
273 | regs->tf_eip = ddb_regs.tf_eip; | | 270 | regs->tf_eip = ddb_regs.tf_eip; |
274 | regs->tf_cs = ddb_regs.tf_cs; | | 271 | regs->tf_cs = ddb_regs.tf_cs; |
275 | regs->tf_eflags = ddb_regs.tf_eflags; | | 272 | regs->tf_eflags = ddb_regs.tf_eflags; |
276 | if (!(flags & TC_TSS) && !KERNELMODE(regs->tf_cs, regs->tf_eflags)) { | | 273 | if (!(flags & TC_TSS) && !KERNELMODE(regs->tf_cs, regs->tf_eflags)) { |
277 | /* ring transit - saved esp and ss valid */ | | 274 | /* ring transit - saved esp and ss valid */ |
278 | regs->tf_esp = ddb_regs.tf_esp; | | 275 | regs->tf_esp = ddb_regs.tf_esp; |
279 | regs->tf_ss = ddb_regs.tf_ss; | | 276 | regs->tf_ss = ddb_regs.tf_ss; |
280 | } | | 277 | } |
281 | | | 278 | |
282 | #ifdef TRAPLOG | | 279 | #ifdef TRAPLOG |
283 | wrmsr(MSR_DEBUGCTLMSR, 0x1); | | 280 | wrmsr(MSR_DEBUGCTLMSR, 0x1); |
284 | #endif | | 281 | #endif |
285 | | | 282 | |
286 | return (1); | | 283 | return (1); |
287 | } | | 284 | } |
288 | | | 285 | |
289 | void | | 286 | void |
290 | cpu_Debugger(void) | | 287 | cpu_Debugger(void) |
291 | { | | 288 | { |
292 | breakpoint(); | | 289 | breakpoint(); |
293 | } | | 290 | } |
294 | | | 291 | |
295 | #ifdef MULTIPROCESSOR | | 292 | #ifdef MULTIPROCESSOR |
296 | | | 293 | |
297 | /* | | 294 | /* |
298 | * Called when we receive a debugger IPI (inter-processor interrupt). | | 295 | * Called when we receive a debugger IPI (inter-processor interrupt). |
299 | * As with trap() in trap.c, this function is called from an assembly | | 296 | * As with trap() in trap.c, this function is called from an assembly |
300 | * language IDT gate entry routine which prepares a suitable stack frame, | | 297 | * language IDT gate entry routine which prepares a suitable stack frame, |
301 | * and restores this frame after the exception has been processed. Note | | 298 | * and restores this frame after the exception has been processed. Note |
302 | * that the effect is as if the arguments were passed call by reference. | | 299 | * that the effect is as if the arguments were passed call by reference. |
303 | */ | | 300 | */ |
304 | void | | 301 | void |
305 | ddb_ipi(int cpl, struct trapframe frame) | | 302 | ddb_ipi(int cpl, struct trapframe frame) |
306 | { | | 303 | { |
307 | | | 304 | |
308 | ddb_suspend(&frame); | | 305 | ddb_suspend(&frame); |
309 | } | | 306 | } |
310 | | | 307 | |
311 | void | | 308 | void |
312 | ddb_ipi_tss(struct i386tss *tss) | | 309 | ddb_ipi_tss(struct i386tss *tss) |
313 | { | | 310 | { |
314 | struct trapframe tf; | | 311 | struct trapframe tf; |
315 | | | 312 | |
316 | tf.tf_gs = tss->tss_gs; | | 313 | tf.tf_gs = tss->tss_gs; |
317 | tf.tf_fs = tss->tss_fs; | | 314 | tf.tf_fs = tss->tss_fs; |
318 | tf.tf_es = tss->__tss_es; | | 315 | tf.tf_es = tss->__tss_es; |
319 | tf.tf_ds = tss->__tss_ds; | | 316 | tf.tf_ds = tss->__tss_ds; |
320 | tf.tf_edi = tss->__tss_edi; | | 317 | tf.tf_edi = tss->__tss_edi; |
321 | tf.tf_esi = tss->__tss_esi; | | 318 | tf.tf_esi = tss->__tss_esi; |
322 | tf.tf_ebp = tss->tss_ebp; | | 319 | tf.tf_ebp = tss->tss_ebp; |
323 | tf.tf_ebx = tss->__tss_ebx; | | 320 | tf.tf_ebx = tss->__tss_ebx; |
324 | tf.tf_edx = tss->__tss_edx; | | 321 | tf.tf_edx = tss->__tss_edx; |
325 | tf.tf_ecx = tss->__tss_ecx; | | 322 | tf.tf_ecx = tss->__tss_ecx; |
326 | tf.tf_eax = tss->__tss_eax; | | 323 | tf.tf_eax = tss->__tss_eax; |
327 | tf.tf_trapno = 0; | | 324 | tf.tf_trapno = 0; |
328 | tf.tf_err = TC_TSS; | | 325 | tf.tf_err = TC_TSS; |
329 | tf.tf_eip = tss->__tss_eip; | | 326 | tf.tf_eip = tss->__tss_eip; |
330 | tf.tf_cs = tss->__tss_cs; | | 327 | tf.tf_cs = tss->__tss_cs; |
331 | tf.tf_eflags = tss->__tss_eflags; | | 328 | tf.tf_eflags = tss->__tss_eflags; |
332 | tf.tf_esp = tss->tss_esp; | | 329 | tf.tf_esp = tss->tss_esp; |
333 | tf.tf_ss = tss->__tss_ss; | | 330 | tf.tf_ss = tss->__tss_ss; |
334 | | | 331 | |
335 | ddb_suspend(&tf); | | 332 | ddb_suspend(&tf); |
336 | } | | 333 | } |
337 | | | 334 | |
338 | static void | | 335 | static void |
339 | ddb_suspend(struct trapframe *frame) | | 336 | ddb_suspend(struct trapframe *frame) |
340 | { | | 337 | { |
341 | volatile struct cpu_info *ci = curcpu(); | | 338 | volatile struct cpu_info *ci = curcpu(); |
342 | db_regs_t regs; | | 339 | db_regs_t regs; |
343 | int flags; | | 340 | int flags; |
344 | | | 341 | |
345 | regs = *frame; | | 342 | regs = *frame; |
346 | flags = regs.tf_err & TC_FLAGMASK; | | 343 | flags = regs.tf_err & TC_FLAGMASK; |
347 | regs.tf_err &= ~TC_FLAGMASK; | | 344 | regs.tf_err &= ~TC_FLAGMASK; |
348 | if (!(flags & TC_TSS) && KERNELMODE(regs.tf_cs, regs.tf_eflags)) { | | 345 | if (!(flags & TC_TSS) && KERNELMODE(regs.tf_cs, regs.tf_eflags)) { |
349 | /* | | 346 | /* |
350 | * Kernel mode - esp and ss not saved | | 347 | * Kernel mode - esp and ss not saved |
351 | */ | | 348 | */ |
352 | regs.tf_esp = (int)&frame->tf_esp; /* kernel stack pointer */ | | 349 | regs.tf_esp = (int)&frame->tf_esp; /* kernel stack pointer */ |
353 | regs.tf_ss = x86_getss(); | | 350 | regs.tf_ss = x86_getss(); |
354 | } | | 351 | } |
355 | | | 352 | |
356 | ci->ci_ddb_regs = ®s; | | 353 | ci->ci_ddb_regs = ®s; |
357 | | | 354 | |
358 | atomic_or_32(&ci->ci_flags, CPUF_PAUSE); | | 355 | atomic_or_32(&ci->ci_flags, CPUF_PAUSE); |
| | | 356 | |
359 | while (ci->ci_flags & CPUF_PAUSE) | | 357 | while (ci->ci_flags & CPUF_PAUSE) |
360 | ; | | 358 | ; |
361 | ci->ci_ddb_regs = 0; | | 359 | ci->ci_ddb_regs = 0; |
362 | tlbflushg(); | | 360 | tlbflushg(); |
363 | } | | 361 | } |
364 | | | 362 | |
365 | | | 363 | |
366 | extern void cpu_debug_dump(void); /* XXX */ | | 364 | extern void cpu_debug_dump(void); /* XXX */ |
367 | | | 365 | |
368 | void | | 366 | void |
369 | db_mach_cpu( | | 367 | db_mach_cpu(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) |
370 | db_expr_t addr, | | | |
371 | bool have_addr, | | | |
372 | db_expr_t count, | | | |
373 | const char * modif) | | | |
374 | { | | 368 | { |
375 | struct cpu_info *ci; | | 369 | struct cpu_info *ci; |
376 | if (!have_addr) { | | 370 | if (!have_addr) { |
377 | cpu_debug_dump(); | | 371 | cpu_debug_dump(); |
378 | return; | | 372 | return; |
379 | } | | 373 | } |
380 | | | 374 | |
381 | if (addr < 0) { | | 375 | if (addr < 0) { |
382 | db_printf("%ld: CPU out of range\n", addr); | | 376 | db_printf("%ld: CPU out of range\n", addr); |
383 | return; | | 377 | return; |
384 | } | | 378 | } |
385 | ci = cpu_lookup(addr); | | 379 | ci = cpu_lookup(addr); |
386 | if (ci == NULL) { | | 380 | if (ci == NULL) { |
387 | db_printf("CPU %ld not configured\n", addr); | | 381 | db_printf("CPU %ld not configured\n", addr); |
388 | return; | | 382 | return; |
389 | } | | 383 | } |
390 | if (ci != curcpu()) { | | 384 | if (ci != curcpu()) { |
391 | if (!(ci->ci_flags & CPUF_PAUSE)) { | | 385 | if (!(ci->ci_flags & CPUF_PAUSE)) { |
392 | db_printf("CPU %ld not paused\n", addr); | | 386 | db_printf("CPU %ld not paused\n", addr); |
393 | return; | | 387 | return; |
394 | } | | 388 | } |
395 | } | | 389 | } |
396 | if (ci->ci_ddb_regs == 0) { | | 390 | if (ci->ci_ddb_regs == 0) { |
397 | db_printf("CPU %ld has no saved regs\n", addr); | | 391 | db_printf("CPU %ld has no saved regs\n", addr); |
398 | return; | | 392 | return; |
399 | } | | 393 | } |
400 | db_printf("using CPU %ld", addr); | | 394 | db_printf("using CPU %ld", addr); |
401 | ddb_regp = ci->ci_ddb_regs; | | 395 | ddb_regp = ci->ci_ddb_regs; |
402 | } | | 396 | } |
403 | | | 397 | |
404 | | | | |
405 | #endif | | 398 | #endif |