]> git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/db_interface.c
xnu-1456.1.26.tar.gz
[apple/xnu.git] / osfmk / i386 / db_interface.c
1 /*
2 * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * @OSF_COPYRIGHT@
30 */
31 /*
32 * Mach Operating System
33 * Copyright (c) 1991,1990 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56 /*
57 */
58
59 /*
60 * Interface to new debugger.
61 */
62 #include <platforms.h>
63 #include <time_stamp.h>
64 #include <mach_mp_debug.h>
65 #include <mach_ldebug.h>
66 #include <kern/spl.h>
67 #include <kern/cpu_number.h>
68 #include <kern/kern_types.h>
69 #include <kern/misc_protos.h>
70 #include <vm/pmap.h>
71
72 #include <i386/thread.h>
73 #include <i386/db_machdep.h>
74 #include <i386/seg.h>
75 #include <i386/trap.h>
76 #include <i386/setjmp.h>
77 #include <i386/pmap.h>
78 #include <i386/misc_protos.h>
79 #include <i386/mp.h>
80 #include <i386/machine_cpu.h>
81
82 #include <mach/vm_param.h>
83 #include <vm/vm_map.h>
84 #include <kern/thread.h>
85 #include <kern/task.h>
86
87 #include <ddb/db_command.h>
88 #include <ddb/db_task_thread.h>
89 #include <ddb/db_run.h>
90 #include <ddb/db_trap.h>
91 #include <ddb/db_output.h>
92 #include <ddb/db_access.h>
93 #include <ddb/db_sym.h>
94 #include <ddb/db_break.h>
95 #include <ddb/db_watch.h>
96
97 #include <i386/cpu_data.h>
98
99 int db_active = 0;
100 x86_saved_state32_t *i386_last_saved_statep;
101 x86_saved_state32_t i386_nested_saved_state;
102 unsigned i386_last_kdb_sp;
103 db_regs_t ddb_regs; /* register state */
104
105 extern thread_t db_default_act;
106 extern pt_entry_t *DMAP1;
107 extern caddr_t DADDR1;
108
109 #if MACH_MP_DEBUG
110 extern int masked_state_cnt[];
111 #endif /* MACH_MP_DEBUG */
112
113 /*
114 * Enter KDB through a keyboard trap.
115 * We show the registers as of the keyboard interrupt
116 * instead of those at its call to KDB.
117 */
118 struct int_regs {
119 int gs;
120 int fs;
121 int edi;
122 int esi;
123 int ebp;
124 int ebx;
125 x86_saved_state32_t *is;
126 };
127
128 extern char * trap_type[];
129 extern int TRAP_TYPES;
130
131 /* Forward */
132
133 extern void kdbprinttrap(
134 int type,
135 int code,
136 int *pc,
137 int sp);
138 extern void kdb_kentry(
139 struct int_regs *int_regs);
140 extern int db_user_to_kernel_address(
141 task_t task,
142 vm_offset_t addr,
143 unsigned *kaddr,
144 int flag);
145 extern void db_write_bytes_user_space(
146 vm_offset_t addr,
147 int size,
148 char *data,
149 task_t task);
150 extern int db_search_null(
151 task_t task,
152 unsigned *svaddr,
153 unsigned evaddr,
154 unsigned *skaddr,
155 int flag);
156 extern int kdb_enter(int);
157 extern void kdb_leave(void);
158 extern void lock_kdb(void);
159 extern void unlock_kdb(void);
160
161 /*
162 * kdb_trap - field a TRACE or BPT trap
163 */
164
165
166 extern jmp_buf_t *db_recover;
167
168 /*
169 * Translate the state saved in a task state segment into an
170 * exception frame. Since we "know" we always want the state
171 * in a ktss, we hard-wire that in, rather than indexing the gdt
172 * with tss_sel to derive a pointer to the desired tss.
173 */
174
175 /*
176 * Code used to synchronize kdb among all cpus, one active at a time, switch
177 * from one to another using cpu #cpu
178 */
179
180 decl_simple_lock_data(, kdb_lock) /* kdb lock */
181
182 #define db_simple_lock_init(l, e) hw_lock_init(&((l)->interlock))
183 #define db_simple_lock_try(l) hw_lock_try(&((l)->interlock))
184 #define db_simple_unlock(l) hw_lock_unlock(&((l)->interlock))
185
186 int kdb_cpu = -1; /* current cpu running kdb */
187 int kdb_debug = 1;
188 volatile unsigned int cpus_holding_bkpts; /* counter for number of cpus
189 * holding breakpoints
190 */
191 extern boolean_t db_breakpoints_inserted;
192
193 void
194 db_tss_to_frame(
195 int tss_sel,
196 x86_saved_state32_t *regs)
197 {
198 extern struct i386_tss ktss;
199 int mycpu = cpu_number();
200 struct i386_tss *tss;
201
202 tss = cpu_datap(mycpu)->cpu_desc_index.cdi_ktss; /* XXX */
203
204 /*
205 * ddb will overwrite whatever's in esp, so put esp0 elsewhere, too.
206 */
207 regs->cr2 = tss->esp0;
208 regs->efl = tss->eflags;
209 regs->eip = tss->eip;
210 regs->trapno = tss->ss0; /* XXX */
211 regs->err = tss->esp0; /* XXX */
212 regs->eax = tss->eax;
213 regs->ecx = tss->ecx;
214 regs->edx = tss->edx;
215 regs->ebx = tss->ebx;
216 regs->uesp = tss->esp;
217 regs->ebp = tss->ebp;
218 regs->esi = tss->esi;
219 regs->edi = tss->edi;
220 regs->es = tss->es;
221 regs->ss = tss->ss;
222 regs->cs = tss->cs;
223 regs->ds = tss->ds;
224 regs->fs = tss->fs;
225 regs->gs = tss->gs;
226 }
227
228 /*
229 * Compose a call to the debugger from the saved state in regs. (No
230 * reason not to do this in C.)
231 */
232 boolean_t
233 db_trap_from_asm(
234 x86_saved_state32_t *regs)
235 {
236 int code;
237 int type;
238
239 type = regs->trapno;
240 code = regs->err;
241 return (kdb_trap(type, code, regs));
242 }
243
244 int
245 kdb_trap(
246 int type,
247 int code,
248 x86_saved_state32_t *regs)
249 {
250 extern char etext;
251 boolean_t trap_from_user;
252 spl_t s;
253 int previous_console_device;
254
255 s = splhigh();
256
257 previous_console_device = switch_to_serial_console();
258
259 db_printf("kdb_trap(): type %d, code %d, regs->eip 0x%x\n", type, code, regs->eip);
260 switch (type) {
261 case T_DEBUG: /* single_step */
262 {
263 extern int dr_addr[];
264 int addr;
265 uint32_t status;
266
267 __asm__ volatile ("movl %%dr6, %0" : "=r" (status));
268
269 if (status & 0xf) { /* hmm hdw break */
270 addr = status & 0x8 ? dr_addr[3] :
271 status & 0x4 ? dr_addr[2] :
272 status & 0x2 ? dr_addr[1] :
273 dr_addr[0];
274 regs->efl |= EFL_RF;
275 db_single_step_cmd(addr, 0, 1, "p");
276 }
277 }
278 case T_INT3: /* breakpoint */
279 case T_WATCHPOINT: /* watchpoint */
280 case -1: /* keyboard interrupt */
281 break;
282
283 default:
284 if (db_recover) {
285 i386_nested_saved_state = *regs;
286 db_printf("Caught ");
287 if (type < 0 || type > TRAP_TYPES)
288 db_printf("type %d", type);
289 else
290 db_printf("%s", trap_type[type]);
291 db_printf(" trap, code = %x, pc = %x\n",
292 code, regs->eip);
293 splx(s);
294 db_error("");
295 /*NOTREACHED*/
296 }
297 kdbprinttrap(type, code, (int *)&regs->eip, regs->uesp);
298 }
299
300 disable_preemption();
301
302 current_cpu_datap()->cpu_kdb_saved_ipl = s;
303 current_cpu_datap()->cpu_kdb_saved_state = regs;
304
305 i386_last_saved_statep = regs;
306 i386_last_kdb_sp = (unsigned) &type;
307
308 if (!kdb_enter(regs->eip))
309 goto kdb_exit;
310
311 /* Should switch to kdb's own stack here. */
312
313 if (!IS_USER_TRAP(regs, &etext)) {
314 bzero((char *)&ddb_regs, sizeof (ddb_regs));
315 *(struct x86_saved_state32_from_kernel *)&ddb_regs =
316 *(struct x86_saved_state32_from_kernel *)regs;
317 trap_from_user = FALSE;
318 }
319 else {
320 ddb_regs = *regs;
321 trap_from_user = TRUE;
322 }
323 if (!trap_from_user) {
324 /*
325 * Kernel mode - esp and ss not saved
326 */
327 ddb_regs.uesp = (int)&regs->uesp; /* kernel stack pointer */
328 ddb_regs.ss = KERNEL_DS;
329 }
330
331 db_active++;
332 db_task_trap(type, code, trap_from_user);
333 db_active--;
334
335 regs->eip = ddb_regs.eip;
336 regs->efl = ddb_regs.efl;
337 regs->eax = ddb_regs.eax;
338 regs->ecx = ddb_regs.ecx;
339 regs->edx = ddb_regs.edx;
340 regs->ebx = ddb_regs.ebx;
341
342 if (trap_from_user) {
343 /*
344 * user mode - saved esp and ss valid
345 */
346 regs->uesp = ddb_regs.uesp; /* user stack pointer */
347 regs->ss = ddb_regs.ss & 0xffff; /* user stack segment */
348 }
349
350 regs->ebp = ddb_regs.ebp;
351 regs->esi = ddb_regs.esi;
352 regs->edi = ddb_regs.edi;
353 regs->es = ddb_regs.es & 0xffff;
354 regs->cs = ddb_regs.cs & 0xffff;
355 regs->ds = ddb_regs.ds & 0xffff;
356 regs->fs = ddb_regs.fs & 0xffff;
357 regs->gs = ddb_regs.gs & 0xffff;
358
359 if ((type == T_INT3) &&
360 (db_get_task_value(regs->eip,
361 BKPT_SIZE,
362 FALSE,
363 db_target_space(current_thread(),
364 trap_from_user))
365 == BKPT_INST))
366 regs->eip += BKPT_SIZE;
367
368 switch_to_old_console(previous_console_device);
369 kdb_exit:
370 kdb_leave();
371
372 current_cpu_datap()->cpu_kdb_saved_state = 0;
373
374 enable_preemption();
375
376 splx(s);
377
378 /* Allow continue to upper layers of exception handling if
379 * trap was not a debugging trap.
380 */
381
382 if (trap_from_user && type != T_DEBUG && type != T_INT3
383 && type != T_WATCHPOINT)
384 return 0;
385 else
386 return (1);
387 }
388
389 /*
390 * Enter KDB through a keyboard trap.
391 * We show the registers as of the keyboard interrupt
392 * instead of those at its call to KDB.
393 */
394
395 spl_t kdb_oldspl;
396
397 void
398 kdb_kentry(
399 struct int_regs *int_regs)
400 {
401 extern char etext;
402 boolean_t trap_from_user;
403 x86_saved_state32_t *is = int_regs->is;
404 x86_saved_state32_t regs;
405 spl_t s;
406
407 s = splhigh();
408 kdb_oldspl = s;
409
410 if (IS_USER_TRAP(is, &etext))
411 {
412 regs.uesp = ((int *)(is+1))[0];
413 regs.ss = ((int *)(is+1))[1];
414 }
415 else {
416 regs.ss = KERNEL_DS;
417 regs.uesp= (int)(is+1);
418 }
419 regs.efl = is->efl;
420 regs.cs = is->cs;
421 regs.eip = is->eip;
422 regs.eax = is->eax;
423 regs.ecx = is->ecx;
424 regs.edx = is->edx;
425 regs.ebx = int_regs->ebx;
426 regs.ebp = int_regs->ebp;
427 regs.esi = int_regs->esi;
428 regs.edi = int_regs->edi;
429 regs.ds = is->ds;
430 regs.es = is->es;
431 regs.fs = int_regs->fs;
432 regs.gs = int_regs->gs;
433
434 disable_preemption();
435
436 current_cpu_datap()->cpu_kdb_saved_state = &regs;
437
438 if (!kdb_enter(regs.eip))
439 goto kdb_exit;
440
441 bcopy((char *)&regs, (char *)&ddb_regs, sizeof (ddb_regs));
442 trap_from_user = IS_USER_TRAP(&ddb_regs, &etext);
443
444 db_active++;
445 db_task_trap(-1, 0, trap_from_user);
446 db_active--;
447
448 if (trap_from_user) {
449 ((int *)(is+1))[0] = ddb_regs.uesp;
450 ((int *)(is+1))[1] = ddb_regs.ss & 0xffff;
451 }
452 is->efl = ddb_regs.efl;
453 is->cs = ddb_regs.cs & 0xffff;
454 is->eip = ddb_regs.eip;
455 is->eax = ddb_regs.eax;
456 is->ecx = ddb_regs.ecx;
457 is->edx = ddb_regs.edx;
458 int_regs->ebx = ddb_regs.ebx;
459 int_regs->ebp = ddb_regs.ebp;
460 int_regs->esi = ddb_regs.esi;
461 int_regs->edi = ddb_regs.edi;
462 is->ds = ddb_regs.ds & 0xffff;
463 is->es = ddb_regs.es & 0xffff;
464 int_regs->fs = ddb_regs.fs & 0xffff;
465 int_regs->gs = ddb_regs.gs & 0xffff;
466
467 kdb_exit:
468 kdb_leave();
469 current_cpu_datap()->cpu_kdb_saved_state = 0;
470
471 enable_preemption();
472
473 splx(s);
474 }
475
476 /*
477 * Print trap reason.
478 */
479
480 void
481 kdbprinttrap(
482 int type,
483 int code,
484 int *pc,
485 int sp)
486 {
487 printf("kernel: ");
488 if (type < 0 || type > TRAP_TYPES)
489 db_printf("type %d", type);
490 else
491 db_printf("%s", trap_type[type]);
492 db_printf(" trap, code=%x eip@%x = %x esp=%x\n",
493 code, pc, *(int *)pc, sp);
494 db_run_mode = STEP_CONTINUE;
495 }
496
497 int
498 db_user_to_kernel_address(
499 task_t task,
500 vm_offset_t addr,
501 unsigned *kaddr,
502 int flag)
503 {
504 register pt_entry_t *ptp;
505 vm_offset_t src;
506
507 /*
508 * must not pre-empted while using the pte pointer passed
509 * back since it's been mapped through a per-cpu window
510 */
511 mp_disable_preemption();
512
513 ptp = pmap_pte(task->map->pmap, (vm_map_offset_t)addr);
514 if (ptp == PT_ENTRY_NULL || (*ptp & INTEL_PTE_VALID) == 0) {
515 if (flag) {
516 db_printf("\nno memory is assigned to address %08x\n", addr);
517 db_error(0);
518 /* NOTREACHED */
519 }
520 mp_enable_preemption();
521 return(-1);
522 }
523 src = (vm_offset_t)pte_to_pa(*ptp);
524 mp_enable_preemption();
525
526 *(int *) DMAP1 = INTEL_PTE_VALID | INTEL_PTE_RW | (src & PG_FRAME) |
527 INTEL_PTE_REF | INTEL_PTE_MOD;
528 #if defined(I386_CPU)
529 if (cpu_class == CPUCLASS_386) {
530 invltlb();
531 } else
532 #endif
533 {
534 invlpg((u_int)DADDR1);
535 }
536
537 *kaddr = (unsigned)DADDR1 + (addr & PAGE_MASK);
538
539 return(0);
540 }
541
542 /*
543 * Read bytes from kernel address space for debugger.
544 */
545
546 void
547 db_read_bytes(
548 vm_offset_t addr,
549 int size,
550 char *data,
551 task_t task)
552 {
553 register char *src;
554 register int n;
555 unsigned kern_addr;
556
557 src = (char *)addr;
558 if (task == kernel_task || task == TASK_NULL) {
559 while (--size >= 0) {
560 if (addr++ > VM_MAX_KERNEL_ADDRESS) {
561 db_printf("\nbad address %x\n", addr);
562 db_error(0);
563 /* NOTREACHED */
564 }
565 *data++ = *src++;
566 }
567 return;
568 }
569 while (size > 0) {
570 if (db_user_to_kernel_address(task, addr, &kern_addr, 1) < 0)
571 return;
572 src = (char *)kern_addr;
573 n = intel_trunc_page(addr+INTEL_PGBYTES) - addr;
574 if (n > size)
575 n = size;
576 size -= n;
577 addr += n;
578 while (--n >= 0)
579 *data++ = *src++;
580 }
581 }
582
583 /*
584 * Write bytes to kernel address space for debugger.
585 */
586
587 void
588 db_write_bytes(
589 vm_offset_t addr,
590 int size,
591 char *data,
592 task_t task)
593 {
594 register char *dst;
595
596 register pt_entry_t *ptep0 = 0;
597 pt_entry_t oldmap0 = 0;
598 vm_offset_t addr1;
599 register pt_entry_t *ptep1 = 0;
600 pt_entry_t oldmap1 = 0;
601 extern char etext;
602
603 if (task && task != kernel_task) {
604 db_write_bytes_user_space(addr, size, data, task);
605 return;
606 }
607
608
609 if (addr >= VM_MIN_KERNEL_LOADED_ADDRESS) {
610 db_write_bytes_user_space(addr, size, data, kernel_task);
611 return;
612 }
613
614 if (addr >= VM_MIN_KERNEL_ADDRESS &&
615 addr <= (vm_offset_t)&etext)
616 {
617 ptep0 = pmap_pte(kernel_pmap, (vm_map_offset_t)addr);
618 oldmap0 = *ptep0;
619 *ptep0 |= INTEL_PTE_WRITE;
620
621 addr1 = i386_trunc_page(addr + size - 1);
622 if (i386_trunc_page(addr) != addr1) {
623 /* data crosses a page boundary */
624
625 ptep1 = pmap_pte(kernel_pmap, (vm_map_offset_t)addr1);
626 oldmap1 = *ptep1;
627 *ptep1 |= INTEL_PTE_WRITE;
628 }
629 flush_tlb();
630 }
631
632 dst = (char *)addr;
633
634 while (--size >= 0) {
635 if (addr++ > VM_MAX_KERNEL_ADDRESS) {
636 db_printf("\nbad address %x\n", addr);
637 db_error(0);
638 /* NOTREACHED */
639 }
640 *dst++ = *data++;
641 }
642
643 if (ptep0) {
644 *ptep0 = oldmap0;
645 if (ptep1) {
646 *ptep1 = oldmap1;
647 }
648 flush_tlb();
649 }
650 }
651
652 void
653 db_write_bytes_user_space(
654 vm_offset_t addr,
655 int size,
656 char *data,
657 task_t task)
658 {
659 register char *dst;
660 register int n;
661 unsigned kern_addr;
662
663 while (size > 0) {
664 if (db_user_to_kernel_address(task, addr, &kern_addr, 1) < 0)
665 return;
666 dst = (char *)kern_addr;
667 n = intel_trunc_page(addr+INTEL_PGBYTES) - addr;
668 if (n > size)
669 n = size;
670 size -= n;
671 addr += n;
672 while (--n >= 0)
673 *dst++ = *data++;
674 }
675 }
676
677 boolean_t
678 db_check_access(
679 vm_offset_t addr,
680 int size,
681 task_t task)
682 {
683 register n;
684 unsigned kern_addr;
685
686 if (task == kernel_task || task == TASK_NULL) {
687 if (kernel_task == TASK_NULL)
688 return(TRUE);
689 task = kernel_task;
690 } else if (task == TASK_NULL) {
691 if (current_thread() == THREAD_NULL)
692 return(FALSE);
693 task = current_thread()->task;
694 }
695 while (size > 0) {
696 if (db_user_to_kernel_address(task, addr, &kern_addr, 0) < 0)
697 return(FALSE);
698 n = intel_trunc_page(addr+INTEL_PGBYTES) - addr;
699 if (n > size)
700 n = size;
701 size -= n;
702 addr += n;
703 }
704 return(TRUE);
705 }
706
707 boolean_t
708 db_phys_eq(
709 task_t task1,
710 vm_offset_t addr1,
711 task_t task2,
712 vm_offset_t addr2)
713 {
714 unsigned kern_addr1, kern_addr2;
715
716 if ((addr1 & (INTEL_PGBYTES-1)) != (addr2 & (INTEL_PGBYTES-1)))
717 return(FALSE);
718 if (task1 == TASK_NULL) {
719 if (current_thread() == THREAD_NULL)
720 return(FALSE);
721 task1 = current_thread()->task;
722 }
723 if (db_user_to_kernel_address(task1, addr1, &kern_addr1, 0) < 0 ||
724 db_user_to_kernel_address(task2, addr2, &kern_addr2, 0) < 0)
725 return(FALSE);
726 return(kern_addr1 == kern_addr2);
727 }
728
729 #define DB_USER_STACK_ADDR (VM_MIN_KERNEL_ADDRESS)
730 #define DB_NAME_SEARCH_LIMIT (DB_USER_STACK_ADDR-(INTEL_PGBYTES*3))
731
732 int
733 db_search_null(
734 task_t task,
735 unsigned *svaddr,
736 unsigned evaddr,
737 unsigned *skaddr,
738 int flag)
739 {
740 register unsigned vaddr;
741 register unsigned *kaddr;
742
743 kaddr = (unsigned *)*skaddr;
744 for (vaddr = *svaddr; vaddr > evaddr; vaddr -= sizeof(unsigned)) {
745 if (vaddr % INTEL_PGBYTES == 0) {
746 vaddr -= sizeof(unsigned);
747 if (db_user_to_kernel_address(task, vaddr, skaddr, 0) < 0)
748 return(-1);
749 kaddr = (unsigned *)*skaddr;
750 } else {
751 vaddr -= sizeof(unsigned);
752 kaddr--;
753 }
754 if ((*kaddr == 0) ^ (flag == 0)) {
755 *svaddr = vaddr;
756 *skaddr = (unsigned)kaddr;
757 return(0);
758 }
759 }
760 return(-1);
761 }
762
763 void
764 db_task_name(
765 task_t task)
766 {
767 register char *p;
768 register n;
769 unsigned vaddr, kaddr;
770
771 vaddr = DB_USER_STACK_ADDR;
772 kaddr = 0;
773
774 /*
775 * skip nulls at the end
776 */
777 if (db_search_null(task, &vaddr, DB_NAME_SEARCH_LIMIT, &kaddr, 0) < 0) {
778 db_printf(DB_NULL_TASK_NAME);
779 return;
780 }
781 /*
782 * search start of args
783 */
784 if (db_search_null(task, &vaddr, DB_NAME_SEARCH_LIMIT, &kaddr, 1) < 0) {
785 db_printf(DB_NULL_TASK_NAME);
786 return;
787 }
788
789 n = DB_TASK_NAME_LEN-1;
790 p = (char *)kaddr + sizeof(unsigned);
791 for (vaddr += sizeof(int); vaddr < DB_USER_STACK_ADDR && n > 0;
792 vaddr++, p++, n--) {
793 if (vaddr % INTEL_PGBYTES == 0) {
794 (void)db_user_to_kernel_address(task, vaddr, &kaddr, 0);
795 p = (char*)kaddr;
796 }
797 db_printf("%c", (*p < ' ' || *p > '~')? ' ': *p);
798 }
799 while (n-- >= 0) /* compare with >= 0 for one more space */
800 db_printf(" ");
801 }
802
803 void
804 db_machdep_init(void)
805 {
806 int c;
807
808 db_simple_lock_init(&kdb_lock, 0);
809 for (c = 0; c < real_ncpus; ++c) {
810 if (c == master_cpu) {
811 master_dbtss.esp0 = (int)(db_task_stack_store +
812 (INTSTACK_SIZE * (c + 1)) - sizeof (natural_t));
813 master_dbtss.esp = master_dbtss.esp0;
814 master_dbtss.eip = (int)&db_task_start;
815 /*
816 * The TSS for the debugging task on each slave CPU
817 * is set up in cpu_desc_init().
818 */
819 }
820 }
821 }
822
823 /*
824 * Called when entering kdb:
825 * Takes kdb lock. If if we were called remotely (slave state) we just
826 * wait for kdb_cpu to be equal to cpu_number(). Otherwise enter kdb if
827 * not active on another cpu.
828 * If db_pass_thru[cpu_number()] > 0, then kdb can't stop now.
829 */
830
831 int
832 kdb_enter(int pc)
833 {
834 int my_cpu;
835 int retval;
836
837 disable_preemption();
838
839 my_cpu = cpu_number();
840
841 if (current_cpu_datap()->cpu_db_pass_thru) {
842 retval = 0;
843 goto kdb_exit;
844 }
845
846 current_cpu_datap()->cpu_kdb_active++;
847
848 lock_kdb();
849
850 db_printf("kdb_enter(): cpu_number %d, kdb_cpu %d\n", my_cpu, kdb_cpu);
851
852 if (db_breakpoints_inserted)
853 cpus_holding_bkpts++;
854
855 if (kdb_cpu == -1 && !current_cpu_datap()->cpu_kdb_is_slave) {
856 kdb_cpu = my_cpu;
857 db_printf("Signaling other processors..\n");
858 remote_kdb(); /* stop other cpus */
859 retval = 1;
860 } else if (kdb_cpu == my_cpu)
861 retval = 1;
862 else
863 retval = 0;
864
865 kdb_exit:
866 enable_preemption();
867
868 return (retval);
869 }
870
871 void
872 kdb_leave(void)
873 {
874 int my_cpu;
875 boolean_t wait = FALSE;
876
877 disable_preemption();
878
879 my_cpu = cpu_number();
880
881 if (db_run_mode == STEP_CONTINUE) {
882 wait = TRUE;
883 kdb_cpu = -1;
884 }
885 if (db_breakpoints_inserted)
886 cpus_holding_bkpts--;
887 if (current_cpu_datap()->cpu_kdb_is_slave)
888 current_cpu_datap()->cpu_kdb_is_slave--;
889 if (kdb_debug)
890 db_printf("kdb_leave: cpu %d, kdb_cpu %d, run_mode %d pc %x (%x) holds %d\n",
891 my_cpu, kdb_cpu, db_run_mode,
892 ddb_regs.eip, *(int *)ddb_regs.eip,
893 cpus_holding_bkpts);
894 clear_kdb_intr();
895 unlock_kdb();
896 current_cpu_datap()->cpu_kdb_active--;
897
898 mp_kdb_exit();
899
900 enable_preemption();
901
902 if (wait) {
903 while(cpus_holding_bkpts);
904 }
905 }
906
907 void
908 lock_kdb(void)
909 {
910 int my_cpu;
911 register i;
912
913 disable_preemption();
914
915 my_cpu = cpu_number();
916
917 for(;;) {
918 if (kdb_cpu != -1 && kdb_cpu != my_cpu) {
919 continue;
920 }
921 if (db_simple_lock_try(&kdb_lock)) {
922 if (kdb_cpu == -1 || kdb_cpu == my_cpu)
923 break;
924 db_simple_unlock(&kdb_lock);
925 }
926 }
927
928 enable_preemption();
929 }
930
931 #if TIME_STAMP
932 extern unsigned old_time_stamp;
933 #endif /* TIME_STAMP */
934
935 void
936 unlock_kdb(void)
937 {
938 db_simple_unlock(&kdb_lock);
939 #if TIME_STAMP
940 old_time_stamp = 0;
941 #endif /* TIME_STAMP */
942 }
943
944
945 #ifdef __STDC__
946 #define KDB_SAVE(type, name) extern type name; type name##_save = name
947 #define KDB_RESTORE(name) name = name##_save
948 #else /* __STDC__ */
949 #define KDB_SAVE(type, name) extern type name; type name/**/_save = name
950 #define KDB_RESTORE(name) name = name/**/_save
951 #endif /* __STDC__ */
952
953 #define KDB_SAVE_CTXT() \
954 KDB_SAVE(int, db_run_mode); \
955 KDB_SAVE(boolean_t, db_sstep_print); \
956 KDB_SAVE(int, db_loop_count); \
957 KDB_SAVE(int, db_call_depth); \
958 KDB_SAVE(int, db_inst_count); \
959 KDB_SAVE(int, db_last_inst_count); \
960 KDB_SAVE(int, db_load_count); \
961 KDB_SAVE(int, db_store_count); \
962 KDB_SAVE(boolean_t, db_cmd_loop_done); \
963 KDB_SAVE(jmp_buf_t *, db_recover); \
964 KDB_SAVE(db_addr_t, db_dot); \
965 KDB_SAVE(db_addr_t, db_last_addr); \
966 KDB_SAVE(db_addr_t, db_prev); \
967 KDB_SAVE(db_addr_t, db_next); \
968 KDB_SAVE(db_regs_t, ddb_regs);
969
970 #define KDB_RESTORE_CTXT() \
971 KDB_RESTORE(db_run_mode); \
972 KDB_RESTORE(db_sstep_print); \
973 KDB_RESTORE(db_loop_count); \
974 KDB_RESTORE(db_call_depth); \
975 KDB_RESTORE(db_inst_count); \
976 KDB_RESTORE(db_last_inst_count); \
977 KDB_RESTORE(db_load_count); \
978 KDB_RESTORE(db_store_count); \
979 KDB_RESTORE(db_cmd_loop_done); \
980 KDB_RESTORE(db_recover); \
981 KDB_RESTORE(db_dot); \
982 KDB_RESTORE(db_last_addr); \
983 KDB_RESTORE(db_prev); \
984 KDB_RESTORE(db_next); \
985 KDB_RESTORE(ddb_regs);
986
987 /*
988 * switch to another cpu
989 */
990
991 void
992 kdb_on(
993 int cpu)
994 {
995 KDB_SAVE_CTXT();
996 if (cpu < 0 || cpu >= real_ncpus || !cpu_datap(cpu)->cpu_kdb_active)
997 return;
998 db_set_breakpoints();
999 db_set_watchpoints();
1000 kdb_cpu = cpu;
1001 unlock_kdb();
1002 lock_kdb();
1003 db_clear_breakpoints();
1004 db_clear_watchpoints();
1005 KDB_RESTORE_CTXT();
1006 if (kdb_cpu == -1) {/* someone continued */
1007 kdb_cpu = cpu_number();
1008 db_continue_cmd(0, 0, 0, "");
1009 }
1010 }
1011
1012 /*
1013 * system reboot
1014 */
1015
1016 extern void kdp_machine_reboot(void);
1017
1018 void db_reboot(
1019 db_expr_t addr,
1020 boolean_t have_addr,
1021 db_expr_t count,
1022 char *modif)
1023 {
1024 kdp_machine_reboot();
1025 }