]> 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_ignore_mem_op_in_progress(bool val);
7   bool is_ignore_mem_op_in_progress() const { return _ignore_mem_op_in_progess; }
8
9 private:
10   bool _ignore_mem_op_in_progess;
11 };
12
13 // ------------------------------------------------------------------------
14 INTERFACE [armv6plus]:
15
16 EXTENSION class Context
17 {
18 private:
19   Mword _tpidrurw;
20
21 protected:
22   Mword _tpidruro;
23 };
24
25 // ------------------------------------------------------------------------
26 IMPLEMENTATION [arm]:
27
28 #include <cassert>
29 #include <cstdio>
30
31 #include "globals.h"            // current()
32 #include "l4_types.h"
33 #include "cpu_lock.h"
34 #include "kmem.h"
35 #include "lock_guard.h"
36 #include "space.h"
37 #include "thread_state.h"
38 #include "utcb_support.h"
39
40
41 IMPLEMENT inline
42 void
43 Context::fill_user_state()
44 {
45   // do not use 'Return_frame const *rf = regs();' here as it triggers an
46   // optimization bug in gcc-4.4(.1)
47   Entry_frame const *ef = regs();
48   asm volatile ("ldmia %[rf], {sp, lr}^"
49       : : "m"(ef->usp), "m"(ef->ulr), [rf] "r" (&ef->usp));
50 }
51
52 IMPLEMENT inline
53 void
54 Context::spill_user_state()
55 {
56   Entry_frame *ef = regs();
57   assert_kdb (current() == this);
58   asm volatile ("stmia %[rf], {sp, lr}^"
59       : "=m"(ef->usp), "=m"(ef->ulr) : [rf] "r" (&ef->usp));
60 }
61
62 IMPLEMENT inline NEEDS[Context::spill_user_state, Context::store_tpidrurw,
63                        Context::load_tpidrurw, Context::load_tpidruro]
64 void
65 Context::switch_cpu(Context *t)
66 {
67   update_consumed_time();
68
69   spill_user_state();
70   store_tpidrurw();
71   t->fill_user_state();
72   t->load_tpidrurw();
73   t->load_tpidruro();
74
75   {
76     register Mword _old_this asm("r1") = (Mword)this;
77     register Mword _new_this asm("r0") = (Mword)t;
78     unsigned long dummy1, dummy2;
79
80     asm volatile
81       (// save context of old thread
82        "   stmdb sp!, {fp}          \n"
83        "   adr   lr, 1f             \n"
84        "   str   lr, [sp, #-4]!     \n"
85        "   str   sp, [%[old_sp]]    \n"
86
87        // switch to new stack
88        "   mov   sp, %[new_sp]      \n"
89
90        // deliver requests to new thread
91        "   bl switchin_context_label \n" // call Context::switchin_context(Context *)
92
93        // return to new context
94        "   ldr   pc, [sp], #4       \n"
95        "1: ldmia sp!, {fp}          \n"
96
97        :
98                     "=r" (_old_this),
99                     "=r" (_new_this),
100        [old_sp]     "=r" (dummy1),
101        [new_sp]     "=r" (dummy2)
102        :
103        "0" (_old_this),
104        "1" (_new_this),
105        "2" (&_kernel_sp),
106        "3" (t->_kernel_sp)
107        : "r4", "r5", "r6", "r7", "r8", "r9",
108          "r10", "r12", "r14", "memory");
109   }
110 }
111
112 /** Thread context switchin.  Called on every re-activation of a
113     thread (switch_exec()).  This method is public only because it is
114     called by an ``extern "C"'' function that is called
115     from assembly code (call_switchin_context).
116  */
117 IMPLEMENT
118 void Context::switchin_context(Context *from)
119 {
120   assert_kdb (this == current());
121   assert_kdb (state() & Thread_ready_mask);
122
123   // switch to our page directory if nessecary
124   vcpu_aware_space()->switchin_context(from->vcpu_aware_space());
125
126   Utcb_support::current(current()->utcb().usr());
127 }
128
129 IMPLEMENT inline
130 void
131 Context::set_ignore_mem_op_in_progress(bool val)
132 {
133   _ignore_mem_op_in_progess = val;
134   Mem::barrier();
135 }
136
137 // ------------------------------------------------------------------------
138 IMPLEMENTATION [armv6plus]:
139
140 PROTECTED inline void Context::arch_setup_utcb_ptr()
141 {
142   _tpidruro = reinterpret_cast<Mword>(utcb().usr().get());
143 }
144
145 IMPLEMENT inline
146 void
147 Context::arch_load_vcpu_kern_state(Vcpu_state *vcpu, bool do_load)
148 {
149   _tpidruro = vcpu->_tpidruro;
150   if (do_load)
151     load_tpidruro();
152 }
153
154 IMPLEMENT inline
155 void
156 Context::arch_load_vcpu_user_state(Vcpu_state *vcpu, bool do_load)
157 {
158   _tpidruro = vcpu->_ts.tpidruro;
159   if (do_load)
160     load_tpidruro();
161 }
162
163 IMPLEMENT inline
164 void
165 Context::arch_update_vcpu_state(Vcpu_state *vcpu)
166 {
167   vcpu->_tpidruro = _tpidruro;
168 }
169
170 PRIVATE inline
171 void
172 Context::store_tpidrurw()
173 {
174   asm volatile ("mrc p15, 0, %0, c13, c0, 2" : "=r" (_tpidrurw));
175 }
176
177 PRIVATE inline
178 void
179 Context::load_tpidrurw() const
180 {
181   asm volatile ("mcr p15, 0, %0, c13, c0, 2" : : "r" (_tpidrurw));
182 }
183
184 PROTECTED inline
185 void
186 Context::load_tpidruro() const
187 {
188   asm volatile ("mcr p15, 0, %0, c13, c0, 3" : : "r" (_tpidruro));
189 }
190
191 PUBLIC inline
192 Mword
193 Context::tpidrurw() const
194 {
195   return _tpidrurw;
196 }
197
198 PUBLIC inline
199 Mword
200 Context::tpidruro() const
201 {
202   return _tpidruro;
203 }
204
205 // ------------------------------------------------------------------------
206 IMPLEMENTATION [!armv6plus]:
207
208 PROTECTED inline void Context::arch_setup_utcb_ptr()
209 {}
210
211 PRIVATE inline
212 void
213 Context::store_tpidrurw() const
214 {}
215
216 PRIVATE inline
217 void
218 Context::load_tpidrurw() const
219 {}
220
221 PROTECTED inline
222 void
223 Context::load_tpidruro() const
224 {}
225
226 PUBLIC inline
227 Mword
228 Context::tpidrurw() const
229 {
230   return 0;
231 }
232
233 PUBLIC inline
234 Mword
235 Context::tpidruro() const
236 {
237   return 0;
238 }