]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/ppc32/thread-ppc32.cpp
update
[l4.git] / kernel / fiasco / src / kern / ppc32 / thread-ppc32.cpp
1 INTERFACE [ppc32]:
2
3 class Trap_state;
4
5 IMPLEMENTATION [ppc32]:
6
7 #include <cassert>
8 #include <cstdio>
9 #include <feature.h>
10
11 #include "globals.h"
12 #include "kmem.h"
13 #include "thread_state.h"
14 #include "trap_state.h"
15 #include "types.h"
16 #include "vmem_alloc.h"
17
18 enum {
19   FSR_STATUS_MASK = 0x0d,
20   FSR_TRANSL      = 0x05,
21   FSR_DOMAIN      = 0x09,
22   FSR_PERMISSION  = 0x0d,
23 };
24
25 Per_cpu<Thread::Dbg_stack> DEFINE_PER_CPU Thread::dbg_stack;
26
27 PRIVATE static
28 void
29 Thread::print_page_fault_error(Mword e)
30 {
31   char const *const excpts[] =
32     { "reset","undef. insn", "swi", "pref. abort", "data abort",
33       "XXX", "XXX", "XXX" };
34
35   unsigned ex = (e >> 20) & 0x07;
36
37   printf("(%lx) %s, %s(%c)",e & 0xff, excpts[ex],
38          (e & 0x00010000)?"user":"kernel",
39          (e & 0x00020000)?'r':'w');
40 }
41
42 //
43 // Public services
44 //
45 PRIVATE static 
46 void
47 Thread::dump_bats()
48 {
49   Mword batu, batl;
50     asm volatile (" mfdbatl %0, %2 \n"
51                   " mfdbatu %1, %2 \n"
52                   : "=r"(batl), "=r"(batu) : "i"(0));
53     printf("DBAT0 U:%08lx L:%08lx\n", batu, batl);
54     asm volatile (" mfdbatl %0, %2 \n"
55                   " mfdbatu %1, %2 \n"
56                   : "=r"(batl), "=r"(batu) : "i"(1));
57     printf("DBAT1 U:%08lx L:%08lx\n", batu, batl);
58     asm volatile (" mfdbatl %0, %2 \n"
59                   " mfdbatu %1, %2 \n"
60                   : "=r"(batl), "=r"(batu) : "i"(2));
61     printf("DBAT2 U:%08lx L:%08lx\n", batu, batl);
62     asm volatile (" mfdbatl %0, %2 \n"
63                   " mfdbatu %1, %2 \n"
64                   : "=r"(batl), "=r"(batu) : "i"(3));
65     printf("DBAT3 U:%08lx L:%08lx\n", batu, batl);
66   
67     asm volatile (" mfibatl %0, %2 \n"
68                   " mfibatu %1, %2 \n"
69                   : "=r"(batl), "=r"(batu) : "i"(0));
70     printf("IBAT0 U:%08lx L:%08lx\n", batu, batl);
71     asm volatile (" mfibatl %0, %2 \n"
72                   " mfibatu %1, %2 \n"
73                   : "=r"(batl), "=r"(batu) : "i"(1));
74     printf("IBAT1 U:%08lx L:%08lx\n", batu, batl);
75     asm volatile (" mfibatl %0, %2 \n"
76                   " mfibatu %1, %2 \n"
77                   : "=r"(batl), "=r"(batu) : "i"(2));
78     printf("IBAT2 U:%08lx L:%08lx\n", batu, batl);
79     asm volatile (" mfibatl %0, %2 \n"
80                   " mfibatu %1, %2 \n"
81                   : "=r"(batl), "=r"(batu) : "i"(3));
82     printf("IBAT3 U:%08lx L:%08lx\n", batu, batl);
83 }
84
85 PUBLIC template<typename T> inline
86 void FIASCO_NORETURN
87 Thread::fast_return_to_user(Mword ip, Mword sp, T arg)
88 {
89   (void)ip; (void)sp; (void)arg;
90   //assert_kdb(check that exiting privs are user privs);
91   // XXX: UNIMPLEMENTED
92   panic("__builtin_trap()");
93 }
94
95 IMPLEMENT
96 void
97 Thread::user_invoke()
98 {
99   user_invoke_generic();
100   assert(current()->state() & Thread_ready);
101
102   Return_frame *r = nonull_static_cast<Return_frame*>(current()->regs());
103   Kip *kip = (EXPECT_FALSE(current_thread()->mem_space()->is_sigma0())) ?
104              Kip::k() : 0;
105
106   /* DEBUGGING */
107   Mword vsid, utcb;
108
109   asm volatile(" mfsr %0, 0 \n"
110                " mr %1, %%r2\n"
111                : "=r"(vsid), "=r"(utcb));
112   printf("\n[%lx]leaving kernel ip %lx sp %lx vsid %lx\n",
113          current_thread()->dbg_id(), r->ip(), r->sp(), vsid);
114          printf("kernel_sp %p kip %p utcb %08lx\n", current_thread()->regs() + 1, kip, utcb);
115
116   asm volatile ( " mtsprg1 %[kernel_sp]              \n" //correct kernel stack
117                                                          //pointer
118                  " mtsrr0  %[ip]                     \n"
119                  " mtsrr1  %[state]                  \n"
120                  " mr      %%r1, %[sp]               \n"
121                  " mr      %%r3, %[kip]              \n"
122                  " rfi                               \n"
123                  :
124                  : [ip]"r" (r->ip()),
125                    [sp]"r" (r->sp()),
126                    [state]"r" (Msr::Msr_user),
127                    [kip]"r" (kip),
128                    [kernel_sp]"r" (current_thread()->regs() + 1)
129                  : "r3"
130                  );
131
132   // never returns
133 }
134
135 IMPLEMENT inline NEEDS["space.h", <cstdio>, "types.h" ,"config.h"]
136 bool Thread::handle_sigma0_page_fault(Address pfa)
137 {
138   bool ret = (mem_space()->v_insert(Mem_space::Phys_addr(pfa & Config::PAGE_MASK),
139                                     Mem_space::Addr(pfa & Config::PAGE_MASK),
140                                     Mem_space::Size(Config::PAGE_SIZE),
141                                     Mem_space::Page_writable |
142                                     Mem_space::Page_user_accessible |
143                                     Mem_space::Page_cacheable
144                                    )
145         != Mem_space::Insert_err_nomem);
146
147   return ret;
148 }
149
150 extern "C" {
151   void except_notimpl(void)
152   {
153     Mword etype,  dar, dsisr, vsid, msr, ksp;
154     asm volatile(" mflr    %0    \n"
155                  " mfdar   %1    \n"
156                  " mfdsisr %2    \n"
157                  " mfsr    %3, 0 \n"
158                  " mfmsr   %4    \n"
159                  " mfsprg1 %5    \n"
160                  : "=r"(etype), "=r"(dar), "=r"(dsisr), "=r"(vsid), "=r"(msr), "=r"(ksp) : : "memory");
161     printf("\n\n[dbg_id: %lx] Exception: %lx\n", current_thread()->dbg_id(), etype & ~0xff);
162     Entry_frame *e = current()->regs();
163
164     e->Return_frame::dump();
165     printf("MSR %08lx DAR  %08lx DSISR %08lx VSID: %08lx KSP: %08lx\n\n", msr, dar, dsisr,vsid, ksp);
166     e->Syscall_frame::dump();
167     e->Return_frame::dump_scratch();
168     panic("STOPPED");
169   }
170
171 };
172
173 extern "C" {
174
175   /**
176    * The low-level page fault handler called from entry.S.  We're invoked with
177    * interrupts turned off.  Apart from turning on interrupts 
178    * all casesi,  just forwards
179    * the call to Thread::handle_page_fault().
180    * @param pfa page-fault virtual address
181    * @param error_code CPU error code
182    * @return true if page fault could be resolved, false otherwise
183    */
184   Mword pagefault_entry(const Mword pfa, const Mword error_code,
185                         const Mword pc, Return_frame *ret_frame)
186   {
187     //printf("Page fault at %08lx (%s)\n", pfa, PF::is_read_error(error_code)?"ro":"rw" );
188     if(EXPECT_TRUE(PF::is_usermode_error(error_code)))
189       {
190         if (current_thread()->vcpu_pagefault(pfa, error_code, pc))
191           return 1;
192
193         current_thread()->state_del(Thread_cancel);
194         Proc::sti();
195       }
196
197     //lookup in page cache
198     if(current_mem_space()->try_htab_fault((Address)(pfa & Config::PAGE_MASK)))
199       return 1;
200
201     int ret = current_thread()->handle_page_fault(pfa, error_code, pc, ret_frame);
202
203     return ret;
204   }
205
206   void slowtrap_entry(Trap_state * /*ts*/)
207   {
208     NOT_IMPL_PANIC;
209   }
210
211 };
212
213 IMPLEMENT inline
214 bool
215 Thread::pagein_tcb_request(Return_frame * /*regs*/)
216 {
217   NOT_IMPL_PANIC;
218   return false;
219 }
220
221 extern "C"
222 {
223   void timer_handler()
224   {
225     Return_frame *rf = nonull_static_cast<Return_frame*>(current()->regs());
226     //disable power savings mode, when we come from privileged mode
227     if(EXPECT_FALSE(rf->user_mode()))
228       rf->srr1 = Proc::wake(rf->srr1);
229
230     Timer::update_system_clock();
231     current_thread()->handle_timer_interrupt();
232   }
233 }
234 //---------------------------------------------------------------------------
235 IMPLEMENTATION [ppc32]:
236
237 /** Constructor.
238     @param id user-visible thread ID of the sender
239     @param init_prio initial priority
240     @param mcp thread's maximum controlled priority
241     @post state() != Thread_invalid
242  */
243 IMPLEMENT
244 Thread::Thread()
245   : Sender            (0),      // select optimized version of constructor
246     _pager(Thread_ptr::Invalid),
247     _exc_handler(Thread_ptr::Invalid),
248     _del_observer(0)
249 {
250
251   assert(state() == Thread_invalid);
252
253   inc_ref();
254
255   if (Config::stack_depth)
256     std::memset((char*)this + sizeof(Thread), '5',
257                 Config::thread_block_size-sizeof(Thread)-64);
258
259   // set a magic value -- we use it later to verify the stack hasn't
260   // been overrun
261   _magic = magic;
262   _recover_jmpbuf = 0;
263   _timeout = 0;
264
265   *reinterpret_cast<void(**)()> (--_kernel_sp) = user_invoke;
266
267   // clear out user regs that can be returned from the thread_ex_regs
268   // system call to prevent covert channel
269   Entry_frame *r = regs();
270   r->sp(0);
271   r->ip(0);
272
273   state_add(Thread_dead | Thread_suspended);
274   // ok, we're ready to go!
275 }
276
277 IMPLEMENT inline
278 Mword
279 Thread::user_sp() const
280 { return regs()->sp(); }
281
282 IMPLEMENT inline
283 void
284 Thread::user_sp(Mword sp)
285 { return regs()->sp(sp); }
286
287 IMPLEMENT inline NEEDS[Thread::exception_triggered]
288 Mword
289 Thread::user_ip() const
290 { return exception_triggered() ? _exc_cont.ip() : regs()->ip(); }
291
292 IMPLEMENT inline
293 Mword
294 Thread::user_flags() const
295 { return 0; }
296
297 IMPLEMENT inline NEEDS[Thread::exception_triggered]
298 void
299 Thread::user_ip(Mword ip)
300 {
301   if (exception_triggered())
302     _exc_cont.ip(ip);
303   else
304     {
305       Entry_frame *r = regs();
306       r->ip(ip);
307     }
308 }
309
310 PUBLIC inline NEEDS ["trap_state.h"]
311 int
312 Thread::send_exception_arch(Trap_state * /*ts*/)
313 {
314   NOT_IMPL_PANIC;
315   return 1;      // We did it
316 }
317
318 PROTECTED inline
319 void
320 Thread::vcpu_resume_user_arch()
321 {}
322
323
324 PRIVATE static inline
325 void
326 Thread::save_fpu_state_to_utcb(Trap_state *, Utcb *)
327 {
328 }
329
330 PROTECTED inline
331 int
332 Thread::do_trigger_exception(Entry_frame * /*r*/, void * /*ret_handler*/)
333 {
334   NOT_IMPL_PANIC;
335   return 0;
336 }
337
338 PRIVATE static inline
339 bool FIASCO_WARN_RESULT
340 Thread::copy_utcb_to_ts(L4_msg_tag const &/*tag*/, Thread * /*snd*/,
341                         Thread * /*rcv*/, unsigned char /*rights*/)
342 {
343   NOT_IMPL_PANIC;
344   return true;
345 }
346
347 PRIVATE static inline
348 bool FIASCO_WARN_RESULT
349 Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread * /*snd*/, Thread * /*rcv*/,
350                         unsigned char /*rights*/)
351 {
352   NOT_IMPL_PANIC;
353   return true;
354 }
355
356 PROTECTED inline
357 bool
358 Thread::invoke_arch(L4_msg_tag & /*tag*/, Utcb * /*utcb*/)
359 {
360   return false;
361 }
362
363 PROTECTED inline
364 int
365 Thread::sys_control_arch(Utcb *)
366 {
367   return 0;
368 }
369
370 //-----------------------------------------------------------------------------
371 IMPLEMENTATION [!mp]:
372
373 PUBLIC static inline
374 bool
375 Thread::check_for_ipi(unsigned)
376 { return false; }