From 203fbef2fb5e60fe57347146ca20880aca6e5594 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Mon, 3 Sep 2012 11:21:59 +0100 Subject: libxl/xl: implement support for guest ioport and irq permissions. This is useful for passing legacy ISA devices (e.g. com ports, parallel ports) to guests. Supported syntax is as described in http://cmrg.fifthhorseman.net/wiki/xen#grantingaccesstoserialhardwaretoadomU I tested this using Xen's 'q' key handler which prints out the I/O port and IRQ ranges allowed for each domain. e.g.: (XEN) Rangesets belonging to domain 31: (XEN) I/O Ports { 2e8-2ef, 2f8-2ff } (XEN) Interrupts { 3, 5-6 } Signed-off-by: Ian Campbell Tested-by: Dieter Bloms Acked-by: Ian Jackson Committed-by: Ian Campbell --- tools/libxl/libxl_create.c | 30 ++++++++++++++++ tools/libxl/libxl_types.idl | 8 +++++ tools/libxl/xl_cmdimpl.c | 87 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 124 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c index 57a497d11e..ef17f052c0 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -933,6 +933,36 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev, LOG(ERROR, "unable to add disk devices"); goto error_out; } + + for (i = 0; i < d_config->b_info.num_ioports; i++) { + libxl_ioport_range *io = &d_config->b_info.ioports[i]; + + LOG(DEBUG, "dom%d ioports %"PRIx32"-%"PRIx32, + domid, io->first, io->first + io->number - 1); + + ret = xc_domain_ioport_permission(CTX->xch, domid, + io->first, io->number, 1); + if ( ret<0 ){ + LOGE(ERROR, + "failed give dom%d access to ioports %"PRIx32"-%"PRIx32, + domid, io->first, io->first + io->number - 1); + ret = ERROR_FAIL; + } + } + + for (i = 0; i < d_config->b_info.num_irqs; i++) { + uint32_t irq = d_config->b_info.irqs[i]; + + LOG(DEBUG, "dom%d irq %"PRIx32, domid, irq); + + ret = xc_domain_irq_permission(CTX->xch, domid, irq, 1); + if ( ret<0 ){ + LOGE(ERROR, + "failed give dom%d access to irq %"PRId32, domid, irq); + ret = ERROR_FAIL; + } + } + for (i = 0; i < d_config->num_nics; i++) { /* We have to init the nic here, because we still haven't * called libxl_device_nic_add at this point, but qemu needs diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index c5716a44bd..6d5c578519 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -135,6 +135,11 @@ libxl_vga_interface_type = Enumeration("vga_interface_type", [ # Complex libxl types # +libxl_ioport_range = Struct("ioport_range", [ + ("first", uint32), + ("number", uint32), + ]) + libxl_vga_interface_info = Struct("vga_interface_info", [ ("kind", libxl_vga_interface_type), ]) @@ -277,6 +282,9 @@ libxl_domain_build_info = Struct("domain_build_info",[ # parameters for all type of scheduler ("sched_params", libxl_domain_sched_params), + ("ioports", Array(libxl_ioport_range, "num_ioports")), + ("irqs", Array(uint32, "num_irqs")), + ("u", KeyedUnion(None, libxl_domain_type, "type", [("hvm", Struct(None, [("firmware", string), ("bios", libxl_bios_type), diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index dfdb5ffc82..2d6ab97298 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -573,10 +573,12 @@ static void parse_config_data(const char *config_source, long l; XLU_Config *config; XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids; + XLU_ConfigList *ioports, *irqs; + int num_ioports, num_irqs; int pci_power_mgmt = 0; int pci_msitranslate = 0; int pci_permissive = 0; - int e; + int i, e; libxl_domain_create_info *c_info = &d_config->c_info; libxl_domain_build_info *b_info = &d_config->b_info; @@ -919,6 +921,89 @@ static void parse_config_data(const char *config_source, abort(); } + if (!xlu_cfg_get_list(config, "ioports", &ioports, &num_ioports, 0)) { + b_info->num_ioports = num_ioports; + b_info->ioports = calloc(num_ioports, sizeof(*b_info->ioports)); + if (b_info->ioports == NULL) { + fprintf(stderr, "unable to allocate memory for ioports\n"); + exit(-1); + } + + for (i = 0; i < num_ioports; i++) { + const char *buf2; + char *ep; + uint32_t start, end; + unsigned long ul; + + buf = xlu_cfg_get_listitem (ioports, i); + if (!buf) { + fprintf(stderr, + "xl: Unable to get element #%d in ioport list\n", i); + exit(1); + } + ul = strtoul(buf, &ep, 16); + if (ep == buf) { + fprintf(stderr, "xl: Invalid argument parsing ioport: %s\n", + buf); + exit(1); + } + if (ul >= UINT32_MAX) { + fprintf(stderr, "xl: ioport %lx too big\n", ul); + exit(1); + } + start = end = ul; + + if (*ep == '-') { + buf2 = ep + 1; + ul = strtoul(buf2, &ep, 16); + if (ep == buf2 || *ep != '\0' || start > end) { + fprintf(stderr, + "xl: Invalid argument parsing ioport: %s\n", buf); + exit(1); + } + if (ul >= UINT32_MAX) { + fprintf(stderr, "xl: ioport %lx too big\n", ul); + exit(1); + } + end = ul; + } else if ( *ep != '\0' ) + fprintf(stderr, + "xl: Invalid argument parsing ioport: %s\n", buf); + b_info->ioports[i].first = start; + b_info->ioports[i].number = end - start + 1; + } + } + + if (!xlu_cfg_get_list(config, "irqs", &irqs, &num_irqs, 0)) { + b_info->num_irqs = num_irqs; + b_info->irqs = calloc(num_irqs, sizeof(*b_info->irqs)); + if (b_info->irqs == NULL) { + fprintf(stderr, "unable to allocate memory for ioports\n"); + exit(-1); + } + for (i = 0; i < num_irqs; i++) { + char *ep; + unsigned long ul; + buf = xlu_cfg_get_listitem (irqs, i); + if (!buf) { + fprintf(stderr, + "xl: Unable to get element %d in irq list\n", i); + exit(1); + } + ul = strtoul(buf, &ep, 10); + if (ep == buf) { + fprintf(stderr, + "xl: Invalid argument parsing irq: %s\n", buf); + exit(1); + } + if (ul >= UINT32_MAX) { + fprintf(stderr, "xl: irq %lx too big\n", ul); + exit(1); + } + b_info->irqs[i] = ul; + } + } + if (!xlu_cfg_get_list (config, "disk", &vbds, 0, 0)) { d_config->num_disks = 0; d_config->disks = NULL; -- cgit v1.2.3