1 /*
2 * Mach Operating System
3 * Copyright (c) 1993,1992 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 "AS IS"
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 Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * The i386 machine specific Kernel TTD code.
28 *
29 * HISTORY:
30 * $Log: kttd_interface.c,v $
31 * Revision 2.2 93/05/10 23:23:34 rvb
32 * Checkin for MK80 branch.
33 * [93/05/10 15:11:12 grm]
34 *
35 * Revision 2.1.1.2 93/04/20 11:44:01 grm
36 * Changed for use with different asyncronous entry logic.
37 *
38 * Revision 2.1.1.1 93/03/25 11:31:47 grm
39 * Moved here from ../i386at.
40 *
41 *
42 */
43 #include <kern/thread.h>
44 #include <kern/processor.h>
45 #include <mach/thread_status.h>
46 #include <mach/vm_param.h>
47 #include <i386/eflags.h>
48 #include <i386/seg.h>
49 #include <sys/types.h>
50
51 #include <ttd/ttd_types.h>
52 #include <ttd/ttd_stub.h>
53 #include <machine/kttd_machdep.h>
54
55 /*
56 * Shamelessly copied from the ddb sources:
57 */
58 struct i386_saved_state *kttd_last_saved_statep;
59 struct i386_saved_state kttd_nested_saved_state;
60 unsigned last_kttd_sp;
61
62 struct i386_saved_state kttd_regs; /* was ddb_regs */
63
64 extern int kttd_debug;
65 extern boolean_t kttd_enabled;
66 extern vm_offset_t virtual_end;
67
68 #define I386_BREAKPOINT 0xcc
69
70 /*
71 * kernel map
72 */
73 extern vm_map_t kernel_map;
74
75 boolean_t kttd_console_init(void)
76 {
77 /*
78 * Get local machine's IP address via bootp.
79 */
80 return(ttd_ip_bootp());
81 }
82
83 /*
84 * Execute a break instruction that will invoke ttd
85 */
86 void kttd_break(void)
87 {
88 if (!kttd_enabled)
89 return;
90 asm("int3");
91 }
92
93 /*
94 * Halt all processors on the 386at (not really applicable).
95 */
96 void kttd_halt_processors(void)
97 {
98 /* XXX Fix for Sequent!!! */
99 /* Only one on AT386, so ignore for now... */
100 }
101
102 /*
103 * Determine whether or not the ehternet device driver supports
104 * ttd.
105 */
106 boolean_t kttd_supported(void)
107 {
108 return ((int)ttd_get_packet != NULL);
109 }
110
111 /*
112 * Return the ttd machine type for the i386at
113 */
114 ttd_machine_type get_ttd_machine_type(void)
115 {
116 return TTD_AT386;
117 }
118
119 void kttd_machine_getregs(struct i386_gdb_register_state *ttd_state)
120 {
121 ttd_state->gs = kttd_regs.gs;
122 ttd_state->fs = kttd_regs.fs;
123 ttd_state->es = kttd_regs.es;
124 ttd_state->ds = kttd_regs.ds;
125 ttd_state->edi = kttd_regs.edi;
126 ttd_state->esi = kttd_regs.esi;
127 ttd_state->ebp = kttd_regs.ebp;
128
129 /*
130 * This is set up to point to the right place in
131 * kttd_trap and .
132 */
133 ttd_state->esp = kttd_regs.uesp;
134
135 ttd_state->ebx = kttd_regs.ebx;
136 ttd_state->edx = kttd_regs.edx;
137 ttd_state->ecx = kttd_regs.ecx;
138 ttd_state->eax = kttd_regs.eax;
139 ttd_state->eip = kttd_regs.eip;
140 ttd_state->cs = kttd_regs.cs;
141 ttd_state->efl = kttd_regs.efl;
142 ttd_state->ss = kttd_regs.ss;
143 }
144
145 void kttd_machine_setregs(struct i386_gdb_register_state *ttd_state)
146 {
147 if (kttd_regs.gs != ttd_state->gs) {
148 if (kttd_debug)
149 printf("gs 0x%x:0x%x, ", kttd_regs.gs, ttd_state->gs);
150 kttd_regs.gs = ttd_state->gs;
151 }
152 if (kttd_regs.fs != ttd_state->fs) {
153 if (kttd_debug)
154 printf("fs 0x%x:0x%x, ", kttd_regs.fs, ttd_state->fs);
155 kttd_regs.fs = ttd_state->fs;
156 }
157 if (kttd_regs.es != ttd_state->es) {
158 if (kttd_debug)
159 printf("es 0x%x:0x%x, ", kttd_regs.es, ttd_state->es);
160 kttd_regs.es = ttd_state->es;
161 }
162 if (kttd_regs.ds != ttd_state->ds) {
163 if (kttd_debug)
164 printf("ds 0x%x:0x%x, ", kttd_regs.ds, ttd_state->ds);
165 kttd_regs.ds = ttd_state->ds;
166 }
167 if (kttd_regs.edi != ttd_state->edi) {
168 if (kttd_debug)
169 printf("edi 0x%x:0x%x, ", kttd_regs.edi, ttd_state->edi);
170 kttd_regs.edi = ttd_state->edi;
171 }
172 if (kttd_regs.esi != ttd_state->esi) {
173 if (kttd_debug)
174 printf("esi 0x%x:0x%x, ", kttd_regs.esi, ttd_state->esi);
175 kttd_regs.esi = ttd_state->esi;
176 }
177 if (kttd_regs.ebp != ttd_state->ebp) {
178 if (kttd_debug)
179 printf("ebp 0x%x:0x%x, ", kttd_regs.ebp, ttd_state->ebp);
180 kttd_regs.ebp = ttd_state->ebp;
181 }
182 if (kttd_regs.ebx != ttd_state->ebx) {
183 if (kttd_debug)
184 printf("ebx 0x%x:0x%x, ", kttd_regs.ebx, ttd_state->ebx);
185 kttd_regs.ebx = ttd_state->ebx;
186 }
187 if (kttd_regs.edx != ttd_state->edx) {
188 if (kttd_debug)
189 printf("edx 0x%x:0x%x, ", kttd_regs.edx, ttd_state->edx);
190 kttd_regs.edx = ttd_state->edx;
191 }
192 if (kttd_regs.ecx != ttd_state->ecx) {
193 if (kttd_debug)
194 printf("ecx 0x%x:0x%x, ", kttd_regs.ecx, ttd_state->ecx);
195 kttd_regs.ecx = ttd_state->ecx;
196 }
197 if (kttd_regs.eax != ttd_state->eax) {
198 if (kttd_debug)
199 printf("eax 0x%x:0x%x, ", kttd_regs.eax, ttd_state->eax);
200 kttd_regs.eax = ttd_state->eax;
201 }
202 if (kttd_regs.eip != ttd_state->eip) {
203 if (kttd_debug)
204 printf("eip 0x%x:0x%x, ", kttd_regs.eip, ttd_state->eip);
205 kttd_regs.eip = ttd_state->eip;
206 }
207 if (kttd_regs.cs != ttd_state->cs) {
208 if (kttd_debug)
209 printf("cs 0x%x:0x%x, ", kttd_regs.cs, ttd_state->cs);
210 kttd_regs.cs = ttd_state->cs;
211 }
212 if (kttd_regs.efl != ttd_state->efl) {
213 if (kttd_debug)
214 printf("efl 0x%x:0x%x, ", kttd_regs.efl, ttd_state->efl);
215 kttd_regs.efl = ttd_state->efl;
216 }
217 #if 0
218 /*
219 * We probably shouldn't mess with the uesp or the ss? XXX
220 */
221 if (kttd_regs.ss != ttd_state->ss) {
222 if (kttd_debug)
223 printf("ss 0x%x:0x%x, ", kttd_regs.ss, ttd_state->ss);
224 kttd_regs.ss = ttd_state->ss;
225 }
226 #endif 0
227
228 }
229
230 /*
231 * Enable a page for access, faulting it in if necessary
232 */
233 boolean_t kttd_mem_access(vm_offset_t offset, vm_prot_t access)
234 {
235 kern_return_t code;
236
237 /*
238 * VM_MIN_KERNEL_ADDRESS if the beginning of equiv
239 * mapped kernel memory. virtual_end is the end.
240 * If it's in between it's always accessible
241 */
242 if (offset >= VM_MIN_KERNEL_ADDRESS && offset < virtual_end)
243 return TRUE;
244
245 if (offset >= virtual_end) {
246 /*
247 * fault in the memory just to make sure we can access it
248 */
249 if (kttd_debug)
250 printf(">>>>>>>>>>Faulting in memory: 0x%x, 0x%x\n",
251 trunc_page(offset), access);
252 code = vm_fault(kernel_map, trunc_page(offset), access, FALSE,
253 FALSE, (void (*)()) 0);
254 }else{
255 /*
256 * Check for user thread
257 */
258 #if 1
259 if ((current_thread() != THREAD_NULL) &&
260 (current_thread()->task->map->pmap != kernel_pmap) &&
261 (current_thread()->task->map->pmap != PMAP_NULL)) {
262 code = vm_fault(current_thread()->task->map,
263 trunc_page(offset), access, FALSE,
264 FALSE, (void (*)()) 0);
265 }else{
266 /*
267 * Invalid kernel address (below VM_MIN_KERNEL_ADDRESS)
268 */
269 return FALSE;
270 }
271 #else
272 if (kttd_debug)
273 printf("==========Would've tried to map in user area 0x%x\n",
274 trunc_page(offset));
275 return FALSE;
276 #endif /* 0 */
277 }
278
279 return (code == KERN_SUCCESS);
280 }
281
282 /*
283 * See if we modified the kernel text and if so flush the caches.
284 * This routine is never called with a range that crosses a page
285 * boundary.
286 */
287 void kttd_flush_cache(vm_offset_t offset, vm_size_t length)
288 {
289 /* 386 doesn't need this */
290 return;
291 }
292
293 /*
294 * Insert a breakpoint into memory.
295 */
296 boolean_t kttd_insert_breakpoint(vm_address_t address,
297 ttd_saved_inst *saved_inst)
298 {
299 /*
300 * Saved old memory data:
301 */
302 *saved_inst = *(unsigned char *)address;
303
304 /*
305 * Put in a Breakpoint:
306 */
307 *(unsigned char *)address = I386_BREAKPOINT;
308
309 return TRUE;
310 }
311
312 /*
313 * Remove breakpoint from memory.
314 */
315 boolean_t kttd_remove_breakpoint(vm_address_t address,
316 ttd_saved_inst saved_inst)
317 {
318 /*
319 * replace it:
320 */
321 *(unsigned char *)address = (saved_inst & 0xff);
322
323 return TRUE;
324 }
325
326 /*
327 * Set single stepping mode. Assumes that program counter is set
328 * to the location where single stepping is to begin. The 386 is
329 * an easy single stepping machine, ie. built into the processor.
330 */
331 boolean_t kttd_set_machine_single_step(void)
332 {
333 /* Turn on Single Stepping */
334 kttd_regs.efl |= EFL_TF;
335
336 return TRUE;
337 }
338
339 /*
340 * Clear single stepping mode.
341 */
342 boolean_t kttd_clear_machine_single_step(void)
343 {
344 /* Turn off the trace flag */
345 kttd_regs.efl &= ~EFL_TF;
346
347 return TRUE;
348 }
349
350
351 /*
352 * kttd_type_to_ttdtrap:
353 *
354 * Fills in the task and thread info structures with the reason
355 * for entering the Teledebugger (bp, single step, pg flt, etc.)
356 *
357 */
358 void kttd_type_to_ttdtrap(int type)
359 {
360 /* XXX Fill this in sometime for i386 */
361 }
362
363 /*
364 * kttd_trap:
365 *
366 * This routine is called from the trap or interrupt handler when a
367 * breakpoint instruction is encountered or a single step operation
368 * completes. The argument is a pointer to a machine dependent
369 * saved_state structure that was built on the interrupt or kernel stack.
370 *
371 */
372 boolean_t kttd_trap(int type, int code, struct i386_saved_state *regs)
373 {
374 int s;
375
376 if (kttd_debug)
377 printf("kttd_TRAP, before splhigh()\n");
378
379 /*
380 * TTD isn't supported by the driver.
381 *
382 * Try to switch off to kdb if it is resident.
383 * Otherwise just hang (this might be panic).
384 *
385 * Check to make sure that TTD is supported.
386 * (Both by the machine's driver's, and bootp if using ether).
387 */
388 if (!kttd_supported()) {
389 kttd_enabled = FALSE;
390 return FALSE;
391 }
392
393 s = splhigh();
394
395 /*
396 * We are already in TTD!
397 */
398 if (++kttd_active > MAX_KTTD_ACTIVE) {
399 printf("kttd_trap: RE-ENTERED!!!\n");
400 }
401
402 if (kttd_debug)
403 printf("kttd_TRAP, after splhigh()\n");
404
405 /* Should switch to kttd's own stack here. */
406
407 kttd_regs = *regs;
408
409 if ((regs->cs & 0x3) == 0) {
410 /*
411 * Kernel mode - esp and ss not saved
412 */
413 kttd_regs.uesp = (int)®s->uesp; /* kernel stack pointer */
414 kttd_regs.ss = KERNEL_DS;
415 }
416
417 /*
418 * If this was not entered via an interrupt (type != -1)
419 * then we've entered via a bpt, single, etc. and must
420 * set the globals.
421 *
422 * Setup the kttd globals for entry....
423 */
424 if (type != -1) {
425 kttd_current_request = NULL;
426 kttd_current_length = 0;
427 kttd_current_kmsg = NULL;
428 kttd_run_status = FULL_STOP;
429 }else{
430 /*
431 * We know that we can only get here if we did a kttd_intr
432 * since it's the way that we are called with type -1 (via
433 * the trampoline), so we don't have to worry about entering
434 * from Cntl-Alt-D like the mips does.
435 */
436 /*
437 * Perform sanity check!
438 */
439 if ((kttd_current_request == NULL) ||
440 (kttd_current_length == 0) ||
441 (kttd_current_kmsg == NULL) ||
442 (kttd_run_status != ONE_STOP)) {
443
444 printf("kttd_trap: INSANITY!!!\n");
445 }
446 }
447
448 kttd_task_trap(type, code, (regs->cs & 0x3) != 0);
449
450 regs->eip = kttd_regs.eip;
451 regs->efl = kttd_regs.efl;
452 regs->eax = kttd_regs.eax;
453 regs->ecx = kttd_regs.ecx;
454 regs->edx = kttd_regs.edx;
455 regs->ebx = kttd_regs.ebx;
456 if (regs->cs & 0x3) {
457 /*
458 * user mode - saved esp and ss valid
459 */
460 regs->uesp = kttd_regs.uesp; /* user stack pointer */
461 regs->ss = kttd_regs.ss & 0xffff; /* user stack segment */
462 }
463 regs->ebp = kttd_regs.ebp;
464 regs->esi = kttd_regs.esi;
465 regs->edi = kttd_regs.edi;
466 regs->es = kttd_regs.es & 0xffff;
467 regs->cs = kttd_regs.cs & 0xffff;
468 regs->ds = kttd_regs.ds & 0xffff;
469 regs->fs = kttd_regs.fs & 0xffff;
470 regs->gs = kttd_regs.gs & 0xffff;
471
472 if (--kttd_active < MIN_KTTD_ACTIVE)
473 printf("ttd_trap: kttd_active < 0\n");
474
475 if (kttd_debug) {
476 printf("Leaving kttd_trap, kttd_active = %d\n", kttd_active);
477 }
478
479 /*
480 * Only reset this if we entered kttd_trap via an async trampoline.
481 */
482 if (type == -1) {
483 if (kttd_run_status == RUNNING)
484 printf("kttd_trap: $$$$$ run_status already RUNNING! $$$$$\n");
485 kttd_run_status = RUNNING;
486 }
487
488 /* Is this right? XXX */
489 kttd_run_status = RUNNING;
490
491 (void) splx(s);
492
493 /*
494 * Return true, that yes we handled the trap.
495 */
496 return TRUE;
497 }
498
499 /*
500 * Enter KTTD through a network packet trap.
501 * We show the registers as of the network interrupt
502 * instead of those at its call to KDB.
503 */
504 struct int_regs {
505 int gs;
506 int fs;
507 int edi;
508 int esi;
509 int ebp;
510 int ebx;
511 struct i386_interrupt_state *is;
512 };
513
514 void
515 kttd_netentry(int_regs)
516 struct int_regs *int_regs;
517 {
518 struct i386_interrupt_state *is = int_regs->is;
519 int s;
520
521 if (kttd_debug)
522 printf("kttd_NETENTRY before slphigh()\n");
523
524 s = splhigh();
525
526 if (kttd_debug)
527 printf("kttd_NETENTRY after slphigh()\n");
528
529 if (is->cs & 0x3) {
530 /*
531 * Interrupted from User Space
532 */
533 kttd_regs.uesp = ((int *)(is+1))[0];
534 kttd_regs.ss = ((int *)(is+1))[1];
535 }
536 else {
537 /*
538 * Interrupted from Kernel Space
539 */
540 kttd_regs.ss = KERNEL_DS;
541 kttd_regs.uesp= (int)(is+1);
542 }
543 kttd_regs.efl = is->efl;
544 kttd_regs.cs = is->cs;
545 kttd_regs.eip = is->eip;
546 kttd_regs.eax = is->eax;
547 kttd_regs.ecx = is->ecx;
548 kttd_regs.edx = is->edx;
549 kttd_regs.ebx = int_regs->ebx;
550 kttd_regs.ebp = int_regs->ebp;
551 kttd_regs.esi = int_regs->esi;
552 kttd_regs.edi = int_regs->edi;
553 kttd_regs.ds = is->ds;
554 kttd_regs.es = is->es;
555 kttd_regs.fs = int_regs->fs;
556 kttd_regs.gs = int_regs->gs;
557
558 kttd_active++;
559 kttd_task_trap(-1, 0, (kttd_regs.cs & 0x3) != 0);
560 kttd_active--;
561
562 if (kttd_regs.cs & 0x3) {
563 ((int *)(is+1))[0] = kttd_regs.uesp;
564 ((int *)(is+1))[1] = kttd_regs.ss & 0xffff;
565 }
566 is->efl = kttd_regs.efl;
567 is->cs = kttd_regs.cs & 0xffff;
568 is->eip = kttd_regs.eip;
569 is->eax = kttd_regs.eax;
570 is->ecx = kttd_regs.ecx;
571 is->edx = kttd_regs.edx;
572 int_regs->ebx = kttd_regs.ebx;
573 int_regs->ebp = kttd_regs.ebp;
574 int_regs->esi = kttd_regs.esi;
575 int_regs->edi = kttd_regs.edi;
576 is->ds = kttd_regs.ds & 0xffff;
577 is->es = kttd_regs.es & 0xffff;
578 int_regs->fs = kttd_regs.fs & 0xffff;
579 int_regs->gs = kttd_regs.gs & 0xffff;
580
581 if (kttd_run_status == RUNNING)
582 printf("kttd_netentry: %%%%% run_status already RUNNING! %%%%%\n");
583 kttd_run_status = RUNNING;
584
585 (void) splx(s);
586 }
Cache object: 20771ebfe5b4a09d2fc00ea0cb44ff5e
|