xref: /haiku/headers/private/kernel/arch/x86/arch_user_debugger.h (revision 4f00613311d0bd6b70fa82ce19931c41f071ea4e)
1 /*
2  * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net.
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef _KERNEL_ARCH_X86_USER_DEBUGGER_H
6 #define _KERNEL_ARCH_X86_USER_DEBUGGER_H
7 
8 #define ARCH_INIT_USER_DEBUG i386_init_user_debug
9 
10 // number of breakpoints the CPU supports
11 // Actually it supports 4, but DR3 is used to hold the struct thread*.
12 enum {
13 	X86_BREAKPOINT_COUNT = 3,
14 };
15 
16 // debug status register DR6
17 enum {
18 	X86_DR6_B0			= 0,	// breakpoint condition detected
19 	X86_DR6_B1			= 1,	//
20 	X86_DR6_B2			= 2,	//
21 	X86_DR6_B3			= 3,	//
22 	X86_DR6_BD			= 13,	// debug register access detected
23 	X86_DR6_BS			= 14,	// single step
24 	X86_DR6_BT			= 15,	// task switch
25 
26 	X86_DR6_BREAKPOINT_MASK	= (1 << X86_DR6_B0) | (1 << X86_DR6_B1)
27 								| (1 << X86_DR6_B2) | (1 << X86_DR6_B3),
28 };
29 
30 // debug control register DR7 layout:
31 // 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
32 // LEN3  R/W3  LEN2  R/W2  LEN1  R/W1  LEN0  R/W0
33 //
34 // 15 14 13 12 11 10 9  8  7  6  5  4  3  2  1  0
35 // 0  0  GD 0  0  1  GE LE G3 L3 G2 L2 G1 L1 G0 L0
36 //
37 enum {
38 	X86_DR7_L0			= 0,	// local/global breakpoints enable
39 	X86_DR7_G0			= 1,	//
40 	X86_DR7_L1			= 2,	//
41 	X86_DR7_G1			= 3,	//
42 	X86_DR7_L2			= 4,	//
43 	X86_DR7_G2			= 5,	//
44 	X86_DR7_L3			= 6,	//
45 	X86_DR7_G3			= 7,	//
46 	X86_DR7_LE			= 8,	// local/global exact breakpoint
47 	X86_DR7_GE			= 9,	//
48 	X86_DR7_GD			= 13,	// general detect enable: disallows debug
49 								// register access
50 	X86_DR7_RW0_LSB		= 16,	// breakpoints type and len
51 	X86_DR7_LEN0_LSB	= 18,	//
52 	X86_DR7_RW1_LSB		= 20,	//
53 	X86_DR7_LEN1_LSB	= 22,	//
54 	X86_DR7_RW2_LSB		= 24,	//
55 	X86_DR7_LEN2_LSB	= 26,	//
56 	X86_DR7_RW3_LSB		= 28,	//
57 	X86_DR7_LEN3_LSB	= 30,	//
58 
59 	X86_BREAKPOINTS_DISABLED_DR7
60 		= (1 << 10) | (1 << X86_DR7_GE) | (1 << X86_DR7_LE),
61 		// all breakpoints disabled
62 };
63 
64 // the EFLAGS flags we need
65 enum {
66 	X86_EFLAGS_CF	= 0,		// carry flag
67 	X86_EFLAGS_PF	= 2,		// parity flag
68 	X86_EFLAGS_AF	= 4,		// auxiliary carry flag (adjust flag)
69 	X86_EFLAGS_ZF	= 6,		// zero flag
70 	X86_EFLAGS_SF	= 7,		// sign flag
71 	X86_EFLAGS_TF	= 8,		// trap flag (single stepping)
72 	X86_EFLAGS_DF	= 10,		// direction flag
73 	X86_EFLAGS_OF	= 11,		// overflow flag
74 	X86_EFLAGS_RF	= 16,		// resume flag (skips instruction breakpoint)
75 
76 	X86_EFLAGS_USER_SETTABLE_FLAGS
77 		= (1 << X86_EFLAGS_CF) | (1 << X86_EFLAGS_PF) | (1 << X86_EFLAGS_AF)
78 			| (1 << X86_EFLAGS_ZF) | (1 << X86_EFLAGS_SF) | (1 << X86_EFLAGS_DF)
79 			| (1 << X86_EFLAGS_OF),
80 };
81 
82 // x86 breakpoint types
83 enum {
84 	X86_INSTRUCTION_BREAKPOINT		= 0x0,
85 	X86_DATA_WRITE_BREAKPOINT		= 0x1,
86 	X86_IO_READ_WRITE_BREAKPOINT	= 0x2,		// >= 586
87 	X86_DATA_READ_WRITE_BREAKPOINT	= 0x3,
88 };
89 
90 // x86 breakpoint lengths
91 enum {
92 	X86_BREAKPOINT_LENGTH_1	= 0x0,
93 	X86_BREAKPOINT_LENGTH_2	= 0x1,
94 	X86_BREAKPOINT_LENGTH_4	= 0x3,
95 };
96 
97 // thread debug flags
98 enum {
99 	X86_THREAD_DEBUG_DR7_SET			= 0x01,
100 };
101 
102 struct arch_breakpoint {
103 	void	*address;	// NULL, if deactivated
104 	uint32	type;		// one of the architecture types above
105 	uint32	length;		// one of the length values above
106 };
107 
108 struct arch_team_debug_info {
109 	struct arch_breakpoint	breakpoints[X86_BREAKPOINT_COUNT];
110 
111 	uint32					dr7;	// debug control register DR7
112 };
113 
114 struct arch_thread_debug_info {
115 	uint32	flags;
116 };
117 
118 #ifdef __cplusplus
119 extern "C" {
120 #endif
121 
122 struct iframe;
123 struct thread;
124 
125 extern void i386_init_user_debug_at_kernel_exit(struct iframe *frame);
126 extern void i386_exit_user_debug_at_kernel_entry();
127 extern void i386_reinit_user_debug_after_context_switch(struct thread *thread);
128 
129 extern int i386_handle_debug_exception(struct iframe *frame);
130 extern int i386_handle_breakpoint_exception(struct iframe *frame);
131 
132 extern void i386_init_user_debug();
133 
134 #ifdef __cplusplus
135 }
136 #endif
137 
138 #endif	// _KERNEL_ARCH_X86_USER_DEBUGGER_H
139