]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/arm/context-arm.cpp
update
[l4.git] / kernel / fiasco / src / kern / arm / context-arm.cpp
1 INTERFACE [arm]:
2
3 EXTENSION class Context
4 {
5 public:
6   void set_mem_op_in_progress(bool val);
7   bool is_mem_op_in_progress() const { return _mem_op_in_progess; }
8
9 private:
10   bool _mem_op_in_progess;
11 };
12
13 // ------------------------------------------------------------------------
14 IMPLEMENTATION [arm]:
15
16 #include <cassert>
17 #include <cstdio>
18
19 #include "globals.h"            // current()
20 #include "l4_types.h"
21 #include "cpu_lock.h"
22 #include "kmem.h"
23 #include "lock_guard.h"
24 #include "space.h"
25 #include "thread_state.h"
26 #include "utcb_support.h"
27
28
29 IMPLEMENT inline
30 void
31 Context::fill_user_state()
32 {
33   // do not use 'Return_frame const *rf = regs();' here as it triggers an
34   // optimization bug in gcc-4.4(.1)
35   Entry_frame const *ef = regs();
36   asm volatile ("ldmia %[rf], {sp, lr}^"
37       : : "m"(ef->usp), "m"(ef->ulr), [rf] "r" (&ef->usp));
38 }
39
40 IMPLEMENT inline
41 void
42 Context::spill_user_state()
43 {
44   Entry_frame *ef = regs();
45   assert_kdb (current() == this);
46   asm volatile ("stmia %[rf], {sp, lr}^"
47       : "=m"(ef->usp), "=m"(ef->ulr) : [rf] "r" (&ef->usp));
48 }
49
50 IMPLEMENT inline
51 void
52 Context::switch_cpu(Context *t)
53 {
54   update_consumed_time();
55
56   spill_user_state();
57   t->fill_user_state();
58
59   {
60     register Mword _old_this asm("r1") = (Mword)this;
61     register Mword _new_this asm("r0") = (Mword)t;
62     unsigned long dummy1, dummy2;
63
64     asm volatile
65       (// save context of old thread
66        "   stmdb sp!, {fp}          \n"
67        "   adr   lr, 1f             \n"
68        "   str   lr, [sp, #-4]!     \n"
69        "   str   sp, [%[old_sp]]    \n"
70
71        // switch to new stack
72        "   mov   sp, %[new_sp]      \n"
73
74        // deliver requests to new thread
75        "   bl switchin_context_label \n" // call Context::switchin_context(Context *)
76
77        // return to new context
78        "   ldr   pc, [sp], #4       \n"
79        "1: ldmia sp!, {fp}          \n"
80
81        :
82                     "=r" (_old_this),
83                     "=r" (_new_this),
84        [old_sp]     "=r" (dummy1),
85        [new_sp]     "=r" (dummy2)
86        :
87        "0" (_old_this),
88        "1" (_new_this),
89        "2" (&_kernel_sp),
90        "3" (t->_kernel_sp)
91        : "r4", "r5", "r6", "r7", "r8", "r9",
92          "r10", "r12", "r14", "memory");
93   }
94 }
95
96 /** Thread context switchin.  Called on every re-activation of a
97     thread (switch_exec()).  This method is public only because it is
98     called by an ``extern "C"'' function that is called
99     from assembly code (call_switchin_context).
100  */
101 IMPLEMENT
102 void Context::switchin_context(Context *from)
103 {
104   assert_kdb (this == current());
105   assert_kdb (state() & Thread_ready_mask);
106
107 #if 0
108   printf("switch in address space: %p\n",_space);
109 #endif
110
111   // switch to our page directory if nessecary
112   vcpu_aware_space()->switchin_context(from->vcpu_aware_space());
113
114   Utcb_support::current((Utcb*)local_id());
115 }
116
117
118 IMPLEMENT inline
119 void
120 Context::set_mem_op_in_progress(bool val)
121 {
122   _mem_op_in_progess = val;
123   Mem::barrier();
124 }