* [PATCH v8 0/5] Display IO topology when PXM data is available (plus some cleanup)
@ 2015-05-06 18:14 Boris Ostrovsky
2015-05-06 18:14 ` [PATCH v8 1/5] sysctl: Add sysctl interface for querying PCI topology Boris Ostrovsky
` (4 more replies)
0 siblings, 5 replies; 13+ messages in thread
From: Boris Ostrovsky @ 2015-05-06 18:14 UTC (permalink / raw)
To: ian.jackson, ian.campbell, wei.liu2, stefano.stabellini, dgdegra,
jbeulich, andrew.cooper3, keir
Cc: elena.ufimtseva, dario.faggioli, boris.ostrovsky, xen-devel
Changes in v8:
* Change sysctl's pcitopo interface such that if device is not found then XEN_INVALID_DEV
is returned in nodes array. Changes to patches 1 and 5.
* Get rid of first_dev and use num_devs in xen_sysctl_pcitopoinfo as an OUT argument
that reports how many devices have been processed. Changes to patches 1 and 5.
-- Add set_xen_guest_handle_offset macro to help toolstack handle this (new patch 4)
* Replace LOGEV with LOGE (patches 2, 3, 5)
Changes in v7:
* Allow one of arguments to NUMA info sysctls to be NULL, in which case only
the non-NULL buffer will be filled in by hypervisor (patches 1 and 4)
* Properly handle -ENODEVS in PCI topology sysctl (patch 2)
* Error handling changes in patch 5
Changes in v6:
* PCI topology interface changes: no continuations, userspace will be dealing
with "unfinished" sysctl (patches 2 and 5)
* Unknown device will cause ENODEV in sysctl
* No NULL tests in libxc
* Loop control initialization fix (similar to commit 26da081ac91a)
* Other minor changes (see per-patch notes)
Changes in v5:
* Make CPU topology and NUMA info sysctls behave more like XEN_DOMCTL_get_vcpu_msrs
when passed NULL buffers. This required toolstack changes as well
* Don't use 8-bit data types in interfaces
* Fold interface version update into patch#3
Changes in v4:
* Split cputopology and NUMA info changes into separate patches
* Added patch#1 (partly because patch#4 needs to know when when distance is invalid,
i.e. NUMA_NO_DISTANCE)
* Split sysctl version update into a separate patch
* Other changes are listed in each patch
* NOTE: I did not test python's xc changes since I don't think I know how.
Changes in v3:
* Added patch #1 to more consistently define nodes as a u8 and properly
use NUMA_NO_NODE.
* Make changes to xen_sysctl_numainfo, similar to those made to
xen_sysctl_topologyinfo. (Q: I kept both sets of changes in the same
patch #3 to avoid bumping interface version twice. Perhaps it's better
to split it into two?)
* Instead of copying data for each loop index allocate a buffer and copy
once for all three queries in sysctl.c.
* Move hypercall buffer management from libxl to libxc (as requested by
Dario, patches #5 and #6).
* Report topology info for offlined CPUs as well
* Added LIBXL_HAVE_PCITOPO macro
Changes in v2:
* Split topology sysctls into two --- one for CPU topology and the other
for devices
* Avoid long loops in the hypervisor by using continuations. (I am not
particularly happy about using first_dev in the interface, suggestions
for a better interface would be appreciated)
* Use proper libxl conventions for interfaces
* Avoid hypervisor stack corruption when copying PXM data from guest
A few patches that add interface for querying hypervisor about device
topology and allow 'xl info -n' display this information if PXM object
is provided by ACPI.
This series also makes some optimizations and cleanup of current CPU
topology and NUMA sysctl queries.
Boris Ostrovsky (5):
sysctl: Add sysctl interface for querying PCI topology
libxl/libxc: Move libxl_get_cpu_topology()'s hypercall buffer
management to libxc
libxl/libxc: Move libxl_get_numainfo()'s hypercall buffer management
to libxc
libxc: Provide set_xen_guest_handle_offset macro
libxl: Add interface for querying hypervisor about PCI topology
tools/libxc/include/xenctrl.h | 23 +++++--
tools/libxc/xc_misc.c | 92 +++++++++++++++++++++----
tools/libxl/libxl.c | 129 +++++++++++++++++++----------------
tools/libxl/libxl.h | 12 +++
tools/libxl/libxl_freebsd.c | 12 +++
tools/libxl/libxl_internal.h | 5 ++
tools/libxl/libxl_linux.c | 70 +++++++++++++++++++
tools/libxl/libxl_netbsd.c | 12 +++
tools/libxl/libxl_types.idl | 7 ++
tools/libxl/libxl_utils.c | 8 ++
tools/libxl/xl_cmdimpl.c | 40 +++++++++--
tools/misc/xenpm.c | 51 ++++++--------
tools/python/xen/lowlevel/xc/xc.c | 58 ++++++----------
xen/common/sysctl.c | 55 +++++++++++++++
xen/include/public/sysctl.h | 27 +++++++
xen/xsm/flask/hooks.c | 1 +
xen/xsm/flask/policy/access_vectors | 1 +
17 files changed, 453 insertions(+), 150 deletions(-)
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v8 1/5] sysctl: Add sysctl interface for querying PCI topology
2015-05-06 18:14 [PATCH v8 0/5] Display IO topology when PXM data is available (plus some cleanup) Boris Ostrovsky
@ 2015-05-06 18:14 ` Boris Ostrovsky
2015-05-07 13:52 ` Andrew Cooper
2015-05-06 18:14 ` [PATCH v8 2/5] libxl/libxc: Move libxl_get_cpu_topology()'s hypercall buffer management to libxc Boris Ostrovsky
` (3 subsequent siblings)
4 siblings, 1 reply; 13+ messages in thread
From: Boris Ostrovsky @ 2015-05-06 18:14 UTC (permalink / raw)
To: ian.jackson, ian.campbell, wei.liu2, stefano.stabellini, dgdegra,
jbeulich, andrew.cooper3, keir
Cc: elena.ufimtseva, dario.faggioli, boris.ostrovsky, xen-devel
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
---
Changes in v8
* Report XEN_INVALID_DEV for unknown devices
* Get rid of first_dev and use num_devs as an OUT argument that reports
how many devices have been processed
* Update comments in sysctl.h
* Drop changes to xsm-flask.txt
xen/common/sysctl.c | 55 +++++++++++++++++++++++++++++++++++
xen/include/public/sysctl.h | 27 +++++++++++++++++
xen/xsm/flask/hooks.c | 1 +
xen/xsm/flask/policy/access_vectors | 1 +
4 files changed, 84 insertions(+), 0 deletions(-)
diff --git a/xen/common/sysctl.c b/xen/common/sysctl.c
index 7361064..2a48e45 100644
--- a/xen/common/sysctl.c
+++ b/xen/common/sysctl.c
@@ -412,6 +412,61 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
break;
#endif
+#ifdef HAS_PCI
+ case XEN_SYSCTL_pcitopoinfo:
+ {
+ xen_sysctl_pcitopoinfo_t *ti = &op->u.pcitopoinfo;
+ unsigned i = 0;
+
+ if ( guest_handle_is_null(ti->devs) ||
+ guest_handle_is_null(ti->nodes) )
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ while ( i < ti->num_devs )
+ {
+ physdev_pci_device_t dev;
+ uint32_t node;
+ struct pci_dev *pdev;
+
+ if ( copy_from_guest_offset(&dev, ti->devs, i, 1) )
+ {
+ ret = -EFAULT;
+ break;
+ }
+
+ spin_lock(&pcidevs_lock);
+ pdev = pci_get_pdev(dev.seg, dev.bus, dev.devfn);
+ if ( !pdev )
+ node = XEN_INVALID_DEV;
+ else if ( pdev->node == NUMA_NO_NODE )
+ node = XEN_INVALID_NODE_ID;
+ else
+ node = pdev->node;
+ spin_unlock(&pcidevs_lock);
+
+ if ( copy_to_guest_offset(ti->nodes, i, &node, 1) )
+ {
+ ret = -EFAULT;
+ break;
+ }
+
+ if ( (++i > 0x3f) && hypercall_preempt_check() )
+ break;
+ }
+
+ if ( !ret && (ti->num_devs != i) )
+ {
+ ti->num_devs = i;
+ if ( __copy_field_to_guest(u_sysctl, op, u.pcitopoinfo.num_devs) )
+ ret = -EFAULT;
+ }
+ }
+ break;
+#endif
+
default:
ret = arch_do_sysctl(op, u_sysctl);
copyback = 0;
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index 021d505..fbe3c6e 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -33,6 +33,7 @@
#include "xen.h"
#include "domctl.h"
+#include "physdev.h"
#define XEN_SYSCTL_INTERFACE_VERSION 0x0000000C
@@ -669,6 +670,30 @@ struct xen_sysctl_psr_cmt_op {
typedef struct xen_sysctl_psr_cmt_op xen_sysctl_psr_cmt_op_t;
DEFINE_XEN_GUEST_HANDLE(xen_sysctl_psr_cmt_op_t);
+/* XEN_SYSCTL_pcitopoinfo */
+#define XEN_INVALID_DEV (XEN_INVALID_NODE_ID - 1)
+struct xen_sysctl_pcitopoinfo {
+ /*
+ * IN: Number of elements in 'pcitopo' and 'nodes' arrays.
+ * OUT: Number of processed elements of those arrays.
+ */
+ uint32_t num_devs;
+
+ /* IN: list of devices for which node IDs are requested. */
+ XEN_GUEST_HANDLE_64(physdev_pci_device_t) devs;
+
+ /*
+ * OUT: node identifier for each device.
+ * If information for a particular device is not avalable then
+ * corresponding entry will be set to XEN_INVALID_NODE_ID. If
+ * device is not known to the hypervisor then XEN_INVALID_DEV
+ * will be provided.
+ */
+ XEN_GUEST_HANDLE_64(uint32) nodes;
+};
+typedef struct xen_sysctl_pcitopoinfo xen_sysctl_pcitopoinfo_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_pcitopoinfo_t);
+
struct xen_sysctl {
uint32_t cmd;
#define XEN_SYSCTL_readconsole 1
@@ -691,12 +716,14 @@ struct xen_sysctl {
#define XEN_SYSCTL_scheduler_op 19
#define XEN_SYSCTL_coverage_op 20
#define XEN_SYSCTL_psr_cmt_op 21
+#define XEN_SYSCTL_pcitopoinfo 22
uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
union {
struct xen_sysctl_readconsole readconsole;
struct xen_sysctl_tbuf_op tbuf_op;
struct xen_sysctl_physinfo physinfo;
struct xen_sysctl_cputopoinfo cputopoinfo;
+ struct xen_sysctl_pcitopoinfo pcitopoinfo;
struct xen_sysctl_numainfo numainfo;
struct xen_sysctl_sched_id sched_id;
struct xen_sysctl_perfc_op perfc_op;
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index 6215001..32763da 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -783,6 +783,7 @@ static int flask_sysctl(int cmd)
case XEN_SYSCTL_physinfo:
case XEN_SYSCTL_cputopoinfo:
case XEN_SYSCTL_numainfo:
+ case XEN_SYSCTL_pcitopoinfo:
return domain_has_xen(current->domain, XEN__PHYSINFO);
case XEN_SYSCTL_psr_cmt_op:
diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors
index af4a6ae..356ca3b 100644
--- a/xen/xsm/flask/policy/access_vectors
+++ b/xen/xsm/flask/policy/access_vectors
@@ -28,6 +28,7 @@ class xen
# XENPF_microcode_update
microcode
# XEN_SYSCTL_physinfo, XEN_SYSCTL_cputopoinfo, XEN_SYSCTL_numainfo
+# XEN_SYSCTL_pcitopoinfo
physinfo
# XENPF_platform_quirk
quirk
--
1.7.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v8 2/5] libxl/libxc: Move libxl_get_cpu_topology()'s hypercall buffer management to libxc
2015-05-06 18:14 [PATCH v8 0/5] Display IO topology when PXM data is available (plus some cleanup) Boris Ostrovsky
2015-05-06 18:14 ` [PATCH v8 1/5] sysctl: Add sysctl interface for querying PCI topology Boris Ostrovsky
@ 2015-05-06 18:14 ` Boris Ostrovsky
2015-05-06 18:15 ` [PATCH v8 3/5] libxl/libxc: Move libxl_get_numainfo()'s " Boris Ostrovsky
` (2 subsequent siblings)
4 siblings, 0 replies; 13+ messages in thread
From: Boris Ostrovsky @ 2015-05-06 18:14 UTC (permalink / raw)
To: ian.jackson, ian.campbell, wei.liu2, stefano.stabellini, dgdegra,
jbeulich, andrew.cooper3, keir
Cc: elena.ufimtseva, dario.faggioli, boris.ostrovsky, xen-devel
xc_cputopoinfo() is not expected to be used on a hot path and therefore
hypercall buffer management can be pushed into libxc. This will simplify
life for callers.
Also update error reporting macros.
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
Changes in v8:
* Replace LOGEV with LOGE
tools/libxc/include/xenctrl.h | 5 ++-
tools/libxc/xc_misc.c | 23 +++++++++++-----
tools/libxl/libxl.c | 37 ++++++++------------------
tools/misc/xenpm.c | 51 ++++++++++++++++---------------------
tools/python/xen/lowlevel/xc/xc.c | 20 ++++++--------
5 files changed, 61 insertions(+), 75 deletions(-)
diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 6994c51..c5a74f4 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -1229,7 +1229,7 @@ int xc_readconsolering(xc_interface *xch,
int xc_send_debug_keys(xc_interface *xch, char *keys);
typedef xen_sysctl_physinfo_t xc_physinfo_t;
-typedef xen_sysctl_cputopoinfo_t xc_cputopoinfo_t;
+typedef xen_sysctl_cputopo_t xc_cputopo_t;
typedef xen_sysctl_numainfo_t xc_numainfo_t;
typedef uint32_t xc_cpu_to_node_t;
@@ -1240,7 +1240,8 @@ typedef uint64_t xc_node_to_memfree_t;
typedef uint32_t xc_node_to_node_dist_t;
int xc_physinfo(xc_interface *xch, xc_physinfo_t *info);
-int xc_cputopoinfo(xc_interface *xch, xc_cputopoinfo_t *info);
+int xc_cputopoinfo(xc_interface *xch, unsigned *max_cpus,
+ xc_cputopo_t *cputopo);
int xc_numainfo(xc_interface *xch, xc_numainfo_t *info);
int xc_sched_id(xc_interface *xch,
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index be68291..630a86c 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -177,22 +177,31 @@ int xc_physinfo(xc_interface *xch,
return 0;
}
-int xc_cputopoinfo(xc_interface *xch,
- xc_cputopoinfo_t *put_info)
+int xc_cputopoinfo(xc_interface *xch, unsigned *max_cpus,
+ xc_cputopo_t *cputopo)
{
int ret;
DECLARE_SYSCTL;
+ DECLARE_HYPERCALL_BOUNCE(cputopo, *max_cpus * sizeof(*cputopo),
+ XC_HYPERCALL_BUFFER_BOUNCE_OUT);
- sysctl.cmd = XEN_SYSCTL_cputopoinfo;
+ if ( (ret = xc_hypercall_bounce_pre(xch, cputopo)) )
+ goto out;
- memcpy(&sysctl.u.cputopoinfo, put_info, sizeof(*put_info));
+ sysctl.u.cputopoinfo.num_cpus = *max_cpus;
+ set_xen_guest_handle(sysctl.u.cputopoinfo.cputopo, cputopo);
+
+ sysctl.cmd = XEN_SYSCTL_cputopoinfo;
if ( (ret = do_sysctl(xch, &sysctl)) != 0 )
- return ret;
+ goto out;
- memcpy(put_info, &sysctl.u.cputopoinfo, sizeof(*put_info));
+ *max_cpus = sysctl.u.cputopoinfo.num_cpus;
- return 0;
+out:
+ xc_hypercall_bounce_post(xch, cputopo);
+
+ return ret;
}
int xc_numainfo(xc_interface *xch,
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 516713e..5f2fcff 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -5102,37 +5102,28 @@ int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo)
libxl_cputopology *libxl_get_cpu_topology(libxl_ctx *ctx, int *nb_cpu_out)
{
GC_INIT(ctx);
- xc_cputopoinfo_t tinfo;
- DECLARE_HYPERCALL_BUFFER(xen_sysctl_cputopo_t, cputopo);
+ xc_cputopo_t *cputopo;
libxl_cputopology *ret = NULL;
int i;
+ unsigned num_cpus;
- /* Setting buffer to NULL makes the hypercall return number of CPUs */
- set_xen_guest_handle(tinfo.cputopo, HYPERCALL_BUFFER_NULL);
- if (xc_cputopoinfo(ctx->xch, &tinfo) != 0)
+ /* Setting buffer to NULL makes the call return number of CPUs */
+ if (xc_cputopoinfo(ctx->xch, &num_cpus, NULL))
{
- LIBXL__LOG(ctx, XTL_ERROR, "Unable to determine number of CPUS");
- ret = NULL;
+ LOGE(ERROR, "Unable to determine number of CPUS");
goto out;
}
- cputopo = xc_hypercall_buffer_alloc(ctx->xch, cputopo,
- sizeof(*cputopo) * tinfo.num_cpus);
- if (cputopo == NULL) {
- LIBXL__LOG_ERRNOVAL(ctx, XTL_ERROR, ENOMEM,
- "Unable to allocate hypercall arguments");
- goto fail;
- }
- set_xen_guest_handle(tinfo.cputopo, cputopo);
+ cputopo = libxl__zalloc(gc, sizeof(*cputopo) * num_cpus);
- if (xc_cputopoinfo(ctx->xch, &tinfo) != 0) {
- LIBXL__LOG_ERRNO(ctx, XTL_ERROR, "CPU topology info hypercall failed");
- goto fail;
+ if (xc_cputopoinfo(ctx->xch, &num_cpus, cputopo)) {
+ LOGE(ERROR, "CPU topology info hypercall failed");
+ goto out;
}
- ret = libxl__zalloc(NOGC, sizeof(libxl_cputopology) * tinfo.num_cpus);
+ ret = libxl__zalloc(NOGC, sizeof(libxl_cputopology) * num_cpus);
- for (i = 0; i < tinfo.num_cpus; i++) {
+ for (i = 0; i < num_cpus; i++) {
#define V(map, i, invalid) ( cputopo[i].map == invalid) ? \
LIBXL_CPUTOPOLOGY_INVALID_ENTRY : cputopo[i].map
ret[i].core = V(core, i, XEN_INVALID_CORE_ID);
@@ -5141,11 +5132,7 @@ libxl_cputopology *libxl_get_cpu_topology(libxl_ctx *ctx, int *nb_cpu_out)
#undef V
}
-fail:
- xc_hypercall_buffer_free(ctx->xch, cputopo);
-
- if (ret)
- *nb_cpu_out = tinfo.num_cpus;
+ *nb_cpu_out = num_cpus;
out:
GC_FREE;
diff --git a/tools/misc/xenpm.c b/tools/misc/xenpm.c
index a5d07de..24ee6ef 100644
--- a/tools/misc/xenpm.c
+++ b/tools/misc/xenpm.c
@@ -355,20 +355,17 @@ static void signal_int_handler(int signo)
int i, j, k;
struct timeval tv;
int cx_cap = 0, px_cap = 0;
- DECLARE_HYPERCALL_BUFFER(xen_sysctl_cputopo_t, cputopo);
- xc_cputopoinfo_t info = { 0 };
+ xc_cputopo_t *cputopo;
+ unsigned max_cpus;
- set_xen_guest_handle(info.cputopo, HYPERCALL_BUFFER_NULL);
- if ( xc_cputopoinfo(xc_handle, &info) != 0 )
+ if ( xc_cputopoinfo(xc_handle, &max_cpus, NULL) != 0 )
{
fprintf(stderr, "failed to discover number of CPUs: %s\n",
strerror(errno));
goto out;
}
- cputopo = xc_hypercall_buffer_alloc(xc_handle, cputopo,
- sizeof(*cputopo) * info.num_cpus);
-
+ cputopo = calloc(max_cpus, sizeof(*cputopo));
if ( cputopo == NULL )
{
fprintf(stderr, "failed to allocate hypercall buffers\n");
@@ -453,28 +450,26 @@ static void signal_int_handler(int signo)
printf(" Avg freq\t%d\tKHz\n", avgfreq[i]);
}
- set_xen_guest_handle(info.cputopo, cputopo);
-
- if ( cx_cap && !xc_cputopoinfo(xc_handle, &info) )
+ if ( cx_cap && !xc_cputopoinfo(xc_handle, &max_cpus, cputopo) )
{
uint32_t socket_ids[MAX_NR_CPU];
uint32_t core_ids[MAX_NR_CPU];
uint32_t socket_nr = 0;
uint32_t core_nr = 0;
- if ( info.num_cpus > MAX_NR_CPU )
- info.num_cpus = MAX_NR_CPU;
+ if ( max_cpus > MAX_NR_CPU )
+ max_cpus = MAX_NR_CPU;
/* check validity */
- for ( i = 0; i < info.num_cpus; i++ )
+ for ( i = 0; i < max_cpus; i++ )
{
if ( cputopo[i].core == XEN_INVALID_CORE_ID ||
cputopo[i].socket == XEN_INVALID_SOCKET_ID )
break;
}
- if ( i >= info.num_cpus )
+ if ( i >= max_cpus )
{
/* find socket nr & core nr per socket */
- for ( i = 0; i < info.num_cpus; i++ )
+ for ( i = 0; i < max_cpus; i++ )
{
for ( j = 0; j < socket_nr; j++ )
if ( cputopo[i].socket == socket_ids[j] )
@@ -501,7 +496,7 @@ static void signal_int_handler(int signo)
unsigned int n;
uint64_t res;
- for ( j = 0; j < info.num_cpus; j++ )
+ for ( j = 0; j < max_cpus; j++ )
{
if ( cputopo[j].socket == socket_ids[i] )
break;
@@ -520,7 +515,7 @@ static void signal_int_handler(int signo)
}
for ( k = 0; k < core_nr; k++ )
{
- for ( j = 0; j < info.num_cpus; j++ )
+ for ( j = 0; j < max_cpus; j++ )
{
if ( cputopo[j].socket == socket_ids[i] &&
cputopo[j].core == core_ids[k] )
@@ -558,7 +553,7 @@ static void signal_int_handler(int signo)
free(sum);
free(avgfreq);
out:
- xc_hypercall_buffer_free(xc_handle, cputopo);
+ free(cputopo);
xc_interface_close(xc_handle);
exit(0);
}
@@ -965,12 +960,11 @@ void scaling_governor_func(int argc, char *argv[])
void cpu_topology_func(int argc, char *argv[])
{
- DECLARE_HYPERCALL_BUFFER(xen_sysctl_cputopo_t, cputopo);
- xc_cputopoinfo_t info = { 0 };
- int i, rc = ENOMEM;
+ xc_cputopo_t *cputopo;
+ unsigned max_cpus;
+ int i, rc;
- set_xen_guest_handle(info.cputopo, HYPERCALL_BUFFER_NULL);
- if ( xc_cputopoinfo(xc_handle, &info) )
+ if ( xc_cputopoinfo(xc_handle, &max_cpus, NULL) != 0 )
{
rc = errno;
fprintf(stderr, "failed to discover number of CPUs (%d - %s)\n",
@@ -978,16 +972,15 @@ void cpu_topology_func(int argc, char *argv[])
goto out;
}
- cputopo = xc_hypercall_buffer_alloc(xc_handle, cputopo,
- sizeof(*cputopo) * info.num_cpus);
+ cputopo = calloc(max_cpus, sizeof(*cputopo));
if ( cputopo == NULL )
{
+ rc = ENOMEM;
fprintf(stderr, "failed to allocate hypercall buffers\n");
goto out;
}
- set_xen_guest_handle(info.cputopo, cputopo);
- if ( xc_cputopoinfo(xc_handle, &info) )
+ if ( xc_cputopoinfo(xc_handle, &max_cpus, cputopo) )
{
rc = errno;
fprintf(stderr, "Cannot get Xen CPU topology (%d - %s)\n",
@@ -996,7 +989,7 @@ void cpu_topology_func(int argc, char *argv[])
}
printf("CPU\tcore\tsocket\tnode\n");
- for ( i = 0; i < info.num_cpus; i++ )
+ for ( i = 0; i < max_cpus; i++ )
{
if ( cputopo[i].core == XEN_INVALID_CORE_ID )
continue;
@@ -1005,7 +998,7 @@ void cpu_topology_func(int argc, char *argv[])
}
rc = 0;
out:
- xc_hypercall_buffer_free(xc_handle, cputopo);
+ free(cputopo);
if ( rc )
exit(rc);
}
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index ba66d55..21ba57d 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -1220,30 +1220,26 @@ static PyObject *pyxc_getcpuinfo(XcObject *self, PyObject *args, PyObject *kwds)
static PyObject *pyxc_topologyinfo(XcObject *self)
{
- xc_cputopoinfo_t tinfo = { 0 };
- unsigned i;
+ xc_cputopo_t *cputopo = NULL;
+ unsigned i, num_cpus;
PyObject *ret_obj = NULL;
PyObject *cpu_to_core_obj, *cpu_to_socket_obj, *cpu_to_node_obj;
- DECLARE_HYPERCALL_BUFFER(xen_sysctl_cputopo_t, cputopo);
- set_xen_guest_handle(tinfo.cputopo, HYPERCALL_BUFFER_NULL);
- if ( xc_cputopoinfo(self->xc_handle, &tinfo) != 0 )
+ if ( xc_cputopoinfo(self->xc_handle, &num_cpus, NULL) != 0 )
goto out;
- cputopo = xc_hypercall_buffer_alloc(self->xc_handle, cputopo,
- sizeof(*cputopo) * tinfo.num_cpus);
+ cputopo = calloc(num_cpus, sizeof(*cputopo));
if ( cputopo == NULL )
goto out;
- set_xen_guest_handle(tinfo.cputopo, cputopo);
- if ( xc_cputopoinfo(self->xc_handle, &tinfo) != 0 )
+ if ( xc_cputopoinfo(self->xc_handle, &num_cpus, cputopo) != 0 )
goto out;
/* Construct cpu-to-* lists. */
cpu_to_core_obj = PyList_New(0);
cpu_to_socket_obj = PyList_New(0);
cpu_to_node_obj = PyList_New(0);
- for ( i = 0; i < tinfo.num_cpus; i++ )
+ for ( i = 0; i < num_cpus; i++ )
{
if ( cputopo[i].core == XEN_INVALID_CORE_ID )
{
@@ -1279,7 +1275,7 @@ static PyObject *pyxc_topologyinfo(XcObject *self)
}
}
- ret_obj = Py_BuildValue("{s:i}", "max_cpu_index", tinfo.num_cpus + 1);
+ ret_obj = Py_BuildValue("{s:i}", "max_cpu_index", num_cpus + 1);
PyDict_SetItemString(ret_obj, "cpu_to_core", cpu_to_core_obj);
Py_DECREF(cpu_to_core_obj);
@@ -1291,7 +1287,7 @@ static PyObject *pyxc_topologyinfo(XcObject *self)
Py_DECREF(cpu_to_node_obj);
out:
- xc_hypercall_buffer_free(self->xc_handle, cputopo);
+ free(cputopo);
return ret_obj ? ret_obj : pyxc_error_to_exception(self->xc_handle);
}
--
1.7.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v8 3/5] libxl/libxc: Move libxl_get_numainfo()'s hypercall buffer management to libxc
2015-05-06 18:14 [PATCH v8 0/5] Display IO topology when PXM data is available (plus some cleanup) Boris Ostrovsky
2015-05-06 18:14 ` [PATCH v8 1/5] sysctl: Add sysctl interface for querying PCI topology Boris Ostrovsky
2015-05-06 18:14 ` [PATCH v8 2/5] libxl/libxc: Move libxl_get_cpu_topology()'s hypercall buffer management to libxc Boris Ostrovsky
@ 2015-05-06 18:15 ` Boris Ostrovsky
2015-05-06 18:15 ` [PATCH v8 4/5] libxc: Provide set_xen_guest_handle_offset macro Boris Ostrovsky
2015-05-06 18:15 ` [PATCH v8 5/5] libxl: Add interface for querying hypervisor about PCI topology Boris Ostrovsky
4 siblings, 0 replies; 13+ messages in thread
From: Boris Ostrovsky @ 2015-05-06 18:15 UTC (permalink / raw)
To: ian.jackson, ian.campbell, wei.liu2, stefano.stabellini, dgdegra,
jbeulich, andrew.cooper3, keir
Cc: elena.ufimtseva, dario.faggioli, boris.ostrovsky, xen-devel
xc_numainfo() is not expected to be used on a hot path and therefore
hypercall buffer management can be pushed into libxc. This will simplify
life for callers.
Also update error logging macros.
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
Changes in v8:
* Replace LOGEV with LOGE
tools/libxc/include/xenctrl.h | 4 ++-
tools/libxc/xc_misc.c | 30 ++++++++++++++++-----
tools/libxl/libxl.c | 51 ++++++++++++------------------------
tools/python/xen/lowlevel/xc/xc.c | 38 ++++++++++-----------------
4 files changed, 57 insertions(+), 66 deletions(-)
diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index c5a74f4..8c8eae6 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -1231,6 +1231,7 @@ int xc_send_debug_keys(xc_interface *xch, char *keys);
typedef xen_sysctl_physinfo_t xc_physinfo_t;
typedef xen_sysctl_cputopo_t xc_cputopo_t;
typedef xen_sysctl_numainfo_t xc_numainfo_t;
+typedef xen_sysctl_meminfo_t xc_meminfo_t;
typedef uint32_t xc_cpu_to_node_t;
typedef uint32_t xc_cpu_to_socket_t;
@@ -1242,7 +1243,8 @@ typedef uint32_t xc_node_to_node_dist_t;
int xc_physinfo(xc_interface *xch, xc_physinfo_t *info);
int xc_cputopoinfo(xc_interface *xch, unsigned *max_cpus,
xc_cputopo_t *cputopo);
-int xc_numainfo(xc_interface *xch, xc_numainfo_t *info);
+int xc_numainfo(xc_interface *xch, unsigned *max_nodes,
+ xc_meminfo_t *meminfo, uint32_t *distance);
int xc_sched_id(xc_interface *xch,
int *sched_id);
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index 630a86c..94b70b4 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -204,22 +204,38 @@ out:
return ret;
}
-int xc_numainfo(xc_interface *xch,
- xc_numainfo_t *put_info)
+int xc_numainfo(xc_interface *xch, unsigned *max_nodes,
+ xc_meminfo_t *meminfo, uint32_t *distance)
{
int ret;
DECLARE_SYSCTL;
+ DECLARE_HYPERCALL_BOUNCE(meminfo, *max_nodes * sizeof(*meminfo),
+ XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+ DECLARE_HYPERCALL_BOUNCE(distance,
+ *max_nodes * *max_nodes * sizeof(*distance),
+ XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+
+ if ( (ret = xc_hypercall_bounce_pre(xch, meminfo)) )
+ goto out;
+ if ((ret = xc_hypercall_bounce_pre(xch, distance)) )
+ goto out;
+
+ sysctl.u.numainfo.num_nodes = *max_nodes;
+ set_xen_guest_handle(sysctl.u.numainfo.meminfo, meminfo);
+ set_xen_guest_handle(sysctl.u.numainfo.distance, distance);
sysctl.cmd = XEN_SYSCTL_numainfo;
- memcpy(&sysctl.u.numainfo, put_info, sizeof(*put_info));
+ if ( (ret = do_sysctl(xch, &sysctl)) != 0 )
+ goto out;
- if ((ret = do_sysctl(xch, &sysctl)) != 0)
- return ret;
+ *max_nodes = sysctl.u.numainfo.num_nodes;
- memcpy(put_info, &sysctl.u.numainfo, sizeof(*put_info));
+out:
+ xc_hypercall_bounce_post(xch, meminfo);
+ xc_hypercall_bounce_post(xch, distance);
- return 0;
+ return ret;
}
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 5f2fcff..5c88a88 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -5142,61 +5142,44 @@ libxl_cputopology *libxl_get_cpu_topology(libxl_ctx *ctx, int *nb_cpu_out)
libxl_numainfo *libxl_get_numainfo(libxl_ctx *ctx, int *nr)
{
GC_INIT(ctx);
- xc_numainfo_t ninfo;
- DECLARE_HYPERCALL_BUFFER(xen_sysctl_meminfo_t, meminfo);
- DECLARE_HYPERCALL_BUFFER(uint32_t, distance);
+ xc_meminfo_t *meminfo;
+ uint32_t *distance;
libxl_numainfo *ret = NULL;
int i, j;
+ unsigned num_nodes;
- set_xen_guest_handle(ninfo.meminfo, HYPERCALL_BUFFER_NULL);
- set_xen_guest_handle(ninfo.distance, HYPERCALL_BUFFER_NULL);
- if (xc_numainfo(ctx->xch, &ninfo) != 0) {
- LIBXL__LOG(ctx, XTL_ERROR, "Unable to determine number of NODES");
- ret = NULL;
+ if (xc_numainfo(ctx->xch, &num_nodes, NULL, NULL)) {
+ LOGE(ERROR, "Unable to determine number of nodes");
goto out;
}
- meminfo = xc_hypercall_buffer_alloc(ctx->xch, meminfo,
- sizeof(*meminfo) * ninfo.num_nodes);
- distance = xc_hypercall_buffer_alloc(ctx->xch, distance,
- sizeof(*distance) *
- ninfo.num_nodes * ninfo.num_nodes);
- if ((meminfo == NULL) || (distance == NULL)) {
- LIBXL__LOG_ERRNOVAL(ctx, XTL_ERROR, ENOMEM,
- "Unable to allocate hypercall arguments");
- goto fail;
- }
+ meminfo = libxl__zalloc(gc, sizeof(*meminfo) * num_nodes);
+ distance = libxl__zalloc(gc, sizeof(*distance) * num_nodes * num_nodes);
- set_xen_guest_handle(ninfo.meminfo, meminfo);
- set_xen_guest_handle(ninfo.distance, distance);
- if (xc_numainfo(ctx->xch, &ninfo) != 0) {
- LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting numainfo");
- goto fail;
+ if (xc_numainfo(ctx->xch, &num_nodes, meminfo, distance)) {
+ LOGE(ERROR, "getting numainfo");
+ goto out;
}
- *nr = ninfo.num_nodes;
+ *nr = num_nodes;
- ret = libxl__zalloc(NOGC, sizeof(libxl_numainfo) * ninfo.num_nodes);
- for (i = 0; i < ninfo.num_nodes; i++)
- ret[i].dists = libxl__calloc(NOGC, ninfo.num_nodes, sizeof(*distance));
+ ret = libxl__zalloc(NOGC, sizeof(libxl_numainfo) * num_nodes);
+ for (i = 0; i < num_nodes; i++)
+ ret[i].dists = libxl__calloc(NOGC, num_nodes, sizeof(*distance));
- for (i = 0; i < ninfo.num_nodes; i++) {
+ for (i = 0; i < num_nodes; i++) {
#define V(val, invalid) (val == invalid) ? \
LIBXL_NUMAINFO_INVALID_ENTRY : val
ret[i].size = V(meminfo[i].memsize, XEN_INVALID_MEM_SZ);
ret[i].free = V(meminfo[i].memfree, XEN_INVALID_MEM_SZ);
- ret[i].num_dists = ninfo.num_nodes;
+ ret[i].num_dists = num_nodes;
for (j = 0; j < ret[i].num_dists; j++) {
- unsigned idx = i * ninfo.num_nodes + j;
+ unsigned idx = i * num_nodes + j;
ret[i].dists[j] = V(distance[idx], XEN_INVALID_NODE_DIST);
}
#undef V
}
- fail:
- xc_hypercall_buffer_free(ctx->xch, meminfo);
- xc_hypercall_buffer_free(ctx->xch, distance);
-
out:
GC_FREE;
return ret;
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index 21ba57d..fbd93db 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -1293,33 +1293,23 @@ out:
static PyObject *pyxc_numainfo(XcObject *self)
{
- xc_numainfo_t ninfo = { 0 };
- unsigned i, j;
+ unsigned i, j, num_nodes;
uint64_t free_heap;
PyObject *ret_obj = NULL, *node_to_node_dist_list_obj;
PyObject *node_to_memsize_obj, *node_to_memfree_obj;
PyObject *node_to_dma32_mem_obj, *node_to_node_dist_obj;
- DECLARE_HYPERCALL_BUFFER(xen_sysctl_meminfo_t, meminfo);
- DECLARE_HYPERCALL_BUFFER(uint32_t, distance);
+ xc_meminfo_t *meminfo = NULL;
+ uint32_t *distance = NULL;
- set_xen_guest_handle(ninfo.meminfo, HYPERCALL_BUFFER_NULL);
- set_xen_guest_handle(ninfo.distance, HYPERCALL_BUFFER_NULL);
- if ( xc_numainfo(self->xc_handle, &ninfo) != 0 )
+ if ( xc_numainfo(self->xc_handle, &num_nodes, NULL, NULL) != 0 )
goto out;
- meminfo = xc_hypercall_buffer_alloc(self->xc_handle, meminfo,
- sizeof(*meminfo) * ninfo.num_nodes);
- if ( meminfo == NULL )
- goto out;
- distance = xc_hypercall_buffer_alloc(self->xc_handle, distance,
- sizeof(*distance) *
- ninfo.num_nodes * ninfo.num_nodes);
- if ( distance == NULL )
+ meminfo = calloc(num_nodes, sizeof(*meminfo));
+ distance = calloc(num_nodes * num_nodes, sizeof(*distance));
+ if ( (meminfo == NULL) || (distance == NULL) )
goto out;
- set_xen_guest_handle(ninfo.meminfo, meminfo);
- set_xen_guest_handle(ninfo.distance, distance);
- if ( xc_numainfo(self->xc_handle, &ninfo) != 0 )
+ if ( xc_numainfo(self->xc_handle, &num_nodes, meminfo, distance) != 0 )
goto out;
/* Construct node-to-* lists. */
@@ -1327,7 +1317,7 @@ static PyObject *pyxc_numainfo(XcObject *self)
node_to_memfree_obj = PyList_New(0);
node_to_dma32_mem_obj = PyList_New(0);
node_to_node_dist_list_obj = PyList_New(0);
- for ( i = 0; i < ninfo.num_nodes; i++ )
+ for ( i = 0; i < num_nodes; i++ )
{
PyObject *pyint;
unsigned invalid_node;
@@ -1351,9 +1341,9 @@ static PyObject *pyxc_numainfo(XcObject *self)
/* Node to Node Distance */
node_to_node_dist_obj = PyList_New(0);
invalid_node = (meminfo[i].memsize == XEN_INVALID_MEM_SZ);
- for ( j = 0; j < ninfo.num_nodes; j++ )
+ for ( j = 0; j < num_nodes; j++ )
{
- uint32_t dist = distance[i * ninfo.num_nodes + j];
+ uint32_t dist = distance[i * num_nodes + j];
if ( invalid_node || (dist == XEN_INVALID_NODE_DIST) )
{
PyList_Append(node_to_node_dist_obj, Py_None);
@@ -1369,7 +1359,7 @@ static PyObject *pyxc_numainfo(XcObject *self)
Py_DECREF(node_to_node_dist_obj);
}
- ret_obj = Py_BuildValue("{s:i}", "max_node_index", ninfo.num_nodes + 1);
+ ret_obj = Py_BuildValue("{s:i}", "max_node_index", num_nodes + 1);
PyDict_SetItemString(ret_obj, "node_memsize", node_to_memsize_obj);
Py_DECREF(node_to_memsize_obj);
@@ -1385,8 +1375,8 @@ static PyObject *pyxc_numainfo(XcObject *self)
Py_DECREF(node_to_node_dist_list_obj);
out:
- xc_hypercall_buffer_free(self->xc_handle, meminfo);
- xc_hypercall_buffer_free(self->xc_handle, distance);
+ free(meminfo);
+ free(distance);
return ret_obj ? ret_obj : pyxc_error_to_exception(self->xc_handle);
}
--
1.7.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v8 4/5] libxc: Provide set_xen_guest_handle_offset macro
2015-05-06 18:14 [PATCH v8 0/5] Display IO topology when PXM data is available (plus some cleanup) Boris Ostrovsky
` (2 preceding siblings ...)
2015-05-06 18:15 ` [PATCH v8 3/5] libxl/libxc: Move libxl_get_numainfo()'s " Boris Ostrovsky
@ 2015-05-06 18:15 ` Boris Ostrovsky
2015-05-08 14:57 ` Ian Campbell
2015-05-06 18:15 ` [PATCH v8 5/5] libxl: Add interface for querying hypervisor about PCI topology Boris Ostrovsky
4 siblings, 1 reply; 13+ messages in thread
From: Boris Ostrovsky @ 2015-05-06 18:15 UTC (permalink / raw)
To: ian.jackson, ian.campbell, wei.liu2, stefano.stabellini, dgdegra,
jbeulich, andrew.cooper3, keir
Cc: elena.ufimtseva, dario.faggioli, boris.ostrovsky, xen-devel
Add set_xen_guest_handle_offset() macro that can be used for setting
xen_guest_handle to an offset into hypercall buffer.
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
---
tools/libxc/include/xenctrl.h | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 8c8eae6..4e6f62c 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -322,16 +322,21 @@ typedef struct xc_hypercall_buffer xc_hypercall_buffer_t;
* Set a xen_guest_handle in a type safe manner, ensuring that the
* data pointer has been correctly allocated.
*/
-#undef set_xen_guest_handle
-#define set_xen_guest_handle(_hnd, _val) \
+#undef set_xen_guest_handle_offset
+#define set_xen_guest_handle_offset(_hnd, _val, _off) \
do { \
xc_hypercall_buffer_t _hcbuf_hnd1; \
typeof(XC__HYPERCALL_BUFFER_NAME(_val)) *_hcbuf_hnd2 = \
HYPERCALL_BUFFER(_val); \
(void) (&_hcbuf_hnd1 == _hcbuf_hnd2); \
- set_xen_guest_handle_raw(_hnd, (_hcbuf_hnd2)->hbuf); \
+ set_xen_guest_handle_raw(_hnd, \
+ (_hcbuf_hnd2)->hbuf + (_off)); \
} while (0)
+#undef set_xen_guest_handle
+#define set_xen_guest_handle(_hnd, _val) \
+ set_xen_guest_handle_offset(_hnd, _val, 0)
+
/* Use with set_xen_guest_handle in place of NULL */
extern xc_hypercall_buffer_t XC__HYPERCALL_BUFFER_NAME(HYPERCALL_BUFFER_NULL);
--
1.7.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v8 5/5] libxl: Add interface for querying hypervisor about PCI topology
2015-05-06 18:14 [PATCH v8 0/5] Display IO topology when PXM data is available (plus some cleanup) Boris Ostrovsky
` (3 preceding siblings ...)
2015-05-06 18:15 ` [PATCH v8 4/5] libxc: Provide set_xen_guest_handle_offset macro Boris Ostrovsky
@ 2015-05-06 18:15 ` Boris Ostrovsky
2015-05-08 15:11 ` Ian Campbell
4 siblings, 1 reply; 13+ messages in thread
From: Boris Ostrovsky @ 2015-05-06 18:15 UTC (permalink / raw)
To: ian.jackson, ian.campbell, wei.liu2, stefano.stabellini, dgdegra,
jbeulich, andrew.cooper3, keir
Cc: elena.ufimtseva, dario.faggioli, boris.ostrovsky, xen-devel
.. and use this new interface to display it along with CPU topology
and NUMA information when 'xl info -n' command is issued
The output will look like
...
cpu_topology :
cpu: core socket node
0: 0 0 0
...
device topology :
device node
0000:00:00.0 0
0000:00:01.0 0
...
Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
---
Changes in v8:
* sysctl now returns number of processed devices in num_devs and
xc_pcitopoinfo() call sysctl again with hypercall buffer adjusted
with set_xen_guest_handle_offset() (introduced in previous patch)
* Map hypervisor's XEN_INVALID_DEV to LIBXL_PCITOPOLOGY_INVALID_ENTRY
* Replace LOGEV with LOGE
tools/libxc/include/xenctrl.h | 3 ++
tools/libxc/xc_misc.c | 39 +++++++++++++++++++++++
tools/libxl/libxl.c | 43 +++++++++++++++++++++++++
tools/libxl/libxl.h | 12 +++++++
tools/libxl/libxl_freebsd.c | 12 +++++++
tools/libxl/libxl_internal.h | 5 +++
tools/libxl/libxl_linux.c | 70 +++++++++++++++++++++++++++++++++++++++++
tools/libxl/libxl_netbsd.c | 12 +++++++
tools/libxl/libxl_types.idl | 7 ++++
tools/libxl/libxl_utils.c | 8 +++++
tools/libxl/xl_cmdimpl.c | 40 +++++++++++++++++++----
11 files changed, 244 insertions(+), 7 deletions(-)
diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 4e6f62c..a65b62d 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -1237,6 +1237,7 @@ typedef xen_sysctl_physinfo_t xc_physinfo_t;
typedef xen_sysctl_cputopo_t xc_cputopo_t;
typedef xen_sysctl_numainfo_t xc_numainfo_t;
typedef xen_sysctl_meminfo_t xc_meminfo_t;
+typedef xen_sysctl_pcitopoinfo_t xc_pcitopoinfo_t;
typedef uint32_t xc_cpu_to_node_t;
typedef uint32_t xc_cpu_to_socket_t;
@@ -1250,6 +1251,8 @@ int xc_cputopoinfo(xc_interface *xch, unsigned *max_cpus,
xc_cputopo_t *cputopo);
int xc_numainfo(xc_interface *xch, unsigned *max_nodes,
xc_meminfo_t *meminfo, uint32_t *distance);
+int xc_pcitopoinfo(xc_interface *xch, unsigned num_devs,
+ physdev_pci_device_t *devs, uint32_t *nodes);
int xc_sched_id(xc_interface *xch,
int *sched_id);
diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c
index 94b70b4..828e885 100644
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -238,6 +238,45 @@ out:
return ret;
}
+int xc_pcitopoinfo(xc_interface *xch, unsigned num_devs,
+ physdev_pci_device_t *devs,
+ uint32_t *nodes)
+{
+ int ret = 0;
+ unsigned processed = 0;
+ DECLARE_SYSCTL;
+ DECLARE_HYPERCALL_BOUNCE(devs, num_devs * sizeof(*devs),
+ XC_HYPERCALL_BUFFER_BOUNCE_IN);
+ DECLARE_HYPERCALL_BOUNCE(nodes, num_devs* sizeof(*nodes),
+ XC_HYPERCALL_BUFFER_BOUNCE_BOTH);
+
+ if ( (ret = xc_hypercall_bounce_pre(xch, devs)) )
+ goto out;
+ if ( (ret = xc_hypercall_bounce_pre(xch, nodes)) )
+ goto out;
+
+ sysctl.cmd = XEN_SYSCTL_pcitopoinfo;
+
+ while ( processed < num_devs )
+ {
+ sysctl.u.pcitopoinfo.num_devs = num_devs - processed;
+ set_xen_guest_handle_offset(sysctl.u.pcitopoinfo.devs, devs,
+ processed * sizeof(*devs));
+ set_xen_guest_handle_offset(sysctl.u.pcitopoinfo.nodes, nodes,
+ processed * sizeof(*nodes));
+
+ if ( (ret = do_sysctl(xch, &sysctl)) != 0 )
+ break;
+
+ processed += sysctl.u.pcitopoinfo.num_devs;
+ }
+
+ out:
+ xc_hypercall_bounce_post(xch, devs);
+ xc_hypercall_bounce_post(xch, nodes);
+
+ return ret;
+}
int xc_sched_id(xc_interface *xch,
int *sched_id)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 5c88a88..f2a0136 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -5139,6 +5139,49 @@ libxl_cputopology *libxl_get_cpu_topology(libxl_ctx *ctx, int *nb_cpu_out)
return ret;
}
+libxl_pcitopology *libxl_get_pci_topology(libxl_ctx *ctx, int *num_devs)
+{
+ GC_INIT(ctx);
+ physdev_pci_device_t *devs;
+ uint32_t *nodes;
+ libxl_pcitopology *ret = NULL;
+ int i;
+
+ *num_devs = libxl__pci_numdevs(gc);
+ if (*num_devs < 0) {
+ LOGE(ERROR, "Unable to determine number of PCI devices");
+ goto out;
+ }
+
+ devs = libxl__zalloc(gc, sizeof(*devs) * *num_devs);
+ nodes = libxl__zalloc(gc, sizeof(*nodes) * *num_devs);
+
+ if (libxl__pci_topology_init(gc, devs, *num_devs)) {
+ LOGE(ERROR, "Cannot initialize PCI hypercall structure");
+ goto out;
+ }
+
+ if (xc_pcitopoinfo(ctx->xch, *num_devs, devs, nodes) != 0) {
+ LOGE(ERROR, "PCI topology info hypercall failed");
+ goto out;
+ }
+
+ ret = libxl__zalloc(NOGC, sizeof(libxl_pcitopology) * *num_devs);
+
+ for (i = 0; i < *num_devs; i++) {
+ ret[i].seg = devs[i].seg;
+ ret[i].bus = devs[i].bus;
+ ret[i].devfn = devs[i].devfn;
+ ret[i].node = ((nodes[i] == XEN_INVALID_NODE_ID) ||
+ (nodes[i] == XEN_INVALID_DEV)) ?
+ LIBXL_PCITOPOLOGY_INVALID_ENTRY : nodes[i];
+ }
+
+ out:
+ GC_FREE;
+ return ret;
+}
+
libxl_numainfo *libxl_get_numainfo(libxl_ctx *ctx, int *nr)
{
GC_INIT(ctx);
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 44bd8e2..2b50f8e 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -750,6 +750,14 @@ void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, libxl_mac *src);
#define LIBXL_HAVE_PSR_MBM 1
#endif
+/*
+ * LIBXL_HAVE_PCITOPOLOGY
+ *
+ * If this is defined, then interface to query hypervisor about PCI device
+ * topology is available.
+ */
+#define LIBXL_HAVE_PCITOPOLOGY 1
+
typedef char **libxl_string_list;
void libxl_string_list_dispose(libxl_string_list *sl);
int libxl_string_list_length(const libxl_string_list *sl);
@@ -1142,6 +1150,10 @@ void libxl_vminfo_list_free(libxl_vminfo *list, int nb_vm);
libxl_cputopology *libxl_get_cpu_topology(libxl_ctx *ctx, int *nb_cpu_out);
void libxl_cputopology_list_free(libxl_cputopology *, int nb_cpu);
+#define LIBXL_PCITOPOLOGY_INVALID_ENTRY (~(uint32_t)0)
+libxl_pcitopology *libxl_get_pci_topology(libxl_ctx *ctx, int *num_devs);
+void libxl_pcitopology_list_free(libxl_pcitopology *, int num_devs);
+
#define LIBXL_NUMAINFO_INVALID_ENTRY (~(uint32_t)0)
libxl_numainfo *libxl_get_numainfo(libxl_ctx *ctx, int *nr);
void libxl_numainfo_list_free(libxl_numainfo *, int nr);
diff --git a/tools/libxl/libxl_freebsd.c b/tools/libxl/libxl_freebsd.c
index e8b88b3..47c3391 100644
--- a/tools/libxl/libxl_freebsd.c
+++ b/tools/libxl/libxl_freebsd.c
@@ -131,3 +131,15 @@ libxl_device_model_version libxl__default_device_model(libxl__gc *gc)
{
return LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN;
}
+
+int libxl__pci_numdevs(libxl__gc *gc)
+{
+ return ERROR_NI;
+}
+
+int libxl__pci_topology_init(libxl__gc *gc,
+ physdev_pci_device_t *devs,
+ int num_devs)
+{
+ return ERROR_NI;
+}
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 8eb38aa..8aaa1ad 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1196,6 +1196,11 @@ _hidden int libxl__try_phy_backend(mode_t st_mode);
_hidden char *libxl__devid_to_localdev(libxl__gc *gc, int devid);
+_hidden int libxl__pci_numdevs(libxl__gc *gc);
+_hidden int libxl__pci_topology_init(libxl__gc *gc,
+ physdev_pci_device_t *devs,
+ int num_devs);
+
/* from libxl_pci */
_hidden int libxl__device_pci_add(libxl__gc *gc, uint32_t domid, libxl_device_pci *pcidev, int starting);
diff --git a/tools/libxl/libxl_linux.c b/tools/libxl/libxl_linux.c
index b51930c..f42a89a 100644
--- a/tools/libxl/libxl_linux.c
+++ b/tools/libxl/libxl_linux.c
@@ -279,3 +279,73 @@ libxl_device_model_version libxl__default_device_model(libxl__gc *gc)
{
return LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN;
}
+
+int libxl__pci_numdevs(libxl__gc *gc)
+{
+ DIR *dir;
+ struct dirent *entry;
+ int num_devs = 0;
+
+ dir = opendir("/sys/bus/pci/devices");
+ if (!dir) {
+ LOGE(ERROR, "Cannot open /sys/bus/pci/devices");
+ return ERROR_FAIL;
+ }
+
+ while ((entry = readdir(dir))) {
+ if (entry->d_name[0] == '.')
+ continue;
+ num_devs++;
+ }
+ closedir(dir);
+
+ return num_devs;
+}
+
+int libxl__pci_topology_init(libxl__gc *gc,
+ physdev_pci_device_t *devs,
+ int num_devs)
+{
+
+ DIR *dir;
+ struct dirent *entry;
+ int i, err = 0;
+
+ dir = opendir("/sys/bus/pci/devices");
+ if (!dir) {
+ LOGE(ERROR, "Cannot open /sys/bus/pci/devices");
+ return ERROR_FAIL;
+ }
+
+ i = 0;
+ while ((entry = readdir(dir))) {
+ unsigned int dom, bus, dev, func;
+
+ if (entry->d_name[0] == '.')
+ continue;
+
+ if (i == num_devs) {
+ LOG(ERROR, "Too many devices");
+ err = ERROR_FAIL;
+ errno = -ENOSPC;
+ goto out;
+ }
+
+ if (sscanf(entry->d_name, "%x:%x:%x.%d", &dom, &bus, &dev, &func) < 4) {
+ LOGE(ERROR, "Error processing /sys/bus/pci/devices");
+ err = ERROR_FAIL;
+ goto out;
+ }
+
+ devs[i].seg = dom;
+ devs[i].bus = bus;
+ devs[i].devfn = ((dev & 0x1f) << 3) | (func & 7);
+
+ i++;
+ }
+
+ out:
+ closedir(dir);
+
+ return err;
+}
diff --git a/tools/libxl/libxl_netbsd.c b/tools/libxl/libxl_netbsd.c
index 898e160..a2a962e 100644
--- a/tools/libxl/libxl_netbsd.c
+++ b/tools/libxl/libxl_netbsd.c
@@ -95,3 +95,15 @@ libxl_device_model_version libxl__default_device_model(libxl__gc *gc)
{
return LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL;
}
+
+int libxl__pci_numdevs(libxl__gc *gc)
+{
+ return ERROR_NI;
+}
+
+int libxl__pci_topology_init(libxl__gc *gc,
+ physdev_pci_device_t *devs,
+ int num_devs)
+{
+ return ERROR_NI;
+}
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 117b61d..3d7d46a 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -656,6 +656,13 @@ libxl_cputopology = Struct("cputopology", [
("node", uint32),
], dir=DIR_OUT)
+libxl_pcitopology = Struct("pcitopology", [
+ ("seg", uint16),
+ ("bus", uint8),
+ ("devfn", uint8),
+ ("node", uint32),
+ ], dir=DIR_OUT)
+
libxl_sched_credit_params = Struct("sched_credit_params", [
("tslice_ms", integer),
("ratelimit_us", integer),
diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c
index 67c0b1c..f6be2d7 100644
--- a/tools/libxl/libxl_utils.c
+++ b/tools/libxl/libxl_utils.c
@@ -952,6 +952,14 @@ void libxl_cputopology_list_free(libxl_cputopology *list, int nr)
free(list);
}
+void libxl_pcitopology_list_free(libxl_pcitopology *list, int nr)
+{
+ int i;
+ for (i = 0; i < nr; i++)
+ libxl_pcitopology_dispose(&list[i]);
+ free(list);
+}
+
void libxl_numainfo_list_free(libxl_numainfo *list, int nr)
{
int i;
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 648ca08..3990dd4 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -5418,12 +5418,15 @@ static void output_numainfo(void)
static void output_topologyinfo(void)
{
- libxl_cputopology *info;
+ libxl_cputopology *cpuinfo;
int i, nr;
+ libxl_pcitopology *pciinfo;
+ int valid_devs;
- info = libxl_get_cpu_topology(ctx, &nr);
- if (info == NULL) {
- fprintf(stderr, "libxl_get_topologyinfo failed.\n");
+
+ cpuinfo = libxl_get_cpu_topology(ctx, &nr);
+ if (cpuinfo == NULL) {
+ fprintf(stderr, "libxl_get_cpu_topology failed.\n");
return;
}
@@ -5431,12 +5434,35 @@ static void output_topologyinfo(void)
printf("cpu: core socket node\n");
for (i = 0; i < nr; i++) {
- if (info[i].core != LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
+ if (cpuinfo[i].core != LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
printf("%3d: %4d %4d %4d\n", i,
- info[i].core, info[i].socket, info[i].node);
+ cpuinfo[i].core, cpuinfo[i].socket, cpuinfo[i].node);
+ }
+
+ libxl_cputopology_list_free(cpuinfo, nr);
+
+ pciinfo = libxl_get_pci_topology(ctx, &nr);
+ if (pciinfo == NULL) {
+ fprintf(stderr, "libxl_get_pci_topology failed.\n");
+ return;
}
- libxl_cputopology_list_free(info, nr);
+ printf("device topology :\n");
+ printf("device node\n");
+ for (i = 0; i < nr; i++) {
+ if (pciinfo[i].node != LIBXL_PCITOPOLOGY_INVALID_ENTRY) {
+ printf("%04x:%02x:%02x.%01x %d\n", pciinfo[i].seg,
+ pciinfo[i].bus,
+ ((pciinfo[i].devfn >> 3) & 0x1f), (pciinfo[i].devfn & 7),
+ pciinfo[i].node);
+ valid_devs++;
+ }
+ }
+
+ if (valid_devs == 0)
+ printf("No device topology data available\n");
+
+ libxl_pcitopology_list_free(pciinfo, nr);
return;
}
--
1.7.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v8 1/5] sysctl: Add sysctl interface for querying PCI topology
2015-05-06 18:14 ` [PATCH v8 1/5] sysctl: Add sysctl interface for querying PCI topology Boris Ostrovsky
@ 2015-05-07 13:52 ` Andrew Cooper
0 siblings, 0 replies; 13+ messages in thread
From: Andrew Cooper @ 2015-05-07 13:52 UTC (permalink / raw)
To: Boris Ostrovsky, ian.jackson, ian.campbell, wei.liu2,
stefano.stabellini, dgdegra, jbeulich, keir
Cc: elena.ufimtseva, dario.faggioli, xen-devel
On 06/05/2015 19:14, Boris Ostrovsky wrote:
> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v8 4/5] libxc: Provide set_xen_guest_handle_offset macro
2015-05-06 18:15 ` [PATCH v8 4/5] libxc: Provide set_xen_guest_handle_offset macro Boris Ostrovsky
@ 2015-05-08 14:57 ` Ian Campbell
2015-05-08 15:41 ` Boris Ostrovsky
0 siblings, 1 reply; 13+ messages in thread
From: Ian Campbell @ 2015-05-08 14:57 UTC (permalink / raw)
To: Boris Ostrovsky
Cc: elena.ufimtseva, wei.liu2, stefano.stabellini, andrew.cooper3,
dario.faggioli, ian.jackson, xen-devel, jbeulich, keir, dgdegra
On Wed, 2015-05-06 at 14:15 -0400, Boris Ostrovsky wrote:
> Add set_xen_guest_handle_offset() macro that can be used for setting
> xen_guest_handle to an offset into hypercall buffer.
>
> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> ---
> tools/libxc/include/xenctrl.h | 11 ++++++++---
> 1 files changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
> index 8c8eae6..4e6f62c 100644
> --- a/tools/libxc/include/xenctrl.h
> +++ b/tools/libxc/include/xenctrl.h
> @@ -322,16 +322,21 @@ typedef struct xc_hypercall_buffer xc_hypercall_buffer_t;
> * Set a xen_guest_handle in a type safe manner, ensuring that the
> * data pointer has been correctly allocated.
> */
> -#undef set_xen_guest_handle
> -#define set_xen_guest_handle(_hnd, _val) \
> +#undef set_xen_guest_handle_offset
This isn't strictly speaking needed since you aren't trying to override
a version of this interface provided by the hypervisor headers.
> +#define set_xen_guest_handle_offset(_hnd, _val, _off) \
> do { \
> xc_hypercall_buffer_t _hcbuf_hnd1; \
> typeof(XC__HYPERCALL_BUFFER_NAME(_val)) *_hcbuf_hnd2 = \
> HYPERCALL_BUFFER(_val); \
> (void) (&_hcbuf_hnd1 == _hcbuf_hnd2); \
> - set_xen_guest_handle_raw(_hnd, (_hcbuf_hnd2)->hbuf); \
> + set_xen_guest_handle_raw(_hnd, \
> + (_hcbuf_hnd2)->hbuf + (_off)); \
The hypervisor side guest_handle_add_offset equivalents operate in
multiples of the type. If we can arrange that here too then I think that
would be good.
I think that means
+ (_hcbuf_hnd2)->hbuf + ((sizeof(*_val)*(_off))); \
Then the caller becomes e.g.
set_xen_guest_handle_offset(sysctl.u.pcitopoinfo.devs, devs, processed);
which is much nicer IMHO.
Ian.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v8 5/5] libxl: Add interface for querying hypervisor about PCI topology
2015-05-06 18:15 ` [PATCH v8 5/5] libxl: Add interface for querying hypervisor about PCI topology Boris Ostrovsky
@ 2015-05-08 15:11 ` Ian Campbell
0 siblings, 0 replies; 13+ messages in thread
From: Ian Campbell @ 2015-05-08 15:11 UTC (permalink / raw)
To: Boris Ostrovsky
Cc: elena.ufimtseva, wei.liu2, stefano.stabellini, andrew.cooper3,
dario.faggioli, ian.jackson, xen-devel, jbeulich, keir, dgdegra
On Wed, 2015-05-06 at 14:15 -0400, Boris Ostrovsky wrote:
> .. and use this new interface to display it along with CPU topology
> and NUMA information when 'xl info -n' command is issued
>
> The output will look like
> ...
> cpu_topology :
> cpu: core socket node
> 0: 0 0 0
> ...
> device topology :
> device node
> 0000:00:00.0 0
> 0000:00:01.0 0
> ...
>
> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
[...]
> + sysctl.u.pcitopoinfo.num_devs = num_devs - processed;
> + set_xen_guest_handle_offset(sysctl.u.pcitopoinfo.devs, devs,
> + processed * sizeof(*devs));
> + set_xen_guest_handle_offset(sysctl.u.pcitopoinfo.nodes, nodes,
> + processed * sizeof(*nodes));
Changing these in the obvious way based on my feedback to the previous
patch wouldn't invalidate my ack.
[...]
> + if (libxl__pci_topology_init(gc, devs, *num_devs)) {
> + LOGE(ERROR, "Cannot initialize PCI hypercall structure");
libxl__pci_topology_init might be an exception but libxl__* functions
don't typically set errno, they return ERROR_FOO things. So you may want
just LOG and not LOGE. You might also want to arrange to print the error
code.
Ian.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v8 4/5] libxc: Provide set_xen_guest_handle_offset macro
2015-05-08 14:57 ` Ian Campbell
@ 2015-05-08 15:41 ` Boris Ostrovsky
2015-05-08 15:56 ` Ian Campbell
0 siblings, 1 reply; 13+ messages in thread
From: Boris Ostrovsky @ 2015-05-08 15:41 UTC (permalink / raw)
To: Ian Campbell
Cc: elena.ufimtseva, wei.liu2, stefano.stabellini, andrew.cooper3,
dario.faggioli, ian.jackson, xen-devel, jbeulich, keir, dgdegra
On 05/08/2015 10:57 AM, Ian Campbell wrote:
> On Wed, 2015-05-06 at 14:15 -0400, Boris Ostrovsky wrote:
>> Add set_xen_guest_handle_offset() macro that can be used for setting
>> xen_guest_handle to an offset into hypercall buffer.
>>
>> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
>> ---
>> tools/libxc/include/xenctrl.h | 11 ++++++++---
>> 1 files changed, 8 insertions(+), 3 deletions(-)
>>
>> diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
>> index 8c8eae6..4e6f62c 100644
>> --- a/tools/libxc/include/xenctrl.h
>> +++ b/tools/libxc/include/xenctrl.h
>> @@ -322,16 +322,21 @@ typedef struct xc_hypercall_buffer xc_hypercall_buffer_t;
>> * Set a xen_guest_handle in a type safe manner, ensuring that the
>> * data pointer has been correctly allocated.
>> */
>> -#undef set_xen_guest_handle
>> -#define set_xen_guest_handle(_hnd, _val) \
>> +#undef set_xen_guest_handle_offset
> This isn't strictly speaking needed since you aren't trying to override
> a version of this interface provided by the hypervisor headers.
>
>> +#define set_xen_guest_handle_offset(_hnd, _val, _off) \
>> do { \
>> xc_hypercall_buffer_t _hcbuf_hnd1; \
>> typeof(XC__HYPERCALL_BUFFER_NAME(_val)) *_hcbuf_hnd2 = \
>> HYPERCALL_BUFFER(_val); \
>> (void) (&_hcbuf_hnd1 == _hcbuf_hnd2); \
>> - set_xen_guest_handle_raw(_hnd, (_hcbuf_hnd2)->hbuf); \
>> + set_xen_guest_handle_raw(_hnd, \
>> + (_hcbuf_hnd2)->hbuf + (_off)); \
> The hypervisor side guest_handle_add_offset equivalents operate in
> multiples of the type. If we can arrange that here too then I think that
> would be good.
>
> I think that means
> + (_hcbuf_hnd2)->hbuf + ((sizeof(*_val)*(_off))); \
>
> Then the caller becomes e.g.
>
> set_xen_guest_handle_offset(sysctl.u.pcitopoinfo.devs, devs, processed);
>
> which is much nicer IMHO.
That's what I started with.
This, however, breaks at least two things:
-- Callers that pass HYPERCALL_BUFFER_NULL to set_xen_guest_handle().
This I think can be fixed by declaring a void *HYPERCALL_BUFFER_NULL
(currenty HYPERCALL_BUFFER_NULL is just a syntactic building block)
-- DECLARE_NAMED_HYPERCALL_BOUNCE. This makes _val a non-existing symbol
(it creates a xc__hypercall_buffer_val). That I am not sure I know how
to fix. Add type size filed to struct xc_hypercall_buffer?
-boris
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v8 4/5] libxc: Provide set_xen_guest_handle_offset macro
2015-05-08 15:41 ` Boris Ostrovsky
@ 2015-05-08 15:56 ` Ian Campbell
2015-05-08 16:05 ` Boris Ostrovsky
0 siblings, 1 reply; 13+ messages in thread
From: Ian Campbell @ 2015-05-08 15:56 UTC (permalink / raw)
To: Boris Ostrovsky
Cc: elena.ufimtseva, wei.liu2, stefano.stabellini, andrew.cooper3,
dario.faggioli, ian.jackson, xen-devel, jbeulich, keir, dgdegra
On Fri, 2015-05-08 at 11:41 -0400, Boris Ostrovsky wrote:
> On 05/08/2015 10:57 AM, Ian Campbell wrote:
> > On Wed, 2015-05-06 at 14:15 -0400, Boris Ostrovsky wrote:
> >> Add set_xen_guest_handle_offset() macro that can be used for setting
> >> xen_guest_handle to an offset into hypercall buffer.
> >>
> >> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> >> ---
> >> tools/libxc/include/xenctrl.h | 11 ++++++++---
> >> 1 files changed, 8 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
> >> index 8c8eae6..4e6f62c 100644
> >> --- a/tools/libxc/include/xenctrl.h
> >> +++ b/tools/libxc/include/xenctrl.h
> >> @@ -322,16 +322,21 @@ typedef struct xc_hypercall_buffer xc_hypercall_buffer_t;
> >> * Set a xen_guest_handle in a type safe manner, ensuring that the
> >> * data pointer has been correctly allocated.
> >> */
> >> -#undef set_xen_guest_handle
> >> -#define set_xen_guest_handle(_hnd, _val) \
> >> +#undef set_xen_guest_handle_offset
> > This isn't strictly speaking needed since you aren't trying to override
> > a version of this interface provided by the hypervisor headers.
> >
> >> +#define set_xen_guest_handle_offset(_hnd, _val, _off) \
> >> do { \
> >> xc_hypercall_buffer_t _hcbuf_hnd1; \
> >> typeof(XC__HYPERCALL_BUFFER_NAME(_val)) *_hcbuf_hnd2 = \
> >> HYPERCALL_BUFFER(_val); \
> >> (void) (&_hcbuf_hnd1 == _hcbuf_hnd2); \
> >> - set_xen_guest_handle_raw(_hnd, (_hcbuf_hnd2)->hbuf); \
> >> + set_xen_guest_handle_raw(_hnd, \
> >> + (_hcbuf_hnd2)->hbuf + (_off)); \
> > The hypervisor side guest_handle_add_offset equivalents operate in
> > multiples of the type. If we can arrange that here too then I think that
> > would be good.
> >
> > I think that means
> > + (_hcbuf_hnd2)->hbuf + ((sizeof(*_val)*(_off))); \
> >
> > Then the caller becomes e.g.
> >
> > set_xen_guest_handle_offset(sysctl.u.pcitopoinfo.devs, devs, processed);
> >
> > which is much nicer IMHO.
>
>
> That's what I started with.
>
> This, however, breaks at least two things:
> -- Callers that pass HYPERCALL_BUFFER_NULL to set_xen_guest_handle().
> This I think can be fixed by declaring a void *HYPERCALL_BUFFER_NULL
> (currenty HYPERCALL_BUFFER_NULL is just a syntactic building block)
>
> -- DECLARE_NAMED_HYPERCALL_BOUNCE. This makes _val a non-existing symbol
> (it creates a xc__hypercall_buffer_val). That I am not sure I know how
> to fix. Add type size filed to struct xc_hypercall_buffer?
How about refactoring such that this macro becomes an internal helper
used by both set_xen_guest_handle and set_xen_guest_handle_offset and
takes the (_hcbuf_hnd2)->hbuf or (_hcbuf_hnd2)->hbuf +
((sizeof(*_val)*(_off)) as appropriate? (iow don't implement set as
set_offset(0))
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v8 4/5] libxc: Provide set_xen_guest_handle_offset macro
2015-05-08 15:56 ` Ian Campbell
@ 2015-05-08 16:05 ` Boris Ostrovsky
2015-05-08 16:19 ` Ian Campbell
0 siblings, 1 reply; 13+ messages in thread
From: Boris Ostrovsky @ 2015-05-08 16:05 UTC (permalink / raw)
To: Ian Campbell
Cc: elena.ufimtseva, wei.liu2, stefano.stabellini, andrew.cooper3,
dario.faggioli, ian.jackson, xen-devel, jbeulich, keir, dgdegra
On 05/08/2015 11:56 AM, Ian Campbell wrote:
> On Fri, 2015-05-08 at 11:41 -0400, Boris Ostrovsky wrote:
>> On 05/08/2015 10:57 AM, Ian Campbell wrote:
>>> On Wed, 2015-05-06 at 14:15 -0400, Boris Ostrovsky wrote:
>>>> Add set_xen_guest_handle_offset() macro that can be used for setting
>>>> xen_guest_handle to an offset into hypercall buffer.
>>>>
>>>> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
>>>> ---
>>>> tools/libxc/include/xenctrl.h | 11 ++++++++---
>>>> 1 files changed, 8 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
>>>> index 8c8eae6..4e6f62c 100644
>>>> --- a/tools/libxc/include/xenctrl.h
>>>> +++ b/tools/libxc/include/xenctrl.h
>>>> @@ -322,16 +322,21 @@ typedef struct xc_hypercall_buffer xc_hypercall_buffer_t;
>>>> * Set a xen_guest_handle in a type safe manner, ensuring that the
>>>> * data pointer has been correctly allocated.
>>>> */
>>>> -#undef set_xen_guest_handle
>>>> -#define set_xen_guest_handle(_hnd, _val) \
>>>> +#undef set_xen_guest_handle_offset
>>> This isn't strictly speaking needed since you aren't trying to override
>>> a version of this interface provided by the hypervisor headers.
>>>
>>>> +#define set_xen_guest_handle_offset(_hnd, _val, _off) \
>>>> do { \
>>>> xc_hypercall_buffer_t _hcbuf_hnd1; \
>>>> typeof(XC__HYPERCALL_BUFFER_NAME(_val)) *_hcbuf_hnd2 = \
>>>> HYPERCALL_BUFFER(_val); \
>>>> (void) (&_hcbuf_hnd1 == _hcbuf_hnd2); \
>>>> - set_xen_guest_handle_raw(_hnd, (_hcbuf_hnd2)->hbuf); \
>>>> + set_xen_guest_handle_raw(_hnd, \
>>>> + (_hcbuf_hnd2)->hbuf + (_off)); \
>>> The hypervisor side guest_handle_add_offset equivalents operate in
>>> multiples of the type. If we can arrange that here too then I think that
>>> would be good.
>>>
>>> I think that means
>>> + (_hcbuf_hnd2)->hbuf + ((sizeof(*_val)*(_off))); \
>>>
>>> Then the caller becomes e.g.
>>>
>>> set_xen_guest_handle_offset(sysctl.u.pcitopoinfo.devs, devs, processed);
>>>
>>> which is much nicer IMHO.
>>
>> That's what I started with.
>>
>> This, however, breaks at least two things:
>> -- Callers that pass HYPERCALL_BUFFER_NULL to set_xen_guest_handle().
>> This I think can be fixed by declaring a void *HYPERCALL_BUFFER_NULL
>> (currenty HYPERCALL_BUFFER_NULL is just a syntactic building block)
>>
>> -- DECLARE_NAMED_HYPERCALL_BOUNCE. This makes _val a non-existing symbol
>> (it creates a xc__hypercall_buffer_val). That I am not sure I know how
>> to fix. Add type size filed to struct xc_hypercall_buffer?
> How about refactoring such that this macro becomes an internal helper
> used by both set_xen_guest_handle and set_xen_guest_handle_offset and
> takes the (_hcbuf_hnd2)->hbuf or (_hcbuf_hnd2)->hbuf +
> ((sizeof(*_val)*(_off)) as appropriate? (iow don't implement set as
> set_offset(0))
But that will preclude us from using _offset() variant of the macro for
variables declared with DECLARE_NAMED_HYPERCALL_BOUNCE (and possibly
others, I haven't checked), won't it? We don't have any such uses now
but nevertheless...
-boris
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v8 4/5] libxc: Provide set_xen_guest_handle_offset macro
2015-05-08 16:05 ` Boris Ostrovsky
@ 2015-05-08 16:19 ` Ian Campbell
0 siblings, 0 replies; 13+ messages in thread
From: Ian Campbell @ 2015-05-08 16:19 UTC (permalink / raw)
To: Boris Ostrovsky
Cc: elena.ufimtseva, wei.liu2, stefano.stabellini, andrew.cooper3,
dario.faggioli, ian.jackson, xen-devel, jbeulich, keir, dgdegra
On Fri, 2015-05-08 at 12:05 -0400, Boris Ostrovsky wrote:
> On 05/08/2015 11:56 AM, Ian Campbell wrote:
> > On Fri, 2015-05-08 at 11:41 -0400, Boris Ostrovsky wrote:
> >> On 05/08/2015 10:57 AM, Ian Campbell wrote:
> >>> On Wed, 2015-05-06 at 14:15 -0400, Boris Ostrovsky wrote:
> >>>> Add set_xen_guest_handle_offset() macro that can be used for setting
> >>>> xen_guest_handle to an offset into hypercall buffer.
> >>>>
> >>>> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
> >>>> ---
> >>>> tools/libxc/include/xenctrl.h | 11 ++++++++---
> >>>> 1 files changed, 8 insertions(+), 3 deletions(-)
> >>>>
> >>>> diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
> >>>> index 8c8eae6..4e6f62c 100644
> >>>> --- a/tools/libxc/include/xenctrl.h
> >>>> +++ b/tools/libxc/include/xenctrl.h
> >>>> @@ -322,16 +322,21 @@ typedef struct xc_hypercall_buffer xc_hypercall_buffer_t;
> >>>> * Set a xen_guest_handle in a type safe manner, ensuring that the
> >>>> * data pointer has been correctly allocated.
> >>>> */
> >>>> -#undef set_xen_guest_handle
> >>>> -#define set_xen_guest_handle(_hnd, _val) \
> >>>> +#undef set_xen_guest_handle_offset
> >>> This isn't strictly speaking needed since you aren't trying to override
> >>> a version of this interface provided by the hypervisor headers.
> >>>
> >>>> +#define set_xen_guest_handle_offset(_hnd, _val, _off) \
> >>>> do { \
> >>>> xc_hypercall_buffer_t _hcbuf_hnd1; \
> >>>> typeof(XC__HYPERCALL_BUFFER_NAME(_val)) *_hcbuf_hnd2 = \
> >>>> HYPERCALL_BUFFER(_val); \
> >>>> (void) (&_hcbuf_hnd1 == _hcbuf_hnd2); \
> >>>> - set_xen_guest_handle_raw(_hnd, (_hcbuf_hnd2)->hbuf); \
> >>>> + set_xen_guest_handle_raw(_hnd, \
> >>>> + (_hcbuf_hnd2)->hbuf + (_off)); \
> >>> The hypervisor side guest_handle_add_offset equivalents operate in
> >>> multiples of the type. If we can arrange that here too then I think that
> >>> would be good.
> >>>
> >>> I think that means
> >>> + (_hcbuf_hnd2)->hbuf + ((sizeof(*_val)*(_off))); \
> >>>
> >>> Then the caller becomes e.g.
> >>>
> >>> set_xen_guest_handle_offset(sysctl.u.pcitopoinfo.devs, devs, processed);
> >>>
> >>> which is much nicer IMHO.
> >>
> >> That's what I started with.
> >>
> >> This, however, breaks at least two things:
> >> -- Callers that pass HYPERCALL_BUFFER_NULL to set_xen_guest_handle().
> >> This I think can be fixed by declaring a void *HYPERCALL_BUFFER_NULL
> >> (currenty HYPERCALL_BUFFER_NULL is just a syntactic building block)
> >>
> >> -- DECLARE_NAMED_HYPERCALL_BOUNCE. This makes _val a non-existing symbol
> >> (it creates a xc__hypercall_buffer_val). That I am not sure I know how
> >> to fix. Add type size filed to struct xc_hypercall_buffer?
> > How about refactoring such that this macro becomes an internal helper
> > used by both set_xen_guest_handle and set_xen_guest_handle_offset and
> > takes the (_hcbuf_hnd2)->hbuf or (_hcbuf_hnd2)->hbuf +
> > ((sizeof(*_val)*(_off)) as appropriate? (iow don't implement set as
> > set_offset(0))
>
> But that will preclude us from using _offset() variant of the macro for
> variables declared with DECLARE_NAMED_HYPERCALL_BOUNCE (and possibly
> others, I haven't checked), won't it? We don't have any such uses now
> but nevertheless...
Lets cross that bridge if/when we come to it.
Ian.
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2015-05-08 16:19 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-06 18:14 [PATCH v8 0/5] Display IO topology when PXM data is available (plus some cleanup) Boris Ostrovsky
2015-05-06 18:14 ` [PATCH v8 1/5] sysctl: Add sysctl interface for querying PCI topology Boris Ostrovsky
2015-05-07 13:52 ` Andrew Cooper
2015-05-06 18:14 ` [PATCH v8 2/5] libxl/libxc: Move libxl_get_cpu_topology()'s hypercall buffer management to libxc Boris Ostrovsky
2015-05-06 18:15 ` [PATCH v8 3/5] libxl/libxc: Move libxl_get_numainfo()'s " Boris Ostrovsky
2015-05-06 18:15 ` [PATCH v8 4/5] libxc: Provide set_xen_guest_handle_offset macro Boris Ostrovsky
2015-05-08 14:57 ` Ian Campbell
2015-05-08 15:41 ` Boris Ostrovsky
2015-05-08 15:56 ` Ian Campbell
2015-05-08 16:05 ` Boris Ostrovsky
2015-05-08 16:19 ` Ian Campbell
2015-05-06 18:15 ` [PATCH v8 5/5] libxl: Add interface for querying hypervisor about PCI topology Boris Ostrovsky
2015-05-08 15:11 ` Ian Campbell
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.