mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
This patch adds a new domain config option, 'cpus' which is a list of
CPUs a domains' vcpus can use. The older 'cpu' config option is prepended to the list of cpus to use and will keep the behavior of pinning VCPU0. The cpus option supports ranges and negation, so: cpus = "0-3,5,^1" produces -> [0,2,3,5] The list is circular, so in a domain with the following config: vcpus = 4 cpus = "0,3,7" # Use any of 0, 3, 7 for this domain. would see vcpus 0-3 pinned to cpus 0,3,7,0 respectively. Also, the pin operation is moved before the memory reservation as vcpu to cpu mapping will be helpful for future NUMA work when trying to allocate pages close to the physical cpus being used. An update to the display of cpumap was needed to normalize the cpumap values to the range of possible cpus. I've also included some text for the xmdomain.cfg(5) man page. Signed-off-by: Ryan Harper <ryanh@us.ibm.com>
This commit is contained in:
1 parent
895f3158e2
commit
9b08b0371d
9 files changed
+90
-17
No files matched your search
@@ -286,6 +286,7 @@ def parseConfig(config):
|
||||
result[e[0]] = get_cfg(e[0], e[1])
|
||||
|
||||
result['cpu'] = get_cfg('cpu', int)
|
||||
result['cpus'] = get_cfg('cpus', str)
|
||||
result['image'] = get_cfg('image')
|
||||
|
||||
try:
|
||||
@@ -299,6 +300,43 @@ def parseConfig(config):
|
||||
'Invalid configuration setting: vcpus = %s: %s' %
|
||||
(sxp.child_value(result['image'], 'vcpus', 1), str(exn)))
|
||||
|
||||
try:
|
||||
# support legacy config files with 'cpu' parameter
|
||||
# NB: prepending to list to support previous behavior
|
||||
# where 'cpu' parameter pinned VCPU0.
|
||||
if result['cpu']:
|
||||
if result['cpus']:
|
||||
result['cpus'] = "%s,%s" % (str(result['cpu']), result['cpus'])
|
||||
else:
|
||||
result['cpus'] = str(result['cpu'])
|
||||
|
||||
# convert 'cpus' string to list of ints
|
||||
# 'cpus' supports a list of ranges (0-3), seperated by
|
||||
# commas, and negation, (^1).
|
||||
# Precedence is settled by order of the string:
|
||||
# "0-3,^1" -> [0,2,3]
|
||||
# "0-3,^1,1" -> [0,1,2,3]
|
||||
if result['cpus']:
|
||||
cpus = []
|
||||
for c in result['cpus'].split(','):
|
||||
if c.find('-') != -1:
|
||||
(x,y) = c.split('-')
|
||||
for i in range(int(x),int(y)+1):
|
||||
cpus.append(int(i))
|
||||
else:
|
||||
# remove this element from the list
|
||||
if c[0] == '^':
|
||||
cpus = [x for x in cpus if x != int(c[1])]
|
||||
else:
|
||||
cpus.append(int(c))
|
||||
|
||||
result['cpus'] = cpus
|
||||
|
||||
except ValueError, exn:
|
||||
raise VmError(
|
||||
'Invalid configuration setting: cpus = %s: %s' %
|
||||
(result['cpus'], exn))
|
||||
|
||||
result['backend'] = []
|
||||
for c in sxp.children(config, 'backend'):
|
||||
result['backend'].append(sxp.name(sxp.child0(c)))
|
||||
@@ -486,6 +524,7 @@ class XendDomainInfo:
|
||||
defaultInfo('on_reboot', lambda: "restart")
|
||||
defaultInfo('on_crash', lambda: "restart")
|
||||
defaultInfo('cpu', lambda: None)
|
||||
defaultInfo('cpus', lambda: [])
|
||||
defaultInfo('cpu_weight', lambda: 1.0)
|
||||
|
||||
# some domains don't have a config file (e.g. dom0 )
|
||||
@@ -1130,9 +1169,15 @@ class XendDomainInfo:
|
||||
xc.domain_setmaxmem(self.domid, m)
|
||||
xc.domain_memory_increase_reservation(self.domid, m, 0, 0)
|
||||
|
||||
cpu = self.info['cpu']
|
||||
if cpu is not None and cpu != -1:
|
||||
xc.domain_pincpu(self.domid, 0, 1 << cpu)
|
||||
# repin domain vcpus if a restricted cpus list is provided
|
||||
# this is done prior to memory allocation to aide in memory
|
||||
# distribution for NUMA systems.
|
||||
cpus = self.info['cpus']
|
||||
if cpus is not None and len(cpus) > 0:
|
||||
for v in range(0, self.info['max_vcpu_id']+1):
|
||||
# pincpu takes a list of ints
|
||||
cpu = [ int( cpus[v % len(cpus)] ) ]
|
||||
xc.domain_pincpu(self.domid, v, cpu)
|
||||
|
||||
self.createChannels()
|
||||
|
||||
|
||||
@@ -154,7 +154,11 @@ gopts.var('maxmem', val='MEMORY',
|
||||
|
||||
gopts.var('cpu', val='CPU',
|
||||
fn=set_int, default=None,
|
||||
use="CPU to run the domain on.")
|
||||
use="CPU to run the VCPU0 on.")
|
||||
|
||||
gopts.var('cpus', val='CPUS',
|
||||
fn=set_int, default=None,
|
||||
use="CPUS to run the domain on.")
|
||||
|
||||
gopts.var('lapic', val='LAPIC',
|
||||
fn=set_int, default=0,
|
||||
@@ -572,6 +576,8 @@ def make_config(vals):
|
||||
|
||||
if vals.cpu is not None:
|
||||
config.append(['cpu', vals.cpu])
|
||||
if vals.cpus is not None:
|
||||
config.append(['cpus', vals.cpus])
|
||||
if vals.cpu_weight is not None:
|
||||
config.append(['cpu_weight', vals.cpu_weight])
|
||||
if vals.blkif:
|
||||
|
||||
@@ -459,7 +459,9 @@ def xm_vcpu_list(args):
|
||||
for x in server.xend_node()[1:]:
|
||||
if len(x) > 1 and x[0] == 'nr_cpus':
|
||||
nr_cpus = int(x[1])
|
||||
cpumap = filter(lambda x: x < nr_cpus, cpumap)
|
||||
# normalize cpumap by modulus nr_cpus, and drop duplicates
|
||||
cpumap = dict.fromkeys(
|
||||
map(lambda x: x % nr_cpus, cpumap)).keys()
|
||||
if len(cpumap) == nr_cpus:
|
||||
return "any cpu"
|
||||
break
|
||||
|
||||