]> git.saurik.com Git - apple/xnu.git/blame - osfmk/i386/db_interface.c
xnu-792.13.8.tar.gz
[apple/xnu.git] / osfmk / i386 / db_interface.c
CommitLineData
1c79356b 1/*
5d5c5d0d 2 * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
8ad349bb 4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
1c79356b 5 *
8ad349bb
A
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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
1c79356b
A
29 */
30/*
31 * @OSF_COPYRIGHT@
32 */
33/*
34 * Mach Operating System
35 * Copyright (c) 1991,1990 Carnegie Mellon University
36 * All Rights Reserved.
37 *
38 * Permission to use, copy, modify and distribute this software and its
39 * documentation is hereby granted, provided that both the copyright
40 * notice and this permission notice appear in all copies of the
41 * software, derivative works or modified versions, and any portions
42 * thereof, and that both notices appear in supporting documentation.
43 *
44 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
45 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
46 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
47 *
48 * Carnegie Mellon requests users of this software to return to
49 *
50 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
51 * School of Computer Science
52 * Carnegie Mellon University
53 * Pittsburgh PA 15213-3890
54 *
55 * any improvements or extensions that they make and grant Carnegie Mellon
56 * the rights to redistribute these changes.
57 */
58/*
59 */
60
61/*
62 * Interface to new debugger.
63 */
1c79356b
A
64#include <platforms.h>
65#include <time_stamp.h>
66#include <mach_mp_debug.h>
67#include <mach_ldebug.h>
68#include <kern/spl.h>
69#include <kern/cpu_number.h>
70#include <kern/kern_types.h>
71#include <kern/misc_protos.h>
72#include <vm/pmap.h>
73
74#include <i386/thread.h>
75#include <i386/db_machdep.h>
76#include <i386/seg.h>
77#include <i386/trap.h>
78#include <i386/setjmp.h>
79#include <i386/pmap.h>
80#include <i386/misc_protos.h>
5d5c5d0d
A
81#include <i386/mp.h>
82#include <i386/machine_cpu.h>
1c79356b
A
83
84#include <mach/vm_param.h>
85#include <vm/vm_map.h>
86#include <kern/thread.h>
87#include <kern/task.h>
88
89#include <ddb/db_command.h>
90#include <ddb/db_task_thread.h>
91#include <ddb/db_run.h>
92#include <ddb/db_trap.h>
93#include <ddb/db_output.h>
94#include <ddb/db_access.h>
95#include <ddb/db_sym.h>
96#include <ddb/db_break.h>
97#include <ddb/db_watch.h>
98
5d5c5d0d
A
99#include <i386/cpu_data.h>
100
1c79356b 101int db_active = 0;
5d5c5d0d
A
102x86_saved_state32_t *i386_last_saved_statep;
103x86_saved_state32_t i386_nested_saved_state;
1c79356b
A
104unsigned i386_last_kdb_sp;
105
91447636
A
106extern thread_t db_default_act;
107extern pt_entry_t *DMAP1;
108extern caddr_t DADDR1;
1c79356b
A
109
110#if MACH_MP_DEBUG
111extern int masked_state_cnt[];
112#endif /* MACH_MP_DEBUG */
113
114/*
115 * Enter KDB through a keyboard trap.
116 * We show the registers as of the keyboard interrupt
117 * instead of those at its call to KDB.
118 */
119struct int_regs {
120 int gs;
121 int fs;
122 int edi;
123 int esi;
124 int ebp;
125 int ebx;
5d5c5d0d 126 x86_saved_state32_t *is;
1c79356b
A
127};
128
129extern char * trap_type[];
130extern int TRAP_TYPES;
131
132/* Forward */
133
134extern void kdbprinttrap(
135 int type,
136 int code,
137 int *pc,
138 int sp);
139extern void kdb_kentry(
140 struct int_regs *int_regs);
141extern int db_user_to_kernel_address(
142 task_t task,
143 vm_offset_t addr,
144 unsigned *kaddr,
145 int flag);
146extern void db_write_bytes_user_space(
147 vm_offset_t addr,
148 int size,
149 char *data,
150 task_t task);
151extern int db_search_null(
152 task_t task,
153 unsigned *svaddr,
154 unsigned evaddr,
155 unsigned *skaddr,
156 int flag);
157extern int kdb_enter(int);
158extern void kdb_leave(void);
159extern void lock_kdb(void);
160extern void unlock_kdb(void);
161
162/*
163 * kdb_trap - field a TRACE or BPT trap
164 */
165
166
167extern jmp_buf_t *db_recover;
1c79356b
A
168
169/*
170 * Translate the state saved in a task state segment into an
171 * exception frame. Since we "know" we always want the state
172 * in a ktss, we hard-wire that in, rather than indexing the gdt
173 * with tss_sel to derive a pointer to the desired tss.
174 */
5d5c5d0d
A
175
176/*
177 * Code used to synchronize kdb among all cpus, one active at a time, switch
178 * from one to another using cpu #cpu
179 */
180
181decl_simple_lock_data(, kdb_lock) /* kdb lock */
182
183#define db_simple_lock_init(l, e) hw_lock_init(&((l)->interlock))
184#define db_simple_lock_try(l) hw_lock_try(&((l)->interlock))
185#define db_simple_unlock(l) hw_lock_unlock(&((l)->interlock))
186
187int kdb_cpu = -1; /* current cpu running kdb */
188int kdb_debug = 1;
189volatile unsigned int cpus_holding_bkpts; /* counter for number of cpus
190 * holding breakpoints
191 */
192extern boolean_t db_breakpoints_inserted;
193
1c79356b
A
194void
195db_tss_to_frame(
196 int tss_sel,
5d5c5d0d 197 x86_saved_state32_t *regs)
1c79356b
A
198{
199 extern struct i386_tss ktss;
200 int mycpu = cpu_number();
201 struct i386_tss *tss;
202
91447636 203 tss = cpu_datap(mycpu)->cpu_desc_index.cdi_ktss; /* XXX */
1c79356b
A
204
205 /*
206 * ddb will overwrite whatever's in esp, so put esp0 elsewhere, too.
207 */
5d5c5d0d 208 regs->cr2 = tss->esp0;
1c79356b
A
209 regs->efl = tss->eflags;
210 regs->eip = tss->eip;
211 regs->trapno = tss->ss0; /* XXX */
212 regs->err = tss->esp0; /* XXX */
213 regs->eax = tss->eax;
214 regs->ecx = tss->ecx;
215 regs->edx = tss->edx;
216 regs->ebx = tss->ebx;
217 regs->uesp = tss->esp;
218 regs->ebp = tss->ebp;
219 regs->esi = tss->esi;
220 regs->edi = tss->edi;
221 regs->es = tss->es;
222 regs->ss = tss->ss;
223 regs->cs = tss->cs;
224 regs->ds = tss->ds;
225 regs->fs = tss->fs;
226 regs->gs = tss->gs;
227}
228
229/*
230 * Compose a call to the debugger from the saved state in regs. (No
231 * reason not to do this in C.)
232 */
233boolean_t
234db_trap_from_asm(
5d5c5d0d 235 x86_saved_state32_t *regs)
1c79356b
A
236{
237 int code;
238 int type;
239
240 type = regs->trapno;
241 code = regs->err;
242 return (kdb_trap(type, code, regs));
243}
244
245int
246kdb_trap(
247 int type,
248 int code,
5d5c5d0d 249 x86_saved_state32_t *regs)
1c79356b
A
250{
251 extern char etext;
252 boolean_t trap_from_user;
5d5c5d0d
A
253 spl_t s;
254 int previous_console_device;
1c79356b 255
5d5c5d0d
A
256 s = splhigh();
257
258 previous_console_device = switch_to_serial_console();
259
260 db_printf("kdb_trap(): type %d, code %d, regs->eip 0x%x\n", type, code, regs->eip);
1c79356b
A
261 switch (type) {
262 case T_DEBUG: /* single_step */
263 {
264 extern int dr_addr[];
265 int addr;
266 int status = dr6();
267
268 if (status & 0xf) { /* hmm hdw break */
269 addr = status & 0x8 ? dr_addr[3] :
270 status & 0x4 ? dr_addr[2] :
271 status & 0x2 ? dr_addr[1] :
272 dr_addr[0];
273 regs->efl |= EFL_RF;
274 db_single_step_cmd(addr, 0, 1, "p");
275 }
276 }
277 case T_INT3: /* breakpoint */
278 case T_WATCHPOINT: /* watchpoint */
279 case -1: /* keyboard interrupt */
280 break;
281
282 default:
283 if (db_recover) {
284 i386_nested_saved_state = *regs;
285 db_printf("Caught ");
286 if (type < 0 || type > TRAP_TYPES)
287 db_printf("type %d", type);
288 else
289 db_printf("%s", trap_type[type]);
290 db_printf(" trap, code = %x, pc = %x\n",
291 code, regs->eip);
292 splx(s);
293 db_error("");
294 /*NOTREACHED*/
295 }
296 kdbprinttrap(type, code, (int *)&regs->eip, regs->uesp);
297 }
298
1c79356b 299 disable_preemption();
1c79356b 300
91447636
A
301 current_cpu_datap()->cpu_kdb_saved_ipl = s;
302 current_cpu_datap()->cpu_kdb_saved_state = regs;
1c79356b
A
303
304 i386_last_saved_statep = regs;
305 i386_last_kdb_sp = (unsigned) &type;
306
1c79356b
A
307 if (!kdb_enter(regs->eip))
308 goto kdb_exit;
1c79356b
A
309
310 /* Should switch to kdb's own stack here. */
311
312 if (!IS_USER_TRAP(regs, &etext)) {
313 bzero((char *)&ddb_regs, sizeof (ddb_regs));
5d5c5d0d
A
314 *(struct x86_saved_state32_from_kernel *)&ddb_regs =
315 *(struct x86_saved_state32_from_kernel *)regs;
1c79356b
A
316 trap_from_user = FALSE;
317 }
318 else {
319 ddb_regs = *regs;
320 trap_from_user = TRUE;
321 }
322 if (!trap_from_user) {
323 /*
324 * Kernel mode - esp and ss not saved
325 */
326 ddb_regs.uesp = (int)&regs->uesp; /* kernel stack pointer */
327 ddb_regs.ss = KERNEL_DS;
328 }
329
330 db_active++;
331 db_task_trap(type, code, trap_from_user);
332 db_active--;
333
334 regs->eip = ddb_regs.eip;
335 regs->efl = ddb_regs.efl;
336 regs->eax = ddb_regs.eax;
337 regs->ecx = ddb_regs.ecx;
338 regs->edx = ddb_regs.edx;
339 regs->ebx = ddb_regs.ebx;
5d5c5d0d 340
1c79356b
A
341 if (trap_from_user) {
342 /*
343 * user mode - saved esp and ss valid
344 */
345 regs->uesp = ddb_regs.uesp; /* user stack pointer */
346 regs->ss = ddb_regs.ss & 0xffff; /* user stack segment */
347 }
5d5c5d0d 348
1c79356b
A
349 regs->ebp = ddb_regs.ebp;
350 regs->esi = ddb_regs.esi;
351 regs->edi = ddb_regs.edi;
352 regs->es = ddb_regs.es & 0xffff;
353 regs->cs = ddb_regs.cs & 0xffff;
354 regs->ds = ddb_regs.ds & 0xffff;
355 regs->fs = ddb_regs.fs & 0xffff;
356 regs->gs = ddb_regs.gs & 0xffff;
357
358 if ((type == T_INT3) &&
359 (db_get_task_value(regs->eip,
360 BKPT_SIZE,
361 FALSE,
91447636 362 db_target_space(current_thread(),
1c79356b
A
363 trap_from_user))
364 == BKPT_INST))
365 regs->eip += BKPT_SIZE;
5d5c5d0d
A
366
367 switch_to_old_console(previous_console_device);
1c79356b
A
368kdb_exit:
369 kdb_leave();
1c79356b 370
91447636 371 current_cpu_datap()->cpu_kdb_saved_state = 0;
1c79356b 372
1c79356b 373 enable_preemption();
1c79356b
A
374
375 splx(s);
376
377 /* Allow continue to upper layers of exception handling if
378 * trap was not a debugging trap.
379 */
380
381 if (trap_from_user && type != T_DEBUG && type != T_INT3
382 && type != T_WATCHPOINT)
383 return 0;
384 else
385 return (1);
386}
387
388/*
389 * Enter KDB through a keyboard trap.
390 * We show the registers as of the keyboard interrupt
391 * instead of those at its call to KDB.
392 */
393
394spl_t kdb_oldspl;
395
396void
397kdb_kentry(
398 struct int_regs *int_regs)
399{
400 extern char etext;
401 boolean_t trap_from_user;
5d5c5d0d
A
402 x86_saved_state32_t *is = int_regs->is;
403 x86_saved_state32_t regs;
1c79356b
A
404 spl_t s;
405
406 s = splhigh();
407 kdb_oldspl = s;
408
409 if (IS_USER_TRAP(is, &etext))
410 {
411 regs.uesp = ((int *)(is+1))[0];
412 regs.ss = ((int *)(is+1))[1];
413 }
414 else {
415 regs.ss = KERNEL_DS;
416 regs.uesp= (int)(is+1);
417 }
418 regs.efl = is->efl;
419 regs.cs = is->cs;
420 regs.eip = is->eip;
421 regs.eax = is->eax;
422 regs.ecx = is->ecx;
423 regs.edx = is->edx;
424 regs.ebx = int_regs->ebx;
425 regs.ebp = int_regs->ebp;
426 regs.esi = int_regs->esi;
427 regs.edi = int_regs->edi;
428 regs.ds = is->ds;
429 regs.es = is->es;
430 regs.fs = int_regs->fs;
431 regs.gs = int_regs->gs;
432
1c79356b 433 disable_preemption();
1c79356b 434
91447636 435 current_cpu_datap()->cpu_kdb_saved_state = &regs;
1c79356b 436
1c79356b
A
437 if (!kdb_enter(regs.eip))
438 goto kdb_exit;
1c79356b
A
439
440 bcopy((char *)&regs, (char *)&ddb_regs, sizeof (ddb_regs));
441 trap_from_user = IS_USER_TRAP(&ddb_regs, &etext);
442
443 db_active++;
444 db_task_trap(-1, 0, trap_from_user);
445 db_active--;
446
447 if (trap_from_user) {
448 ((int *)(is+1))[0] = ddb_regs.uesp;
449 ((int *)(is+1))[1] = ddb_regs.ss & 0xffff;
450 }
451 is->efl = ddb_regs.efl;
452 is->cs = ddb_regs.cs & 0xffff;
453 is->eip = ddb_regs.eip;
454 is->eax = ddb_regs.eax;
455 is->ecx = ddb_regs.ecx;
456 is->edx = ddb_regs.edx;
457 int_regs->ebx = ddb_regs.ebx;
458 int_regs->ebp = ddb_regs.ebp;
459 int_regs->esi = ddb_regs.esi;
460 int_regs->edi = ddb_regs.edi;
461 is->ds = ddb_regs.ds & 0xffff;
462 is->es = ddb_regs.es & 0xffff;
463 int_regs->fs = ddb_regs.fs & 0xffff;
464 int_regs->gs = ddb_regs.gs & 0xffff;
465
1c79356b
A
466kdb_exit:
467 kdb_leave();
91447636 468 current_cpu_datap()->cpu_kdb_saved_state = 0;
1c79356b 469
1c79356b 470 enable_preemption();
1c79356b
A
471
472 splx(s);
473}
474
475/*
476 * Print trap reason.
477 */
478
479void
480kdbprinttrap(
481 int type,
482 int code,
483 int *pc,
484 int sp)
485{
486 printf("kernel: ");
487 if (type < 0 || type > TRAP_TYPES)
488 db_printf("type %d", type);
489 else
490 db_printf("%s", trap_type[type]);
491 db_printf(" trap, code=%x eip@%x = %x esp=%x\n",
492 code, pc, *(int *)pc, sp);
493 db_run_mode = STEP_CONTINUE;
494}
495
496int
497db_user_to_kernel_address(
498 task_t task,
499 vm_offset_t addr,
500 unsigned *kaddr,
501 int flag)
502{
503 register pt_entry_t *ptp;
5d5c5d0d
A
504 vm_offset_t src;
505
506 /*
507 * must not pre-empted while using the pte pointer passed
508 * back since it's been mapped through a per-cpu window
509 */
510 mp_disable_preemption();
1c79356b 511
5d5c5d0d 512 ptp = pmap_pte(task->map->pmap, (vm_map_offset_t)addr);
1c79356b
A
513 if (ptp == PT_ENTRY_NULL || (*ptp & INTEL_PTE_VALID) == 0) {
514 if (flag) {
515 db_printf("\nno memory is assigned to address %08x\n", addr);
516 db_error(0);
517 /* NOTREACHED */
518 }
5d5c5d0d 519 mp_enable_preemption();
1c79356b
A
520 return(-1);
521 }
8ad349bb 522 src = (vm_offset_t)pte_to_pa(*ptp);
5d5c5d0d
A
523
524 mp_enable_preemption();
525
91447636
A
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
1c79356b
A
539 return(0);
540}
541
542/*
543 * Read bytes from kernel address space for debugger.
544 */
545
546void
547db_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
587void
588db_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 {
5d5c5d0d 617 ptep0 = pmap_pte(kernel_pmap, (vm_map_offset_t)addr);
1c79356b
A
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
5d5c5d0d 625 ptep1 = pmap_pte(kernel_pmap, (vm_map_offset_t)addr1);
1c79356b
A
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
652void
653db_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
677boolean_t
678db_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) {
91447636 691 if (current_thread() == THREAD_NULL)
1c79356b 692 return(FALSE);
91447636 693 task = current_thread()->task;
1c79356b
A
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
707boolean_t
708db_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) {
91447636 719 if (current_thread() == THREAD_NULL)
1c79356b 720 return(FALSE);
91447636 721 task1 = current_thread()->task;
1c79356b
A
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
732int
733db_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
763void
764db_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
1c79356b
A
803void
804db_machdep_init(void)
805{
806 int c;
807
91447636
A
808 db_simple_lock_init(&kdb_lock, 0);
809 for (c = 0; c < real_ncpus; ++c) {
1c79356b 810 if (c == master_cpu) {
5d5c5d0d 811 master_dbtss.esp0 = (int)(db_task_stack_store +
1c79356b 812 (INTSTACK_SIZE * (c + 1)) - sizeof (natural_t));
5d5c5d0d
A
813 master_dbtss.esp = master_dbtss.esp0;
814 master_dbtss.eip = (int)&db_task_start;
1c79356b
A
815 /*
816 * The TSS for the debugging task on each slave CPU
5d5c5d0d 817 * is set up in cpu_desc_init().
1c79356b
A
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
831int
832kdb_enter(int pc)
833{
5d5c5d0d 834 int my_cpu;
1c79356b
A
835 int retval;
836
1c79356b 837 disable_preemption();
1c79356b 838
5d5c5d0d 839 my_cpu = cpu_number();
1c79356b 840
91447636 841 if (current_cpu_datap()->cpu_db_pass_thru) {
1c79356b
A
842 retval = 0;
843 goto kdb_exit;
844 }
845
91447636 846 current_cpu_datap()->cpu_kdb_active++;
5d5c5d0d 847
1c79356b
A
848 lock_kdb();
849
5d5c5d0d
A
850 db_printf("kdb_enter(): cpu_number %d, kdb_cpu %d\n", my_cpu, kdb_cpu);
851
1c79356b
A
852 if (db_breakpoints_inserted)
853 cpus_holding_bkpts++;
5d5c5d0d 854
91447636 855 if (kdb_cpu == -1 && !current_cpu_datap()->cpu_kdb_is_slave) {
1c79356b 856 kdb_cpu = my_cpu;
5d5c5d0d 857 db_printf("Signaling other processors..\n");
1c79356b
A
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
865kdb_exit:
1c79356b 866 enable_preemption();
1c79356b
A
867
868 return (retval);
869}
870
871void
872kdb_leave(void)
873{
874 int my_cpu;
875 boolean_t wait = FALSE;
876
1c79356b 877 disable_preemption();
1c79356b
A
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--;
91447636
A
887 if (current_cpu_datap()->cpu_kdb_is_slave)
888 current_cpu_datap()->cpu_kdb_is_slave--;
1c79356b
A
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();
91447636 896 current_cpu_datap()->cpu_kdb_active--;
1c79356b 897
5d5c5d0d
A
898 mp_kdb_exit();
899
1c79356b 900 enable_preemption();
1c79356b
A
901
902 if (wait) {
903 while(cpus_holding_bkpts);
904 }
905}
906
907void
908lock_kdb(void)
909{
910 int my_cpu;
911 register i;
1c79356b 912
1c79356b 913 disable_preemption();
1c79356b
A
914
915 my_cpu = cpu_number();
916
917 for(;;) {
1c79356b
A
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
1c79356b 928 enable_preemption();
1c79356b
A
929}
930
931#if TIME_STAMP
932extern unsigned old_time_stamp;
933#endif /* TIME_STAMP */
934
935void
936unlock_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
991void
992kdb_on(
993 int cpu)
994{
995 KDB_SAVE_CTXT();
91447636 996 if (cpu < 0 || cpu >= real_ncpus || !cpu_datap(cpu)->cpu_kdb_active)
1c79356b
A
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
5d5c5d0d
A
1012/*
1013 * system reboot
1014 */
1015
1016extern void kdp_reboot(void);
1017
1c79356b
A
1018void db_reboot(
1019 db_expr_t addr,
1020 boolean_t have_addr,
1021 db_expr_t count,
1022 char *modif)
1023{
5d5c5d0d 1024 kdp_reboot();
1c79356b 1025}