Ian Campbell
2012-Aug-31 15:55 UTC
[PATCH V2] libxl/xl: implement support for guest iooprt and irq permissions
# HG changeset patch # User Ian Campbell <ian.campbell@citrix.com> # Date 1346428441 -3600 # Node ID ddde6c2c45de8e60518aafa077f0f3867ff68e17 # Parent ccbee5bcb31b72706497725381f4e6836b9df657 libxl/xl: implement support for guest iooprt 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 <ian.campbell@citrix.com> --- Handle additional error conditions: - (*ep!=0 && *ep!=''-'') - *ep2!=0 - calloc failure - values which are too big for a uint32_t s/parsion/parsing/ diff -r ccbee5bcb31b -r ddde6c2c45de docs/man/xl.cfg.pod.5 --- a/docs/man/xl.cfg.pod.5 Fri Aug 31 12:03:55 2012 +0100 +++ b/docs/man/xl.cfg.pod.5 Fri Aug 31 16:54:01 2012 +0100 @@ -402,6 +402,30 @@ for more information on the "permissive" =back +=item B<ioports=[ "IOPORT_RANGE", "IOPORT_RANGE", ... ]> + +=over 4 + +Allow guest to access specific legacy I/O ports. Each B<IOPORT_RANGE> +is given in hexadecimal and may either a span e.g. C<2f8-2ff> +(inclusive) or a single I/O port C<2f8>. + +It is recommended to use this option only for trusted VMs under +administrator control. + +=back + +=item B<irqs=[ NUMBER, NUMBER, ... ]> + +=over 4 + +Allow a guest to access specific physical IRQs. + +It is recommended to use this option only for trusted VMs under +administrator control. + +=back + =head2 Paravirtualised (PV) Guest Specific Options The following options apply only to Paravirtual guests. diff -r ccbee5bcb31b -r ddde6c2c45de tools/libxl/libxl_create.c --- a/tools/libxl/libxl_create.c Fri Aug 31 12:03:55 2012 +0100 +++ b/tools/libxl/libxl_create.c Fri Aug 31 16:54:01 2012 +0100 @@ -933,6 +933,36 @@ static void domcreate_launch_dm(libxl__e 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 -r ccbee5bcb31b -r ddde6c2c45de tools/libxl/libxl_types.idl --- a/tools/libxl/libxl_types.idl Fri Aug 31 12:03:55 2012 +0100 +++ b/tools/libxl/libxl_types.idl Fri Aug 31 16:54:01 2012 +0100 @@ -135,6 +135,11 @@ libxl_vga_interface_type = Enumeration(" # 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 # 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 -r ccbee5bcb31b -r ddde6c2c45de tools/libxl/xl_cmdimpl.c --- a/tools/libxl/xl_cmdimpl.c Fri Aug 31 12:03:55 2012 +0100 +++ b/tools/libxl/xl_cmdimpl.c Fri Aug 31 16:54:01 2012 +0100 @@ -573,10 +573,12 @@ static void parse_config_data(const char 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 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 s, e; + 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); + } + s = e = ul; + + if (*ep == ''-'') { + buf2 = ep + 1; + ul = strtoul(buf2, &ep, 16); + if (ep == buf2 || *ep != ''\0'' || s > e) { + 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); + } + e = ul; + } else if ( *ep != ''\0'' ) + fprintf(stderr, + "xl: Invalid argument parsing ioport: %s\n", buf); + b_info->ioports[i].first = s; + b_info->ioports[i].number = e - s + 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;
Ian Jackson
2012-Aug-31 16:01 UTC
Re: [PATCH V2] libxl/xl: implement support for guest iooprt and irq permissions
Ian Campbell writes ("[PATCH V2] libxl/xl: implement support for guest iooprt and irq permissions"):> libxl/xl: implement support for guest iooprt and irq permissions....>> - int e; > + int i, e;...> + 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); > + }1. If long and int are the same size, this still mishandles "1100000055\0", passing -1 to libxl. 2. You compare to UINT32_MAX and then assign to a signed integer. That seems odd. Ian.
Ian Campbell
2012-Aug-31 16:04 UTC
Re: [PATCH V2] libxl/xl: implement support for guest iooprt and irq permissions
On Fri, 2012-08-31 at 17:01 +0100, Ian Jackson wrote:> Ian Campbell writes ("[PATCH V2] libxl/xl: implement support for guest iooprt and irq permissions"): > > libxl/xl: implement support for guest iooprt and irq permissions. > ...> > > - int e; > > + int i, e; > ... > > + 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); > > + } > > 1. If long and int are the same size, this still mishandles > "1100000055\0", passing -1 to libxl. > > 2. You compare to UINT32_MAX and then assign to a signed integer. > That seems odd.Everything here is signed now. Oh, I see the confusion, I''ve unwittingly shadowed the e you''ve quoted with an uint32_t in this scope. I''ll change the variable name since that obviously not helpful. Ian.
Possibly Parallel Threads
- PATCH [base vtpm and libxl patches 4/6] add iomem support to libxl
- [PATCH 09/11] add iomem support to libxl
- [PATCH, v2]: xl: move domain struct init functions to libxl
- [PATCH] libxl: do not overwrite user supplied config when running bootloader
- [PATCH] Allow 4 MB of video RAM for Cirrus graphics on traditional QEMU