This function insert a PCI passthrough device in qemu.
Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx>
---
tools/libxl/libxl_internal.h | 4 ++
tools/libxl/libxl_qmp.c | 107 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 105 insertions(+), 0 deletions(-)
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 849b251..09f618f 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -119,6 +119,9 @@ typedef struct {
} libxl__device;
#define XC_PCI_BDF "0x%x, 0x%x, 0x%x, 0x%x"
+#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
+#define PCI_FUNC(devfn) ((devfn) & 0x07)
#define AUTO_PHP_SLOT 0x100
#define SYSFS_PCI_DEV "/sys/bus/pci/devices"
#define SYSFS_PCIBACK_DRIVER "/sys/bus/pci/drivers/pciback"
@@ -444,6 +447,7 @@ _hidden libxl__qmp_handler *libxl__qmp_initialize(libxl_ctx
*ctx,
uint32_t domid);
/* ask to QEMU the serial port information and store it in xenstore. */
_hidden int libxl__qmp_query_serial(libxl__qmp_handler *qmp);
+_hidden int libxl__qmp_pci_add(libxl__gc *gc, int d, libxl_device_pci *pcidev);
/* close and free the QMP handler */
_hidden void libxl__qmp_close(libxl__qmp_handler *qmp);
/* remove the socket file, if the file has already been removed,
diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 547cd53..bce7e16 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -41,6 +41,7 @@
*/
#define QMP_RECEIVE_BUFFER_SIZE 4096
+#define PCI_PT_QDEV_ID "pci-pt-%02x_%02x.%01x"
typedef int (*qmp_callback_t)(libxl__qmp_handler *qmp,
const libxl__json_object *tree,
@@ -619,6 +620,112 @@ int libxl__qmp_query_serial(libxl__qmp_handler *qmp)
return rc;
}
+static int pci_add_callback(libxl__qmp_handler *qmp,
+ const libxl__json_object *response, void *opaque)
+{
+ libxl_device_pci *pcidev = opaque;
+ const libxl__json_object *bus = NULL;
+ libxl__gc gc = LIBXL_INIT_GC(qmp->ctx);
+ int i, j, rc = -1;
+ char *asked_id = libxl__sprintf(&gc, PCI_PT_QDEV_ID,
+ pcidev->bus, pcidev->dev, pcidev->func);
+
+ for (i = 0; (bus = libxl__json_array_get(response, i)); i++) {
+ const libxl__json_object *devices = NULL;
+ const libxl__json_object *device = NULL;
+ const libxl__json_object *o = NULL;
+ const char *id = NULL;
+
+ devices = libxl__json_map_get("devices", bus, JSON_ARRAY);
+
+ for (j = 0; (device = libxl__json_array_get(devices, j)); j++) {
+ o = libxl__json_map_get("qdev_id", device, JSON_STRING);
+ id = libxl__json_object_get_string(o);
+
+ if (id && strcmp(asked_id, id) == 0) {
+ int dev_slot, dev_func;
+
+ o = libxl__json_map_get("slot", device, JSON_INTEGER);
+ if (!o)
+ goto out;
+ dev_slot = libxl__json_object_get_integer(o);
+ o = libxl__json_map_get("function", device, JSON_INTEGER);
+ if (!o)
+ goto out;
+ dev_func = libxl__json_object_get_integer(o);
+
+ pcidev->vdevfn = PCI_DEVFN(dev_slot, dev_func);
+
+ rc = 0;
+ goto out;
+ }
+ }
+ }
+
+
+out:
+ libxl__free_all(&gc);
+ return rc;
+}
+
+int libxl__qmp_pci_add(libxl__gc *gc, int domid, libxl_device_pci *pcidev)
+{
+ libxl__qmp_handler *qmp = NULL;
+ flexarray_t *parameters = NULL;
+ libxl_key_value_list args = NULL;
+ char *hostaddr = NULL;
+ int rc = 0;
+ qmp_request_handle request = {
+ .callback = pci_add_callback,
+ .opaque = pcidev,
+ };
+
+ qmp = libxl__qmp_initialize(libxl__gc_owner(gc), domid);
+ if (!qmp)
+ return -1;
+
+ hostaddr = libxl__sprintf(gc, "%04x:%02x:%02x.%01x", pcidev->domain,
+ pcidev->bus, pcidev->dev, pcidev->func);
+ if (!hostaddr)
+ return -1;
+
+ parameters = flexarray_make(6, 1);
+ flexarray_append_pair(parameters, "driver", "xen-pci-passthrough");
+ flexarray_append_pair(parameters, "id",
+ libxl__sprintf(gc, PCI_PT_QDEV_ID,
+ pcidev->bus, pcidev->dev,
+ pcidev->func));
+ flexarray_append_pair(parameters, "hostaddr", hostaddr);
+ if (pcidev->vdevfn) {
+ flexarray_append_pair(parameters, "addr",
+ libxl__sprintf(gc, "%x.%x",
+ PCI_SLOT(pcidev->vdevfn),
+ PCI_FUNC(pcidev->vdevfn)));
+ }
+ args = libxl__xs_kvs_of_flexarray(gc, parameters, parameters->count);
+ if (!args)
+ return -1;
+
+ rc = qmp_synchronous_send(qmp, "device_add", &args, NULL, qmp->timeout);
+ if (rc == 0) {
+ rc = qmp_synchronous_send(qmp, "query-pci", NULL,
+ &request, qmp->timeout);
+ if (rc == 0) {
+ rc = request.rc;
+ }
+ }
+
+ flexarray_free(parameters);
+ libxl__qmp_close(qmp);
+ return rc;
+}
+
int libxl__qmp_initializations(libxl_ctx *ctx, uint32_t domid)
{
libxl__qmp_handler *qmp = NULL;
--
Anthony PERARD
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|