ia64/xen-unstable

view xen/include/xen/sched.h @ 9024:d0b7281556f2

New VCPUOP_register_runstate_memory_area hypercall. Avoids
need for a hypercall in the guest timer interrupt handler.

Cleaned up stolen/blocked tick handling in Linux.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Sat Feb 25 21:28:27 2006 +0100 (2006-02-25)
parents 2303fb4682e7
children c369d960f96b
line source
2 #ifndef __SCHED_H__
3 #define __SCHED_H__
5 #include <xen/config.h>
6 #include <xen/types.h>
7 #include <xen/spinlock.h>
8 #include <xen/smp.h>
9 #include <public/xen.h>
10 #include <public/dom0_ops.h>
11 #include <public/vcpu.h>
12 #include <xen/time.h>
13 #include <xen/timer.h>
14 #include <xen/grant_table.h>
15 #include <xen/rangeset.h>
16 #include <asm/domain.h>
18 extern unsigned long volatile jiffies;
19 extern rwlock_t domlist_lock;
21 /* A global pointer to the initial domain (DOM0). */
22 extern struct domain *dom0;
24 #define MAX_EVTCHNS NR_EVENT_CHANNELS
25 #define EVTCHNS_PER_BUCKET 128
26 #define NR_EVTCHN_BUCKETS (MAX_EVTCHNS / EVTCHNS_PER_BUCKET)
28 struct evtchn
29 {
30 #define ECS_FREE 0 /* Channel is available for use. */
31 #define ECS_RESERVED 1 /* Channel is reserved. */
32 #define ECS_UNBOUND 2 /* Channel is waiting to bind to a remote domain. */
33 #define ECS_INTERDOMAIN 3 /* Channel is bound to another domain. */
34 #define ECS_PIRQ 4 /* Channel is bound to a physical IRQ line. */
35 #define ECS_VIRQ 5 /* Channel is bound to a virtual IRQ line. */
36 #define ECS_IPI 6 /* Channel is bound to a virtual IPI line. */
37 u16 state; /* ECS_* */
38 u16 notify_vcpu_id; /* VCPU for local delivery notification */
39 union {
40 struct {
41 domid_t remote_domid;
42 } unbound; /* state == ECS_UNBOUND */
43 struct {
44 u16 remote_port;
45 struct domain *remote_dom;
46 } interdomain; /* state == ECS_INTERDOMAIN */
47 u16 pirq; /* state == ECS_PIRQ */
48 u16 virq; /* state == ECS_VIRQ */
49 } u;
50 };
52 int evtchn_init(struct domain *d);
53 void evtchn_destroy(struct domain *d);
55 struct vcpu
56 {
57 int vcpu_id;
59 int processor;
61 vcpu_info_t *vcpu_info;
63 struct domain *domain;
65 struct vcpu *next_in_list;
67 struct timer timer; /* one-shot timer for timeout values */
68 unsigned long sleep_tick; /* tick at which this vcpu started sleep */
70 void *sched_priv; /* scheduler-specific data */
72 struct vcpu_runstate_info runstate;
73 struct vcpu_runstate_info *runstate_guest; /* guest address */
75 unsigned long vcpu_flags;
77 u16 virq_to_evtchn[NR_VIRQS];
79 atomic_t pausecnt;
81 /* Bitmask of CPUs on which this VCPU may run. */
82 cpumask_t cpu_affinity;
84 unsigned long nmi_addr; /* NMI callback address. */
86 /* Bitmask of CPUs which are holding onto this VCPU's state. */
87 cpumask_t vcpu_dirty_cpumask;
89 struct arch_vcpu arch;
90 };
92 /* Per-domain lock can be recursively acquired in fault handlers. */
93 #define LOCK_BIGLOCK(_d) spin_lock_recursive(&(_d)->big_lock)
94 #define UNLOCK_BIGLOCK(_d) spin_unlock_recursive(&(_d)->big_lock)
96 struct domain
97 {
98 domid_t domain_id;
100 shared_info_t *shared_info; /* shared data area */
102 spinlock_t big_lock;
104 spinlock_t page_alloc_lock; /* protects all the following fields */
105 struct list_head page_list; /* linked list, of size tot_pages */
106 struct list_head xenpage_list; /* linked list, of size xenheap_pages */
107 unsigned int tot_pages; /* number of pages currently possesed */
108 unsigned int max_pages; /* maximum value for tot_pages */
109 unsigned int xenheap_pages; /* # pages allocated from Xen heap */
111 /* Scheduling. */
112 int shutdown_code; /* code value from OS (if DOMF_shutdown) */
113 void *sched_priv; /* scheduler-specific data */
115 struct domain *next_in_list;
116 struct domain *next_in_hashbucket;
118 struct list_head rangesets;
119 spinlock_t rangesets_lock;
121 /* Event channel information. */
122 struct evtchn *evtchn[NR_EVTCHN_BUCKETS];
123 spinlock_t evtchn_lock;
125 grant_table_t *grant_table;
127 /*
128 * Interrupt to event-channel mappings. Updates should be protected by the
129 * domain's event-channel spinlock. Read accesses can also synchronise on
130 * the lock, but races don't usually matter.
131 */
132 #define NR_PIRQS 256 /* Put this somewhere sane! */
133 u16 pirq_to_evtchn[NR_PIRQS];
134 u32 pirq_mask[NR_PIRQS/32];
136 /* I/O capabilities (access to IRQs and memory-mapped I/O). */
137 struct rangeset *iomem_caps;
138 struct rangeset *irq_caps;
140 unsigned long domain_flags;
141 unsigned long vm_assist;
143 atomic_t refcnt;
145 struct vcpu *vcpu[MAX_VIRT_CPUS];
147 /* Bitmask of CPUs which are holding onto this domain's state. */
148 cpumask_t domain_dirty_cpumask;
150 struct arch_domain arch;
152 void *ssid; /* sHype security subject identifier */
154 /* Control-plane tools handle for this domain. */
155 xen_domain_handle_t handle;
156 };
158 struct domain_setup_info
159 {
160 /* Initialised by caller. */
161 unsigned long image_addr;
162 unsigned long image_len;
163 /* Initialised by loader: Public. */
164 unsigned long v_start;
165 unsigned long v_end;
166 unsigned long v_kernstart;
167 unsigned long v_kernend;
168 unsigned long v_kernentry;
169 /* Initialised by loader: Private. */
170 unsigned int load_symtab;
171 unsigned long symtab_addr;
172 unsigned long symtab_len;
173 /* Indicate whether it's xen specific image */
174 char *xen_section_string;
175 };
177 extern struct vcpu *idle_vcpu[NR_CPUS];
178 #define IDLE_DOMAIN_ID (0x7FFFU)
179 #define is_idle_domain(d) ((d)->domain_id == IDLE_DOMAIN_ID)
180 #define is_idle_vcpu(v) (is_idle_domain((v)->domain))
182 struct vcpu *alloc_vcpu(
183 struct domain *d, unsigned int vcpu_id, unsigned int cpu_id);
185 struct domain *alloc_domain(void);
186 void free_domain(struct domain *d);
188 #define DOMAIN_DESTROYED (1<<31) /* assumes atomic_t is >= 32 bits */
189 #define put_domain(_d) \
190 if ( atomic_dec_and_test(&(_d)->refcnt) ) domain_destroy(_d)
192 /*
193 * Use this when you don't have an existing reference to @d. It returns
194 * FALSE if @d is being destroyed.
195 */
196 static always_inline int get_domain(struct domain *d)
197 {
198 atomic_t old, new, seen = d->refcnt;
199 do
200 {
201 old = seen;
202 if ( unlikely(_atomic_read(old) & DOMAIN_DESTROYED) )
203 return 0;
204 _atomic_set(new, _atomic_read(old) + 1);
205 seen = atomic_compareandswap(old, new, &d->refcnt);
206 }
207 while ( unlikely(_atomic_read(seen) != _atomic_read(old)) );
208 return 1;
209 }
211 /*
212 * Use this when you already have, or are borrowing, a reference to @d.
213 * In this case we know that @d cannot be destroyed under our feet.
214 */
215 static inline void get_knownalive_domain(struct domain *d)
216 {
217 atomic_inc(&d->refcnt);
218 ASSERT(!(atomic_read(&d->refcnt) & DOMAIN_DESTROYED));
219 }
221 extern struct domain *domain_create(
222 domid_t dom_id, unsigned int cpu);
223 extern int construct_dom0(
224 struct domain *d,
225 unsigned long image_start, unsigned long image_len,
226 unsigned long initrd_start, unsigned long initrd_len,
227 char *cmdline);
228 extern int set_info_guest(struct domain *d, dom0_setvcpucontext_t *);
230 struct domain *find_domain_by_id(domid_t dom);
231 extern void domain_destroy(struct domain *d);
232 extern void domain_kill(struct domain *d);
233 extern void domain_shutdown(struct domain *d, u8 reason);
234 extern void domain_pause_for_debugger(void);
236 /*
237 * Mark specified domain as crashed. This function always returns, even if the
238 * caller is the specified domain. The domain is not synchronously descheduled
239 * from any processor.
240 */
241 extern void __domain_crash(struct domain *d);
242 #define domain_crash(d) do { \
243 printk("domain_crash called from %s:%d\n", __FILE__, __LINE__); \
244 __domain_crash(d); \
245 } while (0)
247 /*
248 * Mark current domain as crashed and synchronously deschedule from the local
249 * processor. This function never returns.
250 */
251 extern void __domain_crash_synchronous(void) __attribute__((noreturn));
252 #define domain_crash_synchronous() do { \
253 printk("domain_crash_sync called from %s:%d\n", __FILE__, __LINE__); \
254 __domain_crash_synchronous(); \
255 } while (0)
257 void new_thread(struct vcpu *d,
258 unsigned long start_pc,
259 unsigned long start_stack,
260 unsigned long start_info);
262 #define set_current_state(_s) do { current->state = (_s); } while (0)
263 void scheduler_init(void);
264 void schedulers_start(void);
265 void sched_add_domain(struct vcpu *);
266 void sched_rem_domain(struct vcpu *);
267 long sched_ctl(struct sched_ctl_cmd *);
268 long sched_adjdom(struct sched_adjdom_cmd *);
269 int sched_id();
270 void vcpu_wake(struct vcpu *d);
271 void vcpu_sleep_nosync(struct vcpu *d);
272 void vcpu_sleep_sync(struct vcpu *d);
274 /*
275 * Force synchronisation of given VCPU's state. If it is currently descheduled,
276 * this call will ensure that all its state is committed to memory and that
277 * no CPU is using critical state (e.g., page tables) belonging to the VCPU.
278 */
279 extern void sync_vcpu_execstate(struct vcpu *v);
281 /*
282 * Called by the scheduler to switch to another VCPU. This function must
283 * call context_saved(@prev) when the local CPU is no longer running in
284 * @prev's context, and that context is saved to memory. Alternatively, if
285 * implementing lazy context switching, it suffices to ensure that invoking
286 * sync_vcpu_execstate() will switch and commit @prev's state.
287 */
288 extern void context_switch(
289 struct vcpu *prev,
290 struct vcpu *next);
292 /*
293 * As described above, context_switch() must call this function when the
294 * local CPU is no longer running in @prev's context, and @prev's context is
295 * saved to memory. Alternatively, if implementing lazy context switching,
296 * ensure that invoking sync_vcpu_execstate() will switch and commit @prev.
297 */
298 #define context_saved(prev) (clear_bit(_VCPUF_running, &(prev)->vcpu_flags))
300 /* Called by the scheduler to continue running the current VCPU. */
301 extern void continue_running(
302 struct vcpu *same);
304 void startup_cpu_idle_loop(void);
306 unsigned long __hypercall_create_continuation(
307 unsigned int op, unsigned int nr_args, ...);
308 #define hypercall0_create_continuation(_op) \
309 __hypercall_create_continuation((_op), 0)
310 #define hypercall1_create_continuation(_op, _a1) \
311 __hypercall_create_continuation((_op), 1, \
312 (unsigned long)(_a1))
313 #define hypercall2_create_continuation(_op, _a1, _a2) \
314 __hypercall_create_continuation((_op), 2, \
315 (unsigned long)(_a1), (unsigned long)(_a2))
316 #define hypercall3_create_continuation(_op, _a1, _a2, _a3) \
317 __hypercall_create_continuation((_op), 3, \
318 (unsigned long)(_a1), (unsigned long)(_a2), (unsigned long)(_a3))
319 #define hypercall4_create_continuation(_op, _a1, _a2, _a3, _a4) \
320 __hypercall_create_continuation((_op), 4, \
321 (unsigned long)(_a1), (unsigned long)(_a2), (unsigned long)(_a3), \
322 (unsigned long)(_a4))
323 #define hypercall5_create_continuation(_op, _a1, _a2, _a3, _a4, _a5) \
324 __hypercall_create_continuation((_op), 5, \
325 (unsigned long)(_a1), (unsigned long)(_a2), (unsigned long)(_a3), \
326 (unsigned long)(_a4), (unsigned long)(_a5))
327 #define hypercall6_create_continuation(_op, _a1, _a2, _a3, _a4, _a5, _a6) \
328 __hypercall_create_continuation((_op), 6, \
329 (unsigned long)(_a1), (unsigned long)(_a2), (unsigned long)(_a3), \
330 (unsigned long)(_a4), (unsigned long)(_a5), (unsigned long)(_a6))
332 #define hypercall_preempt_check() (unlikely( \
333 softirq_pending(smp_processor_id()) | \
334 event_pending(current) \
335 ))
337 /* This domain_hash and domain_list are protected by the domlist_lock. */
338 #define DOMAIN_HASH_SIZE 256
339 #define DOMAIN_HASH(_id) ((int)(_id)&(DOMAIN_HASH_SIZE-1))
340 extern struct domain *domain_hash[DOMAIN_HASH_SIZE];
341 extern struct domain *domain_list;
343 #define for_each_domain(_d) \
344 for ( (_d) = domain_list; \
345 (_d) != NULL; \
346 (_d) = (_d)->next_in_list )
348 #define for_each_vcpu(_d,_v) \
349 for ( (_v) = (_d)->vcpu[0]; \
350 (_v) != NULL; \
351 (_v) = (_v)->next_in_list )
353 /*
354 * Per-VCPU flags (vcpu_flags).
355 */
356 /* Has the FPU been initialised? */
357 #define _VCPUF_fpu_initialised 0
358 #define VCPUF_fpu_initialised (1UL<<_VCPUF_fpu_initialised)
359 /* Has the FPU been used since it was last saved? */
360 #define _VCPUF_fpu_dirtied 1
361 #define VCPUF_fpu_dirtied (1UL<<_VCPUF_fpu_dirtied)
362 /* Domain is blocked waiting for an event. */
363 #define _VCPUF_blocked 2
364 #define VCPUF_blocked (1UL<<_VCPUF_blocked)
365 /* Currently running on a CPU? */
366 #define _VCPUF_running 3
367 #define VCPUF_running (1UL<<_VCPUF_running)
368 /* Initialization completed. */
369 #define _VCPUF_initialised 4
370 #define VCPUF_initialised (1UL<<_VCPUF_initialised)
371 /* VCPU is not-runnable */
372 #define _VCPUF_down 5
373 #define VCPUF_down (1UL<<_VCPUF_down)
374 /* NMI callback pending for this VCPU? */
375 #define _VCPUF_nmi_pending 8
376 #define VCPUF_nmi_pending (1UL<<_VCPUF_nmi_pending)
377 /* Avoid NMI reentry by allowing NMIs to be masked for short periods. */
378 #define _VCPUF_nmi_masked 9
379 #define VCPUF_nmi_masked (1UL<<_VCPUF_nmi_masked)
381 /*
382 * Per-domain flags (domain_flags).
383 */
384 /* Is this domain privileged? */
385 #define _DOMF_privileged 0
386 #define DOMF_privileged (1UL<<_DOMF_privileged)
387 /* Guest shut itself down for some reason. */
388 #define _DOMF_shutdown 1
389 #define DOMF_shutdown (1UL<<_DOMF_shutdown)
390 /* Death rattle. */
391 #define _DOMF_dying 2
392 #define DOMF_dying (1UL<<_DOMF_dying)
393 /* Domain is paused by controller software. */
394 #define _DOMF_ctrl_pause 3
395 #define DOMF_ctrl_pause (1UL<<_DOMF_ctrl_pause)
396 /* Domain is being debugged by controller software. */
397 #define _DOMF_debugging 4
398 #define DOMF_debugging (1UL<<_DOMF_debugging)
400 static inline int vcpu_runnable(struct vcpu *v)
401 {
402 return ( (atomic_read(&v->pausecnt) == 0) &&
403 !(v->vcpu_flags & (VCPUF_blocked|VCPUF_down)) &&
404 !(v->domain->domain_flags & (DOMF_shutdown|DOMF_ctrl_pause)) );
405 }
407 void vcpu_pause(struct vcpu *v);
408 void domain_pause(struct domain *d);
409 void vcpu_unpause(struct vcpu *v);
410 void domain_unpause(struct domain *d);
411 void domain_pause_by_systemcontroller(struct domain *d);
412 void domain_unpause_by_systemcontroller(struct domain *d);
413 void cpu_init(void);
415 int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity);
417 void vcpu_runstate_get(struct vcpu *v, struct vcpu_runstate_info *runstate);
419 static inline void vcpu_unblock(struct vcpu *v)
420 {
421 if ( test_and_clear_bit(_VCPUF_blocked, &v->vcpu_flags) )
422 vcpu_wake(v);
423 }
425 #define IS_PRIV(_d) \
426 (test_bit(_DOMF_privileged, &(_d)->domain_flags))
428 #define VM_ASSIST(_d,_t) (test_bit((_t), &(_d)->vm_assist))
430 #endif /* __SCHED_H__ */
432 /*
433 * Local variables:
434 * mode: C
435 * c-set-style: "BSD"
436 * c-basic-offset: 4
437 * tab-width: 4
438 * indent-tabs-mode: nil
439 * End:
440 */