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