]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/libvcpu/include/vcpu.h
update
[l4.git] / l4 / pkg / libvcpu / include / vcpu.h
1 /*
2  * (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
3  *     economic rights: Technische Universität Dresden (Germany)
4  *
5  * This file is part of TUD:OS and distributed under the terms of the
6  * GNU General Public License 2.
7  * Please see the COPYING-GPL-2 file for details.
8  *
9  * As a special exception, you may use this file as part of a free software
10  * library without restriction.  Specifically, if other files instantiate
11  * templates or use macros or inline functions from this file, or you compile
12  * this file and link it with other files to produce an executable, this
13  * file does not by itself cause the resulting executable to be covered by
14  * the GNU General Public License.  This exception does not however
15  * invalidate any other reasons why the executable file might be covered by
16  * the GNU General Public License.
17  */
18 #pragma once
19
20 #include <l4/sys/vcpu.h>
21
22 __BEGIN_DECLS
23
24 /**
25  * \defgroup api_libvcpu vCPU Support Library
26  * \brief vCPU handling functionality.
27  *
28  * This library provides convenience functionality on top of the l4sys vCPU
29  * interface to ease programming. It wraps commonly used code and abstracts
30  * architecture depends parts as far as reasonable.
31  */
32
33 /**
34  * \brief IRQ/Event enable and disable flags.
35  * \ingroup api_libvcpu
36  */
37 typedef enum l4vcpu_irq_state_t
38 {
39   L4VCPU_IRQ_STATE_DISABLED = 0,             ///< IRQ/Event delivery disabled
40   L4VCPU_IRQ_STATE_ENABLED  = L4_VCPU_F_IRQ, ///< IRQ/Event delivery enabled
41 } l4vcpu_irq_state_t;
42
43 typedef l4_umword_t l4vcpu_state_t;
44 typedef void (*l4vcpu_event_hndl_t)(l4_vcpu_state_t *vcpu);
45
46 /**
47  * \brief Return the state flags of a vCPU.
48  * \ingroup api_libvcpu
49  *
50  * \param vcpu  Pointer to vCPU area.
51  */
52 L4_INLINE
53 l4vcpu_state_t
54 l4vcpu_state(l4_vcpu_state_t const *vcpu) L4_NOTHROW;
55
56 /**
57  * \brief Disable a vCPU for event delivery.
58  * \ingroup api_libvcpu
59  *
60  * \param vcpu  Pointer to vCPU area.
61  */
62 L4_INLINE
63 void
64 l4vcpu_irq_disable(l4_vcpu_state_t *vcpu) L4_NOTHROW;
65
66 /**
67  * \brief Disable a vCPU for event delivery and return previous state.
68  * \ingroup api_libvcpu
69  *
70  * \param vcpu  Pointer to vCPU area.
71  *
72  * \return IRQ state before disabling IRQs.
73  */
74 L4_INLINE
75 l4vcpu_irq_state_t
76 l4vcpu_irq_disable_save(l4_vcpu_state_t *vcpu) L4_NOTHROW;
77
78 /**
79  * \brief Enable a vCPU for event delivery.
80  * \ingroup api_libvcpu
81  *
82  * \param vcpu             Pointer to vCPU area.
83  * \param do_event_work_cb Call-back function that is called in case an
84  *                         event (such as an interrupt) is pending.
85  */
86 L4_INLINE
87 void
88 l4vcpu_irq_enable(l4_vcpu_state_t *vcpu,
89                    l4vcpu_event_hndl_t do_event_work_cb) L4_NOTHROW;
90
91 /**
92  * \brief Restore a previously saved IRQ/event state.
93  * \ingroup api_libvcpu
94  *
95  * \param vcpu             Pointer to vCPU area.
96  * \param s                IRQ state to be restored.
97  * \param do_event_work_cb Call-back function that is called in case an
98  *                         event (such as an interrupt) is pending after
99  *                         enabling.
100  */
101 L4_INLINE
102 void
103 l4vcpu_irq_restore(l4_vcpu_state_t *vcpu, l4vcpu_irq_state_t s,
104                     l4vcpu_event_hndl_t do_event_work_cb) L4_NOTHROW;
105
106 /**
107  * \brief Halt the vCPU (sleep).
108  * \ingroup api_libvcpu
109  *
110  * \param vcpu             Pointer to vCPU area.
111  * \param do_event_work_cb Call-back function that is called when the vCPU
112  *                         awakes and needs to handle an event/IRQ.
113  */
114 L4_INLINE
115 void
116 l4vcpu_halt(l4_vcpu_state_t *vcpu,
117             l4vcpu_event_hndl_t do_event_work_cb) L4_NOTHROW;
118
119
120 /**
121  * \brief Print the state of a vCPU.
122  * \ingroup api_libvcpu
123  *
124  * \param vcpu   Pointer to vCPU area.
125  * \param prefix A prefix for each line printed.
126  */
127 void
128 l4vcpu_print_state(l4_vcpu_state_t *vcpu, const char *prefix) L4_NOTHROW;
129
130 /**
131  * \internal
132  */
133 void
134 l4vcpu_print_state_arch(l4_vcpu_state_t *vcpu, const char *prefix) L4_NOTHROW;
135
136
137 /**
138  * \brief Return whether the entry reason was an IRQ/IPC message.
139  * \ingroup api_libvcpu
140  *
141  * \param vcpu Pointer to vCPU area.
142  *
143  * return 0 if not, !=0 otherwise.
144  */
145 L4_INLINE
146 int
147 l4vcpu_is_irq_entry(l4_vcpu_state_t *vcpu) L4_NOTHROW;
148
149 /**
150  * \brief Return whether the entry reason was a page fault.
151  * \ingroup api_libvcpu
152  *
153  * \param vcpu Pointer to vCPU area.
154  *
155  * return 0 if not, !=0 otherwise.
156  */
157 L4_INLINE
158 int
159 l4vcpu_is_page_fault_entry(l4_vcpu_state_t *vcpu) L4_NOTHROW;
160
161
162 /* ===================================================================== */
163 /* Implementations */
164
165 #include <l4/sys/ipc.h>
166 #include <l4/vcpu/vcpu_arch.h>
167
168 L4_INLINE
169 l4vcpu_state_t
170 l4vcpu_state(l4_vcpu_state_t const *vcpu) L4_NOTHROW
171 {
172   return vcpu->state;
173 }
174
175 L4_INLINE
176 void
177 l4vcpu_irq_disable(l4_vcpu_state_t *vcpu) L4_NOTHROW
178 {
179   vcpu->state &= ~L4_VCPU_F_IRQ;
180   l4_barrier();
181 }
182
183 L4_INLINE
184 l4vcpu_irq_state_t
185 l4vcpu_irq_disable_save(l4_vcpu_state_t *vcpu) L4_NOTHROW
186 {
187   l4vcpu_irq_state_t s = (l4vcpu_irq_state_t)l4vcpu_state(vcpu);
188   l4vcpu_irq_disable(vcpu);
189   return s;
190 }
191
192 L4_INLINE
193 void
194 l4vcpu_irq_enable(l4_vcpu_state_t *vcpu,
195                    void (*do_event_work_cb)(l4_vcpu_state_t *vcpu)) L4_NOTHROW
196 {
197   while (1)
198     {
199       vcpu->state |= L4_VCPU_F_IRQ;
200       l4_barrier();
201
202       if (!(vcpu->sticky_flags & L4_VCPU_SF_IRQ_PENDING))
203         break;
204
205       l4vcpu_irq_disable(vcpu);
206       vcpu->i.tag = l4_ipc_wait(l4_utcb(), &vcpu->i.label, L4_IPC_NEVER);
207       if (!l4_msgtag_has_error(vcpu->i.tag))
208         do_event_work_cb(vcpu);
209     }
210 }
211
212 L4_INLINE
213 void
214 l4vcpu_irq_restore(l4_vcpu_state_t *vcpu, l4vcpu_irq_state_t s,
215                     l4vcpu_event_hndl_t do_event_work_cb) L4_NOTHROW
216 {
217   if (s & L4_VCPU_F_IRQ)
218     l4vcpu_irq_enable(vcpu, do_event_work_cb);
219 }
220
221 L4_INLINE
222 void
223 l4vcpu_halt(l4_vcpu_state_t *vcpu,
224             l4vcpu_event_hndl_t do_event_work_cb) L4_NOTHROW
225 {
226   l4vcpu_irq_disable(vcpu);
227   vcpu->i.tag = l4_ipc_wait(l4_utcb(), &vcpu->i.label, L4_IPC_NEVER);
228   if (!l4_msgtag_has_error(vcpu->i.tag))
229     do_event_work_cb(vcpu);
230   l4vcpu_irq_enable(vcpu, do_event_work_cb);
231 }
232
233 __END_DECLS