aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/libxc/xc_misc.c2
-rw-r--r--tools/libxc/xenctrl.h1
-rw-r--r--tools/python/xen/lowlevel/xc/xc.c69
-rw-r--r--tools/python/xen/xend/XendNode.py50
-rw-r--r--tools/xenmon/xenbaked.c2
-rw-r--r--tools/xenstat/libxenstat/src/xenstat.c2
-rw-r--r--tools/xentrace/xentrace.c2
-rw-r--r--tools/xm-test/tests/info/02_info_compiledata_pos.py4
-rw-r--r--xen/arch/ia64/xen/dom0_ops.c46
-rw-r--r--xen/arch/powerpc/sysctl.c6
-rw-r--r--xen/arch/x86/sysctl.c32
-rw-r--r--xen/include/public/sysctl.h20
-rw-r--r--xen/include/xen/cpumask.h9
13 files changed, 167 insertions, 78 deletions
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index 85f7921e77..13fa65ff18 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -60,6 +60,8 @@ int xc_physinfo(int xc_handle,
sysctl.cmd = XEN_SYSCTL_physinfo;
+ memcpy(&sysctl.u.physinfo, put_info, sizeof(*put_info));
+
if ( (ret = do_sysctl(xc_handle, &sysctl)) != 0 )
return ret;
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index 4f885cffb2..6ba6c8b034 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -473,6 +473,7 @@ int xc_readconsolering(int xc_handle,
int xc_send_debug_keys(int xc_handle, char *keys);
typedef xen_sysctl_physinfo_t xc_physinfo_t;
+typedef uint32_t xc_cpu_to_node_t;
int xc_physinfo(int xc_handle,
xc_physinfo_t *info);
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index afe5d19c27..021d7f2a7a 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -680,33 +680,62 @@ static PyObject *pyxc_pages_to_kib(XcObject *self, PyObject *args)
static PyObject *pyxc_physinfo(XcObject *self)
{
+#define MAX_CPU_ID 255
xc_physinfo_t info;
char cpu_cap[128], *p=cpu_cap, *q=cpu_cap;
- int i;
-
+ int i, j, max_cpu_id;
+ PyObject *ret_obj, *node_to_cpu_obj;
+ xc_cpu_to_node_t map[MAX_CPU_ID];
+
+ set_xen_guest_handle(info.cpu_to_node, map);
+ info.max_cpu_id = MAX_CPU_ID;
+
if ( xc_physinfo(self->xc_handle, &info) != 0 )
return pyxc_error_to_exception();
- *q=0;
- for(i=0;i<sizeof(info.hw_cap)/4;i++)
+ *q = 0;
+ for ( i = 0; i < sizeof(info.hw_cap)/4; i++ )
{
- p+=sprintf(p,"%08x:",info.hw_cap[i]);
- if(info.hw_cap[i])
- q=p;
+ p += sprintf(p, "%08x:", info.hw_cap[i]);
+ if ( info.hw_cap[i] )
+ q = p;
}
- if(q>cpu_cap)
- *(q-1)=0;
-
- return Py_BuildValue("{s:i,s:i,s:i,s:i,s:l,s:l,s:l,s:i,s:s}",
- "threads_per_core", info.threads_per_core,
- "cores_per_socket", info.cores_per_socket,
- "sockets_per_node", info.sockets_per_node,
- "nr_nodes", info.nr_nodes,
- "total_memory", pages_to_kib(info.total_pages),
- "free_memory", pages_to_kib(info.free_pages),
- "scrub_memory", pages_to_kib(info.scrub_pages),
- "cpu_khz", info.cpu_khz,
- "hw_caps", cpu_cap);
+ if ( q > cpu_cap )
+ *(q-1) = 0;
+
+ ret_obj = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:l,s:l,s:l,s:i,s:s}",
+ "nr_nodes", info.nr_nodes,
+ "max_cpu_id", info.max_cpu_id,
+ "threads_per_core", info.threads_per_core,
+ "cores_per_socket", info.cores_per_socket,
+ "sockets_per_node", info.sockets_per_node,
+ "total_memory", pages_to_kib(info.total_pages),
+ "free_memory", pages_to_kib(info.free_pages),
+ "scrub_memory", pages_to_kib(info.scrub_pages),
+ "cpu_khz", info.cpu_khz,
+ "hw_caps", cpu_cap);
+
+ max_cpu_id = info.max_cpu_id;
+ if ( max_cpu_id > MAX_CPU_ID )
+ max_cpu_id = MAX_CPU_ID;
+
+ /* Construct node-to-cpu lists. */
+ node_to_cpu_obj = PyList_New(0);
+
+ /* Make a list for each node. */
+ for ( i = 0; i < info.nr_nodes; i++ )
+ {
+ PyObject *cpus = PyList_New(0);
+ for ( j = 0; j <= max_cpu_id; j++ )
+ if ( i == map[j])
+ PyList_Append(cpus, PyInt_FromLong(j));
+ PyList_Append(node_to_cpu_obj, cpus);
+ }
+
+ PyDict_SetItemString(ret_obj, "node_to_cpu", node_to_cpu_obj);
+
+ return ret_obj;
+#undef MAX_CPU_ID
}
static PyObject *pyxc_xeninfo(XcObject *self)
diff --git a/tools/python/xen/xend/XendNode.py b/tools/python/xen/xend/XendNode.py
index b5fa1b7fb4..60189fbe7b 100644
--- a/tools/python/xen/xend/XendNode.py
+++ b/tools/python/xen/xend/XendNode.py
@@ -533,6 +533,54 @@ class XendNode:
['version', ver],
['machine', mch]]
+ def list_to_rangepairs(self,cmap):
+ cmap.sort()
+ pairs = []
+ x = y = 0
+ for i in range(0,len(cmap)):
+ try:
+ if ((cmap[y+1] - cmap[i]) > 1):
+ pairs.append((cmap[x],cmap[y]))
+ x = y = i+1
+ else:
+ y = y + 1
+ # if we go off the end, then just add x to y
+ except IndexError:
+ pairs.append((cmap[x],cmap[y]))
+
+ return pairs
+
+ def format_pairs(self,pairs):
+ if not pairs:
+ return "no cpus"
+ out = ""
+ for f,s in pairs:
+ if (f==s):
+ out += '%d'%f
+ else:
+ out += '%d-%d'%(f,s)
+ out += ','
+ # trim trailing ','
+ return out[:-1]
+
+ def list_to_strrange(self,list):
+ return self.format_pairs(self.list_to_rangepairs(list))
+
+ def format_node_to_cpu(self, pinfo):
+ str=''
+ whitespace=''
+ try:
+ node_to_cpu=pinfo['node_to_cpu']
+ for i in range(0, pinfo['nr_nodes']):
+ str+='%snode%d:%s\n' % (whitespace,
+ i,
+ self.list_to_strrange(node_to_cpu[i]))
+ whitespace='%25s' % ''
+ except:
+ str='none\n'
+ return str[:-1];
+
+
def physinfo(self):
info = self.xc.physinfo()
@@ -545,6 +593,7 @@ class XendNode:
# physinfo is in KiB, need it in MiB
info['total_memory'] = info['total_memory'] / 1024
info['free_memory'] = info['free_memory'] / 1024
+ info['node_to_cpu'] = self.format_node_to_cpu(info)
ITEM_ORDER = ['nr_cpus',
'nr_nodes',
@@ -555,6 +604,7 @@ class XendNode:
'hw_caps',
'total_memory',
'free_memory',
+ 'node_to_cpu'
]
return [[k, info[k]] for k in ITEM_ORDER]
diff --git a/tools/xenmon/xenbaked.c b/tools/xenmon/xenbaked.c
index 5908a6c1c9..1587016335 100644
--- a/tools/xenmon/xenbaked.c
+++ b/tools/xenmon/xenbaked.c
@@ -444,7 +444,7 @@ struct t_rec **init_rec_ptrs(struct t_buf **meta, unsigned int num)
*/
unsigned int get_num_cpus(void)
{
- xc_physinfo_t physinfo;
+ xc_physinfo_t physinfo = { 0 };
int xc_handle = xc_interface_open();
int ret;
diff --git a/tools/xenstat/libxenstat/src/xenstat.c b/tools/xenstat/libxenstat/src/xenstat.c
index 93d228c2f6..a109960c41 100644
--- a/tools/xenstat/libxenstat/src/xenstat.c
+++ b/tools/xenstat/libxenstat/src/xenstat.c
@@ -135,7 +135,7 @@ xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags)
{
#define DOMAIN_CHUNK_SIZE 256
xenstat_node *node;
- xc_physinfo_t physinfo;
+ xc_physinfo_t physinfo = { 0 };
xc_domaininfo_t domaininfo[DOMAIN_CHUNK_SIZE];
unsigned int new_domains;
unsigned int i;
diff --git a/tools/xentrace/xentrace.c b/tools/xentrace/xentrace.c
index 45fb99f7e7..ad06778592 100644
--- a/tools/xentrace/xentrace.c
+++ b/tools/xentrace/xentrace.c
@@ -256,7 +256,7 @@ struct t_rec **init_rec_ptrs(struct t_buf **meta, unsigned int num)
*/
unsigned int get_num_cpus(void)
{
- xc_physinfo_t physinfo;
+ xc_physinfo_t physinfo = { 0 };
int xc_handle = xc_interface_open();
int ret;
diff --git a/tools/xm-test/tests/info/02_info_compiledata_pos.py b/tools/xm-test/tests/info/02_info_compiledata_pos.py
index 189fce17cb..9430ecf62f 100644
--- a/tools/xm-test/tests/info/02_info_compiledata_pos.py
+++ b/tools/xm-test/tests/info/02_info_compiledata_pos.py
@@ -18,9 +18,7 @@ map = {}
for line in lines:
pieces = line.split(" : ", 1)
- if len(pieces) < 2:
- FAIL("Found invalid line: [%s]" % line)
- else:
+ if len(pieces) > 1:
map[pieces[0]] = pieces[1]
for field in ["cores_per_socket", "threads_per_core", "cpu_mhz",
diff --git a/xen/arch/ia64/xen/dom0_ops.c b/xen/arch/ia64/xen/dom0_ops.c
index 3651a55f8f..4a18fd57df 100644
--- a/xen/arch/ia64/xen/dom0_ops.c
+++ b/xen/arch/ia64/xen/dom0_ops.c
@@ -240,8 +240,7 @@ long arch_do_sysctl(xen_sysctl_t *op, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
{
#ifdef IA64_NUMA_PHYSINFO
int i;
- node_data_t *chunks;
- u64 *map, cpu_to_node_map[MAX_NUMNODES];
+ uint32_t *map, cpu_to_node_map[NR_CPUS];
#endif
xen_sysctl_physinfo_t *pi = &op->u.physinfo;
@@ -250,11 +249,9 @@ long arch_do_sysctl(xen_sysctl_t *op, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
cpus_weight(cpu_sibling_map[0]);
pi->cores_per_socket =
cpus_weight(cpu_core_map[0]) / pi->threads_per_core;
- pi->sockets_per_node =
- num_online_cpus() / cpus_weight(cpu_core_map[0]);
-#ifndef IA64_NUMA_PHYSINFO
- pi->nr_nodes = 1;
-#endif
+ pi->nr_nodes = num_online_nodes();
+ pi->sockets_per_node = num_online_cpus() /
+ (pi->nr_nodes * pi->cores_per_socket * pi->threads_per_core);
pi->total_pages = total_pages;
pi->free_pages = avail_domheap_pages();
pi->scrub_pages = avail_scrub_pages();
@@ -264,41 +261,6 @@ long arch_do_sysctl(xen_sysctl_t *op, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
ret = 0;
#ifdef IA64_NUMA_PHYSINFO
- /* fetch memory_chunk pointer from guest */
- get_xen_guest_handle(chunks, pi->memory_chunks);
-
- printk("chunks=%p, num_node_memblks=%u\n", chunks, num_node_memblks);
- /* if it is set, fill out memory chunk array */
- if (chunks != NULL) {
- if (num_node_memblks == 0) {
- /* Non-NUMA machine. Put pseudo-values. */
- node_data_t data;
- data.node_start_pfn = 0;
- data.node_spanned_pages = total_pages;
- data.node_id = 0;
- /* copy memory chunk structs to guest */
- if (copy_to_guest_offset(pi->memory_chunks, 0, &data, 1)) {
- ret = -EFAULT;
- break;
- }
- } else {
- for (i = 0; i < num_node_memblks && i < PUBLIC_MAXCHUNKS; i++) {
- node_data_t data;
- data.node_start_pfn = node_memblk[i].start_paddr >>
- PAGE_SHIFT;
- data.node_spanned_pages = node_memblk[i].size >> PAGE_SHIFT;
- data.node_id = node_memblk[i].nid;
- /* copy memory chunk structs to guest */
- if (copy_to_guest_offset(pi->memory_chunks, i, &data, 1)) {
- ret = -EFAULT;
- break;
- }
- }
- }
- }
- /* set number of notes */
- pi->nr_nodes = num_online_nodes();
-
/* fetch cpu_to_node pointer from guest */
get_xen_guest_handle(map, pi->cpu_to_node);
diff --git a/xen/arch/powerpc/sysctl.c b/xen/arch/powerpc/sysctl.c
index 3b25b5f89b..5f9a5432c8 100644
--- a/xen/arch/powerpc/sysctl.c
+++ b/xen/arch/powerpc/sysctl.c
@@ -45,10 +45,10 @@ long arch_do_sysctl(struct xen_sysctl *sysctl,
cpus_weight(cpu_sibling_map[0]);
pi->cores_per_socket =
cpus_weight(cpu_core_map[0]) / pi->threads_per_core;
- pi->sockets_per_node =
- num_online_cpus() / cpus_weight(cpu_core_map[0]);
+ pi->sockets_per_node = num_online_cpus() /
+ (num_online_nodes() * pi->cores_per_socket * pi->threads_per_core);
- pi->nr_nodes = 1;
+ pi->nr_nodes = num_online_nodes();
pi->total_pages = total_pages;
pi->free_pages = avail_domheap_pages();
pi->cpu_khz = cpu_khz;
diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c
index fe4c049908..ff7018a930 100644
--- a/xen/arch/x86/sysctl.c
+++ b/xen/arch/x86/sysctl.c
@@ -23,6 +23,10 @@
#include <asm/hvm/hvm.h>
#include <asm/hvm/support.h>
#include <asm/processor.h>
+#include <asm/numa.h>
+#include <xen/nodemask.h>
+
+#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0)
long arch_do_sysctl(
struct xen_sysctl *sysctl, XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl)
@@ -34,25 +38,41 @@ long arch_do_sysctl(
case XEN_SYSCTL_physinfo:
{
+ uint32_t i, max_array_ent;
+
xen_sysctl_physinfo_t *pi = &sysctl->u.physinfo;
pi->threads_per_core =
cpus_weight(cpu_sibling_map[0]);
pi->cores_per_socket =
cpus_weight(cpu_core_map[0]) / pi->threads_per_core;
- pi->sockets_per_node =
- num_online_cpus() / cpus_weight(cpu_core_map[0]);
+ pi->nr_nodes = num_online_nodes();
+ pi->sockets_per_node = num_online_cpus() /
+ (pi->nr_nodes * pi->cores_per_socket * pi->threads_per_core);
- pi->nr_nodes = 1;
pi->total_pages = total_pages;
pi->free_pages = avail_domheap_pages();
pi->scrub_pages = avail_scrub_pages();
pi->cpu_khz = cpu_khz;
memset(pi->hw_cap, 0, sizeof(pi->hw_cap));
memcpy(pi->hw_cap, boot_cpu_data.x86_capability, NCAPINTS*4);
- ret = 0;
- if ( copy_to_guest(u_sysctl, sysctl, 1) )
- ret = -EFAULT;
+
+ max_array_ent = pi->max_cpu_id;
+ pi->max_cpu_id = last_cpu(cpu_online_map);
+ max_array_ent = min_t(uint32_t, max_array_ent, pi->max_cpu_id);
+
+ ret = -EFAULT;
+ if ( !guest_handle_is_null(pi->cpu_to_node) )
+ {
+ for ( i = 0; i <= max_array_ent; i++ )
+ {
+ uint32_t node = cpu_online(i) ? cpu_to_node(i) : ~0u;
+ if ( copy_to_guest_offset(pi->cpu_to_node, i, &node, 1) )
+ break;
+ }
+ }
+
+ ret = copy_to_guest(u_sysctl, sysctl, 1) ? -EFAULT : 0;
}
break;
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index d51052aefe..06eb0e78c5 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -34,7 +34,7 @@
#include "xen.h"
#include "domctl.h"
-#define XEN_SYSCTL_INTERFACE_VERSION 0x00000003
+#define XEN_SYSCTL_INTERFACE_VERSION 0x00000004
/*
* Read console content from Xen buffer ring.
@@ -76,6 +76,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_sysctl_tbuf_op_t);
*/
#define XEN_SYSCTL_physinfo 3
struct xen_sysctl_physinfo {
+ /* IN variables. */
uint32_t threads_per_core;
uint32_t cores_per_socket;
uint32_t sockets_per_node;
@@ -85,6 +86,23 @@ struct xen_sysctl_physinfo {
uint64_aligned_t free_pages;
uint64_aligned_t scrub_pages;
uint32_t hw_cap[8];
+
+ /* IN/OUT variables. */
+ /*
+ * IN: maximum addressable entry in the caller-provided cpu_to_node array.
+ * OUT: largest cpu identifier in the system.
+ * If OUT is greater than IN then the cpu_to_node array is truncated!
+ */
+ uint32_t max_cpu_id;
+ /*
+ * If not NULL, this array is filled with node identifier for each cpu.
+ * If a cpu has no node information (e.g., cpu not present) then the
+ * sentinel value ~0u is written.
+ * The size of this array is specified by the caller in @max_cpu_id.
+ * If the actual @max_cpu_id is smaller than the array then the trailing
+ * elements of the array will not be written by the sysctl.
+ */
+ XEN_GUEST_HANDLE_64(uint32_t) cpu_to_node;
};
typedef struct xen_sysctl_physinfo xen_sysctl_physinfo_t;
DEFINE_XEN_GUEST_HANDLE(xen_sysctl_physinfo_t);
diff --git a/xen/include/xen/cpumask.h b/xen/include/xen/cpumask.h
index d9296201cb..7e24f84876 100644
--- a/xen/include/xen/cpumask.h
+++ b/xen/include/xen/cpumask.h
@@ -222,6 +222,15 @@ static inline int __next_cpu(int n, const cpumask_t *srcp, int nbits)
return min_t(int, nbits, find_next_bit(srcp->bits, nbits, n+1));
}
+#define last_cpu(src) __last_cpu(&(src), NR_CPUS)
+static inline int __last_cpu(const cpumask_t *srcp, int nbits)
+{
+ int cpu, pcpu = NR_CPUS;
+ for (cpu = first_cpu(*srcp); cpu < NR_CPUS; cpu = next_cpu(cpu, *srcp))
+ pcpu = cpu;
+ return pcpu;
+}
+
#define cpumask_of_cpu(cpu) \
({ \
typeof(_unused_cpumask_arg_) m; \