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