]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/arm/thread-jdb.cpp
Some minor fixes.
[l4.git] / kernel / fiasco / src / kern / arm / thread-jdb.cpp
1 INTERFACE [arm-debug]:
2
3 #include "trap_state.h"
4
5 EXTENSION class Thread
6 {
7 public:
8   typedef void (*Dbg_extension_entry)(Thread *t, Entry_frame *r);
9   static Dbg_extension_entry dbg_extension[64];
10
11 protected:
12   static int call_nested_trap_handler(Trap_state *ts) asm ("call_nested_trap_handler");
13   static Trap_state::Handler nested_trap_handler FIASCO_FASTCALL;
14 };
15
16
17 //-----------------------------------------------------------------------------
18 IMPLEMENTATION [arm && debug]:
19
20 #include "kernel_task.h"
21 #include "mem_layout.h"
22 #include "mmu.h"
23
24 #include <cstring>
25
26 Thread::Dbg_extension_entry Thread::dbg_extension[64];
27
28 Trap_state::Handler Thread::nested_trap_handler FIASCO_FASTCALL;
29
30 extern "C" void sys_kdb_ke()
31 {
32   cpu_lock.lock();
33   Thread *t = current_thread();
34   Unsigned32 x = Thread::peek_user((Unsigned32 *)t->regs()->ip(), t);
35
36   if (EXPECT_FALSE(t->is_kernel_mem_op_hit_and_clear()))
37     x = 0;
38
39   if ((x & 0xffff0000) == 0xe35e0000)
40     {
41       unsigned func = x & 0x3f;
42       if (Thread::dbg_extension[func])
43         {
44           Thread::dbg_extension[func](t, t->regs());
45           t->regs()->ip(t->regs()->ip() + 4);
46           return;
47         }
48     }
49
50   char str[32] = "USER ENTRY";
51   if ((x & 0xfffffff0) == 0xea000000)
52     // check for always branch, no return, maximum 32 bytes forward
53     {
54       char const *user_str = reinterpret_cast<char const *>(t->regs()->ip() + 4);
55       for (unsigned i = 0; i < sizeof(str); ++i)
56         {
57           str[i] = Thread::peek_user(user_str + i, t);
58           if (EXPECT_FALSE(t->is_kernel_mem_op_hit_and_clear()))
59             {
60               str[0] = 0;
61               break;
62             }
63           if (str[i] == 0)
64             break;
65         }
66
67       str[sizeof(str)-1] = 0;
68     }
69
70   kdb_ke(str);
71 }
72
73 IMPLEMENT
74 int
75 Thread::call_nested_trap_handler(Trap_state *ts)
76 {
77   Cpu_phys_id phys_cpu = Proc::cpu_id();
78   Cpu_number log_cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(phys_cpu));
79   if (log_cpu == Cpu_number::nil())
80     {
81       printf("Trap on unknown CPU phys_id=%x\n",
82              cxx::int_value<Cpu_phys_id>(phys_cpu));
83       log_cpu = Cpu_number::boot_cpu();
84     }
85
86   unsigned long &ntr = nested_trap_recover.cpu(log_cpu);
87
88   void *stack = 0;
89
90   if (!ntr)
91     stack = dbg_stack.cpu(log_cpu).stack_top;
92
93   Mem_space *m = Mem_space::current_mem_space(log_cpu);
94
95   if (Kernel_task::kernel_task() != m)
96     Kernel_task::kernel_task()->make_current();
97
98   Mword dummy1, tmp, ret;
99   {
100     register Mword _ts asm("r0") = (Mword)ts;
101     register Cpu_number _lcpu asm("r1") = log_cpu;
102
103     asm volatile(
104         "mov    %[origstack], sp         \n"
105         "ldr    %[tmp], [%[ntr]]         \n"
106         "teq    %[tmp], #0               \n"
107         "moveq  sp, %[stack]             \n"
108         "add    %[tmp], %[tmp], #1       \n"
109         "str    %[tmp], [%[ntr]]         \n"
110         "str    %[origstack], [sp, #-4]! \n"
111         "str    %[ntr], [sp, #-4]!       \n"
112         "adr    lr, 1f                   \n"
113         "mov    pc, %[handler]           \n"
114         "1:                              \n"
115         "ldr    %[ntr], [sp], #4         \n"
116         "ldr    sp, [sp]                 \n"
117         "ldr    %[tmp], [%[ntr]]         \n"
118         "sub    %[tmp], %[tmp], #1       \n"
119         "str    %[tmp], [%[ntr]]         \n"
120         : [origstack] "=&r" (dummy1), [tmp] "=&r" (tmp),
121           "=r" (_ts), "=r" (_lcpu)
122         : [ntr] "r" (&ntr), [stack] "r" (stack),
123           [handler] "r" (*nested_trap_handler),
124           "2" (_ts), "3" (_lcpu)
125         : "memory", "r2", "r3", "r4");
126
127     ret = _ts;
128   }
129
130   // the jdb-cpu might have changed things we shouldn't miss!
131   Mmu<Mem_layout::Cache_flush_area, true>::flush_cache();
132   Mem::isb();
133
134   if (m != Kernel_task::kernel_task())
135     m->make_current();
136
137   if (!ntr)
138     Cpu_call::handle_global_requests();
139
140   return ret;
141 }
142
143 //-----------------------------------------------------------------------------
144 IMPLEMENTATION [arm-!debug]:
145
146 extern "C" void sys_kdb_ke()
147 {}
148
149 PRIVATE static inline
150 int
151 Thread::call_nested_trap_handler(Trap_state *)
152 { return -1; }