ia64/xen-unstable

view xen/include/xen/sched.h @ 14635:5c52e5ca8459

hvm: Clean up handling of exception intercepts.
Only intercept #DB/#BP if a debugger is attached.
Signed-off-by: Keir Fraser <keir@xensource.com>
author Keir Fraser <keir@xensource.com>
date Wed Mar 28 18:47:17 2007 +0100 (2007-03-28)
parents 215b799fa181
children 4b13fc910acf
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 <xen/shared.h>
10 #include <public/xen.h>
11 #include <public/domctl.h>
12 #include <public/vcpu.h>
13 #include <xen/time.h>
14 #include <xen/timer.h>
15 #include <xen/grant_table.h>
16 #include <xen/rangeset.h>
17 #include <asm/domain.h>
18 #include <xen/xenoprof.h>
19 #include <xen/rcupdate.h>
20 #include <xen/irq.h>
22 #ifdef CONFIG_COMPAT
23 #include <compat/vcpu.h>
24 DEFINE_XEN_GUEST_HANDLE(vcpu_runstate_info_compat_t);
25 #endif
27 extern unsigned long volatile jiffies;
29 /* A global pointer to the initial domain (DOM0). */
30 extern struct domain *dom0;
32 #ifndef CONFIG_COMPAT
33 #define MAX_EVTCHNS(d) NR_EVENT_CHANNELS
34 #else
35 #define MAX_EVTCHNS(d) (!IS_COMPAT(d) ? \
36 NR_EVENT_CHANNELS : \
37 sizeof(unsigned int) * sizeof(unsigned int) * 64)
38 #endif
39 #define EVTCHNS_PER_BUCKET 128
40 #define NR_EVTCHN_BUCKETS (NR_EVENT_CHANNELS / EVTCHNS_PER_BUCKET)
42 struct evtchn
43 {
44 #define ECS_FREE 0 /* Channel is available for use. */
45 #define ECS_RESERVED 1 /* Channel is reserved. */
46 #define ECS_UNBOUND 2 /* Channel is waiting to bind to a remote domain. */
47 #define ECS_INTERDOMAIN 3 /* Channel is bound to another domain. */
48 #define ECS_PIRQ 4 /* Channel is bound to a physical IRQ line. */
49 #define ECS_VIRQ 5 /* Channel is bound to a virtual IRQ line. */
50 #define ECS_IPI 6 /* Channel is bound to a virtual IPI line. */
51 u8 state; /* ECS_* */
52 u8 consumer_is_xen; /* Consumed by Xen or by guest? */
53 u16 notify_vcpu_id; /* VCPU for local delivery notification */
54 union {
55 struct {
56 domid_t remote_domid;
57 } unbound; /* state == ECS_UNBOUND */
58 struct {
59 u16 remote_port;
60 struct domain *remote_dom;
61 } interdomain; /* state == ECS_INTERDOMAIN */
62 u16 pirq; /* state == ECS_PIRQ */
63 u16 virq; /* state == ECS_VIRQ */
64 } u;
65 };
67 int evtchn_init(struct domain *d);
68 void evtchn_destroy(struct domain *d);
70 struct vcpu
71 {
72 int vcpu_id;
74 int processor;
76 vcpu_info_t *vcpu_info;
78 struct domain *domain;
80 struct vcpu *next_in_list;
82 uint64_t periodic_period;
83 uint64_t periodic_last_event;
84 struct timer periodic_timer;
85 struct timer singleshot_timer;
87 struct timer poll_timer; /* timeout for SCHEDOP_poll */
89 void *sched_priv; /* scheduler-specific data */
91 struct vcpu_runstate_info runstate;
92 #ifndef CONFIG_COMPAT
93 # define runstate_guest(v) ((v)->runstate_guest)
94 XEN_GUEST_HANDLE(vcpu_runstate_info_t) runstate_guest; /* guest address */
95 #else
96 # define runstate_guest(v) ((v)->runstate_guest.native)
97 union {
98 XEN_GUEST_HANDLE(vcpu_runstate_info_t) native;
99 XEN_GUEST_HANDLE(vcpu_runstate_info_compat_t) compat;
100 } runstate_guest; /* guest address */
101 #endif
103 unsigned long vcpu_flags;
105 spinlock_t pause_lock;
106 unsigned int pause_count;
108 u16 virq_to_evtchn[NR_VIRQS];
110 /* Bitmask of CPUs on which this VCPU may run. */
111 cpumask_t cpu_affinity;
113 unsigned long nmi_addr; /* NMI callback address. */
115 /* Bitmask of CPUs which are holding onto this VCPU's state. */
116 cpumask_t vcpu_dirty_cpumask;
118 struct arch_vcpu arch;
119 };
121 /* Per-domain lock can be recursively acquired in fault handlers. */
122 #define LOCK_BIGLOCK(_d) spin_lock_recursive(&(_d)->big_lock)
123 #define UNLOCK_BIGLOCK(_d) spin_unlock_recursive(&(_d)->big_lock)
125 struct domain
126 {
127 domid_t domain_id;
129 shared_info_t *shared_info; /* shared data area */
131 spinlock_t big_lock;
133 spinlock_t page_alloc_lock; /* protects all the following fields */
134 struct list_head page_list; /* linked list, of size tot_pages */
135 struct list_head xenpage_list; /* linked list, of size xenheap_pages */
136 unsigned int tot_pages; /* number of pages currently possesed */
137 unsigned int max_pages; /* maximum value for tot_pages */
138 unsigned int xenheap_pages; /* # pages allocated from Xen heap */
140 /* Scheduling. */
141 int shutdown_code; /* code value from OS (if DOMF_shutdown) */
142 void *sched_priv; /* scheduler-specific data */
144 struct domain *next_in_list;
145 struct domain *next_in_hashbucket;
147 struct list_head rangesets;
148 spinlock_t rangesets_lock;
150 /* Event channel information. */
151 struct evtchn *evtchn[NR_EVTCHN_BUCKETS];
152 spinlock_t evtchn_lock;
154 struct grant_table *grant_table;
156 /*
157 * Interrupt to event-channel mappings. Updates should be protected by the
158 * domain's event-channel spinlock. Read accesses can also synchronise on
159 * the lock, but races don't usually matter.
160 */
161 u16 pirq_to_evtchn[NR_IRQS];
162 DECLARE_BITMAP(pirq_mask, NR_IRQS);
164 /* I/O capabilities (access to IRQs and memory-mapped I/O). */
165 struct rangeset *iomem_caps;
166 struct rangeset *irq_caps;
168 unsigned long domain_flags;
170 /* Is this an HVM guest? */
171 bool_t is_hvm;
172 /* Is this guest fully privileged (aka dom0)? */
173 bool_t is_privileged;
174 /* Is this guest being debugged by dom0? */
175 bool_t debugger_attached;
177 spinlock_t pause_lock;
178 unsigned int pause_count;
180 unsigned long vm_assist;
182 atomic_t refcnt;
184 struct vcpu *vcpu[MAX_VIRT_CPUS];
186 /* Bitmask of CPUs which are holding onto this domain's state. */
187 cpumask_t domain_dirty_cpumask;
189 struct arch_domain arch;
191 void *ssid; /* sHype security subject identifier */
193 /* Control-plane tools handle for this domain. */
194 xen_domain_handle_t handle;
196 /* OProfile support. */
197 struct xenoprof *xenoprof;
198 int32_t time_offset_seconds;
200 struct rcu_head rcu;
201 };
203 struct domain_setup_info
204 {
205 /* Initialised by caller. */
206 unsigned long image_addr;
207 unsigned long image_len;
208 /* Initialised by loader: Public. */
209 unsigned long v_start;
210 unsigned long v_end;
211 unsigned long v_kernstart;
212 unsigned long v_kernend;
213 unsigned long v_kernentry;
214 #define PAEKERN_no 0
215 #define PAEKERN_yes 1
216 #define PAEKERN_extended_cr3 2
217 #define PAEKERN_bimodal 3
218 unsigned int pae_kernel;
219 /* Initialised by loader: Private. */
220 unsigned long elf_paddr_offset;
221 unsigned int load_symtab;
222 unsigned long symtab_addr;
223 unsigned long symtab_len;
224 };
226 extern struct vcpu *idle_vcpu[NR_CPUS];
227 #define IDLE_DOMAIN_ID (0x7FFFU)
228 #define is_idle_domain(d) ((d)->domain_id == IDLE_DOMAIN_ID)
229 #define is_idle_vcpu(v) (is_idle_domain((v)->domain))
231 #define DOMAIN_DESTROYED (1<<31) /* assumes atomic_t is >= 32 bits */
232 #define put_domain(_d) \
233 if ( atomic_dec_and_test(&(_d)->refcnt) ) domain_destroy(_d)
235 /*
236 * Use this when you don't have an existing reference to @d. It returns
237 * FALSE if @d is being destroyed.
238 */
239 static always_inline int get_domain(struct domain *d)
240 {
241 atomic_t old, new, seen = d->refcnt;
242 do
243 {
244 old = seen;
245 if ( unlikely(_atomic_read(old) & DOMAIN_DESTROYED) )
246 return 0;
247 _atomic_set(new, _atomic_read(old) + 1);
248 seen = atomic_compareandswap(old, new, &d->refcnt);
249 }
250 while ( unlikely(_atomic_read(seen) != _atomic_read(old)) );
251 return 1;
252 }
254 /*
255 * Use this when you already have, or are borrowing, a reference to @d.
256 * In this case we know that @d cannot be destroyed under our feet.
257 */
258 static inline void get_knownalive_domain(struct domain *d)
259 {
260 atomic_inc(&d->refcnt);
261 ASSERT(!(atomic_read(&d->refcnt) & DOMAIN_DESTROYED));
262 }
264 /* Obtain a reference to the currently-running domain. */
265 static inline struct domain *get_current_domain(void)
266 {
267 struct domain *d = current->domain;
268 get_knownalive_domain(d);
269 return d;
270 }
272 struct domain *domain_create(domid_t domid, unsigned int domcr_flags);
273 /* DOMCRF_hvm: Create an HVM domain, as opposed to a PV domain. */
274 #define _DOMCRF_hvm 0
275 #define DOMCRF_hvm (1U<<_DOMCRF_hvm)
277 int construct_dom0(
278 struct domain *d,
279 unsigned long image_start, unsigned long image_len,
280 unsigned long initrd_start, unsigned long initrd_len,
281 char *cmdline);
283 /*
284 * rcu_lock_domain_by_id() is more efficient than get_domain_by_id().
285 * This is the preferred function if the returned domain reference
286 * is short lived, but it cannot be used if the domain reference needs
287 * to be kept beyond the current scope (e.g., across a softirq).
288 * The returned domain reference must be discarded using rcu_unlock_domain().
289 */
290 struct domain *rcu_lock_domain_by_id(domid_t dom);
292 /* Finish a RCU critical region started by rcu_lock_domain_by_id(). */
293 static inline void rcu_unlock_domain(struct domain *d)
294 {
295 rcu_read_unlock(&domlist_read_lock);
296 }
298 static inline struct domain *rcu_lock_domain(struct domain *d)
299 {
300 rcu_read_lock(d);
301 return d;
302 }
304 static inline struct domain *rcu_lock_current_domain(void)
305 {
306 return rcu_lock_domain(current->domain);
307 }
309 struct domain *get_domain_by_id(domid_t dom);
310 void domain_destroy(struct domain *d);
311 void domain_kill(struct domain *d);
312 void domain_shutdown(struct domain *d, u8 reason);
313 void domain_pause_for_debugger(void);
314 void domain_debug_state_changed(struct domain *d);
316 /*
317 * Mark specified domain as crashed. This function always returns, even if the
318 * caller is the specified domain. The domain is not synchronously descheduled
319 * from any processor.
320 */
321 void __domain_crash(struct domain *d);
322 #define domain_crash(d) do { \
323 printk("domain_crash called from %s:%d\n", __FILE__, __LINE__); \
324 __domain_crash(d); \
325 } while (0)
327 /*
328 * Mark current domain as crashed and synchronously deschedule from the local
329 * processor. This function never returns.
330 */
331 void __domain_crash_synchronous(void) __attribute__((noreturn));
332 #define domain_crash_synchronous() do { \
333 printk("domain_crash_sync called from %s:%d\n", __FILE__, __LINE__); \
334 __domain_crash_synchronous(); \
335 } while (0)
337 #define set_current_state(_s) do { current->state = (_s); } while (0)
338 void scheduler_init(void);
339 int sched_init_vcpu(struct vcpu *v, unsigned int processor);
340 void sched_destroy_vcpu(struct vcpu *v);
341 int sched_init_domain(struct domain *d);
342 void sched_destroy_domain(struct domain *d);
343 long sched_adjust(struct domain *, struct xen_domctl_scheduler_op *);
344 int sched_id(void);
345 void vcpu_wake(struct vcpu *d);
346 void vcpu_sleep_nosync(struct vcpu *d);
347 void vcpu_sleep_sync(struct vcpu *d);
349 /*
350 * Force synchronisation of given VCPU's state. If it is currently descheduled,
351 * this call will ensure that all its state is committed to memory and that
352 * no CPU is using critical state (e.g., page tables) belonging to the VCPU.
353 */
354 void sync_vcpu_execstate(struct vcpu *v);
356 /*
357 * Called by the scheduler to switch to another VCPU. This function must
358 * call context_saved(@prev) when the local CPU is no longer running in
359 * @prev's context, and that context is saved to memory. Alternatively, if
360 * implementing lazy context switching, it suffices to ensure that invoking
361 * sync_vcpu_execstate() will switch and commit @prev's state.
362 */
363 void context_switch(
364 struct vcpu *prev,
365 struct vcpu *next);
367 /*
368 * As described above, context_switch() must call this function when the
369 * local CPU is no longer running in @prev's context, and @prev's context is
370 * saved to memory. Alternatively, if implementing lazy context switching,
371 * ensure that invoking sync_vcpu_execstate() will switch and commit @prev.
372 */
373 void context_saved(struct vcpu *prev);
375 /* Called by the scheduler to continue running the current VCPU. */
376 void continue_running(
377 struct vcpu *same);
379 void startup_cpu_idle_loop(void);
381 /*
382 * Creates a continuation to resume the current hypercall. The caller should
383 * return immediately, propagating the value returned from this invocation.
384 * The format string specifies the types and number of hypercall arguments.
385 * It contains one character per argument as follows:
386 * 'i' [unsigned] {char, int}
387 * 'l' [unsigned] long
388 * 'h' guest handle (XEN_GUEST_HANDLE(foo))
389 */
390 unsigned long hypercall_create_continuation(
391 unsigned int op, const char *format, ...);
393 #define hypercall_preempt_check() (unlikely( \
394 softirq_pending(smp_processor_id()) | \
395 local_events_need_delivery() \
396 ))
398 /* Protect updates/reads (resp.) of domain_list and domain_hash. */
399 extern spinlock_t domlist_update_lock;
400 extern rcu_read_lock_t domlist_read_lock;
402 extern struct domain *domain_list;
404 /* Caller must hold the domlist_read_lock or domlist_update_lock. */
405 #define for_each_domain(_d) \
406 for ( (_d) = rcu_dereference(domain_list); \
407 (_d) != NULL; \
408 (_d) = rcu_dereference((_d)->next_in_list )) \
410 #define for_each_vcpu(_d,_v) \
411 for ( (_v) = (_d)->vcpu[0]; \
412 (_v) != NULL; \
413 (_v) = (_v)->next_in_list )
415 /*
416 * Per-VCPU flags (vcpu_flags).
417 */
418 /* Has the FPU been initialised? */
419 #define _VCPUF_fpu_initialised 0
420 #define VCPUF_fpu_initialised (1UL<<_VCPUF_fpu_initialised)
421 /* Has the FPU been used since it was last saved? */
422 #define _VCPUF_fpu_dirtied 1
423 #define VCPUF_fpu_dirtied (1UL<<_VCPUF_fpu_dirtied)
424 /* Domain is blocked waiting for an event. */
425 #define _VCPUF_blocked 2
426 #define VCPUF_blocked (1UL<<_VCPUF_blocked)
427 /* Currently running on a CPU? */
428 #define _VCPUF_running 3
429 #define VCPUF_running (1UL<<_VCPUF_running)
430 /* Initialization completed. */
431 #define _VCPUF_initialised 4
432 #define VCPUF_initialised (1UL<<_VCPUF_initialised)
433 /* VCPU is offline. */
434 #define _VCPUF_down 5
435 #define VCPUF_down (1UL<<_VCPUF_down)
436 /* NMI callback pending for this VCPU? */
437 #define _VCPUF_nmi_pending 8
438 #define VCPUF_nmi_pending (1UL<<_VCPUF_nmi_pending)
439 /* Avoid NMI reentry by allowing NMIs to be masked for short periods. */
440 #define _VCPUF_nmi_masked 9
441 #define VCPUF_nmi_masked (1UL<<_VCPUF_nmi_masked)
442 /* VCPU is polling a set of event channels (SCHEDOP_poll). */
443 #define _VCPUF_polling 10
444 #define VCPUF_polling (1UL<<_VCPUF_polling)
445 /* VCPU is paused by the hypervisor? */
446 #define _VCPUF_paused 11
447 #define VCPUF_paused (1UL<<_VCPUF_paused)
448 /* VCPU is blocked awaiting an event to be consumed by Xen. */
449 #define _VCPUF_blocked_in_xen 12
450 #define VCPUF_blocked_in_xen (1UL<<_VCPUF_blocked_in_xen)
451 /* VCPU affinity has changed: migrating to a new CPU. */
452 #define _VCPUF_migrating 13
453 #define VCPUF_migrating (1UL<<_VCPUF_migrating)
455 /*
456 * Per-domain flags (domain_flags).
457 */
458 /* Guest shut itself down for some reason. */
459 #define _DOMF_shutdown 0
460 #define DOMF_shutdown (1UL<<_DOMF_shutdown)
461 /* Death rattle. */
462 #define _DOMF_dying 1
463 #define DOMF_dying (1UL<<_DOMF_dying)
464 /* Domain is paused by controller software. */
465 #define _DOMF_ctrl_pause 2
466 #define DOMF_ctrl_pause (1UL<<_DOMF_ctrl_pause)
467 /* Are any VCPUs polling event channels (SCHEDOP_poll)? */
468 #define _DOMF_polling 3
469 #define DOMF_polling (1UL<<_DOMF_polling)
470 /* Domain is paused by the hypervisor? */
471 #define _DOMF_paused 4
472 #define DOMF_paused (1UL<<_DOMF_paused)
473 /* Domain is a compatibility one? */
474 #define _DOMF_compat 5
475 #define DOMF_compat (1UL<<_DOMF_compat)
477 static inline int vcpu_runnable(struct vcpu *v)
478 {
479 return ( !(v->vcpu_flags &
480 ( VCPUF_blocked |
481 VCPUF_down |
482 VCPUF_paused |
483 VCPUF_blocked_in_xen |
484 VCPUF_migrating )) &&
485 !(v->domain->domain_flags &
486 ( DOMF_shutdown |
487 DOMF_ctrl_pause |
488 DOMF_paused )));
489 }
491 void vcpu_pause(struct vcpu *v);
492 void vcpu_pause_nosync(struct vcpu *v);
493 void domain_pause(struct domain *d);
494 void vcpu_unpause(struct vcpu *v);
495 void domain_unpause(struct domain *d);
496 void domain_pause_by_systemcontroller(struct domain *d);
497 void domain_unpause_by_systemcontroller(struct domain *d);
498 void cpu_init(void);
500 void vcpu_force_reschedule(struct vcpu *v);
501 int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity);
503 void vcpu_runstate_get(struct vcpu *v, struct vcpu_runstate_info *runstate);
505 static inline void vcpu_unblock(struct vcpu *v)
506 {
507 if ( test_and_clear_bit(_VCPUF_blocked, &v->vcpu_flags) )
508 vcpu_wake(v);
509 }
511 #define IS_PRIV(_d) ((_d)->is_privileged)
513 #ifdef CONFIG_COMPAT
514 #define IS_COMPAT(_d) \
515 (test_bit(_DOMF_compat, &(_d)->domain_flags))
516 #else
517 #define IS_COMPAT(_d) 0
518 #endif
520 #define VM_ASSIST(_d,_t) (test_bit((_t), &(_d)->vm_assist))
522 #define is_hvm_domain(d) ((d)->is_hvm)
523 #define is_hvm_vcpu(v) (is_hvm_domain(v->domain))
525 #endif /* __SCHED_H__ */
527 /*
528 * Local variables:
529 * mode: C
530 * c-set-style: "BSD"
531 * c-basic-offset: 4
532 * tab-width: 4
533 * indent-tabs-mode: nil
534 * End:
535 */