This commit was manufactured by cvs2svn to create tag 'FreeBSD-release/1.0'.
[unix-history] / sys / i386 / i386 / db_interface.c
CommitLineData
15637ed4
RG
1/*
2 * Mach Operating System
3 * Copyright (c) 1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie the
24 * rights to redistribute these changes.
15637ed4 25 *
78ed81a3 26 * $Id$
15637ed4
RG
27 */
28
29/*
30 * Interface to new debugger.
31 */
32#include "param.h"
33#include "proc.h"
34#include <machine/db_machdep.h>
35
36#include <sys/reboot.h>
37#include <vm/vm_statistics.h>
38#include <vm/pmap.h>
39
40#include <setjmp.h>
41#include <sys/systm.h> /* just for boothowto --eichin */
42int db_active = 0;
43
44/*
45 * Received keyboard interrupt sequence.
46 */
47kdb_kbd_trap(regs)
48 struct i386_saved_state *regs;
49{
50 if (db_active == 0 && (boothowto & RB_KDB)) {
51 printf("\n\nkernel: keyboard interrupt\n");
52 kdb_trap(-1, 0, regs);
53 }
54}
55
56/*
57 * kdb_trap - field a TRACE or BPT trap
58 */
59
60static jmp_buf *db_nofault = 0;
61
62kdb_trap(type, code, regs)
63 int type, code;
64 register struct i386_saved_state *regs;
65{
66#if 0
67 if ((boothowto&RB_KDB) == 0)
68 return(0);
69#endif
70
71 switch (type) {
72 case T_BPTFLT /* T_INT3 */: /* breakpoint */
73 case T_KDBTRAP /* T_WATCHPOINT */: /* watchpoint */
74 case T_PRIVINFLT /* T_DEBUG */: /* single_step */
75
76 case -1: /* keyboard interrupt */
77 break;
78
79 default:
80 kdbprinttrap(type, code);
81
82 if (db_nofault) {
83 jmp_buf *no_fault = db_nofault;
84 db_nofault = 0;
85 longjmp(*no_fault, 1);
86 }
87 }
88
89 /* Should switch to kdb`s own stack here. */
90
91 ddb_regs = *regs;
92
93 if ((regs->tf_cs & 0x3) == 0) {
94 /*
95 * Kernel mode - esp and ss not saved
96 */
97 ddb_regs.tf_esp = (int)&regs->tf_esp; /* kernel stack pointer */
98#if 0
99 ddb_regs.ss = KERNEL_DS;
100#endif
101 asm(" movw %%ss,%%ax; movl %%eax,%0 "
102 : "=g" (ddb_regs.tf_ss)
103 :
104 : "ax");
105 }
106
107 db_active++;
108 cnpollc(TRUE);
109 db_trap(type, code);
110 cnpollc(FALSE);
111 db_active--;
112
113 regs->tf_eip = ddb_regs.tf_eip;
114 regs->tf_eflags = ddb_regs.tf_eflags;
115 regs->tf_eax = ddb_regs.tf_eax;
116 regs->tf_ecx = ddb_regs.tf_ecx;
117 regs->tf_edx = ddb_regs.tf_edx;
118 regs->tf_ebx = ddb_regs.tf_ebx;
119 if (regs->tf_cs & 0x3) {
120 /*
121 * user mode - saved esp and ss valid
122 */
123 regs->tf_esp = ddb_regs.tf_esp; /* user stack pointer */
124 regs->tf_ss = ddb_regs.tf_ss & 0xffff; /* user stack segment */
125 }
126 regs->tf_ebp = ddb_regs.tf_ebp;
127 regs->tf_esi = ddb_regs.tf_esi;
128 regs->tf_edi = ddb_regs.tf_edi;
129 regs->tf_es = ddb_regs.tf_es & 0xffff;
130 regs->tf_cs = ddb_regs.tf_cs & 0xffff;
131 regs->tf_ds = ddb_regs.tf_ds & 0xffff;
132#if 0
133 regs->tf_fs = ddb_regs.tf_fs & 0xffff;
134 regs->tf_gs = ddb_regs.tf_gs & 0xffff;
135#endif
136
137 return (1);
138}
139
140/*
141 * Print trap reason.
142 */
143kdbprinttrap(type, code)
144 int type, code;
145{
146 printf("kernel: ");
147 printf("type %d", type);
148 printf(" trap, code=%x\n", code);
149}
150
151/*
152 * Read bytes from kernel address space for debugger.
153 */
154
155extern jmp_buf db_jmpbuf;
156
157void
158db_read_bytes(addr, size, data)
159 vm_offset_t addr;
160 register int size;
161 register char *data;
162{
163 register char *src;
164
165 db_nofault = &db_jmpbuf;
166
167 src = (char *)addr;
168 while (--size >= 0)
169 *data++ = *src++;
170
171 db_nofault = 0;
172}
173
174struct pte *pmap_pte(pmap_t, vm_offset_t);
175
176/*
177 * Write bytes to kernel address space for debugger.
178 */
179void
180db_write_bytes(addr, size, data)
181 vm_offset_t addr;
182 register int size;
183 register char *data;
184{
185 register char *dst;
186
187 register pt_entry_t *ptep0 = 0;
188 pt_entry_t oldmap0 = { 0 };
189 vm_offset_t addr1;
190 register pt_entry_t *ptep1 = 0;
191 pt_entry_t oldmap1 = { 0 };
192 extern char etext;
193
194 db_nofault = &db_jmpbuf;
195
196 if (addr >= VM_MIN_KERNEL_ADDRESS &&
197 addr <= (vm_offset_t)&etext)
198 {
199 ptep0 = pmap_pte(kernel_pmap, addr);
200 oldmap0 = *ptep0;
201 *(int *)ptep0 |= /* INTEL_PTE_WRITE */ PG_RW;
202
203 addr1 = i386_trunc_page(addr + size - 1);
204 if (i386_trunc_page(addr) != addr1) {
205 /* data crosses a page boundary */
206
207 ptep1 = pmap_pte(kernel_pmap, addr1);
208 oldmap1 = *ptep1;
209 *(int *)ptep1 |= /* INTEL_PTE_WRITE */ PG_RW;
210 }
211 tlbflush();
212 }
213
214 dst = (char *)addr;
215
216 while (--size >= 0)
217 *dst++ = *data++;
218
219 db_nofault = 0;
220
221 if (ptep0) {
222 *ptep0 = oldmap0;
223 if (ptep1) {
224 *ptep1 = oldmap1;
225 }
226 tlbflush();
227 }
228}
229
230Debugger (msg)
231char *msg;
232{
233 asm ("int $3");
234}