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