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