]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/jdb/arm/jdb-arm.cpp
a0ac4c139e57dd8a746efdb0cd8362712db689b7
[l4.git] / kernel / fiasco / src / jdb / arm / jdb-arm.cpp
1 IMPLEMENTATION [arm]:
2
3 #include "globals.h"
4 #include "kernel_task.h"
5 #include "kmem_alloc.h"
6 #include "kmem_space.h"
7 #include "space.h"
8 #include "mem_layout.h"
9 #include "mem_unit.h"
10 #include "static_init.h"
11 #include "watchdog.h"
12
13 STATIC_INITIALIZE_P(Jdb, JDB_INIT_PRIO);
14
15 DEFINE_PER_CPU static Per_cpu<Proc::Status> jdb_irq_state;
16
17 // disable interrupts before entering the kernel debugger
18 IMPLEMENT
19 void
20 Jdb::save_disable_irqs(unsigned cpu)
21 {
22   jdb_irq_state.cpu(cpu) = Proc::cli_save();
23   if (cpu == 0)
24     Watchdog::disable();
25 }
26
27 // restore interrupts after leaving the kernel debugger
28 IMPLEMENT
29 void
30 Jdb::restore_irqs(unsigned cpu)
31 {
32   if (cpu == 0)
33     Watchdog::enable();
34   Proc::sti_restore(jdb_irq_state.cpu(cpu));
35 }
36
37 IMPLEMENT inline
38 void
39 Jdb::enter_trap_handler(unsigned /*cpu*/)
40 {}
41
42 IMPLEMENT inline
43 void
44 Jdb::leave_trap_handler(unsigned /*cpu*/)
45 {}
46
47 PROTECTED static inline
48 void
49 Jdb::monitor_address(unsigned, void *)
50 {}
51
52 IMPLEMENT inline
53 bool
54 Jdb::handle_conditional_breakpoint(unsigned /*cpu*/)
55 { return false; }
56
57 IMPLEMENT
58 void
59 Jdb::handle_nested_trap(Jdb_entry_frame *e)
60 {
61   printf("Trap in JDB: IP:%08lx PSR=%08lx ERR=%08lx\n",
62          e->ip(), e->psr, e->error_code);
63 }
64
65 IMPLEMENT
66 bool
67 Jdb::handle_debug_traps(unsigned cpu)
68 {
69   Jdb_entry_frame *ef = entry_frame.cpu(cpu);
70
71   if (ef->error_code == 0x00e00000)
72     snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s",
73              (char const *)ef->r[0]);
74   else if (ef->debug_ipi())
75     snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)),
76              "IPI ENTRY");
77
78   return true;
79 }
80
81 IMPLEMENT inline
82 bool
83 Jdb::handle_user_request(unsigned cpu)
84 {
85   Jdb_entry_frame *ef = Jdb::entry_frame.cpu(cpu);
86   const char *str = (char const *)ef->r[0];
87   Space * task = get_task(cpu);
88   char tmp;
89
90   if (ef->debug_ipi())
91     return cpu != 0;
92
93   if (ef->error_code == 0x00e00001)
94     return execute_command_ni(task, str);
95
96   if (!peek(str, task, tmp) || tmp != '*')
97     return false;
98   if (!peek(str+1, task, tmp) || tmp != '#')
99     return false;
100
101   return execute_command_ni(task, str+2);
102 }
103
104 IMPLEMENT inline
105 bool
106 Jdb::test_checksums()
107 { return true; }
108
109 static
110 bool
111 Jdb::handle_special_cmds(int)
112 { return 1; }
113
114 PUBLIC static
115 FIASCO_INIT FIASCO_NOINLINE void
116 Jdb::init()
117 {
118   static Jdb_handler enter(at_jdb_enter);
119   static Jdb_handler leave(at_jdb_leave);
120
121   Jdb::jdb_enter.add(&enter);
122   Jdb::jdb_leave.add(&leave);
123
124   Thread::nested_trap_handler = (Trap_state::Handler)enter_jdb;
125
126   Kconsole::console()->register_console(push_cons());
127 }
128
129
130 PRIVATE static
131 void *
132 Jdb::access_mem_task(Address virt, Space * task)
133 {
134   // align
135   virt &= ~0x03;
136
137   Address phys;
138
139   if (!task)
140     {
141       if (Mem_layout::in_kernel(virt))
142         {
143           Pte p = Kmem_space::kdir()->walk((void *)virt, 0, false, Ptab::Null_alloc(), 0);
144           if (!p.valid())
145             return 0;
146
147           phys = p.phys((void*)virt);
148         }
149       else
150         phys = virt;
151     }
152   else
153     {
154       phys = Address(task->virt_to_phys(virt));
155
156
157       if (phys == (Address)-1)
158         phys = task->virt_to_phys_s0((void *)virt);
159
160       if (phys == (Address)-1)
161         return 0;
162     }
163
164   unsigned long addr = Mem_layout::phys_to_pmem(phys);
165   if (addr == (Address)-1)
166     {
167       Mem_unit::flush_vdcache();
168       Pte pte = static_cast<Mem_space*>(Kernel_task::kernel_task())
169         ->_dir->walk((void*)Mem_layout::Jdb_tmp_map_area, 0, false, Ptab::Null_alloc(), 0);
170
171       if (pte.phys() != (phys & ~(Config::SUPERPAGE_SIZE - 1)))
172         pte.set(phys & ~(Config::SUPERPAGE_SIZE - 1), Config::SUPERPAGE_SIZE,
173                 Mem_page_attr(Page::KERN_RW | Page::CACHEABLE), true);
174
175       Mem_unit::dtlb_flush();
176
177       addr = Mem_layout::Jdb_tmp_map_area + (phys & (Config::SUPERPAGE_SIZE - 1));
178     }
179
180   return (Mword*)addr;
181 }
182
183 PUBLIC static
184 Space *
185 Jdb::translate_task(Address addr, Space * task)
186 {
187   return (Kmem::is_kmem_page_fault(addr, 0)) ? 0 : task;
188 }
189
190 PUBLIC static
191 int
192 Jdb::peek_task(Address virt, Space * task, void *value, int width)
193 {
194   void const *mem = access_mem_task(virt, task);
195   if (!mem)
196     return -1;
197
198   switch (width)
199     {
200     case 1:
201         {
202           Mword dealign = (virt & 0x3) * 8;
203           *(Mword*)value = (*(Mword*)mem & (0xff << dealign)) >> dealign;
204         }
205         break;
206     case 2:
207         {
208           Mword dealign = ((virt & 0x2) >> 1) * 16;
209           *(Mword*)value = (*(Mword*)mem & (0xffff << dealign)) >> dealign;
210         }
211         break;
212     case 4:
213       memcpy(value, mem, width);
214     }
215
216   return 0;
217 }
218
219 PUBLIC static
220 int
221 Jdb::is_adapter_memory(Address, Space *)
222 {
223   return 0;
224 }
225
226 PUBLIC static
227 int
228 Jdb::poke_task(Address virt, Space * task, void const *val, int width)
229 {
230   void *mem = access_mem_task(virt, task);
231   if (!mem)
232     return -1;
233
234   memcpy(mem, val, width);
235   return 0;
236 }
237
238
239 PRIVATE static
240 void
241 Jdb::at_jdb_enter()
242 {
243   Mem_unit::clean_vdcache();
244 }
245
246 PRIVATE static
247 void
248 Jdb::at_jdb_leave()
249 {
250   Mem_unit::flush_vcache();
251 }
252
253 PUBLIC static inline
254 void
255 Jdb::enter_getchar()
256 {}
257
258 PUBLIC static inline
259 void
260 Jdb::leave_getchar()
261 {}
262
263 PUBLIC static
264 void
265 Jdb::write_tsc_s(Signed64 tsc, char *buf, int maxlen, bool sign)
266 {
267   if (sign)
268     {
269       *buf++ = (tsc < 0) ? '-' : (tsc == 0) ? ' ' : '+';
270       maxlen--;
271     }
272   snprintf(buf, maxlen, "%lld c", tsc);
273 }
274
275 PUBLIC static
276 void
277 Jdb::write_tsc(Signed64 tsc, char *buf, int maxlen, bool sign)
278 {
279   write_tsc_s(tsc, buf, maxlen, sign);
280 }
281
282 //----------------------------------------------------------------------------
283 IMPLEMENTATION [arm && !mp]:
284
285 PROTECTED static inline
286 template< typename T >
287 void
288 Jdb::set_monitored_address(T *dest, T val)
289 { *dest = val; }
290
291 //----------------------------------------------------------------------------
292 IMPLEMENTATION [arm && mp]:
293
294 #include <cstdio>
295
296 static
297 void
298 Jdb::send_nmi(unsigned cpu)
299 {
300   printf("NMI to %d, what's that?\n", cpu);
301 }
302
303 PROTECTED static inline
304 template< typename T >
305 void
306 Jdb::set_monitored_address(T *dest, T val)
307 {
308   *dest = val;
309   Mem::dsb();
310   asm volatile("sev");
311 }
312
313 PROTECTED static inline
314 template< typename T >
315 T Jdb::monitor_address(unsigned, T volatile *addr)
316 {
317   asm volatile("wfe");
318   return *addr;
319 }