Commit | Line | Data |
---|---|---|
3f4b8ae4 WN |
1 | /* |
2 | * Copyright (c) 1991 Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * %sccs.include.redist.c% | |
6 | * | |
7 | * @(#)kgdb_glue.c 7.1 (Berkeley) %G% | |
8 | */ | |
9 | ||
10 | /* | |
11 | * This file must be compiled with gcc -fno-defer-pop. | |
12 | */ | |
13 | ||
14 | #ifdef KGDB | |
15 | ||
16 | #include "param.h" | |
17 | #include "../include/frame.h" | |
18 | #include "../include/reg.h" | |
19 | ||
20 | #ifndef lint | |
21 | static char rcsid[] = | |
22 | "@(#) $Header: /u/donn/c/gdb/kernel/RCS/kgdb_glue.c,v 1.2 91/03/31 16:04:52 donn Exp Locker: donn $ (LBL)"; | |
23 | #endif | |
24 | ||
25 | #define KGDB_STACKSIZE 0x800 | |
26 | #define KGDB_STACKWORDS (KGDB_STACKSIZE / sizeof(u_long)) | |
27 | ||
28 | u_long kgdb_stack[KGDB_STACKWORDS]; | |
29 | ||
30 | #define getsp(v) asm volatile ("movl %%esp,%0" : "=r" (v)) | |
31 | #define setsp(v) asm volatile ("movl %0,%%esp" :: "r" (v)) | |
32 | ||
33 | static inline void | |
34 | copywords(src, dst, nbytes) | |
35 | register u_long *src, *dst; | |
36 | register u_int nbytes; | |
37 | { | |
38 | u_long *limit = src + (nbytes / sizeof(u_long)); | |
39 | ||
40 | do { | |
41 | *dst++ = *src++; | |
42 | } while (src < limit); | |
43 | if (nbytes & 2) | |
44 | *(u_short *)dst = *(u_short *)src; | |
45 | } | |
46 | ||
47 | kgdb_trap_glue(frame) | |
48 | struct trapframe frame; | |
49 | { | |
50 | u_long osp, nsp; | |
51 | u_int s; | |
52 | ||
53 | /* | |
54 | * On internal traps, the hardware doesn't push ss and esp. | |
55 | */ | |
56 | u_int fsize = sizeof frame - 2 * sizeof (int); | |
57 | #ifdef DONN | |
58 | extern int kgdb_debug; | |
59 | ||
60 | if (kgdb_debug > 3) | |
61 | pg("kgdb_trap_glue: entered, fsize = %d\n", fsize); | |
62 | #endif | |
63 | ||
64 | /* | |
65 | * After a kernel mode trap, the saved sp doesn't point to the right | |
66 | * place. The correct value is the top of the frame. | |
67 | */ | |
68 | frame.tf_isp = (u_long)(&frame) + fsize; | |
69 | ||
70 | /* | |
71 | * Copy the interrupt context and frame to the new stack. | |
72 | * We're throwing away trap()'s frame since we're going to do | |
73 | * our own iret. | |
74 | */ | |
75 | nsp = (u_long)(&kgdb_stack[KGDB_STACKWORDS]) - fsize; | |
76 | ||
77 | copywords((u_long *)&frame, (u_long *)nsp, fsize); | |
78 | ||
79 | s = splhigh(); | |
80 | ||
81 | getsp(osp); | |
82 | setsp(nsp); | |
83 | ||
84 | if (kgdb_trap(frame.tf_trapno, (struct frame *)nsp) == 0) { | |
85 | /* | |
86 | * Get back on kernel stack. This thread of control | |
87 | * will return back up through trap(). If kgdb_trap() | |
88 | * returns 0, it didn't handle the trap at all so | |
89 | * the stack is still intact and everything will | |
90 | * unwind okay from here up. | |
91 | */ | |
92 | setsp(osp); | |
93 | splx(s); | |
94 | return 0; | |
95 | } | |
96 | ||
97 | /* | |
98 | * Copy back context, which has possibly changed. Even the | |
99 | * sp might have changed. | |
100 | */ | |
101 | osp = ((struct trapframe *)nsp)->tf_isp - fsize; | |
102 | copywords((u_long *)nsp, (u_long *)osp, fsize); | |
103 | setsp(osp); | |
104 | ||
105 | /* | |
106 | * Restore the possible new context from frame. | |
107 | */ | |
108 | asm volatile ("pop %es; pop %ds; popal; nop; addl $8,%esp; iret"); | |
109 | } | |
110 | ||
111 | int kgdb_testval; | |
112 | ||
113 | kgdb_test(i) | |
114 | { | |
115 | ++kgdb_testval; | |
116 | return i + 1; | |
117 | } | |
118 | ||
119 | #endif |