]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/sparc/thread-sparc.cpp
398ba44b183b797c7ed8c774571de79521098ed5
[l4.git] / kernel / fiasco / src / kern / sparc / thread-sparc.cpp
1 INTERFACE [sparc]:
2
3 class Trap_state;
4
5 IMPLEMENTATION [sparc]:
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
17 enum {
18   FSR_STATUS_MASK = 0x0d,
19   FSR_TRANSL      = 0x05,
20   FSR_DOMAIN      = 0x09,
21   FSR_PERMISSION  = 0x0d,
22 };
23
24 DEFINE_PER_CPU Per_cpu<Thread::Dbg_stack> Thread::dbg_stack;
25
26 PRIVATE static
27 void
28 Thread::print_page_fault_error(Mword e)
29 {
30   char const *const excpts[] =
31     { "reset","undef. insn", "swi", "pref. abort", "data abort",
32       "XXX", "XXX", "XXX" };
33
34   unsigned ex = (e >> 20) & 0x07;
35
36   printf("(%lx) %s, %s(%c)",e & 0xff, excpts[ex],
37          (e & 0x00010000)?"user":"kernel",
38          (e & 0x00020000)?'r':'w');
39 }
40
41 //
42 // Public services
43 //
44 PRIVATE static 
45 void
46 Thread::dump_bats()
47 {
48 }
49
50 PUBLIC template<typename T> inline
51 void FIASCO_NORETURN
52 Thread::fast_return_to_user(Mword ip, Mword sp, T arg)
53 {
54   (void)ip; (void)sp; (void)arg;
55   //assert_kdb(check that exiting privs are user privs);
56   // XXX: UNIMPLEMENTED
57   panic("__builtin_trap()");
58 }
59
60 IMPLEMENT
61 void
62 Thread::user_invoke()
63 {
64   user_invoke_generic();
65   assert(current()->state() & Thread_ready);
66
67   Return_frame *r = nonull_static_cast<Return_frame*>(current()->regs());
68   Kip *kip = (EXPECT_FALSE(current_thread()->mem_space()->is_sigma0())) ?
69              Kip::k() : 0;
70
71   /* DEBUGGING */
72   Mword vsid = 0xF000, utcb = 0xBAAA;
73
74   printf("\n[%lx]leaving kernel ip %lx sp %lx vsid %lx\n",
75          current_thread()->dbg_id(), r->ip(), r->sp(), vsid);
76          printf("kernel_sp %p kip %p utcb %08lx\n", current_thread()->regs() + 1, kip, utcb);
77
78   // never returns
79 }
80
81 IMPLEMENT inline NEEDS["space.h", <cstdio>, "types.h" ,"config.h"]
82 bool Thread::handle_sigma0_page_fault(Address pfa)
83 {
84   bool ret = (mem_space()->v_insert(Mem_space::Phys_addr(pfa & Config::PAGE_MASK),
85                                     Mem_space::Addr(pfa & Config::PAGE_MASK),
86                                     Mem_space::Size(Config::PAGE_SIZE),
87                                     Mem_space::Page_writable |
88                                     Mem_space::Page_user_accessible |
89                                     Mem_space::Page_cacheable
90                                    )
91         != Mem_space::Insert_err_nomem);
92
93   return ret;
94 }
95
96 extern "C" {
97   void except_notimpl(void)
98   {
99   }
100
101 };
102
103 extern "C" {
104
105   /**
106    * The low-level page fault handler called from entry.S.  We're invoked with
107    * interrupts turned off.  Apart from turning on interrupts 
108    * all casesi,  just forwards
109    * the call to Thread::handle_page_fault().
110    * @param pfa page-fault virtual address
111    * @param error_code CPU error code
112    * @return true if page fault could be resolved, false otherwise
113    */
114   Mword pagefault_entry(const Mword pfa, const Mword error_code,
115                         const Mword pc, Return_frame *ret_frame)
116   {
117     //printf("Page fault at %08lx (%s)\n", pfa, PF::is_read_error(error_code)?"ro":"rw" );
118     if(EXPECT_TRUE(PF::is_usermode_error(error_code)))
119       {
120         if (current_thread()->vcpu_pagefault(pfa, error_code, pc))
121           return 1;
122
123         current_thread()->state_del(Thread_cancel);
124         Proc::sti();
125       }
126
127     int ret = current_thread()->handle_page_fault(pfa, error_code, pc, ret_frame);
128
129     return ret;
130   }
131
132   void slowtrap_entry(Trap_state * /*ts*/)
133   {
134     NOT_IMPL_PANIC;
135   }
136
137 };
138
139 IMPLEMENT inline
140 bool
141 Thread::pagein_tcb_request(Return_frame * /*regs*/)
142 {
143   NOT_IMPL_PANIC;
144   return false;
145 }
146
147 extern "C"
148 {
149   void timer_handler()
150   {
151     Return_frame *rf = nonull_static_cast<Return_frame*>(current()->regs());
152     //disable power savings mode, when we come from privileged mode
153     if(EXPECT_FALSE(rf->user_mode()))
154       rf->srr1 = Proc::wake(rf->srr1);
155
156     Timer::update_system_clock(current_cpu());
157     current_thread()->handle_timer_interrupt();
158   }
159 }
160 //---------------------------------------------------------------------------
161 IMPLEMENTATION [sparc]:
162
163 /** Constructor.
164     @param id user-visible thread ID of the sender
165     @param init_prio initial priority
166     @param mcp thread's maximum controlled priority
167     @post state() != Thread_invalid
168  */
169 IMPLEMENT
170 Thread::Thread()
171   : Sender            (0),      // select optimized version of constructor
172     _pager(Thread_ptr::Invalid),
173     _exc_handler(Thread_ptr::Invalid),
174     _del_observer(0)
175 {
176
177   assert(state(false) == Thread_invalid);
178
179   inc_ref();
180   _space.space(Kernel_task::kernel_task());
181
182   // set a magic value -- we use it later to verify the stack hasn't
183   // been overrun
184   _magic = magic;
185   _recover_jmpbuf = 0;
186   _timeout = 0;
187
188   *reinterpret_cast<void(**)()> (--_kernel_sp) = user_invoke;
189
190   // clear out user regs that can be returned from the thread_ex_regs
191   // system call to prevent covert channel
192   Entry_frame *r = regs();
193   r->sp(0);
194   r->ip(0);
195
196   state_add_dirty(Thread_dead, false);
197   // ok, we're ready to go!
198 }
199
200 IMPLEMENT inline
201 Mword
202 Thread::user_sp() const
203 { return regs()->sp(); }
204
205 IMPLEMENT inline
206 void
207 Thread::user_sp(Mword sp)
208 { return regs()->sp(sp); }
209
210 IMPLEMENT inline NEEDS[Thread::exception_triggered]
211 Mword
212 Thread::user_ip() const
213 { return exception_triggered() ? _exc_cont.ip() : regs()->ip(); }
214
215 IMPLEMENT inline
216 Mword
217 Thread::user_flags() const
218 { return 0; }
219
220 IMPLEMENT inline NEEDS[Thread::exception_triggered]
221 void
222 Thread::user_ip(Mword ip)
223 {
224   if (exception_triggered())
225     _exc_cont.ip(ip);
226   else
227     {
228       Entry_frame *r = regs();
229       r->ip(ip);
230     }
231 }
232
233 PUBLIC inline NEEDS ["trap_state.h"]
234 int
235 Thread::send_exception_arch(Trap_state * /*ts*/)
236 {
237   NOT_IMPL_PANIC;
238   return 1;      // We did it
239 }
240
241 PROTECTED inline
242 void
243 Thread::vcpu_resume_user_arch()
244 {}
245
246
247 PRIVATE static inline
248 void
249 Thread::save_fpu_state_to_utcb(Trap_state *, Utcb *)
250 {
251 }
252
253 PROTECTED inline
254 int
255 Thread::do_trigger_exception(Entry_frame * /*r*/, void * /*ret_handler*/)
256 {
257   NOT_IMPL_PANIC;
258   return 0;
259 }
260
261 PRIVATE static inline
262 bool FIASCO_WARN_RESULT
263 Thread::copy_utcb_to_ts(L4_msg_tag const &/*tag*/, Thread * /*snd*/,
264                         Thread * /*rcv*/, unsigned char /*rights*/)
265 {
266   NOT_IMPL_PANIC;
267   return true;
268 }
269
270 PRIVATE static inline
271 bool FIASCO_WARN_RESULT
272 Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread * /*snd*/, Thread * /*rcv*/,
273                         unsigned char /*rights*/)
274 {
275   NOT_IMPL_PANIC;
276   return true;
277 }
278
279 PROTECTED inline
280 L4_msg_tag
281 Thread::invoke_arch(L4_msg_tag /*tag*/, Utcb * /*utcb*/)
282 {
283   return commit_result(-L4_err::ENosys);
284 }
285
286 PROTECTED inline
287 int
288 Thread::sys_control_arch(Utcb *)
289 {
290   return 0;
291 }
292
293 //-----------------------------------------------------------------------------
294 IMPLEMENTATION [!mp]:
295
296 PUBLIC static inline
297 bool
298 Thread::check_for_ipi(unsigned)
299 { return false; }