aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/ia64/xen/domain.c95
-rw-r--r--xen/arch/powerpc/domain.c23
-rw-r--r--xen/arch/x86/domain.c34
-rw-r--r--xen/arch/x86/hvm/vmx/vmcs.c161
-rw-r--r--xen/arch/x86/hvm/vmx/vmx.c10
-rw-r--r--xen/common/domain.c26
-rw-r--r--xen/common/sched_credit.c81
-rw-r--r--xen/common/sched_sedf.c35
-rw-r--r--xen/common/schedule.c19
-rw-r--r--xen/include/xen/domain.h14
-rw-r--r--xen/include/xen/sched-if.h5
-rw-r--r--xen/include/xen/sched.h4
12 files changed, 239 insertions, 268 deletions
diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c
index 7aada5b9bb..a482bdc9e1 100644
--- a/xen/arch/ia64/xen/domain.c
+++ b/xen/arch/ia64/xen/domain.c
@@ -275,40 +275,61 @@ void hlt_timer_fn(void *data)
vcpu_unblock(v);
}
-struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
+void relinquish_vcpu_resources(struct vcpu *v)
+{
+ if (HAS_PERVCPU_VHPT(v->domain))
+ pervcpu_vhpt_free(v);
+ if (v->arch.privregs != NULL) {
+ free_xenheap_pages(v->arch.privregs,
+ get_order_from_shift(XMAPPEDREGS_SHIFT));
+ v->arch.privregs = NULL;
+ }
+ kill_timer(&v->arch.hlt_timer);
+}
+
+struct vcpu *alloc_vcpu_struct(void)
{
struct vcpu *v;
struct thread_info *ti;
+ static int first_allocation = 1;
- /* Still keep idle vcpu0 static allocated at compilation, due
- * to some code from Linux still requires it in early phase.
- */
- if (is_idle_domain(d) && !vcpu_id)
- v = idle_vcpu[0];
- else {
- if ((v = alloc_xenheap_pages(KERNEL_STACK_SIZE_ORDER)) == NULL)
- return NULL;
- memset(v, 0, sizeof(*v));
-
- ti = alloc_thread_info(v);
- /* Clear thread_info to clear some important fields, like
- * preempt_count
- */
- memset(ti, 0, sizeof(struct thread_info));
- init_switch_stack(v);
+ if (first_allocation) {
+ first_allocation = 0;
+ /* Still keep idle vcpu0 static allocated at compilation, due
+ * to some code from Linux still requires it in early phase.
+ */
+ return idle_vcpu[0];
}
+ if ((v = alloc_xenheap_pages(KERNEL_STACK_SIZE_ORDER)) == NULL)
+ return NULL;
+ memset(v, 0, sizeof(*v));
+
+ ti = alloc_thread_info(v);
+ /* Clear thread_info to clear some important fields, like
+ * preempt_count
+ */
+ memset(ti, 0, sizeof(struct thread_info));
+ init_switch_stack(v);
+
+ return v;
+}
+
+void free_vcpu_struct(struct vcpu *v)
+{
+ free_xenheap_pages(v, KERNEL_STACK_SIZE_ORDER);
+}
+
+int vcpu_initialise(struct vcpu *v)
+{
+ struct domain *d = v->domain;
+ int rc, order, i;
+
if (!is_idle_domain(d)) {
if (!d->arch.is_vti) {
- int order;
- int i;
- // vti domain has its own vhpt policy.
- if (HAS_PERVCPU_VHPT(d)) {
- if (pervcpu_vhpt_alloc(v) < 0) {
- free_xenheap_pages(v, KERNEL_STACK_SIZE_ORDER);
- return NULL;
- }
- }
+ if (HAS_PERVCPU_VHPT(d))
+ if ((rc = pervcpu_vhpt_alloc(v)) != 0)
+ return rc;
/* Create privregs page only if not VTi. */
order = get_order_from_shift(XMAPPEDREGS_SHIFT);
@@ -344,34 +365,20 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
v->arch.breakimm = d->arch.breakimm;
v->arch.last_processor = INVALID_PROCESSOR;
}
- if (!VMX_DOMAIN(v)){
+
+ if (!VMX_DOMAIN(v))
init_timer(&v->arch.hlt_timer, hlt_timer_fn, v,
first_cpu(cpu_online_map));
- }
-
- return v;
-}
-void relinquish_vcpu_resources(struct vcpu *v)
-{
- if (HAS_PERVCPU_VHPT(v->domain))
- pervcpu_vhpt_free(v);
- if (v->arch.privregs != NULL) {
- free_xenheap_pages(v->arch.privregs,
- get_order_from_shift(XMAPPEDREGS_SHIFT));
- v->arch.privregs = NULL;
- }
- kill_timer(&v->arch.hlt_timer);
+ return 0;
}
-void free_vcpu_struct(struct vcpu *v)
+void vcpu_destroy(struct vcpu *v)
{
if (v->domain->arch.is_vti)
vmx_relinquish_vcpu_resources(v);
else
relinquish_vcpu_resources(v);
-
- free_xenheap_pages(v, KERNEL_STACK_SIZE_ORDER);
}
static void init_switch_stack(struct vcpu *v)
diff --git a/xen/arch/powerpc/domain.c b/xen/arch/powerpc/domain.c
index c3c4420dec..636713a8b7 100644
--- a/xen/arch/powerpc/domain.c
+++ b/xen/arch/powerpc/domain.c
@@ -109,27 +109,28 @@ void machine_restart(char * __unused)
while(1);
}
-struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
+struct vcpu *alloc_vcpu_struct(void)
{
struct vcpu *v;
-
- if ( (v = xmalloc(struct vcpu)) == NULL )
- return NULL;
-
- memset(v, 0, sizeof(*v));
- v->vcpu_id = vcpu_id;
-
+ if ( (v = xmalloc(struct vcpu)) != NULL )
+ memset(v, 0, sizeof(*v));
return v;
}
void free_vcpu_struct(struct vcpu *v)
{
- BUG_ON(v->next_in_list != NULL);
- if ( v->vcpu_id != 0 )
- v->domain->vcpu[v->vcpu_id - 1]->next_in_list = NULL;
xfree(v);
}
+int vcpu_initialise(struct vcpu *v)
+{
+ return 0;
+}
+
+void vcpu_destroy(struct vcpu *v)
+{
+}
+
int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_t *c)
{
memcpy(&v->arch.ctxt, &c->user_regs, sizeof(c->user_regs));
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index da2e29f772..a5f89e70ef 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -114,27 +114,30 @@ void dump_pageframe_info(struct domain *d)
}
}
-struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
+struct vcpu *alloc_vcpu_struct(void)
{
struct vcpu *v;
+ if ( (v = xmalloc(struct vcpu)) != NULL )
+ memset(v, 0, sizeof(*v));
+ return v;
+}
- if ( (v = xmalloc(struct vcpu)) == NULL )
- return NULL;
-
- memset(v, 0, sizeof(*v));
+void free_vcpu_struct(struct vcpu *v)
+{
+ xfree(v);
+}
- v->vcpu_id = vcpu_id;
- v->domain = d;
+int vcpu_initialise(struct vcpu *v)
+{
+ struct domain *d = v->domain;
+ int rc;
v->arch.flags = TF_kernel_mode;
if ( is_hvm_domain(d) )
{
- if ( hvm_vcpu_initialise(v) != 0 )
- {
- xfree(v);
- return NULL;
- }
+ if ( (rc = hvm_vcpu_initialise(v)) != 0 )
+ return rc;
}
else
{
@@ -150,16 +153,15 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
}
v->arch.perdomain_ptes =
- d->arch.mm_perdomain_pt + (vcpu_id << GDT_LDT_VCPU_SHIFT);
+ d->arch.mm_perdomain_pt + (v->vcpu_id << GDT_LDT_VCPU_SHIFT);
pae_l3_cache_init(&v->arch.pae_l3_cache);
- return v;
+ return 0;
}
-void free_vcpu_struct(struct vcpu *v)
+void vcpu_destroy(struct vcpu *v)
{
- xfree(v);
}
int arch_domain_create(struct domain *d)
diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index 65be8a3494..882220926b 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -193,11 +193,9 @@ void vmx_vmcs_enter(struct vcpu *v)
{
/*
* NB. We must *always* run an HVM VCPU on its own VMCS, except for
- * vmx_vmcs_enter/exit critical regions. This leads to some XXX TODOs XXX:
- * 1. Move construct_vmcs() much earlier, to domain creation or
- * context initialisation.
- * 2. VMPTRLD as soon as we context-switch to a HVM VCPU.
- * 3. VMCS destruction needs to happen later (from domain_destroy()).
+ * vmx_vmcs_enter/exit critical regions. This leads to some TODOs:
+ * 1. VMPTRLD as soon as we context-switch to a HVM VCPU.
+ * 2. VMCS destruction needs to happen later (from domain_destroy()).
* We can relax this a bit if a paused VCPU always commits its
* architectural state to a software structure.
*/
@@ -235,17 +233,6 @@ void vmx_free_host_vmcs(struct vmcs_struct *vmcs)
vmx_free_vmcs(vmcs);
}
-static inline int construct_vmcs_controls(struct arch_vmx_struct *arch_vmx)
-{
- int error = 0;
-
- error |= __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control);
- error |= __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control);
- error |= __vmwrite(VM_ENTRY_CONTROLS, vmx_vmentry_control);
-
- return error;
-}
-
#define GUEST_LAUNCH_DS 0x08
#define GUEST_LAUNCH_CS 0x10
#define GUEST_SEGMENT_LIMIT 0xffffffff
@@ -366,17 +353,40 @@ static void vmx_do_launch(struct vcpu *v)
v->arch.schedule_tail = arch_vmx_do_resume;
}
-/*
- * Initially set the same environement as host.
- */
-static inline int construct_init_vmcs_guest(cpu_user_regs_t *regs)
+static int construct_vmcs(struct vcpu *v, cpu_user_regs_t *regs)
{
int error = 0;
+ unsigned long tmp, eflags;
union vmcs_arbytes arbytes;
- unsigned long dr7;
- unsigned long eflags;
- /* MSR */
+ /* VMCS controls. */
+ error |= __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control);
+ error |= __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control);
+ error |= __vmwrite(VM_ENTRY_CONTROLS, vmx_vmentry_control);
+
+ /* Host data selectors. */
+ error |= __vmwrite(HOST_SS_SELECTOR, __HYPERVISOR_DS);
+ error |= __vmwrite(HOST_DS_SELECTOR, __HYPERVISOR_DS);
+ error |= __vmwrite(HOST_ES_SELECTOR, __HYPERVISOR_DS);
+#if defined(__i386__)
+ error |= __vmwrite(HOST_FS_SELECTOR, __HYPERVISOR_DS);
+ error |= __vmwrite(HOST_GS_SELECTOR, __HYPERVISOR_DS);
+ error |= __vmwrite(HOST_FS_BASE, 0);
+ error |= __vmwrite(HOST_GS_BASE, 0);
+#elif defined(__x86_64__)
+ rdmsrl(MSR_FS_BASE, tmp); error |= __vmwrite(HOST_FS_BASE, tmp);
+ rdmsrl(MSR_GS_BASE, tmp); error |= __vmwrite(HOST_GS_BASE, tmp);
+#endif
+
+ /* Host control registers. */
+ error |= __vmwrite(HOST_CR0, read_cr0());
+ error |= __vmwrite(HOST_CR4, read_cr4());
+
+ /* Host CS:RIP. */
+ error |= __vmwrite(HOST_CS_SELECTOR, __HYPERVISOR_CS);
+ error |= __vmwrite(HOST_RIP, (unsigned long)vmx_asm_vmexit_handler);
+
+ /* MSR intercepts. */
error |= __vmwrite(VM_EXIT_MSR_LOAD_ADDR, 0);
error |= __vmwrite(VM_EXIT_MSR_STORE_ADDR, 0);
error |= __vmwrite(VM_EXIT_MSR_STORE_COUNT, 0);
@@ -395,7 +405,7 @@ static inline int construct_init_vmcs_guest(cpu_user_regs_t *regs)
error |= __vmwrite(GUEST_ACTIVITY_STATE, 0);
- /* Guest Selectors */
+ /* Guest selectors. */
error |= __vmwrite(GUEST_ES_SELECTOR, GUEST_LAUNCH_DS);
error |= __vmwrite(GUEST_SS_SELECTOR, GUEST_LAUNCH_DS);
error |= __vmwrite(GUEST_DS_SELECTOR, GUEST_LAUNCH_DS);
@@ -403,7 +413,7 @@ static inline int construct_init_vmcs_guest(cpu_user_regs_t *regs)
error |= __vmwrite(GUEST_GS_SELECTOR, GUEST_LAUNCH_DS);
error |= __vmwrite(GUEST_CS_SELECTOR, GUEST_LAUNCH_CS);
- /* Guest segment bases */
+ /* Guest segment bases. */
error |= __vmwrite(GUEST_ES_BASE, 0);
error |= __vmwrite(GUEST_SS_BASE, 0);
error |= __vmwrite(GUEST_DS_BASE, 0);
@@ -411,7 +421,7 @@ static inline int construct_init_vmcs_guest(cpu_user_regs_t *regs)
error |= __vmwrite(GUEST_GS_BASE, 0);
error |= __vmwrite(GUEST_CS_BASE, 0);
- /* Guest segment Limits */
+ /* Guest segment limits. */
error |= __vmwrite(GUEST_ES_LIMIT, GUEST_SEGMENT_LIMIT);
error |= __vmwrite(GUEST_SS_LIMIT, GUEST_SEGMENT_LIMIT);
error |= __vmwrite(GUEST_DS_LIMIT, GUEST_SEGMENT_LIMIT);
@@ -419,7 +429,7 @@ static inline int construct_init_vmcs_guest(cpu_user_regs_t *regs)
error |= __vmwrite(GUEST_GS_LIMIT, GUEST_SEGMENT_LIMIT);
error |= __vmwrite(GUEST_CS_LIMIT, GUEST_SEGMENT_LIMIT);
- /* Guest segment AR bytes */
+ /* Guest segment AR bytes. */
arbytes.bytes = 0;
arbytes.fields.seg_type = 0x3; /* type = 3 */
arbytes.fields.s = 1; /* code or data, i.e. not system */
@@ -428,131 +438,54 @@ static inline int construct_init_vmcs_guest(cpu_user_regs_t *regs)
arbytes.fields.default_ops_size = 1; /* 32-bit */
arbytes.fields.g = 1;
arbytes.fields.null_bit = 0; /* not null */
-
error |= __vmwrite(GUEST_ES_AR_BYTES, arbytes.bytes);
error |= __vmwrite(GUEST_SS_AR_BYTES, arbytes.bytes);
error |= __vmwrite(GUEST_DS_AR_BYTES, arbytes.bytes);
error |= __vmwrite(GUEST_FS_AR_BYTES, arbytes.bytes);
error |= __vmwrite(GUEST_GS_AR_BYTES, arbytes.bytes);
-
arbytes.fields.seg_type = 0xb; /* type = 0xb */
error |= __vmwrite(GUEST_CS_AR_BYTES, arbytes.bytes);
- /* Guest GDT */
+ /* Guest GDT. */
error |= __vmwrite(GUEST_GDTR_BASE, 0);
error |= __vmwrite(GUEST_GDTR_LIMIT, 0);
- /* Guest IDT */
+ /* Guest IDT. */
error |= __vmwrite(GUEST_IDTR_BASE, 0);
error |= __vmwrite(GUEST_IDTR_LIMIT, 0);
- /* Guest LDT & TSS */
+ /* Guest LDT and TSS. */
arbytes.fields.s = 0; /* not code or data segement */
arbytes.fields.seg_type = 0x2; /* LTD */
arbytes.fields.default_ops_size = 0; /* 16-bit */
arbytes.fields.g = 0;
error |= __vmwrite(GUEST_LDTR_AR_BYTES, arbytes.bytes);
-
arbytes.fields.seg_type = 0xb; /* 32-bit TSS (busy) */
error |= __vmwrite(GUEST_TR_AR_BYTES, arbytes.bytes);
- /* CR3 is set in vmx_final_setup_guest */
error |= __vmwrite(GUEST_RSP, 0);
error |= __vmwrite(GUEST_RIP, regs->eip);
- /* Guest EFLAGS */
+ /* Guest EFLAGS. */
eflags = regs->eflags & ~HVM_EFLAGS_RESERVED_0; /* clear 0s */
eflags |= HVM_EFLAGS_RESERVED_1; /* set 1s */
error |= __vmwrite(GUEST_RFLAGS, eflags);
error |= __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
- __asm__ __volatile__ ("mov %%dr7, %0\n" : "=r" (dr7));
- error |= __vmwrite(GUEST_DR7, dr7);
+ __asm__ __volatile__ ("mov %%dr7, %0\n" : "=r" (tmp));
+ error |= __vmwrite(GUEST_DR7, tmp);
error |= __vmwrite(VMCS_LINK_POINTER, ~0UL);
#if defined(__i386__)
error |= __vmwrite(VMCS_LINK_POINTER_HIGH, ~0UL);
#endif
- return error;
-}
-
-static inline int construct_vmcs_host(void)
-{
- int error = 0;
-#ifdef __x86_64__
- unsigned long fs_base;
- unsigned long gs_base;
-#endif
- unsigned long crn;
-
- /* Host Selectors */
- error |= __vmwrite(HOST_ES_SELECTOR, __HYPERVISOR_DS);
- error |= __vmwrite(HOST_SS_SELECTOR, __HYPERVISOR_DS);
- error |= __vmwrite(HOST_DS_SELECTOR, __HYPERVISOR_DS);
-#if defined(__i386__)
- error |= __vmwrite(HOST_FS_SELECTOR, __HYPERVISOR_DS);
- error |= __vmwrite(HOST_GS_SELECTOR, __HYPERVISOR_DS);
- error |= __vmwrite(HOST_FS_BASE, 0);
- error |= __vmwrite(HOST_GS_BASE, 0);
-
-#else
- rdmsrl(MSR_FS_BASE, fs_base);
- rdmsrl(MSR_GS_BASE, gs_base);
- error |= __vmwrite(HOST_FS_BASE, fs_base);
- error |= __vmwrite(HOST_GS_BASE, gs_base);
-
-#endif
- error |= __vmwrite(HOST_CS_SELECTOR, __HYPERVISOR_CS);
-
- __asm__ __volatile__ ("mov %%cr0,%0" : "=r" (crn) : );
- error |= __vmwrite(HOST_CR0, crn); /* same CR0 */
-
- /* CR3 is set in vmx_final_setup_hostos */
- __asm__ __volatile__ ("mov %%cr4,%0" : "=r" (crn) : );
- error |= __vmwrite(HOST_CR4, crn);
-
- error |= __vmwrite(HOST_RIP, (unsigned long) vmx_asm_vmexit_handler);
-
- return error;
-}
-
-/*
- * the working VMCS pointer has been set properly
- * just before entering this function.
- */
-static int construct_vmcs(struct vcpu *v,
- cpu_user_regs_t *regs)
-{
- struct arch_vmx_struct *arch_vmx = &v->arch.hvm_vmx;
- int error;
-
- if ( (error = construct_vmcs_controls(arch_vmx)) ) {
- printk("construct_vmcs: construct_vmcs_controls failed.\n");
- return error;
- }
-
- /* host selectors */
- if ( (error = construct_vmcs_host()) ) {
- printk("construct_vmcs: construct_vmcs_host failed.\n");
- return error;
- }
-
- /* guest selectors */
- if ( (error = construct_init_vmcs_guest(regs)) ) {
- printk("construct_vmcs: construct_vmcs_guest failed.\n");
- return error;
- }
-
- if ( (error = __vmwrite(EXCEPTION_BITMAP,
- MONITOR_DEFAULT_EXCEPTION_BITMAP)) ) {
- printk("construct_vmcs: setting exception bitmap failed.\n");
- return error;
- }
+ error |= __vmwrite(EXCEPTION_BITMAP,
+ MONITOR_DEFAULT_EXCEPTION_BITMAP);
if ( regs->eflags & EF_TF )
- error = __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
+ error |= __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
else
- error = __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
+ error |= __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
return error;
}
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index e91bb58d6a..a220d30fcc 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -566,8 +566,6 @@ static unsigned long vmx_get_ctrl_reg(struct vcpu *v, unsigned int num)
return 0; /* dummy */
}
-
-
/* Make sure that xen intercepts any FP accesses from current */
static void vmx_stts(struct vcpu *v)
{
@@ -591,20 +589,16 @@ static void vmx_stts(struct vcpu *v)
}
}
-
static void vmx_set_tsc_offset(struct vcpu *v, u64 offset)
{
- /* VMX depends on operating on the current vcpu */
- ASSERT(v == current);
-
+ vmx_vmcs_enter(v);
__vmwrite(TSC_OFFSET, offset);
#if defined (__i386__)
__vmwrite(TSC_OFFSET_HIGH, offset >> 32);
#endif
+ vmx_vmcs_exit(v);
}
-
-
/* SMP VMX guest support */
static void vmx_init_ap_context(struct vcpu_guest_context *ctxt,
int vcpuid, int trampoline_vector)
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 0d63c46395..08327a37fd 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -64,12 +64,16 @@ void free_domain(struct domain *d)
struct vcpu *v;
int i;
- sched_destroy_domain(d);
-
for ( i = MAX_VIRT_CPUS-1; i >= 0; i-- )
- if ( (v = d->vcpu[i]) != NULL )
- free_vcpu_struct(v);
+ {
+ if ( (v = d->vcpu[i]) == NULL )
+ continue;
+ vcpu_destroy(v);
+ sched_destroy_vcpu(v);
+ free_vcpu_struct(v);
+ }
+ sched_destroy_domain(d);
xfree(d);
}
@@ -80,7 +84,7 @@ struct vcpu *alloc_vcpu(
BUG_ON(d->vcpu[vcpu_id] != NULL);
- if ( (v = alloc_vcpu_struct(d, vcpu_id)) == NULL )
+ if ( (v = alloc_vcpu_struct()) == NULL )
return NULL;
v->domain = d;
@@ -94,12 +98,19 @@ struct vcpu *alloc_vcpu(
if ( (vcpu_id != 0) && !is_idle_domain(d) )
set_bit(_VCPUF_down, &v->vcpu_flags);
- if ( sched_init_vcpu(v, cpu_id) < 0 )
+ if ( sched_init_vcpu(v, cpu_id) != 0 )
{
free_vcpu_struct(v);
return NULL;
}
+ if ( vcpu_initialise(v) != 0 )
+ {
+ sched_destroy_vcpu(v);
+ free_vcpu_struct(v);
+ return NULL;
+ }
+
d->vcpu[vcpu_id] = v;
if ( vcpu_id != 0 )
d->vcpu[v->vcpu_id-1]->next_in_list = v;
@@ -153,6 +164,9 @@ struct domain *domain_create(domid_t domid, unsigned int domcr_flags)
if ( (d->iomem_caps == NULL) || (d->irq_caps == NULL) )
goto fail4;
+ if ( sched_init_domain(d) != 0 )
+ goto fail4;
+
if ( !is_idle_domain(d) )
{
write_lock(&domlist_lock);
diff --git a/xen/common/sched_credit.c b/xen/common/sched_credit.c
index 9dec930b80..984ef277c0 100644
--- a/xen/common/sched_credit.c
+++ b/xen/common/sched_credit.c
@@ -115,8 +115,10 @@
_MACRO(steal_peer_idle) \
_MACRO(steal_peer_running) \
_MACRO(steal_peer_pinned) \
+ _MACRO(dom_init) \
+ _MACRO(dom_destroy) \
_MACRO(vcpu_init) \
- _MACRO(dom_destroy)
+ _MACRO(vcpu_destroy)
#ifndef NDEBUG
#define CSCHED_STATS_EXPAND_CHECKS(_MACRO) \
@@ -454,43 +456,14 @@ static int
csched_vcpu_init(struct vcpu *vc)
{
struct domain * const dom = vc->domain;
- struct csched_dom *sdom;
+ struct csched_dom *sdom = CSCHED_DOM(dom);
struct csched_vcpu *svc;
- int16_t pri;
CSCHED_STAT_CRANK(vcpu_init);
- /* Allocate, if appropriate, per-domain info */
- if ( is_idle_vcpu(vc) )
- {
- sdom = NULL;
- pri = CSCHED_PRI_IDLE;
- }
- else if ( CSCHED_DOM(dom) )
- {
- sdom = CSCHED_DOM(dom);
- pri = CSCHED_PRI_TS_UNDER;
- }
- else
- {
- sdom = xmalloc(struct csched_dom);
- if ( !sdom )
- return -1;
-
- /* Initialize credit and weight */
- INIT_LIST_HEAD(&sdom->active_vcpu);
- sdom->active_vcpu_count = 0;
- INIT_LIST_HEAD(&sdom->active_sdom_elem);
- sdom->dom = dom;
- sdom->weight = CSCHED_DEFAULT_WEIGHT;
- sdom->cap = 0U;
- dom->sched_priv = sdom;
- pri = CSCHED_PRI_TS_UNDER;
- }
-
/* Allocate per-VCPU info */
svc = xmalloc(struct csched_vcpu);
- if ( !svc )
+ if ( svc == NULL )
return -1;
INIT_LIST_HEAD(&svc->runq_elem);
@@ -498,7 +471,7 @@ csched_vcpu_init(struct vcpu *vc)
svc->sdom = sdom;
svc->vcpu = vc;
atomic_set(&svc->credit, 0);
- svc->pri = pri;
+ svc->pri = is_idle_domain(dom) ? CSCHED_PRI_IDLE : CSCHED_PRI_TS_UNDER;
memset(&svc->stats, 0, sizeof(svc->stats));
vc->sched_priv = svc;
@@ -521,12 +494,14 @@ csched_vcpu_init(struct vcpu *vc)
}
static void
-csched_vcpu_free(struct vcpu *vc)
+csched_vcpu_destroy(struct vcpu *vc)
{
struct csched_vcpu * const svc = CSCHED_VCPU(vc);
struct csched_dom * const sdom = svc->sdom;
unsigned long flags;
+ CSCHED_STAT_CRANK(vcpu_destroy);
+
BUG_ON( sdom == NULL );
BUG_ON( !list_empty(&svc->runq_elem) );
@@ -641,20 +616,39 @@ csched_dom_cntl(
return 0;
}
+static int
+csched_dom_init(struct domain *dom)
+{
+ struct csched_dom *sdom;
+
+ CSCHED_STAT_CRANK(dom_init);
+
+ if ( is_idle_domain(dom) )
+ return 0;
+
+ sdom = xmalloc(struct csched_dom);
+ if ( sdom == NULL )
+ return -ENOMEM;
+
+ /* Initialize credit and weight */
+ INIT_LIST_HEAD(&sdom->active_vcpu);
+ sdom->active_vcpu_count = 0;
+ INIT_LIST_HEAD(&sdom->active_sdom_elem);
+ sdom->dom = dom;
+ sdom->weight = CSCHED_DEFAULT_WEIGHT;
+ sdom->cap = 0U;
+ dom->sched_priv = sdom;
+
+ return 0;
+}
+
static void
csched_dom_destroy(struct domain *dom)
{
struct csched_dom * const sdom = CSCHED_DOM(dom);
- int i;
CSCHED_STAT_CRANK(dom_destroy);
- for ( i = 0; i < MAX_VIRT_CPUS; i++ )
- {
- if ( dom->vcpu[i] )
- csched_vcpu_free(dom->vcpu[i]);
- }
-
xfree(sdom);
}
@@ -1226,9 +1220,12 @@ struct scheduler sched_credit_def = {
.opt_name = "credit",
.sched_id = XEN_SCHEDULER_CREDIT,
- .init_vcpu = csched_vcpu_init,
+ .init_domain = csched_dom_init,
.destroy_domain = csched_dom_destroy,
+ .init_vcpu = csched_vcpu_init,
+ .destroy_vcpu = csched_vcpu_destroy,
+
.sleep = csched_vcpu_sleep,
.wake = csched_vcpu_wake,
diff --git a/xen/common/sched_sedf.c b/xen/common/sched_sedf.c
index 3e041d860e..5b0029575f 100644
--- a/xen/common/sched_sedf.c
+++ b/xen/common/sched_sedf.c
@@ -333,14 +333,6 @@ static int sedf_init_vcpu(struct vcpu *v)
{
struct sedf_vcpu_info *inf;
- if ( v->domain->sched_priv == NULL )
- {
- v->domain->sched_priv = xmalloc(struct sedf_dom_info);
- if ( v->domain->sched_priv == NULL )
- return -1;
- memset(v->domain->sched_priv, 0, sizeof(struct sedf_dom_info));
- }
-
if ( (v->sched_priv = xmalloc(struct sedf_vcpu_info)) == NULL )
return -1;
memset(v->sched_priv, 0, sizeof(struct sedf_vcpu_info));
@@ -398,15 +390,25 @@ static int sedf_init_vcpu(struct vcpu *v)
return 0;
}
-static void sedf_destroy_domain(struct domain *d)
+static void sedf_destroy_vcpu(struct vcpu *v)
{
- int i;
+ xfree(v->sched_priv);
+}
+static int sedf_init_domain(struct domain *d)
+{
+ d->sched_priv = xmalloc(struct sedf_dom_info);
+ if ( d->sched_priv == NULL )
+ return -ENOMEM;
+
+ memset(d->sched_priv, 0, sizeof(struct sedf_dom_info));
+
+ return 0;
+}
+
+static void sedf_destroy_domain(struct domain *d)
+{
xfree(d->sched_priv);
-
- for ( i = 0; i < MAX_VIRT_CPUS; i++ )
- if ( d->vcpu[i] )
- xfree(d->vcpu[i]->sched_priv);
}
/*
@@ -1427,9 +1429,12 @@ struct scheduler sched_sedf_def = {
.opt_name = "sedf",
.sched_id = XEN_SCHEDULER_SEDF,
- .init_vcpu = sedf_init_vcpu,
+ .init_domain = sedf_init_domain,
.destroy_domain = sedf_destroy_domain,
+ .init_vcpu = sedf_init_vcpu,
+ .destroy_vcpu = sedf_destroy_vcpu,
+
.do_schedule = sedf_do_schedule,
.dump_cpu_state = sedf_dump_cpu_state,
.sleep = sedf_sleep,
diff --git a/xen/common/schedule.c b/xen/common/schedule.c
index e85f0846e7..920afde256 100644
--- a/xen/common/schedule.c
+++ b/xen/common/schedule.c
@@ -132,17 +132,20 @@ int sched_init_vcpu(struct vcpu *v, unsigned int processor)
return SCHED_OP(init_vcpu, v);
}
-void sched_destroy_domain(struct domain *d)
+void sched_destroy_vcpu(struct vcpu *v)
{
- struct vcpu *v;
+ kill_timer(&v->timer);
+ kill_timer(&v->poll_timer);
+ SCHED_OP(destroy_vcpu, v);
+}
- for_each_vcpu ( d, v )
- {
- kill_timer(&v->timer);
- kill_timer(&v->poll_timer);
- TRACE_2D(TRC_SCHED_DOM_REM, v->domain->domain_id, v->vcpu_id);
- }
+int sched_init_domain(struct domain *d)
+{
+ return SCHED_OP(init_domain, d);
+}
+void sched_destroy_domain(struct domain *d)
+{
SCHED_OP(destroy_domain, d);
}
diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index 40103e7df5..70e8902a73 100644
--- a/xen/include/xen/domain.h
+++ b/xen/include/xen/domain.h
@@ -15,10 +15,20 @@ void free_domain(struct domain *d);
* Arch-specifics.
*/
-struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id);
-
+/* Allocate/free a VCPU structure. */
+struct vcpu *alloc_vcpu_struct(void);
void free_vcpu_struct(struct vcpu *v);
+/*
+ * Initialise/destroy arch-specific details of a VCPU.
+ * - vcpu_initialise() is called after the basic generic fields of the
+ * VCPU structure are initialised. Many operations can be applied to the
+ * VCPU at this point (e.g., vcpu_pause()).
+ * - vcpu_destroy() is called only if vcpu_initialise() previously succeeded.
+ */
+int vcpu_initialise(struct vcpu *v);
+void vcpu_destroy(struct vcpu *v);
+
int arch_domain_create(struct domain *d);
void arch_domain_destroy(struct domain *d);
diff --git a/xen/include/xen/sched-if.h b/xen/include/xen/sched-if.h
index dc3b04fa22..410358cc48 100644
--- a/xen/include/xen/sched-if.h
+++ b/xen/include/xen/sched-if.h
@@ -63,9 +63,12 @@ struct scheduler {
void (*init) (void);
void (*tick) (unsigned int cpu);
- int (*init_vcpu) (struct vcpu *);
+ int (*init_domain) (struct domain *);
void (*destroy_domain) (struct domain *);
+ int (*init_vcpu) (struct vcpu *);
+ void (*destroy_vcpu) (struct vcpu *);
+
void (*sleep) (struct vcpu *);
void (*wake) (struct vcpu *);
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 42c1d39946..d08959cab1 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -291,7 +291,9 @@ void new_thread(struct vcpu *d,
void scheduler_init(void);
void schedulers_start(void);
int sched_init_vcpu(struct vcpu *v, unsigned int processor);
-void sched_destroy_domain(struct domain *);
+void sched_destroy_vcpu(struct vcpu *v);
+int sched_init_domain(struct domain *d);
+void sched_destroy_domain(struct domain *d);
long sched_adjust(struct domain *, struct xen_domctl_scheduler_op *);
int sched_id(void);
void vcpu_wake(struct vcpu *d);