]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/context-vcpu.cpp
c322bc9f31da59cb9a3cead6f35a223ebf13cd77
[l4.git] / kernel / fiasco / src / kern / context-vcpu.cpp
1 INTERFACE:
2
3 #include "vcpu.h"
4
5 EXTENSION class Context
6 {
7 protected:
8   Space *_vcpu_user_space;
9
10 private:
11   Vcpu_state *_vcpu_state;
12 };
13
14
15 IMPLEMENTATION:
16
17 PROTECTED inline
18 Vcpu_state *
19 Context::vcpu_state() const
20 { return _vcpu_state; }
21
22 PROTECTED inline
23 void
24 Context::vcpu_state(void *s)
25 { _vcpu_state = (Vcpu_state*)s; }
26
27
28 PUBLIC inline
29 Mword
30 Context::vcpu_disable_irqs()
31 {
32   if (EXPECT_FALSE(state() & Thread_vcpu_enabled))
33     {
34       Mword s = vcpu_state()->state;
35       vcpu_state()->state = s & ~Vcpu_state::F_irqs;
36       return s & Vcpu_state::F_irqs;
37     }
38   return 0;
39 }
40
41 PUBLIC inline
42 void
43 Context::vcpu_restore_irqs(bool irqs)
44 {
45   if (EXPECT_FALSE(state() & Thread_vcpu_enabled) && irqs)
46     vcpu_state()->state |= Vcpu_state::F_irqs;
47 }
48
49 PUBLIC inline
50 void
51 Context::vcpu_save_state_and_upcall()
52 {
53   extern char leave_by_vcpu_upcall[];
54   _exc_cont.activate(regs(), leave_by_vcpu_upcall);
55 }
56
57 PUBLIC inline NEEDS["fpu.h"]
58 void
59 Context::vcpu_enter_kernel_mode()
60 {
61   if (EXPECT_FALSE(state() & Thread_vcpu_enabled))
62     {
63       vcpu_state()->_saved_state = vcpu_state()->state;
64       Mword flags = Vcpu_state::F_traps
65                     | Vcpu_state::F_user_mode;
66       vcpu_state()->state &= ~flags;
67       if (state() & Thread_vcpu_user_mode)
68         {
69           vcpu_state()->_sp = vcpu_state()->_entry_sp;
70           state_del_dirty(  Thread_vcpu_user_mode
71                           | Thread_vcpu_fpu_disabled
72                           | Thread_alien);
73
74           if (current() == this)
75             {
76               if (state() & Thread_fpu_owner)
77                 Fpu::enable();
78
79               space()->switchin_context(vcpu_user_space());
80             }
81         }
82       else
83         vcpu_state()->_sp = regs()->sp();
84     }
85 }
86
87
88
89 PUBLIC inline
90 bool
91 Context::vcpu_irqs_enabled() const
92 {
93   return EXPECT_FALSE(state() & Thread_vcpu_enabled)
94     && vcpu_state()->state & Vcpu_state::F_irqs;
95 }
96
97 PUBLIC inline
98 bool
99 Context::vcpu_pagefaults_enabled() const
100 {
101   return EXPECT_FALSE(state() & Thread_vcpu_enabled)
102     && vcpu_state()->state & Vcpu_state::F_page_faults;
103 }
104
105 PUBLIC inline
106 bool
107 Context::vcpu_exceptions_enabled() const
108 {
109   return EXPECT_FALSE(state() & Thread_vcpu_enabled)
110     && vcpu_state()->state & Vcpu_state::F_exceptions;
111 }
112
113 PUBLIC inline
114 void
115 Context::vcpu_set_irq_pending()
116 {
117   if (EXPECT_FALSE(state() & Thread_vcpu_enabled))
118     vcpu_state()->sticky_flags |= Vcpu_state::Sf_irq_pending;
119 }
120
121 PUBLIC inline
122 bool
123 Context::vcpu_irqs_pending() const
124 {
125   if (EXPECT_FALSE(state() & Thread_vcpu_enabled))
126     return vcpu_state()->sticky_flags & Vcpu_state::Sf_irq_pending;
127   return false;
128 }
129
130 /** Return the space context.
131     @return space context used for this execution context.
132             Set with set_space_context().
133  */
134 PUBLIC inline NEEDS["kdb_ke.h", "cpu_lock.h"]
135 Space *
136 Context::vcpu_user_space() const
137 {
138   //assert_kdb (cpu_lock.test());
139   return _vcpu_user_space;
140 }
141
142 PUBLIC inline NEEDS["space.h"]
143 void
144 Context::vcpu_set_user_space(Space *t)
145 {
146   assert_kdb (current() == this);
147   if (t)
148     t->inc_ref();
149   else
150     state_del_dirty(Thread_vcpu_user_mode);
151
152   Space *old = _vcpu_user_space;
153   _vcpu_user_space = t;
154
155   if (old)
156     {
157       if (!old->dec_ref())
158         {
159           rcu_wait();
160           delete old;
161         }
162     }
163 }
164
165
166 // --------------------------------------------------------------------------
167 INTERFACE [debug]:
168
169 EXTENSION class Context
170 {
171   static unsigned vcpu_log_fmt(Tb_entry *, int, char *)
172   asm ("__context_vcpu_log_fmt");
173 };
174
175
176 // --------------------------------------------------------------------------
177 IMPLEMENTATION [debug]:
178
179 #include "kobject_dbg.h"
180
181 IMPLEMENT
182 unsigned
183 Context::vcpu_log_fmt(Tb_entry *e, int maxlen, char *buf)
184 {
185   Vcpu_log *l = e->payload<Vcpu_log>();
186
187   switch (l->type)
188     {
189     case 0:
190     case 4:
191       return snprintf(buf, maxlen, "%sret pc=%lx sp=%lx state=%lx task=D:%lx",
192           l->type == 4 ? "f" : "", l->ip, l->sp, l->state, l->space);
193     case 1:
194       return snprintf(buf, maxlen, "ipc from D:%lx task=D:%lx sp=%lx",
195           Kobject_dbg::pointer_to_id((Kobject*)l->ip), l->state, l->sp);
196     case 2:
197       return snprintf(buf, maxlen, "exc #%x err=%lx pc=%lx sp=%lx state=%lx task=D:%lx",
198           (unsigned)l->trap, l->err, l->ip, l->sp, l->state, l->space);
199     case 3:
200       return snprintf(buf, maxlen, "pf  pc=%lx pfa=%lx state=%lx task=D:%lx",
201           l->ip, l->sp, l->state, l->space);
202     default:
203       return snprintf(buf, maxlen, "unknown");
204     }
205 }
206