]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/jdb/ux/jdb_bp-ux.cpp
update
[l4.git] / kernel / fiasco / src / jdb / ux / jdb_bp-ux.cpp
1 INTERFACE:
2
3 EXTENSION class Jdb_bp
4 {
5 private:
6   static int            test_log_only();
7   static int            test_break(char *errbuf, size_t bufsize);
8 };
9
10
11 IMPLEMENTATION[ux]:
12
13 #include <sys/types.h>                  // for pid_t
14 #include "boot_info.h"
15 #include "task.h"
16 #include "usermode.h"
17 #include "jdb_kobject.h"
18
19 PUBLIC inline
20 Mword
21 Breakpoint::restricted_task()
22 {
23   return restrict.task.task;
24 }
25
26 PUBLIC inline
27 void
28 Breakpoint::set(Address _addr, Mword _len, Mode _mode, Log _log)
29 {
30   addr = _addr;
31   mode = _mode;
32   user = ADDR_USER;   // we don't allow breakpoints in kernel space
33   log  = _log;
34   len  = _len;
35 }
36
37 IMPLEMENT
38 int
39 Jdb_bp::global_breakpoints()
40 {
41   return 0;
42 }
43
44 PUBLIC static
45 Mword
46 Jdb_bp::read_debug_register(int reg, Space *s)
47 {
48   pid_t pid = s ? s->pid() : Boot_info::pid();
49   Mword val;
50   if (!Usermode::read_debug_register(pid, reg, val))
51     printf("[read debugreg #%d task %p/%lx failed]\n", reg, s,
52            static_cast<Task*>(s)->dbg_id());
53
54   return val;
55 }
56
57 static
58 void
59 Jdb_bp::write_debug_register(int reg, Mword val, Space *s)
60 {
61   pid_t pid = s ? s->pid() : Boot_info::pid();
62   if (!Usermode::write_debug_register(pid, reg, val))
63     printf("[write %08lx to debugreg #%d task %p/%lx failed]\n", val, reg, s,
64            static_cast<Task*>(s)->dbg_id());
65 }
66
67 PUBLIC static inline
68 Mword
69 Jdb_bp::get_debug_control_register(Space *task)
70 {
71   return read_debug_register(7, task);
72 }
73
74 PUBLIC static inline
75 void
76 Jdb_bp::set_debug_control_register(Mword val, Space *task)
77 {
78   printf("set_debug_control_register\n");
79   for (int i=0; i<4; i++)
80     if (!(val & (2 << 2*i)))
81       val &= ~(0x0f << (16 + 4*i));
82   write_debug_register(7, val, task);
83 }
84
85 static
86 int
87 Jdb_bp::set_debug_address_register(int num, Mword addr, Mword len,
88                                    Breakpoint::Mode mode, Task *task)
89 {
90   if (!task)
91     {
92       putstr(" => kernel task not allowed for breakpoints");
93       return 0;
94     }
95   if (num >= 0 && num <= 3)
96     {
97       Mword local_dr7;
98       Task *old_task = Kobject::dcast<Task*>(Kobject::id_to_obj(bps[num].restricted_task()));
99
100       if (old_task)
101         {
102           // clear old breakpoint of other process
103           local_dr7 = get_debug_control_register(old_task);
104           clr_dr7(num, local_dr7);
105           set_debug_control_register(local_dr7, old_task);
106         }
107       bps[num].restrict_task(0, task->dbg_id());
108       write_debug_register(num, addr, task);
109       local_dr7 = get_debug_control_register(task);
110       clr_dr7(num, local_dr7);
111       set_dr7(num, len, mode, local_dr7);
112       set_debug_control_register(local_dr7, task);
113       return 1;
114     }
115
116   return 0;
117 }
118
119 static
120 void
121 Jdb_bp::clr_debug_address_register(int num)
122 {
123   Task *task = Kobject::dcast<Task*>(Kobject::id_to_obj(bps[num].restricted_task()));
124   Mword local_dr7 = get_debug_control_register(task);
125   clr_dr7(num, local_dr7);
126   set_debug_control_register(local_dr7, task);
127 }
128
129 IMPLEMENT
130 void
131 Jdb_bp::at_jdb_enter()
132 {}
133
134 IMPLEMENT
135 void
136 Jdb_bp::at_jdb_leave()
137 {
138   if (Jdb::get_current_active()
139       && Jdb::get_current_active()->space() != Kernel_task::kernel_task())
140     write_debug_register(6, 0, Jdb::get_current_active()->space());
141 }
142
143 IMPLEMENT
144 int
145 Jdb_bp::test_log_only()
146 {
147   Space *t = Jdb::get_thread(0)->space();
148   Mword dr6  = read_debug_register(6, t);
149
150   if (dr6 & 0x0000000f)
151     {
152       test_log(dr6);
153       write_debug_register(6, dr6, t);
154       if (!(dr6 & 0x0000e00f))
155         // don't enter jdb, breakpoints only logged
156         return 1;
157     }
158   // enter jdb
159   return 0;
160 }
161
162 /** @return 1 if breakpoint occured */
163 IMPLEMENT
164 int
165 Jdb_bp::test_break(char *errbuf, size_t bufsize)
166 {
167   Space *t = Jdb::get_thread(0)->space();
168   Mword dr6  = read_debug_register(6, t);
169
170   if (!(dr6 & 0x000000f))
171     return 0;
172
173   test_break(dr6, errbuf, bufsize);
174   write_debug_register(6, dr6 & ~0x0000000f, t);
175   return 1;
176 }
177
178 IMPLEMENT
179 void
180 Jdb_bp::init_arch()
181 {
182   Jdb::bp_test_log_only = test_log_only;
183   Jdb::bp_test_break    = test_break;
184 }
185