FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_mp.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: db_mp.c,v $
29 * Revision 2.3 93/01/19 09:00:53 danner
30 * More info in debugging printouts.
31 * [92/12/26 af]
32 *
33 * Revision 2.2 93/01/14 17:25:20 danner
34 * Made more machine-independent, as alpha and mips keep
35 * register states on stack. Spots.
36 * [92/12/16 12:44:42 af]
37 *
38 * Pulled code from OSF/Grenoble and restructured.
39 * [92/10/24 dbg]
40 *
41 */
42 #include <cpus.h>
43
44 #if NCPUS > 1
45
46 #include <mach/boolean.h>
47 #include <mach/machine.h>
48
49 #include <kern/cpu_number.h>
50 #include <kern/lock.h>
51
52 #include <machine/db_machdep.h>
53
54 #include <ddb/db_command.h>
55 #include <ddb/db_run.h>
56
57 /*
58 * Routines to interlock access to the kernel debugger on
59 * multiprocessors.
60 */
61
62 decl_simple_lock_data(,db_lock) /* lock to enter debugger */
63 volatile int db_cpu = -1; /* CPU currently in debugger */
64 /* -1 if none */
65 int db_active[NCPUS] = { 0 }; /* count recursive entries
66 into debugger */
67 int db_slave[NCPUS] = { 0 }; /* nonzero if cpu interrupted
68 by another cpu in debugger */
69
70 int db_enter_debug = 0;
71
72 void remote_db(); /* forward */
73 void lock_db();
74 void unlock_db();
75
76
77 /*
78 * Called when entering kernel debugger.
79 * Takes db lock. If we were called remotely (slave state) we just
80 * wait for db_cpu to be equal to cpu_number(). Otherwise enter debugger
81 * if not active on another cpu
82 */
83
84 boolean_t
85 db_enter()
86 {
87 int mycpu = cpu_number();
88
89 /*
90 * Count recursive entries to debugger.
91 */
92 db_active[mycpu]++;
93
94 /*
95 * Wait for other CPUS to leave debugger.
96 */
97 lock_db();
98
99 if (db_enter_debug)
100 db_printf(
101 "db_enter: cpu %d[%d], master %d, db_cpu %d, run mode %d\n",
102 mycpu, db_slave[mycpu], master_cpu, db_cpu, db_run_mode);
103
104 /*
105 * If no CPU in debugger, and I am not being stopped,
106 * enter the debugger.
107 */
108 if (db_cpu == -1 && !db_slave[mycpu]) {
109 remote_db(); /* stop other cpus */
110 db_cpu = mycpu;
111 return TRUE;
112 }
113 /*
114 * If I am already in the debugger (recursive entry
115 * or returning from single step), enter debugger.
116 */
117 else if (db_cpu == mycpu)
118 return TRUE;
119 /*
120 * Otherwise, cannot enter debugger.
121 */
122 else
123 return FALSE;
124 }
125
126 /*
127 * Leave debugger.
128 */
129 void
130 db_leave()
131 {
132 int mycpu = cpu_number();
133
134 /*
135 * If continuing, give up debugger
136 */
137 if (db_run_mode == STEP_CONTINUE)
138 db_cpu = -1;
139
140 /*
141 * If I am a slave, drop my slave count.
142 */
143 if (db_slave[mycpu])
144 db_slave[mycpu]--;
145 if (db_enter_debug)
146 db_printf("db_leave: cpu %d[%d], db_cpu %d, run_mode %d\n",
147 mycpu, db_slave[mycpu], db_cpu, db_run_mode);
148 /*
149 * Unlock debugger.
150 */
151 unlock_db();
152
153 /*
154 * Drop recursive entry count.
155 */
156 db_active[mycpu]--;
157 }
158
159
160 /*
161 * invoke kernel debugger on slave processors
162 */
163
164 void
165 remote_db() {
166 int my_cpu = cpu_number();
167 register int i;
168
169 for (i = 0; i < NCPUS; i++) {
170 if (i != my_cpu &&
171 machine_slot[i].is_cpu &&
172 machine_slot[i].running)
173 {
174 cpu_interrupt_to_db(i);
175 }
176 }
177 }
178
179 /*
180 * Save and restore DB global registers.
181 *
182 * DB_SAVE_CTXT must be at the start of a block, and
183 * DB_RESTORE_CTXT must be in the same block.
184 */
185
186 #ifdef __STDC__
187 #define DB_SAVE(type, name) extern type name; type name##_save = name
188 #define DB_RESTORE(name) name = name##_save
189 #else /* __STDC__ */
190 #define DB_SAVE(type, name) extern type name; type name/**/_save = name
191 #define DB_RESTORE(name) name = name/**/_save
192 #endif /* __STDC__ */
193
194 #define DB_SAVE_CTXT() \
195 DB_SAVE(int, db_run_mode); \
196 DB_SAVE(boolean_t, db_sstep_print); \
197 DB_SAVE(int, db_loop_count); \
198 DB_SAVE(int, db_call_depth); \
199 DB_SAVE(int, db_inst_count); \
200 DB_SAVE(int, db_last_inst_count); \
201 DB_SAVE(int, db_load_count); \
202 DB_SAVE(int, db_store_count); \
203 DB_SAVE(boolean_t, db_cmd_loop_done); \
204 DB_SAVE(jmp_buf_t *, db_recover); \
205 DB_SAVE(db_addr_t, db_dot); \
206 DB_SAVE(db_addr_t, db_last_addr); \
207 DB_SAVE(db_addr_t, db_prev); \
208 DB_SAVE(db_addr_t, db_next); \
209 SAVE_DDB_REGS
210
211 #define DB_RESTORE_CTXT() \
212 DB_RESTORE(db_run_mode); \
213 DB_RESTORE(db_sstep_print); \
214 DB_RESTORE(db_loop_count); \
215 DB_RESTORE(db_call_depth); \
216 DB_RESTORE(db_inst_count); \
217 DB_RESTORE(db_last_inst_count); \
218 DB_RESTORE(db_load_count); \
219 DB_RESTORE(db_store_count); \
220 DB_RESTORE(db_cmd_loop_done); \
221 DB_RESTORE(db_recover); \
222 DB_RESTORE(db_dot); \
223 DB_RESTORE(db_last_addr); \
224 DB_RESTORE(db_prev); \
225 DB_RESTORE(db_next); \
226 RESTORE_DDB_REGS
227
228 /*
229 * switch to another cpu
230 */
231 void
232 db_on(cpu)
233 int cpu;
234 {
235 /*
236 * Save ddb global variables
237 */
238 DB_SAVE_CTXT();
239
240 /*
241 * Don`t do if bad CPU number.
242 * CPU must also be spinning in db_entry.
243 */
244 if (cpu < 0 || cpu >= NCPUS || !db_active[cpu])
245 return;
246
247 /*
248 * Give debugger to that CPU
249 */
250 db_cpu = cpu;
251 unlock_db();
252
253 /*
254 * Wait for it to come back again
255 */
256 lock_db();
257
258 /*
259 * Restore ddb globals
260 */
261 DB_RESTORE_CTXT();
262
263 if (db_cpu == -1) /* someone continued */
264 db_continue_cmd(0, 0, 0, "");
265 }
266
267 /*
268 * Called by interprocessor interrupt when one CPU is
269 * in kernel debugger and wants to stop other CPUs
270 */
271 void
272 remote_db_enter()
273 {
274 db_slave[cpu_number()]++;
275 kdb_kintr();
276 }
277
278 /*
279 * Acquire kernel debugger.
280 * Conditional code for forwarding characters from slave to console
281 * if console on master only.
282 */
283
284 /*
285 * As long as db_cpu is not -1 or cpu_number(), we know that debugger
286 * is active on another cpu.
287 */
288 void
289 lock_db()
290 {
291 int my_cpu = cpu_number();
292
293 for (;;) {
294 #if CONSOLE_ON_MASTER
295 if (my_cpu == master_cpu) {
296 db_console();
297 }
298 #endif
299 if (db_cpu != -1 && db_cpu != my_cpu)
300 continue;
301
302 #if CONSOLE_ON_MASTER
303 if (my_cpu == master_cpu) {
304 if (!simple_lock_try(&db_lock))
305 continue;
306 }
307 else {
308 simple_lock(&db_lock);
309 }
310 #else
311 simple_lock(&db_lock);
312 #endif
313 if (db_cpu == -1 || db_cpu == my_cpu)
314 break;
315 simple_unlock(&db_lock);
316 }
317 }
318
319 void
320 unlock_db()
321 {
322 simple_unlock(&db_lock);
323 }
324
325 #ifdef sketch
326 void
327 db_console()
328 {
329 if (i_bit(CBUS_PUT_CHAR, my_word)) {
330 volatile u_char c = cbus_ochar;
331 i_bit_clear(CBUS_PUT_CHAR, my_word);
332 cnputc(c);
333 } else if (i_bit(CBUS_GET_CHAR, my_word)) {
334 if (cbus_wait_char)
335 cbus_ichar = cngetc();
336 else
337 cbus_ichar = cnmaygetc();
338 i_bit_clear(CBUS_GET_CHAR, my_word);
339 #ifndef notdef
340 } else if (!cnmaygetc()) {
341 #else /* notdef */
342 } else if (com_is_char() && !com_getc(TRUE)) {
343 #endif /* notdef */
344 simple_unlock(&db_lock);
345 db_cpu = my_cpu;
346 }
347 }
348 #endif /* sketch */
349
350 #endif /* NCPUS > 1 */
Cache object: d209528c4a54a210e6543818d599a44e
|