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