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