L4Re - L4 Runtime Environment
vcpu
1 // vi:se ft=cpp:
2 /*
3  * (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
4  * economic rights: Technische Universit├Ąt Dresden (Germany)
5  *
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU General Public License 2.
8  * Please see the COPYING-GPL-2 file for details.
9  *
10  * As a special exception, you may use this file as part of a free software
11  * library without restriction. Specifically, if other files instantiate
12  * templates or use macros or inline functions from this file, or you compile
13  * this file and link it with other files to produce an executable, this
14  * file does not by itself cause the resulting executable to be covered by
15  * the GNU General Public License. This exception does not however
16  * invalidate any other reasons why the executable file might be covered by
17  * the GNU General Public License.
18  */
19 
20 #pragma once
21 
22 #include <l4/re/env>
23 #include <l4/vcpu/vcpu.h>
24 
25 namespace L4vcpu {
26 
27 /**
28  * \brief C++ implementation of state word in the vCPU area
29  * \ingroup api_libvcpu
30  */
31 class State
32 {
33 public:
34  State() {}
35 
36  /**
37  * \brief Initialize state.
38  *
39  * \param v Initial state.
40  */
41  explicit State(unsigned v) : _s(v) {}
42 
43  /**
44  * \brief Add flags.
45  *
46  * \param bits Bits to add to the word.
47  */
48  void add(unsigned bits) throw() { _s |= bits; }
49 
50  /**
51  * \brief Clear flags.
52  *
53  * \param bits Bits to clear in the word.
54  */
55  void clear(unsigned bits) throw() { _s &= ~bits; }
56 
57  /**
58  * \brief Set flags.
59  *
60  * \param v Set the word to the value of v.
61  */
62  void set(unsigned v) throw() { _s = v; }
63 
64 private:
65  __typeof__(((l4_vcpu_state_t *)0)->state) _s;
66 };
67 
68 /**
69  * \brief C++ implementation of the vCPU save state area
70  * \ingroup api_libvcpu
71  */
72 class Vcpu : private l4_vcpu_state_t
73 {
74 public:
75  /**
76  * \brief Disable the vCPU for event delivery.
77  */
78  void irq_disable() throw()
79  { l4vcpu_irq_disable(this); }
80 
81  /**
82  * \brief Disable the vCPU for event delivery and return previous state.
83  * \return IRQ state before disabling IRQs.
84  */
85  unsigned irq_disable_save() throw()
86  { return l4vcpu_irq_disable_save(this); }
87 
88  l4_vcpu_state_t *s() { return this; }
89  l4_vcpu_state_t const *s() const { return this; }
90 
91  /**
92  * \brief Get state word
93  * \return Pointer to state word in the vCPU
94  */
95  State *state() throw()
96  {
97  static_assert(sizeof(State) == sizeof(l4_vcpu_state_t::state),
98  "size mismatch");
99  return reinterpret_cast<State *>(&(l4_vcpu_state_t::state));
100  }
101 
102  /**
103  * \brief Get state word
104  * \return Pointer to state word in the vCPU
105  */
106  State state() const throw()
107  { return static_cast<State>(l4_vcpu_state_t::state); }
108 
109  /**
110  * \brief Get saved_state word
111  * \return Pointer to saved_state word in the vCPU
112  */
113  State *saved_state() throw()
114  {
115  static_assert(sizeof(State) == sizeof(l4_vcpu_state_t::saved_state),
116  "size mismatch");
117  return reinterpret_cast<State *>(&(l4_vcpu_state_t::saved_state));
118  }
119  /**
120  * \brief Get saved_state word
121  * \return Pointer to saved_state word in the vCPU
122  */
123  State saved_state() const throw()
124  { return static_cast<State>(l4_vcpu_state_t::saved_state); }
125 
126  /**
127  * \brief Get sticky flags
128  */
129  l4_uint16_t sticky_flags() const throw()
130  { return l4_vcpu_state_t::sticky_flags; }
131 
132  /**
133  * \brief Enable the vCPU for event delivery.
134  *
135  * \param utcb The UTCB to use.
136  * \param do_event_work_cb Call-back function that is called in case an
137  * event (such as an interrupt) is pending.
138  * \param setup_ipc Call-back function that is called before an
139  * IPC operation is called, and before event
140  * delivery is enabled.
141  */
142  void irq_enable(l4_utcb_t *utcb, l4vcpu_event_hndl_t do_event_work_cb,
143  l4vcpu_setup_ipc_t setup_ipc) throw()
144  { l4vcpu_irq_enable(this, utcb, do_event_work_cb, setup_ipc); }
145 
146  /**
147  * \brief Restore a previously saved IRQ/event state.
148  *
149  * \param s IRQ state to be restored.
150  * \param utcb The UTCB to use.
151  * \param do_event_work_cb Call-back function that is called in case an
152  * event (such as an interrupt) is pending.
153  * \param setup_ipc Call-back function that is called before an
154  * IPC operation is called, and before event
155  * delivery is enabled.
156  */
157  void irq_restore(unsigned s, l4_utcb_t *utcb,
158  l4vcpu_event_hndl_t do_event_work_cb,
159  l4vcpu_setup_ipc_t setup_ipc) throw()
160  { l4vcpu_irq_restore(this, s, utcb, do_event_work_cb, setup_ipc); }
161 
162  /**
163  * \brief Wait for event.
164  *
165  * \param utcb The UTCB to use.
166  * \param do_event_work_cb Call-back function that is called in case an
167  * event (such as an interrupt) is pending.
168  * \param setup_ipc Call-back function that is called before an
169  * IPC operation is called.
170  *
171  * Note that event delivery remains disabled after this function returns.
172  */
173  void wait_for_event(l4_utcb_t *utcb, l4vcpu_event_hndl_t do_event_work_cb,
174  l4vcpu_setup_ipc_t setup_ipc) throw()
175  { l4vcpu_wait_for_event(this, utcb, do_event_work_cb, setup_ipc); }
176 
177  /**
178  * \brief Set the task of the vCPU.
179  * \param task Task to set, defaults to invalid task.
180  */
181  void task(L4::Cap<L4::Task> const task = L4::Cap<L4::Task>::Invalid) throw()
182  { user_task = task.cap(); }
183 
184  /**
185  * \brief Return whether the entry reason was a page fault.
186  * return 0 if not, !=0 otherwise.
187  */
188  int is_page_fault_entry() const
189  { return l4vcpu_is_page_fault_entry(this); }
190 
191  /**
192  * \brief Return whether the entry reason was an IRQ/IPC message.
193  * return 0 if not, !=0 otherwise.
194  */
195  int is_irq_entry() const
196  { return l4vcpu_is_irq_entry(this); }
197 
198  /**
199  * \brief Return pointer to register state.
200  * \return Pointer to register state.
201  */
202  l4_vcpu_regs_t *r() throw()
203  { return &(l4_vcpu_state_t::r); }
204 
205  /**
206  * \brief Return pointer to register state.
207  * \return Pointer to register state.
208  */
209  l4_vcpu_regs_t const *r() const throw()
210  { return &(l4_vcpu_state_t::r); }
211 
212  /**
213  * \brief Return pointer to IPC state.
214  * \return Pointer to IPC state.
215  */
216  l4_vcpu_ipc_regs_t *i() throw()
217  { return &(l4_vcpu_state_t::i); }
218 
219  /**
220  * \brief Return pointer to IPC state.
221  * \return Pointer to IPC state.
222  */
223  l4_vcpu_ipc_regs_t const *i() const throw()
224  { return &(l4_vcpu_state_t::i); }
225 
226  /**
227  * \brief Set vCPU entry stack pointer.
228  * \param sp Stack pointer address to set.
229  *
230  * \note The value is only used when entering from a user-task.
231  */
232  void entry_sp(l4_umword_t sp)
233  { l4_vcpu_state_t::entry_sp = sp; }
234 
235  /**
236  * \brief Set vCPU entry instruction pointer.
237  * \param ip Instruction pointer address to set.
238  */
239  void entry_ip(l4_umword_t ip)
240  { l4_vcpu_state_t::entry_ip = ip; }
241 
242  /**
243  * \brief Allocate state area for an extended vCPU.
244  *
245  * \retval vcpu Allocated vcpu-state area.
246  * \retval ext_state Allocated extended vcpu-state area.
247  * \param task Task to use for allocation, defaults to own task.
248  * \param rm Region manager to use for allocation defaults to standard region manager.
249  *
250  * \return 0 for success, error code otherwise
251  */
252  L4_CV static int
253  ext_alloc(Vcpu **vcpu,
254  l4_addr_t *ext_state,
255  L4::Cap<L4::Task> task = L4Re::Env::env()->task(),
256  L4::Cap<L4Re::Rm> rm = L4Re::Env::env()->rm()) throw();
257 
258  /**
259  * \brief Cast a void pointer to a class pointer.
260  *
261  * \param x Pointer.
262  *
263  * \return Pointer to Vcpu class.
264  */
265  static inline Vcpu *cast(void *x) throw()
266  { return reinterpret_cast<Vcpu *>(x); }
267 
268  /**
269  * \brief Cast an address to a class pointer.
270  *
271  * \param x Pointer.
272  *
273  * \return Pointer to Vcpu class.
274  */
275  static inline Vcpu *cast(l4_addr_t x) throw()
276  { return reinterpret_cast<Vcpu *>(x); }
277 
278  /**
279  * \brief Print the state of the vCPU.
280  */
281  void print_state(const char *prefix = "") const throw()
282  { l4vcpu_print_state(this, prefix); }
283 };
284 
285 
286 }