]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/jdb/ia32/jdb_bp-ia32-amd64.cpp
Inital import
[l4.git] / kernel / fiasco / src / jdb / ia32 / jdb_bp-ia32-amd64.cpp
1 INTERFACE[ia32,amd64]:
2
3 EXTENSION class Jdb_bp
4 {
5 private:
6   static int            test_sstep();
7   static int            test_break(char *errbuf, size_t bufsize);
8   static int            test_other(char *errbuf, size_t bufsize);
9   static int            test_log_only();
10   static Mword          dr7;
11 };
12
13 #define write_debug_register(num, val) \
14     asm volatile("mov %0, %%db" #num : : "r" ((Mword)val))
15
16 #define read_debug_register(num) \
17     ({Mword val; asm volatile("mov %%db" #num ",%0" : "=r"(val)); val;})
18
19 IMPLEMENTATION[ia32,amd64]:
20
21 #include "kmem.h"
22
23 Mword Jdb_bp::dr7;
24
25 PUBLIC inline NEEDS["kmem.h"]
26 void
27 Breakpoint::set(Address _addr, Mword _len, Mode _mode, Log _log)
28 {
29   addr = _addr;
30   mode = _mode;
31   user = Kmem::is_kmem_page_fault(_addr, 0) ? ADDR_KERNEL : ADDR_USER;
32   log  = _log;
33   len  = _len;
34 }
35
36 PUBLIC static inline
37 Mword
38 Jdb_bp::get_dr(Mword i)
39 {
40   switch (i)
41     {
42     case 0: return read_debug_register(0);
43     case 1: return read_debug_register(1);
44     case 2: return read_debug_register(2);
45     case 3: return read_debug_register(3);
46     case 6: return read_debug_register(6);
47     case 7: return dr7;
48     default: return 0;
49     }
50 }
51
52 IMPLEMENT
53 int
54 Jdb_bp::global_breakpoints()
55 {
56   return 1;
57 }
58
59 static 
60 int
61 Jdb_bp::set_debug_address_register(int num, Mword addr, Mword len,
62                                    Breakpoint::Mode mode, Space *)
63 {
64   clr_dr7(num, dr7);
65   set_dr7(num, len, mode, dr7);
66   switch (num)
67     {
68     case 0: write_debug_register(0, addr); break;
69     case 1: write_debug_register(1, addr); break;
70     case 2: write_debug_register(2, addr); break;
71     case 3: write_debug_register(3, addr); break;
72     default:;
73     }
74   return 1;
75 }
76
77 static
78 void
79 Jdb_bp::clr_debug_address_register(int num)
80 {
81   clr_dr7(num, dr7);
82 }
83
84 IMPLEMENT
85 void
86 Jdb_bp::at_jdb_enter()
87 {
88   dr7 = read_debug_register(7);
89   // disable breakpoints while we are in kernel debugger
90   write_debug_register(7, dr7 & Val_enter);
91 }
92
93 IMPLEMENT
94 void
95 Jdb_bp::at_jdb_leave()
96 {
97   write_debug_register(6, Val_leave);
98   write_debug_register(7, dr7);
99 }
100
101 /** @return 1 if single step occured */
102 IMPLEMENT
103 int
104 Jdb_bp::test_sstep()
105 {
106   Mword dr6 = read_debug_register(6);
107   if (!(dr6 & Val_test_sstep))
108     return 0;
109
110   // single step has highest priority, don't consider other conditions
111   write_debug_register(6, Val_leave);
112   return 1;
113 }
114
115 /** @return 1 if breakpoint occured */
116 IMPLEMENT
117 int
118 Jdb_bp::test_break(char *errbuf, size_t bufsize)
119 {
120   Mword dr6 = read_debug_register(6);
121   if (!(dr6 & Val_test))
122     return 0;
123
124   int ret = test_break(dr6, errbuf, bufsize);
125   write_debug_register(6, dr6 & ~Val_test);
126   return ret;
127 }
128
129 /** @return 1 if other debug exception occured */
130 IMPLEMENT
131 int
132 Jdb_bp::test_other(char *errbuf, size_t bufsize)
133 {
134   Mword dr6 = read_debug_register(6);
135   if (!(dr6 & Val_test_other))
136     return 0;
137
138   snprintf(errbuf, bufsize, "unknown trap 1 (dr6="L4_PTR_FMT")", dr6);
139   write_debug_register(6, Val_leave);
140   return 1;
141 }
142
143 /** @return 0 if only breakpoints were logged and jdb should not be entered */
144 IMPLEMENT
145 int
146 Jdb_bp::test_log_only()
147 {
148   Mword dr6 = read_debug_register(6);
149
150   if (dr6 & Val_test)
151     {
152       dr7 = read_debug_register(7);
153       // disable breakpoints -- we might trigger a r/w breakpoint again
154       write_debug_register(7, dr7 & Val_enter);
155       test_log(dr6);
156       write_debug_register(6, dr6);
157       write_debug_register(7, dr7);
158       if (!(dr6 & Val_test_other))
159         // don't enter jdb, breakpoints only logged
160         return 1;
161     }
162   // enter jdb
163   return 0;
164 }
165
166 IMPLEMENT
167 void
168 Jdb_bp::init_arch()
169 {
170   Jdb::bp_test_log_only = test_log_only;
171   Jdb::bp_test_break    = test_break;
172   Jdb::bp_test_sstep    = test_sstep;
173   Jdb::bp_test_other    = test_other;
174 }
175