# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1271248505 -3600
# Node ID ecdc146344250119b0e81b7aff625f8d2d09a672
# Parent 3cdd4cf2c20e480fc90b088bef0bd37d8696e90e
Improvements and bug fixes to continue_hypercall_on_cpu().
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
xen/common/domain.c | 36 +++++++++++++++++++++++++++++++-----
xen/include/xen/sched.h | 8 --------
2 files changed, 31 insertions(+), 13 deletions(-)
diff -r 3cdd4cf2c20e -r ecdc14634425 xen/common/domain.c
--- a/xen/common/domain.c Wed Apr 14 12:10:19 2010 +0100
+++ b/xen/common/domain.c Wed Apr 14 13:35:05 2010 +0100
@@ -147,6 +147,8 @@ struct vcpu *alloc_vcpu(
spin_lock_init(&v->virq_lock);
+ tasklet_init(&v->continue_hypercall_tasklet, NULL, 0);
+
if ( is_idle_domain(d) )
{
v->runstate.state = RUNSTATE_running;
@@ -587,6 +589,7 @@ static void complete_domain_destroy(stru
{
if ( (v = d->vcpu[i]) == NULL )
continue;
+ tasklet_kill(&v->continue_hypercall_tasklet);
vcpu_destroy(v);
sched_destroy_vcpu(v);
}
@@ -902,6 +905,7 @@ struct migrate_info {
long (*func)(void *data);
void *data;
struct vcpu *vcpu;
+ unsigned int cpu;
unsigned int nest;
};
@@ -912,23 +916,39 @@ static void continue_hypercall_tasklet_h
struct migrate_info *info = (struct migrate_info *)_info;
struct vcpu *v = info->vcpu;
- vcpu_sleep_sync(v);
+ /*
+ * Wait for vcpu to be entirely descheduled. We re-schedule ourselves
+ * meanwhile to allow other work to be done (e.g., descheduling the vcpu!).
+ */
+ BUG_ON(vcpu_runnable(v));
+ if ( v->is_running )
+ {
+ tasklet_schedule(&v->continue_hypercall_tasklet);
+ return;
+ }
+
+ /* Once descheduled, we need to gain access to its register state. */
+ sync_vcpu_execstate(v);
this_cpu(continue_info) = info;
- return_reg(v) = info->func(info->data);
+ return_reg(v) = (info->cpu == smp_processor_id())
+ ? info->func(info->data) : -EINVAL;
this_cpu(continue_info) = NULL;
if ( info->nest-- == 0 )
{
xfree(info);
vcpu_unpause(v);
+ put_domain(v->domain);
}
}
int continue_hypercall_on_cpu(int cpu, long (*func)(void *data), void *data)
{
- struct vcpu *curr = current;
struct migrate_info *info;
+
+ if ( (cpu >= NR_CPUS) || !cpu_online(cpu) )
+ return -EINVAL;
if ( cpu == smp_processor_id() )
return func(data);
@@ -936,6 +956,8 @@ int continue_hypercall_on_cpu(int cpu, l
info = this_cpu(continue_info);
if ( info == NULL )
{
+ struct vcpu *curr = current;
+
info = xmalloc(struct migrate_info);
if ( info == NULL )
return -ENOMEM;
@@ -943,11 +965,14 @@ int continue_hypercall_on_cpu(int cpu, l
info->vcpu = curr;
info->nest = 0;
+ tasklet_kill(
+ &curr->continue_hypercall_tasklet);
tasklet_init(
&curr->continue_hypercall_tasklet,
continue_hypercall_tasklet_handler,
(unsigned long)info);
+ get_knownalive_domain(curr->domain);
vcpu_pause_nosync(curr);
}
else
@@ -958,8 +983,9 @@ int continue_hypercall_on_cpu(int cpu, l
info->func = func;
info->data = data;
-
- tasklet_schedule_on_cpu(&curr->continue_hypercall_tasklet, cpu);
+ info->cpu = cpu;
+
+ tasklet_schedule_on_cpu(&info->vcpu->continue_hypercall_tasklet, cpu);
/* Dummy return value will be overwritten by tasklet. */
return 0;
diff -r 3cdd4cf2c20e -r ecdc14634425 xen/include/xen/sched.h
--- a/xen/include/xen/sched.h Wed Apr 14 12:10:19 2010 +0100
+++ b/xen/include/xen/sched.h Wed Apr 14 13:35:05 2010 +0100
@@ -375,14 +375,6 @@ static inline void get_knownalive_domain
ASSERT(!(atomic_read(&d->refcnt) & DOMAIN_DESTROYED));
}
-/* Obtain a reference to the currently-running domain. */
-static inline struct domain *get_current_domain(void)
-{
- struct domain *d = current->domain;
- get_knownalive_domain(d);
- return d;
-}
-
struct domain *domain_create(
domid_t domid, unsigned int domcr_flags, ssidref_t ssidref);
/* DOMCRF_hvm: Create an HVM domain, as opposed to a PV domain. */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|