ChangeSet 1.1725, 2005/06/21 10:59:24+01:00, cl349@xxxxxxxxxxxxxxxxxxxx
sched.h, xen.h, schedule.c, dom0_ops.c, hypercall.h, smpboot.c,
process.c:
Extend the CONFIG_HOTPLUG_CPU behavior down into the hypervisor.
Adds two SCHEDOPS (vcpu_down/vcpu_up) which set/clear VCPU flag
VCPU_down.
The domain_runnable() check now looks at this flag and subsequently
the
vcpu is not scheduled when VCPU_down is set.
Signed-off-by: Ryan Harper <ryanh@xxxxxxxxxx>
Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>
linux-2.6.11-xen-sparse/arch/xen/i386/kernel/process.c | 7 +
linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c | 4 +
linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/hypercall.h | 31 +++++++
xen/common/dom0_ops.c | 18 ++++
xen/common/schedule.c | 44 +++++++++++
xen/include/public/xen.h | 5 +
xen/include/xen/sched.h | 5 +
7 files changed, 109 insertions(+), 5 deletions(-)
diff -Nru a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/process.c
b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/process.c
--- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/process.c 2005-06-22
11:02:31 -04:00
+++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/process.c 2005-06-22
11:02:31 -04:00
@@ -154,8 +154,13 @@
cpu_clear(cpu, cpu_idle_map);
rmb();
- if (cpu_is_offline(cpu))
+ if (cpu_is_offline(cpu)) {
+#if defined(CONFIG_XEN) && defined(CONFIG_HOTPLUG_CPU)
+ /* Tell hypervisor to take vcpu down. */
+ HYPERVISOR_vcpu_down(cpu);
+#endif
play_dead();
+ }
irq_stat[cpu].idle_timestamp = jiffies;
xen_idle();
diff -Nru a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c
b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c
--- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c 2005-06-22
11:02:31 -04:00
+++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c 2005-06-22
11:02:31 -04:00
@@ -1397,6 +1397,10 @@
}
#ifdef CONFIG_HOTPLUG_CPU
+#ifdef CONFIG_XEN
+ /* Tell hypervisor to bring vcpu up. */
+ HYPERVISOR_vcpu_up(cpu);
+#endif
/* Already up, and in cpu_quiescent now? */
if (cpu_isset(cpu, smp_commenced_mask)) {
cpu_enable(cpu);
diff -Nru a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/hypercall.h
b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/hypercall.h
--- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/hypercall.h
2005-06-22 11:02:31 -04:00
+++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/hypercall.h
2005-06-22 11:02:31 -04:00
@@ -517,4 +517,35 @@
return ret;
}
+static inline int
+HYPERVISOR_vcpu_down(
+ int vcpu)
+{
+ int ret;
+ unsigned long ign1;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1)
+ : "0" (__HYPERVISOR_sched_op),
+ "1" (SCHEDOP_vcpu_down | (vcpu << SCHEDOP_vcpushift))
+ : "memory" );
+
+ return ret;
+}
+
+static inline int
+HYPERVISOR_vcpu_up(
+ int vcpu)
+{
+ int ret;
+ unsigned long ign1;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret), "=b" (ign1)
+ : "0" (__HYPERVISOR_sched_op),
+ "1" (SCHEDOP_vcpu_up | (vcpu << SCHEDOP_vcpushift))
+ : "memory" );
+
+ return ret;
+}
#endif /* __HYPERCALL_H__ */
diff -Nru a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c
--- a/xen/common/dom0_ops.c 2005-06-22 11:02:31 -04:00
+++ b/xen/common/dom0_ops.c 2005-06-22 11:02:31 -04:00
@@ -339,9 +339,14 @@
* - domain is marked as paused or blocked only if all its vcpus
* are paused or blocked
* - domain is marked as running if any of its vcpus is running
+ * - only map vcpus that aren't down. Note, at some point we may
+ * wish to demux the -1 value to indicate down vs. not-ever-booted
+ *
*/
for_each_vcpu ( d, v ) {
- op->u.getdomaininfo.vcpu_to_cpu[v->vcpu_id] = v->processor;
+ /* only map vcpus that are up */
+ if ( !(test_bit(_VCPUF_down, &v->vcpu_flags)) )
+ op->u.getdomaininfo.vcpu_to_cpu[v->vcpu_id] = v->processor;
op->u.getdomaininfo.cpumap[v->vcpu_id] = v->cpumap;
if ( !(v->vcpu_flags & VCPUF_ctrl_pause) )
flags &= ~DOMFLAGS_PAUSED;
@@ -384,6 +389,7 @@
struct vcpu_guest_context *c;
struct domain *d;
struct vcpu *v;
+ int i;
d = find_domain_by_id(op->u.getvcpucontext.domain);
if ( d == NULL )
@@ -398,8 +404,16 @@
put_domain(d);
break;
}
+
+ /* find first valid vcpu starting from request. */
+ v = NULL;
+ for ( i = op->u.getvcpucontext.vcpu; i < MAX_VIRT_CPUS; i++ )
+ {
+ v = d->vcpu[i];
+ if ( v != NULL && !(test_bit(_VCPUF_down, &v->vcpu_flags)) )
+ break;
+ }
- v = d->vcpu[op->u.getvcpucontext.vcpu];
if ( v == NULL )
{
ret = -ESRCH;
diff -Nru a/xen/common/schedule.c b/xen/common/schedule.c
--- a/xen/common/schedule.c 2005-06-22 11:02:31 -04:00
+++ b/xen/common/schedule.c 2005-06-22 11:02:31 -04:00
@@ -261,6 +261,40 @@
return 0;
}
+/* Mark target vcpu as non-runnable so it is not scheduled */
+static long do_vcpu_down(int vcpu)
+{
+ struct vcpu *target;
+
+ if ( vcpu > MAX_VIRT_CPUS )
+ return -EINVAL;
+
+ target = current->domain->vcpu[vcpu];
+ if ( target == NULL )
+ return -ESRCH;
+ set_bit(_VCPUF_down, &target->vcpu_flags);
+
+ return 0;
+}
+
+/* Mark target vcpu as runnable and wake it */
+static long do_vcpu_up(int vcpu)
+{
+ struct vcpu *target;
+
+ if (vcpu > MAX_VIRT_CPUS)
+ return -EINVAL;
+
+ target = current->domain->vcpu[vcpu];
+ if ( target == NULL )
+ return -ESRCH;
+ clear_bit(_VCPUF_down, &target->vcpu_flags);
+ /* wake vcpu */
+ domain_wake(target);
+
+ return 0;
+}
+
/*
* Demultiplex scheduler-related hypercalls.
*/
@@ -288,6 +322,16 @@
current->domain->domain_id, current->vcpu_id,
(op >> SCHEDOP_reasonshift));
domain_shutdown((u8)(op >> SCHEDOP_reasonshift));
+ break;
+ }
+ case SCHEDOP_vcpu_down:
+ {
+ ret = do_vcpu_down((int)(op >> SCHEDOP_vcpushift));
+ break;
+ }
+ case SCHEDOP_vcpu_up:
+ {
+ ret = do_vcpu_up((int)(op >> SCHEDOP_vcpushift));
break;
}
diff -Nru a/xen/include/public/xen.h b/xen/include/public/xen.h
--- a/xen/include/public/xen.h 2005-06-22 11:02:31 -04:00
+++ b/xen/include/public/xen.h 2005-06-22 11:02:31 -04:00
@@ -58,7 +58,7 @@
#define __HYPERVISOR_boot_vcpu 24
#define __HYPERVISOR_set_segment_base 25 /* x86/64 only */
#define __HYPERVISOR_mmuext_op 26
-#define __HYPERVISOR_policy_op 27
+#define __HYPERVISOR_policy_op 27
/*
* VIRTUAL INTERRUPTS
@@ -201,8 +201,11 @@
#define SCHEDOP_yield 0 /* Give up the CPU voluntarily. */
#define SCHEDOP_block 1 /* Block until an event is received. */
#define SCHEDOP_shutdown 2 /* Stop executing this domain. */
+#define SCHEDOP_vcpu_down 3 /* make target VCPU not-runnable. */
+#define SCHEDOP_vcpu_up 4 /* make target VCPU runnable. */
#define SCHEDOP_cmdmask 255 /* 8-bit command. */
#define SCHEDOP_reasonshift 8 /* 8-bit reason code. (SCHEDOP_shutdown) */
+#define SCHEDOP_vcpushift 8 /* 8-bit VCPU target. (SCHEDOP_up|down) */
/*
* Reason codes for SCHEDOP_shutdown. These may be interpreted by control
diff -Nru a/xen/include/xen/sched.h b/xen/include/xen/sched.h
--- a/xen/include/xen/sched.h 2005-06-22 11:02:31 -04:00
+++ b/xen/include/xen/sched.h 2005-06-22 11:02:31 -04:00
@@ -348,6 +348,9 @@
/* Initialization completed. */
#define _VCPUF_initialised 8
#define VCPUF_initialised (1UL<<_VCPUF_initialised)
+ /* VCPU is not-runnable */
+#define _VCPUF_down 9
+#define VCPUF_down (1UL<<_VCPUF_down)
/*
* Per-domain flags (domain_flags).
@@ -377,7 +380,7 @@
static inline int domain_runnable(struct vcpu *v)
{
return ( (atomic_read(&v->pausecnt) == 0) &&
- !(v->vcpu_flags & (VCPUF_blocked|VCPUF_ctrl_pause)) &&
+ !(v->vcpu_flags & (VCPUF_blocked|VCPUF_ctrl_pause|VCPUF_down)) &&
!(v->domain->domain_flags & (DOMF_shutdown|DOMF_shuttingdown)) );
}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|