direct-io.hg

changeset 4845:28e8f35313bb

bitkeeper revision 1.1389.15.10 (428202c9Vz9xfNsG-q-WtZpPrER7xQ)

[PATCH] xen,tools: pincpu use vcpu and cpumap_t

The following patch updates the dom0 pincpu operation to read the VCPU
value from the xend interface rather than hard-coding the exec_domain to
0. This prevented pinning VCPUS other than 0 to a particular cpu. The
pincpu cpu argument is replaced with cpumap, a u64 bitmap representing
which CPUs a VCPU can use.

I added the number of VCPUS to the main xm list output and also included
a new sub-option to xm list to display the VCPU to CPU mapping. While
working on the pincpu code, I fixed an out-of-bounds indexing for the
pincpu operation that wasn't previously exposed since the
vcpu/exec_domain value was hard-coded to 0.

Signed-off-by: Ryan Harper <ryanh@us.ibm.com>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk[cl349]
date Wed May 11 13:04:09 2005 +0000 (2005-05-11)
parents cd6c145a8f97
children e70ba984a87f
files tools/libxc/xc.h tools/libxc/xc_domain.c tools/python/xen/lowlevel/xc/xc.c tools/python/xen/xend/XendClient.py tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/server/SrvDomain.py tools/python/xen/xend/server/SrvUsbif.py tools/python/xen/xm/main.py xen/arch/x86/domain.c xen/common/dom0_ops.c xen/common/domain.c xen/include/public/dom0_ops.h xen/include/public/xen.h xen/include/xen/sched.h
line diff
     1.1 --- a/tools/libxc/xc.h	Wed May 11 08:31:59 2005 +0000
     1.2 +++ b/tools/libxc/xc.h	Wed May 11 13:04:09 2005 +0000
     1.3 @@ -111,6 +111,7 @@ int xc_waitdomain_core(int domain,
     1.4  typedef struct {
     1.5      u32           domid;
     1.6      unsigned int  cpu;
     1.7 +    unsigned int  vcpus;
     1.8      unsigned int  dying:1, crashed:1, shutdown:1, 
     1.9                    paused:1, blocked:1, running:1;
    1.10      unsigned int  shutdown_reason; /* only meaningful if shutdown==1 */
    1.11 @@ -118,6 +119,8 @@ typedef struct {
    1.12      unsigned long shared_info_frame;
    1.13      u64           cpu_time;
    1.14      unsigned long max_memkb;
    1.15 +    u32           vcpu_to_cpu[MAX_VIRT_CPUS];
    1.16 +    cpumap_t      cpumap[MAX_VIRT_CPUS];
    1.17  } xc_dominfo_t;
    1.18  
    1.19  typedef dom0_getdomaininfo_t xc_domaininfo_t;
    1.20 @@ -167,7 +170,8 @@ int xc_domain_destroy(int xc_handle,
    1.21                        u32 domid);
    1.22  int xc_domain_pincpu(int xc_handle,
    1.23                       u32 domid,
    1.24 -                     int cpu);
    1.25 +                     int vcpu,
    1.26 +                     cpumap_t *cpumap);
    1.27  /**
    1.28   * This function will return information about one or more domains.
    1.29   *
     2.1 --- a/tools/libxc/xc_domain.c	Wed May 11 08:31:59 2005 +0000
     2.2 +++ b/tools/libxc/xc_domain.c	Wed May 11 13:04:09 2005 +0000
     2.3 @@ -16,6 +16,8 @@ int xc_domain_create(int xc_handle,
     2.4  {
     2.5      int err, errno_saved;
     2.6      dom0_op_t op;
     2.7 +    u32 vcpu = 0; /* FIXME, hard coded initial pin to vcpu 0 */
     2.8 +    cpumap_t cpumap = 1<<cpu;
     2.9  
    2.10      op.cmd = DOM0_CREATEDOMAIN;
    2.11      op.u.createdomain.domain = (domid_t)*pdomid;
    2.12 @@ -25,7 +27,7 @@ int xc_domain_create(int xc_handle,
    2.13      *pdomid = (u16)op.u.createdomain.domain;
    2.14  
    2.15      if ( (cpu != -1) &&
    2.16 -         ((err = xc_domain_pincpu(xc_handle, *pdomid, cpu)) != 0) )
    2.17 +         ((err = xc_domain_pincpu(xc_handle, *pdomid, vcpu, &cpumap)) != 0) )
    2.18          goto fail;
    2.19  
    2.20      if ( (err = xc_domain_setcpuweight(xc_handle, *pdomid, cpu_weight)) != 0 )
    2.21 @@ -84,13 +86,14 @@ int xc_domain_destroy(int xc_handle,
    2.22  
    2.23  int xc_domain_pincpu(int xc_handle,
    2.24                       u32 domid, 
    2.25 -                     int cpu)
    2.26 +                     int vcpu,
    2.27 +                     cpumap_t *cpumap)
    2.28  {
    2.29      dom0_op_t op;
    2.30      op.cmd = DOM0_PINCPUDOMAIN;
    2.31      op.u.pincpudomain.domain = (domid_t)domid;
    2.32 -    op.u.pincpudomain.exec_domain = 0;
    2.33 -    op.u.pincpudomain.cpu  = cpu;
    2.34 +    op.u.pincpudomain.exec_domain = vcpu;
    2.35 +    op.u.pincpudomain.cpumap  = cpumap;
    2.36      return do_dom0_op(xc_handle, &op);
    2.37  }
    2.38  
    2.39 @@ -133,6 +136,11 @@ int xc_domain_getinfo(int xc_handle,
    2.40          info->max_memkb = op.u.getdomaininfo.max_pages<<(PAGE_SHIFT);
    2.41          info->shared_info_frame = op.u.getdomaininfo.shared_info_frame;
    2.42          info->cpu_time = op.u.getdomaininfo.cpu_time;
    2.43 +        info->vcpus = op.u.getdomaininfo.n_vcpu;
    2.44 +        memcpy(info->vcpu_to_cpu, &op.u.getdomaininfo.vcpu_to_cpu, 
    2.45 +               MAX_VIRT_CPUS*sizeof(u32));
    2.46 +        memcpy(info->cpumap, &op.u.getdomaininfo.cpumap, 
    2.47 +               MAX_VIRT_CPUS*sizeof(cpumap_t));
    2.48  
    2.49          next_domid = (u16)op.u.getdomaininfo.domain + 1;
    2.50          info++;
     3.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Wed May 11 08:31:59 2005 +0000
     3.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Wed May 11 13:04:09 2005 +0000
     3.3 @@ -155,15 +155,16 @@ static PyObject *pyxc_domain_pincpu(PyOb
     3.4      XcObject *xc = (XcObject *)self;
     3.5  
     3.6      u32 dom;
     3.7 -    int cpu = -1;
     3.8 +    int vcpu = 0;
     3.9 +    cpumap_t cpumap = 0xFFFFFFFF;
    3.10  
    3.11 -    static char *kwd_list[] = { "dom", "cpu", NULL };
    3.12 +    static char *kwd_list[] = { "dom", "vcpu", "cpumap", NULL };
    3.13  
    3.14 -    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list, 
    3.15 -                                      &dom, &cpu) )
    3.16 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwd_list, 
    3.17 +                                      &dom, &vcpu, &cpumap) )
    3.18          return NULL;
    3.19  
    3.20 -    if ( xc_domain_pincpu(xc->xc_handle, dom, cpu) != 0 )
    3.21 +    if ( xc_domain_pincpu(xc->xc_handle, dom, vcpu, &cpumap) != 0 )
    3.22          return PyErr_SetFromErrno(xc_error);
    3.23      
    3.24      Py_INCREF(zero);
    3.25 @@ -175,10 +176,10 @@ static PyObject *pyxc_domain_getinfo(PyO
    3.26                                       PyObject *kwds)
    3.27  {
    3.28      XcObject *xc = (XcObject *)self;
    3.29 -    PyObject *list;
    3.30 +    PyObject *list, *vcpu_list, *cpumap_list, *info_dict;
    3.31  
    3.32      u32 first_dom = 0;
    3.33 -    int max_doms = 1024, nr_doms, i;
    3.34 +    int max_doms = 1024, nr_doms, i, j;
    3.35      xc_dominfo_t *info;
    3.36  
    3.37      static char *kwd_list[] = { "first_dom", "max_doms", NULL };
    3.38 @@ -195,23 +196,34 @@ static PyObject *pyxc_domain_getinfo(PyO
    3.39      list = PyList_New(nr_doms);
    3.40      for ( i = 0 ; i < nr_doms; i++ )
    3.41      {
    3.42 -        PyList_SetItem(
    3.43 -            list, i, 
    3.44 -            Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
    3.45 -                          ",s:l,s:L,s:l,s:i}",
    3.46 -                          "dom",       info[i].domid,
    3.47 -                          "cpu",       info[i].cpu,
    3.48 -                          "dying",     info[i].dying,
    3.49 -                          "crashed",   info[i].crashed,
    3.50 -                          "shutdown",  info[i].shutdown,
    3.51 -                          "paused",    info[i].paused,
    3.52 -                          "blocked",   info[i].blocked,
    3.53 -                          "running",   info[i].running,
    3.54 -                          "mem_kb",    info[i].nr_pages*4,
    3.55 -                          "cpu_time",  info[i].cpu_time,
    3.56 -                          "maxmem_kb", info[i].max_memkb,
    3.57 -                          "shutdown_reason", info[i].shutdown_reason
    3.58 -                ));
    3.59 +        vcpu_list = PyList_New(MAX_VIRT_CPUS);
    3.60 +        cpumap_list = PyList_New(MAX_VIRT_CPUS);
    3.61 +        for ( j = 0; j < MAX_VIRT_CPUS; j++ ) {
    3.62 +            PyList_SetItem( vcpu_list, j, 
    3.63 +                            Py_BuildValue("i", info[i].vcpu_to_cpu[j]));
    3.64 +            PyList_SetItem( cpumap_list, j, 
    3.65 +                            Py_BuildValue("i", info[i].cpumap[j]));
    3.66 +        }
    3.67 +                 
    3.68 +        info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
    3.69 +                                  ",s:l,s:L,s:l,s:i}",
    3.70 +                                  "dom",       info[i].domid,
    3.71 +                                  "cpu",       info[i].cpu,
    3.72 +                                  "vcpus",     info[i].vcpus,
    3.73 +                                  "dying",     info[i].dying,
    3.74 +                                  "crashed",   info[i].crashed,
    3.75 +                                  "shutdown",  info[i].shutdown,
    3.76 +                                  "paused",    info[i].paused,
    3.77 +                                  "blocked",   info[i].blocked,
    3.78 +                                  "running",   info[i].running,
    3.79 +                                  "mem_kb",    info[i].nr_pages*4,
    3.80 +                                  "cpu_time",  info[i].cpu_time,
    3.81 +                                  "maxmem_kb", info[i].max_memkb,
    3.82 +                                  "shutdown_reason", info[i].shutdown_reason);
    3.83 +        PyDict_SetItemString( info_dict, "vcpu_to_cpu", vcpu_list );
    3.84 +        PyDict_SetItemString( info_dict, "cpumap", cpumap_list );
    3.85 +        PyList_SetItem( list, i, info_dict);
    3.86 + 
    3.87      }
    3.88  
    3.89      free(info);
    3.90 @@ -959,9 +971,10 @@ static PyMethodDef pyxc_methods[] = {
    3.91      { "domain_pincpu", 
    3.92        (PyCFunction)pyxc_domain_pincpu, 
    3.93        METH_VARARGS | METH_KEYWORDS, "\n"
    3.94 -      "Pin a domain to a specified CPU.\n"
    3.95 -      " dom [int]:     Identifier of domain to be pinned.\n"
    3.96 -      " cpu [int, -1]: CPU to pin to, or -1 to unpin\n\n"
    3.97 +      "Pin a VCPU to a specified set CPUs.\n"
    3.98 +      " dom [int]:     Identifier of domain to which VCPU belongs.\n"
    3.99 +      " vcpu [int, 0]: VCPU being pinned.\n"
   3.100 +      " cpumap [int, -1]: Bitmap of usable CPUs.\n\n"
   3.101        "Returns: [int] 0 on success; -1 on error.\n" },
   3.102  
   3.103      { "domain_getinfo", 
   3.104 @@ -976,6 +989,7 @@ static PyMethodDef pyxc_methods[] = {
   3.105        "         domain-id space was reached.\n"
   3.106        " dom      [int]: Identifier of domain to which this info pertains\n"
   3.107        " cpu      [int]:  CPU to which this domain is bound\n"
   3.108 +      " vcpus    [int]:  Number of Virtual CPUS in this domain\n"
   3.109        " dying    [int]:  Bool - is the domain dying?\n"
   3.110        " crashed  [int]:  Bool - has the domain crashed?\n"
   3.111        " shutdown [int]:  Bool - has the domain shut itself down?\n"
   3.112 @@ -986,7 +1000,8 @@ static PyMethodDef pyxc_methods[] = {
   3.113        " maxmem_kb [int]: Maximum memory limit, in kilobytes\n"
   3.114        " cpu_time [long]: CPU time consumed, in nanoseconds\n"
   3.115        " shutdown_reason [int]: Numeric code from guest OS, explaining "
   3.116 -      "reason why it shut itself down.\n" },
   3.117 +      "reason why it shut itself down.\n" 
   3.118 +      " vcpu_to_cpu [[int]]: List that maps VCPUS to CPUS\n" },
   3.119  
   3.120      { "linux_save", 
   3.121        (PyCFunction)pyxc_linux_save, 
     4.1 --- a/tools/python/xen/xend/XendClient.py	Wed May 11 08:31:59 2005 +0000
     4.2 +++ b/tools/python/xen/xend/XendClient.py	Wed May 11 13:04:09 2005 +0000
     4.3 @@ -246,10 +246,11 @@ class Xend:
     4.4                                'live'       : live,
     4.5                                'resource'   : resource })
     4.6  
     4.7 -    def xend_domain_pincpu(self, id, cpu):
     4.8 +    def xend_domain_pincpu(self, id, vcpu, cpumap):
     4.9          return self.xendPost(self.domainurl(id),
    4.10                               {'op'      : 'pincpu',
    4.11 -                              'cpu'     : cpu })
    4.12 +                              'vcpu'    : vcpu,
    4.13 +                              'cpumap'  : cpumap })
    4.14  
    4.15      def xend_domain_cpu_bvt_set(self, id, mcuadv, warpback, warpvalue, warpl, warpu):
    4.16          return self.xendPost(self.domainurl(id),
     5.1 --- a/tools/python/xen/xend/XendDomain.py	Wed May 11 08:31:59 2005 +0000
     5.2 +++ b/tools/python/xen/xend/XendDomain.py	Wed May 11 13:04:09 2005 +0000
     5.3 @@ -612,15 +612,16 @@ class XendDomain:
     5.4          xmigrate = XendMigrate.instance()
     5.5          return xmigrate.save_begin(dominfo, dst)
     5.6      
     5.7 -    def domain_pincpu(self, id, cpu):
     5.8 -        """Pin a domain to a cpu.
     5.9 +    def domain_pincpu(self, id, vcpu, cpumap):
    5.10 +        """Set which cpus vcpu can use
    5.11  
    5.12 -        @param id: domain
    5.13 -        @param cpu: cpu number
    5.14 +        @param id:   domain
    5.15 +        @param vcpu: vcpu number
    5.16 +        @param cpumap:  bitmap of usbale cpus
    5.17          """
    5.18          dominfo = self.domain_lookup(id)
    5.19          try:
    5.20 -            return xc.domain_pincpu(int(dominfo.id), cpu)
    5.21 +            return xc.domain_pincpu(int(dominfo.id), vcpu, cpumap)
    5.22          except Exception, ex:
    5.23              raise XendError(str(ex))
    5.24  
     6.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Wed May 11 08:31:59 2005 +0000
     6.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Wed May 11 13:04:09 2005 +0000
     6.3 @@ -372,6 +372,10 @@ class XendDomainInfo:
     6.4                  sxpr.append(['shutdown_reason', reason])
     6.5              sxpr.append(['cpu', self.info['cpu']])
     6.6              sxpr.append(['cpu_time', self.info['cpu_time']/1e9])    
     6.7 +            sxpr.append(['vcpus', self.info['vcpus']])
     6.8 +            sxpr.append(['cpumap', self.info['cpumap']])
     6.9 +            sxpr.append(['vcpu_to_cpu', ''.join(map(lambda x: str(x),
    6.10 +                        self.info['vcpu_to_cpu'][0:self.info['vcpus']]))])
    6.11              
    6.12          if self.start_time:
    6.13              up_time =  time.time() - self.start_time  
    6.14 @@ -449,7 +453,7 @@ class XendDomainInfo:
    6.15                  raise VmError('missing memory size')
    6.16              cpu = sxp.child_value(config, 'cpu')
    6.17              if self.recreate and self.dom and cpu is not None:
    6.18 -                xc.domain_pincpu(self.dom, int(cpu))
    6.19 +                xc.domain_pincpu(self.dom, 0, 1<<int(cpu))
    6.20              try:
    6.21                  image = sxp.child_value(self.config, 'image')
    6.22                  self.vcpus = int(sxp.child_value(image, 'vcpus'))
     7.1 --- a/tools/python/xen/xend/server/SrvDomain.py	Wed May 11 08:31:59 2005 +0000
     7.2 +++ b/tools/python/xen/xend/server/SrvDomain.py	Wed May 11 13:04:09 2005 +0000
     7.3 @@ -92,7 +92,8 @@ class SrvDomain(SrvDir):
     7.4      def op_pincpu(self, op, req):
     7.5          fn = FormFn(self.xd.domain_pincpu,
     7.6                      [['dom', 'str'],
     7.7 -                     ['cpu', 'int']])
     7.8 +                     ['vcpu', 'int'],
     7.9 +                     ['cpumap', 'int']])
    7.10          val = fn(req.args, {'dom': self.dom.id})
    7.11          return val
    7.12  
     8.1 --- a/tools/python/xen/xend/server/SrvUsbif.py	Wed May 11 08:31:59 2005 +0000
     8.2 +++ b/tools/python/xen/xend/server/SrvUsbif.py	Wed May 11 13:04:09 2005 +0000
     8.3 @@ -107,6 +107,7 @@ class SrvDomain(SrvDir):
     8.4      def op_pincpu(self, op, req):
     8.5          fn = FormFn(self.xd.domain_pincpu,
     8.6                      [['dom', 'str'],
     8.7 +                     ['vcpu', 'int'],
     8.8                       ['cpu', 'int']])
     8.9          val = fn(req.args, {'dom': self.dom.id})
    8.10          return val
     9.1 --- a/tools/python/xen/xm/main.py	Wed May 11 08:31:59 2005 +0000
     9.2 +++ b/tools/python/xen/xm/main.py	Wed May 11 13:04:09 2005 +0000
     9.3 @@ -6,6 +6,8 @@ import os.path
     9.4  import sys
     9.5  from getopt import getopt
     9.6  import socket
     9.7 +import warnings
     9.8 +warnings.filterwarnings('ignore', category=FutureWarning)
     9.9  
    9.10  from xen.xend import PrettyPrint
    9.11  from xen.xend import sxp
    9.12 @@ -340,8 +342,8 @@ class ProgList(Prog):
    9.13      name = "list"
    9.14      info = """List information about domains."""
    9.15  
    9.16 -    short_options = 'l'
    9.17 -    long_options = ['long']
    9.18 +    short_options = 'lv'
    9.19 +    long_options = ['long','vcpus']
    9.20  
    9.21      def help(self, args):
    9.22          if help:
    9.23 @@ -350,11 +352,13 @@ class ProgList(Prog):
    9.24              Either all domains or the domains given.
    9.25  
    9.26              -l, --long   Get more detailed information.
    9.27 +            -v, --vcpus  Show VCPU to CPU mapping.
    9.28              """
    9.29              return
    9.30          
    9.31      def main(self, args):
    9.32          use_long = 0
    9.33 +        show_vcpus = 0
    9.34          (options, params) = getopt(args[1:],
    9.35                                     self.short_options,
    9.36                                     self.long_options)
    9.37 @@ -362,6 +366,8 @@ class ProgList(Prog):
    9.38          for (k, v) in options:
    9.39              if k in ['-l', '--long']:
    9.40                  use_long = 1
    9.41 +            if k in ['-v', '--vcpus']:
    9.42 +                show_vcpus = 1
    9.43                  
    9.44          if n == 0:
    9.45              doms = server.xend_domains()
    9.46 @@ -371,11 +377,13 @@ class ProgList(Prog):
    9.47              
    9.48          if use_long:
    9.49              self.long_list(doms)
    9.50 +        elif show_vcpus:
    9.51 +            self.show_vcpus(doms)
    9.52          else:
    9.53              self.brief_list(doms)
    9.54  
    9.55      def brief_list(self, doms):
    9.56 -        print 'Name              Id  Mem(MB)  CPU  State  Time(s)  Console'
    9.57 +        print 'Name              Id  Mem(MB)  CPU VCPU(s)  State  Time(s)  Console'
    9.58          for dom in doms:
    9.59              info = server.xend_domain(dom)
    9.60              d = {}
    9.61 @@ -383,6 +391,7 @@ class ProgList(Prog):
    9.62              d['name'] = sxp.child_value(info, 'name', '??')
    9.63              d['mem'] = int(sxp.child_value(info, 'memory', '0'))
    9.64              d['cpu'] = int(sxp.child_value(info, 'cpu', '0'))
    9.65 +            d['vcpus'] = int(sxp.child_value(info, 'vcpus', '0'))
    9.66              d['state'] = sxp.child_value(info, 'state', '??')
    9.67              d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
    9.68              console = sxp.child(info, 'console')
    9.69 @@ -390,9 +399,27 @@ class ProgList(Prog):
    9.70                  d['port'] = sxp.child_value(console, 'console_port')
    9.71              else:
    9.72                  d['port'] = ''
    9.73 -            print ("%(name)-16s %(dom)3d  %(mem)7d  %(cpu)3d  %(state)5s  %(cpu_time)7.1f    %(port)4s"
    9.74 +            print ("%(name)-16s %(dom)3d  %(mem)7d  %(cpu)3d  %(vcpus)5d   %(state)5s  %(cpu_time)7.1f     %(port)4s"
    9.75                     % d)
    9.76  
    9.77 +    def show_vcpus(self, doms):
    9.78 +        print 'Name              Id  VCPU  CPU  CPUMAP'
    9.79 +        for dom in doms:
    9.80 +            info = server.xend_domain(dom)
    9.81 +            vcpu_to_cpu = sxp.child_value(info, 'vcpu_to_cpu', '?').replace('-','')
    9.82 +            cpumap = sxp.child_value(info, 'cpumap', [])
    9.83 +            mask = ((int(sxp.child_value(info, 'vcpus', '0')))**2) - 1
    9.84 +            count = 0
    9.85 +            for cpu in vcpu_to_cpu:
    9.86 +                d = {}
    9.87 +                d['name']   = sxp.child_value(info, 'name', '??')
    9.88 +                d['dom']    = int(sxp.child_value(info, 'id', '-1'))
    9.89 +                d['vcpu']   = int(count)
    9.90 +                d['cpu']    = int(cpu)
    9.91 +                d['cpumap'] = int(cpumap[count])&mask
    9.92 +                count = count + 1
    9.93 +                print ("%(name)-16s %(dom)3d  %(vcpu)4d  %(cpu)3d  0x%(cpumap)x" % d)
    9.94 +
    9.95      def long_list(self, doms):
    9.96          for dom in doms:
    9.97              info = server.xend_domain(dom)
    9.98 @@ -474,17 +501,35 @@ xm.prog(ProgUnpause)
    9.99  class ProgPincpu(Prog):
   9.100      group = 'domain'
   9.101      name = "pincpu"
   9.102 -    info = """Pin a domain to a cpu. """
   9.103 +    info = """Set which cpus a VCPU can use. """
   9.104  
   9.105      def help(self, args):
   9.106 -        print args[0],'DOM CPU'
   9.107 -        print '\nPin domain DOM to cpu CPU.'
   9.108 +        print args[0],'DOM VCPU CPUS'
   9.109 +        print '\nSet which cpus VCPU in domain DOM can use.'
   9.110 +
   9.111 +    # convert list of cpus to bitmap integer value
   9.112 +    def make_map(self, cpulist):
   9.113 +        cpus = []
   9.114 +        cpumap = 0
   9.115 +        for c in cpulist.split(','):
   9.116 +            if len(c) > 1:
   9.117 +                (x,y) = c.split('-')
   9.118 +                for i in range(int(x),int(y)+1):
   9.119 +                    cpus.append(int(i))
   9.120 +            else:
   9.121 +                cpus.append(int(c))
   9.122 +        cpus.sort()
   9.123 +        for c in cpus:
   9.124 +            cpumap = cpumap | 1<<c
   9.125 +
   9.126 +        return cpumap
   9.127  
   9.128      def main(self, args):
   9.129 -        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
   9.130 -        dom = args[1]
   9.131 -        cpu = int(args[2])
   9.132 -        server.xend_domain_pincpu(dom, cpu)
   9.133 +        if len(args) != 4: self.err("%s: Invalid argument(s)" % args[0])
   9.134 +        dom  = args[1]
   9.135 +        vcpu = int(args[2])
   9.136 +        cpumap  = self.make_map(args[3]);
   9.137 +        server.xend_domain_pincpu(dom, vcpu, cpumap)
   9.138  
   9.139  xm.prog(ProgPincpu)
   9.140  
    10.1 --- a/xen/arch/x86/domain.c	Wed May 11 08:31:59 2005 +0000
    10.2 +++ b/xen/arch/x86/domain.c	Wed May 11 13:04:09 2005 +0000
    10.3 @@ -253,6 +253,7 @@ void arch_do_createdomain(struct exec_do
    10.4          d->shared_info = (void *)alloc_xenheap_page();
    10.5          memset(d->shared_info, 0, PAGE_SIZE);
    10.6          ed->vcpu_info = &d->shared_info->vcpu_data[ed->id];
    10.7 +        ed->cpumap = CPUMAP_RUNANYWHERE;
    10.8          SHARE_PFN_WITH_DOMAIN(virt_to_page(d->shared_info), d);
    10.9          machine_to_phys_mapping[virt_to_phys(d->shared_info) >> 
   10.10                                 PAGE_SHIFT] = INVALID_M2P_ENTRY;
    11.1 --- a/xen/common/dom0_ops.c	Wed May 11 08:31:59 2005 +0000
    11.2 +++ b/xen/common/dom0_ops.c	Wed May 11 13:04:09 2005 +0000
    11.3 @@ -221,7 +221,8 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
    11.4          domid_t dom = op->u.pincpudomain.domain;
    11.5          struct domain *d = find_domain_by_id(dom);
    11.6          struct exec_domain *ed;
    11.7 -        int cpu = op->u.pincpudomain.cpu;
    11.8 +        cpumap_t curmap, *cpumap = &curmap;
    11.9 +
   11.10  
   11.11          if ( d == NULL )
   11.12          {
   11.13 @@ -229,6 +230,14 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
   11.14              break;
   11.15          }
   11.16          
   11.17 +        if ( (op->u.pincpudomain.exec_domain >= MAX_VIRT_CPUS) ||
   11.18 +             !d->exec_domain[op->u.pincpudomain.exec_domain] )
   11.19 +        {
   11.20 +            ret = -EINVAL;
   11.21 +            put_domain(d);
   11.22 +            break;
   11.23 +        }
   11.24 +
   11.25          ed = d->exec_domain[op->u.pincpudomain.exec_domain];
   11.26          if ( ed == NULL )
   11.27          {
   11.28 @@ -244,17 +253,29 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
   11.29              break;
   11.30          }
   11.31  
   11.32 -        if ( cpu == -1 )
   11.33 +        if ( copy_from_user(cpumap, 
   11.34 +                            op->u.pincpudomain.cpumap, sizeof(*cpumap)) )
   11.35          {
   11.36 +            ret = -EFAULT;
   11.37 +            put_domain(d);
   11.38 +            break;
   11.39 +        }
   11.40 +
   11.41 +        /* update cpumap for this ed */
   11.42 +        ed->cpumap = *(cpumap);
   11.43 +
   11.44 +        if ( *(cpumap) == CPUMAP_RUNANYWHERE )
   11.45              clear_bit(EDF_CPUPINNED, &ed->flags);
   11.46 -        }
   11.47          else
   11.48          {
   11.49 +            /* pick a new cpu from the usable map */
   11.50 +            int new_cpu = (int)find_first_set_bit(*(cpumap)) % smp_num_cpus;
   11.51 +
   11.52              exec_domain_pause(ed);
   11.53 -            if ( ed->processor != (cpu % smp_num_cpus) )
   11.54 +            if ( ed->processor != new_cpu )
   11.55                  set_bit(EDF_MIGRATED, &ed->flags);
   11.56              set_bit(EDF_CPUPINNED, &ed->flags);
   11.57 -            ed->processor = cpu % smp_num_cpus;
   11.58 +            ed->processor = new_cpu;
   11.59              exec_domain_unpause(ed);
   11.60          }
   11.61  
   11.62 @@ -308,6 +329,12 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
   11.63              break;
   11.64          }
   11.65          
   11.66 +        memset(&op->u.getdomaininfo.vcpu_to_cpu,-1,MAX_VIRT_CPUS*sizeof(u8));
   11.67 +        for_each_exec_domain ( d, ed ) {
   11.68 +            op->u.getdomaininfo.vcpu_to_cpu[ed->id] = ed->processor;
   11.69 +            op->u.getdomaininfo.cpumap[ed->id]      = ed->cpumap;
   11.70 +        }
   11.71 +
   11.72          ed = d->exec_domain[op->u.getdomaininfo.exec_domain];
   11.73  
   11.74          op->u.getdomaininfo.flags =
   11.75 @@ -325,6 +352,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
   11.76          op->u.getdomaininfo.tot_pages   = d->tot_pages;
   11.77          op->u.getdomaininfo.max_pages   = d->max_pages;
   11.78          op->u.getdomaininfo.cpu_time    = ed->cpu_time;
   11.79 +        op->u.getdomaininfo.n_vcpu      = d->shared_info->n_vcpu;
   11.80          op->u.getdomaininfo.shared_info_frame = 
   11.81              __pa(d->shared_info) >> PAGE_SHIFT;
   11.82  
    12.1 --- a/xen/common/domain.c	Wed May 11 08:31:59 2005 +0000
    12.2 +++ b/xen/common/domain.c	Wed May 11 13:04:09 2005 +0000
    12.3 @@ -283,6 +283,7 @@ long do_boot_vcpu(unsigned long vcpu, st
    12.4      ed = d->exec_domain[vcpu];
    12.5  
    12.6      atomic_set(&ed->pausecnt, 0);
    12.7 +    ed->cpumap = CPUMAP_RUNANYWHERE;
    12.8  
    12.9      memcpy(&ed->arch, &idle0_exec_domain.arch, sizeof(ed->arch));
   12.10  
    13.1 --- a/xen/include/public/dom0_ops.h	Wed May 11 08:31:59 2005 +0000
    13.2 +++ b/xen/include/public/dom0_ops.h	Wed May 11 13:04:09 2005 +0000
    13.3 @@ -88,6 +88,9 @@ typedef struct {
    13.4      memory_t max_pages;
    13.5      memory_t shared_info_frame;       /* MFN of shared_info struct */
    13.6      u64      cpu_time;
    13.7 +    u32      n_vcpu;
    13.8 +    u32      vcpu_to_cpu[MAX_VIRT_CPUS];  /* current mapping   */
    13.9 +    cpumap_t cpumap[MAX_VIRT_CPUS];       /* allowable mapping */
   13.10  } dom0_getdomaininfo_t;
   13.11  
   13.12  #define DOM0_SETDOMAININFO      13
   13.13 @@ -170,14 +173,14 @@ typedef struct {
   13.14  } dom0_readconsole_t;
   13.15  
   13.16  /* 
   13.17 - * Pin Domain to a particular CPU  (use -1 to unpin)
   13.18 + * Set which cpus an exec_domain can use
   13.19   */
   13.20  #define DOM0_PINCPUDOMAIN     20
   13.21  typedef struct {
   13.22      /* IN variables. */
   13.23      domid_t      domain;
   13.24      u16          exec_domain;
   13.25 -    s32          cpu;                 /*  -1 implies unpin */
   13.26 +    cpumap_t     *cpumap;
   13.27  } dom0_pincpudomain_t;
   13.28  
   13.29  /* Get trace buffers machine base address */
    14.1 --- a/xen/include/public/xen.h	Wed May 11 08:31:59 2005 +0000
    14.2 +++ b/xen/include/public/xen.h	Wed May 11 13:04:09 2005 +0000
    14.3 @@ -473,6 +473,8 @@ typedef struct {
    14.4  /* For use in guest OSes. */
    14.5  extern shared_info_t *HYPERVISOR_shared_info;
    14.6  
    14.7 +typedef u64 cpumap_t;
    14.8 +
    14.9  #endif /* !__ASSEMBLY__ */
   14.10  
   14.11  #endif /* __XEN_PUBLIC_XEN_H__ */
    15.1 --- a/xen/include/xen/sched.h	Wed May 11 08:31:59 2005 +0000
    15.2 +++ b/xen/include/xen/sched.h	Wed May 11 13:04:09 2005 +0000
    15.3 @@ -58,6 +58,8 @@ int  init_event_channels(struct domain *
    15.4  void destroy_event_channels(struct domain *d);
    15.5  int  init_exec_domain_event_channels(struct exec_domain *ed);
    15.6  
    15.7 +
    15.8 +#define CPUMAP_RUNANYWHERE 0xFFFFFFFF
    15.9  struct exec_domain 
   15.10  {
   15.11      int              id;
   15.12 @@ -84,6 +86,8 @@ struct exec_domain
   15.13  
   15.14      atomic_t         pausecnt;
   15.15  
   15.16 +    cpumap_t  cpumap;               /* which cpus this domain can run on */
   15.17 +
   15.18      struct arch_exec_domain arch;
   15.19  };
   15.20