debuggers.hg

view xen/include/xen/sched.h @ 0:7d21f7218375

Exact replica of unstable on 051908 + README-this
author Mukesh Rathor
date Mon May 19 15:34:57 2008 -0700 (2008-05-19)
parents
children d668634e4f22
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 <public/xsm/acm.h>
14 #include <xen/time.h>
15 #include <xen/timer.h>
16 #include <xen/grant_table.h>
17 #include <xen/rangeset.h>
18 #include <asm/domain.h>
19 #include <xen/xenoprof.h>
20 #include <xen/rcupdate.h>
21 #include <xen/irq.h>
23 #ifdef CONFIG_COMPAT
24 #include <compat/vcpu.h>
25 DEFINE_XEN_GUEST_HANDLE(vcpu_runstate_info_compat_t);
26 #endif
28 /* A global pointer to the initial domain (DOM0). */
29 extern struct domain *dom0;
31 #ifndef CONFIG_COMPAT
32 #define MAX_EVTCHNS(d) NR_EVENT_CHANNELS
33 #else
34 #define MAX_EVTCHNS(d) (!IS_COMPAT(d) ? \
35 NR_EVENT_CHANNELS : \
36 sizeof(unsigned int) * sizeof(unsigned int) * 64)
37 #endif
38 #define EVTCHNS_PER_BUCKET 128
39 #define NR_EVTCHN_BUCKETS (NR_EVENT_CHANNELS / EVTCHNS_PER_BUCKET)
41 struct evtchn
42 {
43 #define ECS_FREE 0 /* Channel is available for use. */
44 #define ECS_RESERVED 1 /* Channel is reserved. */
45 #define ECS_UNBOUND 2 /* Channel is waiting to bind to a remote domain. */
46 #define ECS_INTERDOMAIN 3 /* Channel is bound to another domain. */
47 #define ECS_PIRQ 4 /* Channel is bound to a physical IRQ line. */
48 #define ECS_VIRQ 5 /* Channel is bound to a virtual IRQ line. */
49 #define ECS_IPI 6 /* Channel is bound to a virtual IPI line. */
50 u8 state; /* ECS_* */
51 u8 consumer_is_xen; /* Consumed by Xen or by guest? */
52 u16 notify_vcpu_id; /* VCPU for local delivery notification */
53 union {
54 struct {
55 domid_t remote_domid;
56 } unbound; /* state == ECS_UNBOUND */
57 struct {
58 u16 remote_port;
59 struct domain *remote_dom;
60 } interdomain; /* state == ECS_INTERDOMAIN */
61 u16 pirq; /* state == ECS_PIRQ */
62 u16 virq; /* state == ECS_VIRQ */
63 } u;
64 #ifdef FLASK_ENABLE
65 void *ssid;
66 #endif
67 };
69 int evtchn_init(struct domain *d);
70 void evtchn_destroy(struct domain *d);
72 struct vcpu
73 {
74 int vcpu_id;
76 int processor;
78 vcpu_info_t *vcpu_info;
80 struct domain *domain;
82 struct vcpu *next_in_list;
84 uint64_t periodic_period;
85 uint64_t periodic_last_event;
86 struct timer periodic_timer;
87 struct timer singleshot_timer;
89 struct timer poll_timer; /* timeout for SCHEDOP_poll */
91 void *sched_priv; /* scheduler-specific data */
93 struct vcpu_runstate_info runstate;
94 #ifndef CONFIG_COMPAT
95 # define runstate_guest(v) ((v)->runstate_guest)
96 XEN_GUEST_HANDLE(vcpu_runstate_info_t) runstate_guest; /* guest address */
97 #else
98 # define runstate_guest(v) ((v)->runstate_guest.native)
99 union {
100 XEN_GUEST_HANDLE(vcpu_runstate_info_t) native;
101 XEN_GUEST_HANDLE(vcpu_runstate_info_compat_t) compat;
102 } runstate_guest; /* guest address */
103 #endif
105 /* Has the FPU been initialised? */
106 bool_t fpu_initialised;
107 /* Has the FPU been used since it was last saved? */
108 bool_t fpu_dirtied;
109 /* Is this VCPU polling any event channels (SCHEDOP_poll)? */
110 bool_t is_polling;
111 /* Initialization completed for this VCPU? */
112 bool_t is_initialised;
113 /* Currently running on a CPU? */
114 bool_t is_running;
115 /* NMI callback pending for this VCPU? */
116 bool_t nmi_pending;
117 /* Avoid NMI reentry by allowing NMIs to be masked for short periods. */
118 bool_t nmi_masked;
119 /* Require shutdown to be deferred for some asynchronous operation? */
120 bool_t defer_shutdown;
121 /* VCPU is paused following shutdown request (d->is_shutting_down)? */
122 bool_t paused_for_shutdown;
123 /* VCPU affinity is temporarily locked from controller changes? */
124 bool_t affinity_locked;
126 unsigned long pause_flags;
127 atomic_t pause_count;
129 u16 virq_to_evtchn[NR_VIRQS];
131 /* Bitmask of CPUs on which this VCPU may run. */
132 cpumask_t cpu_affinity;
134 /* Bitmask of CPUs which are holding onto this VCPU's state. */
135 cpumask_t vcpu_dirty_cpumask;
137 struct arch_vcpu arch;
138 };
140 /* Per-domain lock can be recursively acquired in fault handlers. */
141 #define domain_lock(d) spin_lock_recursive(&(d)->domain_lock)
142 #define domain_unlock(d) spin_unlock_recursive(&(d)->domain_lock)
143 #define domain_is_locked(d) spin_is_locked(&(d)->domain_lock)
145 struct domain
146 {
147 domid_t domain_id;
149 shared_info_t *shared_info; /* shared data area */
151 spinlock_t domain_lock;
153 spinlock_t page_alloc_lock; /* protects all the following fields */
154 struct list_head page_list; /* linked list, of size tot_pages */
155 struct list_head xenpage_list; /* linked list, of size xenheap_pages */
156 unsigned int tot_pages; /* number of pages currently possesed */
157 unsigned int max_pages; /* maximum value for tot_pages */
158 unsigned int xenheap_pages; /* # pages allocated from Xen heap */
160 /* Scheduling. */
161 void *sched_priv; /* scheduler-specific data */
163 struct domain *next_in_list;
164 struct domain *next_in_hashbucket;
166 struct list_head rangesets;
167 spinlock_t rangesets_lock;
169 /* Event channel information. */
170 struct evtchn *evtchn[NR_EVTCHN_BUCKETS];
171 spinlock_t evtchn_lock;
173 struct grant_table *grant_table;
175 /*
176 * Interrupt to event-channel mappings. Updates should be protected by the
177 * domain's event-channel spinlock. Read accesses can also synchronise on
178 * the lock, but races don't usually matter.
179 */
180 u16 pirq_to_evtchn[NR_IRQS];
181 DECLARE_BITMAP(pirq_mask, NR_IRQS);
183 /* I/O capabilities (access to IRQs and memory-mapped I/O). */
184 struct rangeset *iomem_caps;
185 struct rangeset *irq_caps;
187 /* Is this an HVM guest? */
188 bool_t is_hvm;
189 /* Is this guest fully privileged (aka dom0)? */
190 bool_t is_privileged;
191 /* Which guest this guest has privileges on */
192 struct domain *target;
193 /* Is this guest being debugged by dom0? */
194 bool_t debugger_attached;
195 /* Are any VCPUs polling event channels (SCHEDOP_poll)? */
196 bool_t is_polling;
197 /* Is this guest dying (i.e., a zombie)? */
198 enum { DOMDYING_alive, DOMDYING_dying, DOMDYING_dead } is_dying;
199 /* Domain is paused by controller software? */
200 bool_t is_paused_by_controller;
201 /* Domain's VCPUs are pinned 1:1 to physical CPUs? */
202 bool_t is_pinned;
204 /* Guest has shut down (inc. reason code)? */
205 spinlock_t shutdown_lock;
206 bool_t is_shutting_down; /* in process of shutting down? */
207 bool_t is_shut_down; /* fully shut down? */
208 int shutdown_code;
210 atomic_t pause_count;
212 unsigned long vm_assist;
214 atomic_t refcnt;
216 struct vcpu *vcpu[MAX_VIRT_CPUS];
218 /* Bitmask of CPUs which are holding onto this domain's state. */
219 cpumask_t domain_dirty_cpumask;
221 struct arch_domain arch;
223 void *ssid; /* sHype security subject identifier */
225 /* Control-plane tools handle for this domain. */
226 xen_domain_handle_t handle;
228 /* OProfile support. */
229 struct xenoprof *xenoprof;
230 int32_t time_offset_seconds;
232 struct rcu_head rcu;
234 /*
235 * Hypercall deadlock avoidance lock. Used if a hypercall might
236 * cause a deadlock. Acquirers don't spin waiting; they preempt.
237 */
238 spinlock_t hypercall_deadlock_mutex;
240 /* VRAM dirty support. */
241 struct sh_dirty_vram *dirty_vram;
242 };
244 struct domain_setup_info
245 {
246 /* Initialised by caller. */
247 unsigned long image_addr;
248 unsigned long image_len;
249 /* Initialised by loader: Public. */
250 unsigned long v_start;
251 unsigned long v_end;
252 unsigned long v_kernstart;
253 unsigned long v_kernend;
254 unsigned long v_kernentry;
255 #define PAEKERN_no 0
256 #define PAEKERN_yes 1
257 #define PAEKERN_extended_cr3 2
258 #define PAEKERN_bimodal 3
259 unsigned int pae_kernel;
260 /* Initialised by loader: Private. */
261 unsigned long elf_paddr_offset;
262 unsigned int load_symtab;
263 unsigned long symtab_addr;
264 unsigned long symtab_len;
265 };
267 extern struct vcpu *idle_vcpu[NR_CPUS];
268 #define IDLE_DOMAIN_ID (0x7FFFU)
269 #define is_idle_domain(d) ((d)->domain_id == IDLE_DOMAIN_ID)
270 #define is_idle_vcpu(v) (is_idle_domain((v)->domain))
272 #define DOMAIN_DESTROYED (1<<31) /* assumes atomic_t is >= 32 bits */
273 #define put_domain(_d) \
274 if ( atomic_dec_and_test(&(_d)->refcnt) ) domain_destroy(_d)
276 /*
277 * Use this when you don't have an existing reference to @d. It returns
278 * FALSE if @d is being destroyed.
279 */
280 static always_inline int get_domain(struct domain *d)
281 {
282 atomic_t old, new, seen = d->refcnt;
283 do
284 {
285 old = seen;
286 if ( unlikely(_atomic_read(old) & DOMAIN_DESTROYED) )
287 return 0;
288 _atomic_set(new, _atomic_read(old) + 1);
289 seen = atomic_compareandswap(old, new, &d->refcnt);
290 }
291 while ( unlikely(_atomic_read(seen) != _atomic_read(old)) );
292 return 1;
293 }
295 /*
296 * Use this when you already have, or are borrowing, a reference to @d.
297 * In this case we know that @d cannot be destroyed under our feet.
298 */
299 static inline void get_knownalive_domain(struct domain *d)
300 {
301 atomic_inc(&d->refcnt);
302 ASSERT(!(atomic_read(&d->refcnt) & DOMAIN_DESTROYED));
303 }
305 /* Obtain a reference to the currently-running domain. */
306 static inline struct domain *get_current_domain(void)
307 {
308 struct domain *d = current->domain;
309 get_knownalive_domain(d);
310 return d;
311 }
313 struct domain *domain_create(
314 domid_t domid, unsigned int domcr_flags, ssidref_t ssidref);
315 /* DOMCRF_hvm: Create an HVM domain, as opposed to a PV domain. */
316 #define _DOMCRF_hvm 0
317 #define DOMCRF_hvm (1U<<_DOMCRF_hvm)
318 #define _DOMCRF_hap 1
319 #define DOMCRF_hap (1U<<_DOMCRF_hap)
321 int construct_dom0(
322 struct domain *d,
323 unsigned long image_start, unsigned long image_len,
324 unsigned long initrd_start, unsigned long initrd_len,
325 char *cmdline);
327 /*
328 * rcu_lock_domain_by_id() is more efficient than get_domain_by_id().
329 * This is the preferred function if the returned domain reference
330 * is short lived, but it cannot be used if the domain reference needs
331 * to be kept beyond the current scope (e.g., across a softirq).
332 * The returned domain reference must be discarded using rcu_unlock_domain().
333 */
334 struct domain *rcu_lock_domain_by_id(domid_t dom);
336 /* Finish a RCU critical region started by rcu_lock_domain_by_id(). */
337 static inline void rcu_unlock_domain(struct domain *d)
338 {
339 rcu_read_unlock(&domlist_read_lock);
340 }
342 static inline struct domain *rcu_lock_domain(struct domain *d)
343 {
344 rcu_read_lock(d);
345 return d;
346 }
348 static inline struct domain *rcu_lock_current_domain(void)
349 {
350 return rcu_lock_domain(current->domain);
351 }
353 struct domain *get_domain_by_id(domid_t dom);
354 void domain_destroy(struct domain *d);
355 int domain_kill(struct domain *d);
356 void domain_shutdown(struct domain *d, u8 reason);
357 void domain_resume(struct domain *d);
358 void domain_pause_for_debugger(void);
360 int vcpu_start_shutdown_deferral(struct vcpu *v);
361 void vcpu_end_shutdown_deferral(struct vcpu *v);
363 /*
364 * Mark specified domain as crashed. This function always returns, even if the
365 * caller is the specified domain. The domain is not synchronously descheduled
366 * from any processor.
367 */
368 void __domain_crash(struct domain *d);
369 #define domain_crash(d) do { \
370 printk("domain_crash called from %s:%d\n", __FILE__, __LINE__); \
371 __domain_crash(d); \
372 } while (0)
374 /*
375 * Mark current domain as crashed and synchronously deschedule from the local
376 * processor. This function never returns.
377 */
378 void __domain_crash_synchronous(void) __attribute__((noreturn));
379 #define domain_crash_synchronous() do { \
380 printk("domain_crash_sync called from %s:%d\n", __FILE__, __LINE__); \
381 __domain_crash_synchronous(); \
382 } while (0)
384 #define set_current_state(_s) do { current->state = (_s); } while (0)
385 void scheduler_init(void);
386 int sched_init_vcpu(struct vcpu *v, unsigned int processor);
387 void sched_destroy_vcpu(struct vcpu *v);
388 int sched_init_domain(struct domain *d);
389 void sched_destroy_domain(struct domain *d);
390 long sched_adjust(struct domain *, struct xen_domctl_scheduler_op *);
391 int sched_id(void);
392 void vcpu_wake(struct vcpu *d);
393 void vcpu_sleep_nosync(struct vcpu *d);
394 void vcpu_sleep_sync(struct vcpu *d);
396 /*
397 * Force synchronisation of given VCPU's state. If it is currently descheduled,
398 * this call will ensure that all its state is committed to memory and that
399 * no CPU is using critical state (e.g., page tables) belonging to the VCPU.
400 */
401 void sync_vcpu_execstate(struct vcpu *v);
403 /*
404 * Called by the scheduler to switch to another VCPU. This function must
405 * call context_saved(@prev) when the local CPU is no longer running in
406 * @prev's context, and that context is saved to memory. Alternatively, if
407 * implementing lazy context switching, it suffices to ensure that invoking
408 * sync_vcpu_execstate() will switch and commit @prev's state.
409 */
410 void context_switch(
411 struct vcpu *prev,
412 struct vcpu *next);
414 /*
415 * As described above, context_switch() must call this function when the
416 * local CPU is no longer running in @prev's context, and @prev's context is
417 * saved to memory. Alternatively, if implementing lazy context switching,
418 * ensure that invoking sync_vcpu_execstate() will switch and commit @prev.
419 */
420 void context_saved(struct vcpu *prev);
422 /* Called by the scheduler to continue running the current VCPU. */
423 void continue_running(
424 struct vcpu *same);
426 void startup_cpu_idle_loop(void);
428 /*
429 * Creates a continuation to resume the current hypercall. The caller should
430 * return immediately, propagating the value returned from this invocation.
431 * The format string specifies the types and number of hypercall arguments.
432 * It contains one character per argument as follows:
433 * 'i' [unsigned] {char, int}
434 * 'l' [unsigned] long
435 * 'h' guest handle (XEN_GUEST_HANDLE(foo))
436 */
437 unsigned long hypercall_create_continuation(
438 unsigned int op, const char *format, ...);
440 #define hypercall_preempt_check() (unlikely( \
441 softirq_pending(smp_processor_id()) | \
442 local_events_need_delivery() \
443 ))
445 /* Protect updates/reads (resp.) of domain_list and domain_hash. */
446 extern spinlock_t domlist_update_lock;
447 extern rcu_read_lock_t domlist_read_lock;
449 extern struct domain *domain_list;
451 /* Caller must hold the domlist_read_lock or domlist_update_lock. */
452 #define for_each_domain(_d) \
453 for ( (_d) = rcu_dereference(domain_list); \
454 (_d) != NULL; \
455 (_d) = rcu_dereference((_d)->next_in_list )) \
457 #define for_each_vcpu(_d,_v) \
458 for ( (_v) = (_d)->vcpu[0]; \
459 (_v) != NULL; \
460 (_v) = (_v)->next_in_list )
462 /*
463 * Per-VCPU pause flags.
464 */
465 /* Domain is blocked waiting for an event. */
466 #define _VPF_blocked 0
467 #define VPF_blocked (1UL<<_VPF_blocked)
468 /* VCPU is offline. */
469 #define _VPF_down 1
470 #define VPF_down (1UL<<_VPF_down)
471 /* VCPU is blocked awaiting an event to be consumed by Xen. */
472 #define _VPF_blocked_in_xen 2
473 #define VPF_blocked_in_xen (1UL<<_VPF_blocked_in_xen)
474 /* VCPU affinity has changed: migrating to a new CPU. */
475 #define _VPF_migrating 3
476 #define VPF_migrating (1UL<<_VPF_migrating)
478 static inline int vcpu_runnable(struct vcpu *v)
479 {
480 return !(v->pause_flags |
481 atomic_read(&v->pause_count) |
482 atomic_read(&v->domain->pause_count));
483 }
485 void vcpu_pause(struct vcpu *v);
486 void vcpu_pause_nosync(struct vcpu *v);
487 void domain_pause(struct domain *d);
488 void vcpu_unpause(struct vcpu *v);
489 void domain_unpause(struct domain *d);
490 void domain_pause_by_systemcontroller(struct domain *d);
491 void domain_unpause_by_systemcontroller(struct domain *d);
492 void cpu_init(void);
494 void vcpu_force_reschedule(struct vcpu *v);
495 int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity);
496 int vcpu_lock_affinity(struct vcpu *v, cpumask_t *affinity);
497 void vcpu_unlock_affinity(struct vcpu *v, cpumask_t *affinity);
499 void vcpu_runstate_get(struct vcpu *v, struct vcpu_runstate_info *runstate);
501 static inline void vcpu_unblock(struct vcpu *v)
502 {
503 if ( test_and_clear_bit(_VPF_blocked, &v->pause_flags) )
504 vcpu_wake(v);
505 }
507 #define IS_PRIV(_d) ((_d)->is_privileged)
508 #define IS_PRIV_FOR(_d, _t) (IS_PRIV(_d) || ((_d)->target && (_d)->target == (_t)))
510 #ifndef IS_COMPAT
511 #define IS_COMPAT(d) 0
512 #endif
514 #define VM_ASSIST(_d,_t) (test_bit((_t), &(_d)->vm_assist))
516 #define is_hvm_domain(d) ((d)->is_hvm)
517 #define is_hvm_vcpu(v) (is_hvm_domain(v->domain))
519 extern enum cpufreq_controller {
520 FREQCTL_none, FREQCTL_dom0_kernel
521 } cpufreq_controller;
523 #endif /* __SCHED_H__ */
525 /*
526 * Local variables:
527 * mode: C
528 * c-set-style: "BSD"
529 * c-basic-offset: 4
530 * tab-width: 4
531 * indent-tabs-mode: nil
532 * End:
533 */