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