New dom0_op, set_max_vcpus, and VCPUOP_create split from VCPUOP_initialize. -- Ryan Harper Software Engineer; Linux Technology Center IBM Corp., Austin, Tx (512) 838-9253 T/L: 678-9253 ryanh@us.ibm.com diffstat output: tools/libxc/xc_domain.c | 22 ++++++++++++ tools/libxc/xenctrl.h | 25 ++++++++++++++ tools/python/xen/lowlevel/xc/xc.c | 56 ++++++++++++++++++++++++++++++++ tools/python/xen/xend/XendDomainInfo.py | 6 +++ xen/arch/x86/domain_build.c | 7 ++++ xen/common/dom0_ops.c | 14 ++++++++ xen/common/domain.c | 45 +++++++++++++++++-------- xen/include/public/dom0_ops.h | 8 ++++ xen/include/public/vcpu.h | 11 +++++- xen/include/xen/domain.h | 2 + xen/include/xen/sched.h | 2 + 11 files changed, 182 insertions(+), 16 deletions(-) Signed-off-by: Ryan Harper <ryanh@us.ibm.com> --- diff -r b7dce4fe2488 tools/libxc/xc_domain.c --- a/tools/libxc/xc_domain.c Mon Oct 10 10:37:10 2005 +++ b/tools/libxc/xc_domain.c Mon Oct 10 09:01:25 2005 @@ -8,6 +8,7 @@ #include "xc_private.h" #include <xen/memory.h> +#include <xen/vcpu.h> int xc_domain_create(int xc_handle, u32 ssidref, @@ -329,6 +330,27 @@ return err; } +int xc_set_max_vcpus(int xc_handle, u32 domid, unsigned int max_vcpus) +{ + dom0_op_t op; + op.cmd = DOM0_SET_MAX_VCPUS; + op.u.set_max_vcpus.domain = (domid_t)domid; + op.u.set_max_vcpus.max_vcpus = (u8)max_vcpus; + return do_dom0_op(xc_handle, &op); +} + +int xc_vcpu_create(int xc_handle, u32 domid, unsigned int vcpuid) +{ + privcmd_hypercall_t hypercall; + + hypercall.op = __HYPERVISOR_vcpu_op; + hypercall.arg[0] = (unsigned long)VCPUOP_create; + hypercall.arg[1] = (unsigned long)vcpuid; + hypercall.arg[2] = (unsigned long)domid; + + return do_xen_hypercall(xc_handle, &hypercall); +} + /* * Local variables: * mode: C diff -r b7dce4fe2488 tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Mon Oct 10 10:37:10 2005 +++ b/tools/libxc/xenctrl.h Mon Oct 10 09:01:25 2005 @@ -152,6 +152,31 @@ u32 ssidref, u32 *pdomid); +/* + * This function sets the maximum number of vcpus a domain is allow to use. + * + * @parm xc_handle a handle to an open hypervisor interface + * @parm domid the domain id in which vcpus are to be created + * @parm max_vcpus the max number of vcpus a domain is allow to use. + * @return 0 on success, -1 on failure. + */ +int xc_set_max_vcpus(int xc_handle, + u32 domid, + unsigned int max_vcpus); + +/* + * This function creates an additional vcpus for a domain. Note that + * the maximum vcpus needs to be increased (default is 1) before + * requesting additional vcpus. + * + * @parm xc_handle a handle to an open hypervisor interface + * @parm domid the domain id in which vcpus are to be created + * @parm vcpuid the vcpuid of the new vcpu. + * @return 0 on success, -1 on failure. + */ +int xc_vcpu_create(int xc_handle, + u32 domid, + unsigned int vcpuid); int xc_domain_dumpcore(int xc_handle, u32 domid, diff -r b7dce4fe2488 tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Mon Oct 10 10:37:10 2005 +++ b/tools/python/xen/lowlevel/xc/xc.c Mon Oct 10 09:01:25 2005 @@ -91,6 +91,46 @@ return PyErr_SetFromErrno(xc_error); return PyInt_FromLong(dom); +} + +static PyObject *pyxc_vcpu_create(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + u32 dom, vcpu; + + static char *kwd_list[] = { "dom", "vcpu", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, &dom, &vcpu) ) + return NULL; + + if ( xc_vcpu_create(xc->xc_handle, dom, vcpu) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_set_max_vcpus(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + + u32 dom, max_vcpu; + + static char *kwd_list[] = { "dom", "max_vcpu", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, &dom, &max_vcpu) ) + return NULL; + + if ( xc_set_max_vcpus(xc->xc_handle, dom, max_vcpu) != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; } static PyObject *pyxc_domain_pause(PyObject *self, @@ -783,6 +823,22 @@ " dom [int, 0]: Domain identifier to use (allocated if zero).\n" "Returns: [int] new domain identifier; -1 on error.\n" }, + { "vcpu_create", + (PyCFunction)pyxc_vcpu_create, + METH_VARARGS | METH_KEYWORDS, "\n" + "Create a new vcpu in domain.\n" + " dom [int, 0]: Domain identifier to use.\n" + " vcpu [int, 0]: Vcpu identifier to create.\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "set_max_vcpus", + (PyCFunction)pyxc_set_max_vcpus, + METH_VARARGS | METH_KEYWORDS, "\n" + "Set the maximum number of vcpus allowed in a domain.\n" + " dom [int, 0]: Domain identifier to use.\n" + " max_vcpus [int, 0]: Max number of vcpus allowed.\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + { "domain_dumpcore", (PyCFunction)pyxc_domain_dumpcore, METH_VARARGS | METH_KEYWORDS, "\n" diff -r b7dce4fe2488 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Mon Oct 10 10:37:10 2005 +++ b/tools/python/xen/xend/XendDomainInfo.py Mon Oct 10 09:01:25 2005 @@ -1018,6 +1018,12 @@ self.image.handleBootloading() xc.domain_setcpuweight(self.domid, self.info[''cpu_weight'']) + + # set the max, and allocate additional vcpus + xc.set_max_vcpus(self.domid, self.info[''vcpus'']); + for v in range(1,int(self.info[''vcpus''])): + xc.vcpu_create(self.domid, v) + # XXX Merge with configure_maxmem? m = self.image.getDomainMemory(self.info[''memory_KiB'']) xc.domain_setmaxmem(self.domid, m) diff -r b7dce4fe2488 xen/arch/x86/domain_build.c --- a/xen/arch/x86/domain_build.c Mon Oct 10 10:37:10 2005 +++ b/xen/arch/x86/domain_build.c Mon Oct 10 09:01:25 2005 @@ -14,6 +14,7 @@ #include <xen/event.h> #include <xen/elf.h> #include <xen/kernel.h> +#include <xen/domain.h> #include <asm/regs.h> #include <asm/system.h> #include <asm/io.h> @@ -559,6 +560,12 @@ d->shared_info->vcpu_data[i].evtchn_upcall_mask = 1; d->shared_info->n_vcpu = num_online_cpus(); + /* up max_vcpus and create extra vcpus */ + d->max_vcpus = num_online_cpus(); + if ( (d->shared_info->n_vcpu > 1) ) + for ( i = 1; i < d->shared_info->n_vcpu; i++ ) + boot_vcpu(d, i); + /* Set up monitor table */ update_pagetables(v); diff -r b7dce4fe2488 xen/common/dom0_ops.c --- a/xen/common/dom0_ops.c Mon Oct 10 10:37:10 2005 +++ b/xen/common/dom0_ops.c Mon Oct 10 09:01:25 2005 @@ -521,6 +521,20 @@ } break; + case DOM0_SET_MAX_VCPUS: + { + struct domain *d; + ret = -ESRCH; + d = find_domain_by_id(op->u.set_max_vcpus.domain); + if ( d != NULL ) + { + d->max_vcpus = op->u.set_max_vcpus.max_vcpus; + put_domain(d); + ret = 0; + } + } + break; + #ifdef PERF_COUNTERS case DOM0_PERFCCONTROL: { diff -r b7dce4fe2488 xen/common/domain.c --- a/xen/common/domain.c Mon Oct 10 10:37:10 2005 +++ b/xen/common/domain.c Mon Oct 10 09:01:25 2005 @@ -44,6 +44,10 @@ d->domain_id = dom_id; v->processor = cpu; + /* default max_vcpus is set to 1, further vcpu allocation is prevented + * without updating via priviledged MAX_VCPUS VCPU_OP. */ + d->max_vcpus = 1; + spin_lock_init(&d->big_lock); spin_lock_init(&d->page_alloc_lock); @@ -368,10 +372,9 @@ return rc; } -int boot_vcpu(struct domain *d, int vcpuid, struct vcpu_guest_context *ctxt) -{ - struct vcpu *v; - int rc; +int boot_vcpu(struct domain *d, int vcpuid) +{ + struct vcpu *v; ASSERT(d->vcpu[vcpuid] == NULL); @@ -387,20 +390,11 @@ arch_do_boot_vcpu(v); - if ( (rc = arch_set_info_guest(v, ctxt)) != 0 ) - goto out; - sched_add_domain(v); set_bit(_VCPUF_down, &v->vcpu_flags); - clear_bit(_VCPUF_ctrl_pause, &v->vcpu_flags); return 0; - - out: - arch_free_vcpu_struct(d->vcpu[vcpuid]); - d->vcpu[vcpuid] = NULL; - return rc; } long do_vcpu_op(int cmd, int vcpuid, void *arg) @@ -408,16 +402,33 @@ struct domain *d = current->domain; struct vcpu *v; struct vcpu_guest_context *ctxt; + domid_t domid; long rc = 0; if ( (vcpuid < 0) || (vcpuid >= MAX_VIRT_CPUS) ) return -EINVAL; - if ( ((v = d->vcpu[vcpuid]) == NULL) && (cmd != VCPUOP_initialise) ) + if ( ((v = d->vcpu[vcpuid]) == NULL) && (cmd != VCPUOP_create) ) return -ENOENT; switch ( cmd ) { + case VCPUOP_create: + /* get correct domain pointer if we are creating vcpus. */ + domid = (domid_t)(unsigned long)arg; + if ( (d = find_domain_by_id(domid)) == NULL ) + return -ESRCH; + + rc = -EINVAL; + if ( vcpuid < d->max_vcpus ) { + LOCK_BIGLOCK(d); + rc = (d->vcpu[vcpuid] == NULL) ? boot_vcpu(d, vcpuid) : -EEXIST; + UNLOCK_BIGLOCK(d); + } + + put_domain(d); + break; + case VCPUOP_initialise: if ( (ctxt = xmalloc(struct vcpu_guest_context)) == NULL ) { @@ -433,7 +444,11 @@ } LOCK_BIGLOCK(d); - rc = (d->vcpu[vcpuid] == NULL) ? boot_vcpu(d, vcpuid, ctxt) : -EEXIST; + clear_bit(_VCPUF_ctrl_pause, &v->vcpu_flags); + if ( (rc = arch_set_info_guest(v, ctxt)) != 0 ) { + arch_free_vcpu_struct(d->vcpu[vcpuid]); + d->vcpu[vcpuid] = NULL; + } UNLOCK_BIGLOCK(d); xfree(ctxt); diff -r b7dce4fe2488 xen/include/public/dom0_ops.h --- a/xen/include/public/dom0_ops.h Mon Oct 10 10:37:10 2005 +++ b/xen/include/public/dom0_ops.h Mon Oct 10 09:01:25 2005 @@ -386,6 +386,13 @@ int is_ram; } *memory_map; } dom0_physical_memory_map_t; + +#define DOM0_SET_MAX_VCPUS 41 +typedef struct { + domid_t domain; /* domain to be affected */ + u8 max_vcpus; /* new max_vcpus value */ +} dom0_set_max_vcpus_t; + typedef struct { u32 cmd; @@ -422,6 +429,7 @@ dom0_getdomaininfolist_t getdomaininfolist; dom0_platform_quirk_t platform_quirk; dom0_physical_memory_map_t physical_memory_map; + dom0_set_max_vcpus_t set_max_vcpus; } u; } dom0_op_t; diff -r b7dce4fe2488 xen/include/public/vcpu.h --- a/xen/include/public/vcpu.h Mon Oct 10 10:37:10 2005 +++ b/xen/include/public/vcpu.h Mon Oct 10 09:01:25 2005 @@ -1,7 +1,7 @@ /****************************************************************************** * vcpu.h * - * VCPU initialisation, query, and hotplug. + * VCPU creation, initialisation, query, and hotplug. * * Copyright (c) 2005, Keir Fraser <keir@xensource.com> */ @@ -51,4 +51,13 @@ /* Returns 1 if the given VCPU is up. */ #define VCPUOP_is_up 3 +/* + * Allocate vcpu structures and prepare for ctxt initialization. A newly + * created VCPU needs to be initialized with VCPUOP_initialize + * before being brought up by VCPUOP_up. + * + * @extra_arg == domid of domain to create vcpus in + */ +#define VCPUOP_create 4 + #endif /* __XEN_PUBLIC_VCPU_H__ */ diff -r b7dce4fe2488 xen/include/xen/domain.h --- a/xen/include/xen/domain.h Mon Oct 10 10:37:10 2005 +++ b/xen/include/xen/domain.h Mon Oct 10 09:01:25 2005 @@ -1,6 +1,8 @@ #ifndef __XEN_DOMAIN_H__ #define __XEN_DOMAIN_H__ + +extern int boot_vcpu(struct domain *d, int vcpuid); /* * Arch-specifics. diff -r b7dce4fe2488 xen/include/xen/sched.h --- a/xen/include/xen/sched.h Mon Oct 10 10:37:10 2005 +++ b/xen/include/xen/sched.h Mon Oct 10 09:01:25 2005 @@ -130,6 +130,8 @@ atomic_t refcnt; + /* max num vcpus allowed */ + u8 max_vcpus; struct vcpu *vcpu[MAX_VIRT_CPUS]; /* Bitmask of CPUs which are holding onto this domain''s state. */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel