diff options
-rw-r--r-- | tools/libxc/xc_misc.c | 2 | ||||
-rw-r--r-- | tools/libxc/xenctrl.h | 1 | ||||
-rw-r--r-- | tools/python/xen/lowlevel/xc/xc.c | 69 | ||||
-rw-r--r-- | tools/python/xen/xend/XendNode.py | 50 | ||||
-rw-r--r-- | tools/xenmon/xenbaked.c | 2 | ||||
-rw-r--r-- | tools/xenstat/libxenstat/src/xenstat.c | 2 | ||||
-rw-r--r-- | tools/xentrace/xentrace.c | 2 | ||||
-rw-r--r-- | tools/xm-test/tests/info/02_info_compiledata_pos.py | 4 | ||||
-rw-r--r-- | xen/arch/ia64/xen/dom0_ops.c | 46 | ||||
-rw-r--r-- | xen/arch/powerpc/sysctl.c | 6 | ||||
-rw-r--r-- | xen/arch/x86/sysctl.c | 32 | ||||
-rw-r--r-- | xen/include/public/sysctl.h | 20 | ||||
-rw-r--r-- | xen/include/xen/cpumask.h | 9 |
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; \ |