[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] PCI passthru: tools changes (generic and vt-d)
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1189784367 -3600 # Node ID acfa9290746f9c00e30dca7a62e9f7a96702b3b5 # Parent b3f681d712659582112c33b36bd31dab6f1a96b8 PCI passthru: tools changes (generic and vt-d) I have added CONFIG_PASSTHROUGH in ioemu/Makefile.target and ioemu/hw/pc.c in attached vtd_tools2.patch. This should turn off libpci usage by default until user specifically enables it. This can be safely check-in without breaking builds for people who do not care about pass-through devices. I will try to think of a better way to enable this. Signed-off-by: Allen Kay <allen.m.kay@xxxxxxxxx> Signed-off-by: Guy Zana <guy@xxxxxxxxxxxx> --- tools/ioemu/Makefile.target | 6 tools/ioemu/hw/pass-through.c | 454 ++++++++++++++++++++++++++++++++++++ tools/ioemu/hw/pass-through.h | 89 +++++++ tools/ioemu/hw/pc.c | 27 +- tools/ioemu/vl.c | 12 tools/ioemu/vl.h | 2 tools/libxc/xc_domain.c | 108 ++++++++ tools/libxc/xenctrl.h | 39 +++ tools/python/xen/xend/XendConfig.py | 3 tools/python/xen/xend/image.py | 2 tools/python/xen/xm/create.py | 2 11 files changed, 732 insertions(+), 12 deletions(-) diff -r b3f681d71265 -r acfa9290746f tools/ioemu/Makefile.target --- a/tools/ioemu/Makefile.target Fri Sep 14 16:10:08 2007 +0100 +++ b/tools/ioemu/Makefile.target Fri Sep 14 16:39:27 2007 +0100 @@ -197,6 +197,9 @@ LIBS+=-lm LIBS+=-lm LIBS+=-L../../libxc -lxenctrl -lxenguest LIBS+=-L../../xenstore -lxenstore +ifdef CONFIG_PASSTHROUGH +LIBS+=-lpci +endif ifndef CONFIG_USER_ONLY LIBS+=-lz endif @@ -400,6 +403,9 @@ VL_OBJS+= xenstore.o VL_OBJS+= xenstore.o VL_OBJS+= xen_platform.o VL_OBJS+= tpm_tis.o +ifdef CONFIG_PASSTHROUGH +VL_OBJS+= pass-through.o +endif CPPFLAGS += -DHAS_AUDIO endif ifeq ($(TARGET_BASE_ARCH), ppc) diff -r b3f681d71265 -r acfa9290746f tools/ioemu/hw/pass-through.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/hw/pass-through.c Fri Sep 14 16:39:27 2007 +0100 @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2007, Neocleus Corporation. + * Copyright (c) 2007, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Alex Novik <alex@xxxxxxxxxxxx> + * Allen Kay <allen.m.kay@xxxxxxxxx> + * Guy Zana <guy@xxxxxxxxxxxx> + * + * This file implements direct PCI assignment to a HVM guest + * + */ +#include "vl.h" +#include "pass-through.h" +#include "pci/header.h" +#include "pci/pci.h" + +extern FILE *logfile; +char *token; + +int pci_devs(const char *direct_pci) +{ + int count = 0; + const char *c; + + /* skip first "[" character */ + c = direct_pci + 1; + while ((c = strchr(c, '[')) != NULL) { + c++; + count++; + } + return (count); +} + +int next_token(char *direct_pci) +{ + if (token == NULL) + token = strtok(direct_pci, ","); + else + token = strtok(NULL, ","); + token = strchr(token, 'x'); + token = token + 1; + return ((int) strtol(token, NULL, 16)); +} + +void next_bdf(char *direct_pci, int *seg, + int *bus, int *dev, int *func) +{ + *seg = next_token(direct_pci); + *bus = next_token(direct_pci); + *dev = next_token(direct_pci); + *func = next_token(direct_pci); +} + +uint8_t find_cap_offset(struct pci_dev *pci_dev, uint8_t cap) +{ + int id; + int max_cap = 48; + int pos = PCI_CAPABILITY_LIST; + int status; + + status = pci_read_byte(pci_dev, PCI_STATUS); + if ( (status & PCI_STATUS_CAP_LIST) == 0 ) + return 0; + + while ( max_cap-- ) + { + pos = pci_read_byte(pci_dev, pos); + if ( pos < 0x40 ) + break; + + pos &= ~3; + id = pci_read_byte(pci_dev, pos + PCI_CAP_LIST_ID); + + if ( id == 0xff ) + break; + if ( id == cap ) + return pos; + + pos += PCI_CAP_LIST_NEXT; + } + return 0; +} + +void pdev_flr(struct pci_dev *pci_dev) +{ + int pos; + int dev_cap; + int dev_status; + + pos = find_cap_offset(pci_dev, PCI_CAP_ID_EXP); + if ( pos ) + { + dev_cap = pci_read_long(pci_dev, pos + PCI_EXP_DEVCAP); + if ( dev_cap & PCI_EXP_DEVCAP_FLR ) + { + pci_write_word(pci_dev, pos + PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_FLR); + do { + dev_status = pci_read_long(pci_dev, pos + PCI_EXP_DEVSTA); + } while (dev_status & PCI_EXP_DEVSTA_TRPND); + } + } +} + +/* Being called each time a mmio region has been updated */ +void pt_iomem_map(PCIDevice *d, int i, uint32_t e_phys, uint32_t e_size, + int type) +{ + struct pt_dev *assigned_device = (struct pt_dev *)d; + uint32_t old_ebase = assigned_device->bases[i].e_physbase; + int first_map = ( assigned_device->bases[i].e_size == 0 ); + int ret = 0; + + assigned_device->bases[i].e_physbase = e_phys; + assigned_device->bases[i].e_size= e_size; + + PT_LOG("e_phys=%08x maddr=%08x type=%d len=%08x index=%d\n", + e_phys, assigned_device->bases[i].access.maddr, type, e_size, i); + + if ( e_size == 0 ) + return; + + if ( !first_map ) + { + /* Remove old mapping */ + ret = xc_domain_memory_mapping(xc_handle, domid, old_ebase >> 12, + assigned_device->bases[i].access.maddr >> 12, + (e_size+0xFFF) >> 12, + DPCI_REMOVE_MAPPING); + if ( ret != 0 ) + { + PT_LOG("Error: remove old mapping failed!\n"); + return; + } + } + + /* Create new mapping */ + ret = xc_domain_memory_mapping(xc_handle, domid, + assigned_device->bases[i].e_physbase >> 12, + assigned_device->bases[i].access.maddr >> 12, + (e_size+0xFFF) >> 12, + DPCI_ADD_MAPPING); + if ( ret != 0 ) + PT_LOG("Error: create new mapping failed!\n"); + +} + +/* Being called each time a pio region has been updated */ +void pt_ioport_map(PCIDevice *d, int i, + uint32_t e_phys, uint32_t e_size, int type) +{ + struct pt_dev *assigned_device = (struct pt_dev *)d; + uint32_t old_ebase = assigned_device->bases[i].e_physbase; + int first_map = ( assigned_device->bases[i].e_size == 0 ); + int ret = 0; + + assigned_device->bases[i].e_physbase = e_phys; + assigned_device->bases[i].e_size= e_size; + + PT_LOG("e_phys=%04x pio_base=%04x len=%04x index=%d\n", + (uint16_t)e_phys, (uint16_t)assigned_device->bases[i].access.pio_base, + (uint16_t)e_size, i); + + if ( e_size == 0 ) + return; + + if ( !first_map ) + { + /* Remove old mapping */ + ret = xc_domain_ioport_mapping(xc_handle, domid, old_ebase, + assigned_device->bases[i].access.pio_base, e_size, + DPCI_REMOVE_MAPPING); + if ( ret != 0 ) + { + PT_LOG("Error: remove old mapping failed!\n"); + return; + } + } + + /* Create new mapping */ + ret = xc_domain_ioport_mapping(xc_handle, domid, e_phys, + assigned_device->bases[i].access.pio_base, e_size, + DPCI_ADD_MAPPING); + if ( ret != 0 ) + PT_LOG("Error: create new mapping failed!\n"); + +} + +static void pt_pci_write_config(PCIDevice *d, uint32_t address, uint32_t val, + int len) +{ + struct pt_dev *assigned_device = (struct pt_dev *)d; + struct pci_dev *pci_dev = assigned_device->pci_dev; + +#ifdef PT_DEBUG_PCI_CONFIG_ACCESS + PT_LOG("(%x.%x): address=%04x val=0x%08x len=%d\n", + (d->devfn >> 3) & 0x1F, (d->devfn & 0x7), address, val, len); +#endif + + /* Pre-write hooking */ + switch ( address ) { + case 0x0C ... 0x3F: + pci_default_write_config(d, address, val, len); + return; + } + + /* PCI config pass-through */ + if (address == 0x4) { + switch (len){ + case 1: + pci_write_byte(pci_dev, address, val); + break; + case 2: + pci_write_word(pci_dev, address, val); + break; + case 4: + pci_write_long(pci_dev, address, val); + break; + } + } + + if (address == 0x4) { + /* Post-write hooking */ + pci_default_write_config(d, address, val, len); + } +} + +static uint32_t pt_pci_read_config(PCIDevice *d, uint32_t address, int len) +{ + struct pt_dev *assigned_device = (struct pt_dev *)d; + struct pci_dev *pci_dev = assigned_device->pci_dev; + uint32_t val = 0xFF; + + /* Pre-hooking */ + switch ( address ) { + case 0x0C ... 0x3F: + val = pci_default_read_config(d, address, len); + goto exit; + } + + switch ( len ) { + case 1: + val = pci_read_byte(pci_dev, address); + break; + case 2: + val = pci_read_word(pci_dev, address); + break; + case 4: + val = pci_read_long(pci_dev, address); + break; + } + +exit: + +#ifdef PT_DEBUG_PCI_CONFIG_ACCESS + PT_LOG("(%x.%x): address=%04x val=0x%08x len=%d\n", + (d->devfn >> 3) & 0x1F, (d->devfn & 0x7), address, val, len); +#endif + + return val; +} + +static int pt_register_regions(struct pt_dev *assigned_device) +{ + int i = 0; + uint32_t bar_data = 0; + struct pci_dev *pci_dev = assigned_device->pci_dev; + PCIDevice *d = &assigned_device->dev; + + /* Register PIO/MMIO BARs */ + for ( i=0; i < PCI_BAR_ENTRIES; i++ ) + { + if ( pci_dev->base_addr[i] ) + { + assigned_device->bases[i].e_physbase = pci_dev->base_addr[i]; + assigned_device->bases[i].access.u = pci_dev->base_addr[i]; + + /* Register current region */ + bar_data = *((uint32_t*)(d->config + PCI_BASE_ADDRESS_0) + i); + if ( bar_data & PCI_ADDRESS_SPACE_IO ) + pci_register_io_region((PCIDevice *)assigned_device, i, + (uint32_t)pci_dev->size[i], PCI_ADDRESS_SPACE_IO, + pt_ioport_map); + else if ( bar_data & PCI_ADDRESS_SPACE_MEM_PREFETCH ) + pci_register_io_region((PCIDevice *)assigned_device, i, + (uint32_t)pci_dev->size[i], PCI_ADDRESS_SPACE_MEM_PREFETCH, + pt_iomem_map); + else + pci_register_io_region((PCIDevice *)assigned_device, i, + (uint32_t)pci_dev->size[i], PCI_ADDRESS_SPACE_MEM, + pt_iomem_map); + + PT_LOG("IO region registered (size=0x%08x base_addr=0x%08x)\n", + (uint32_t)(pci_dev->size[i]), + (uint32_t)(pci_dev->base_addr[i])); + } + } + + /* Register expansion ROM address */ + if ( pci_dev->rom_base_addr && pci_dev->rom_size ) + { + assigned_device->bases[PCI_ROM_SLOT].e_physbase = + pci_dev->rom_base_addr; + assigned_device->bases[PCI_ROM_SLOT].access.maddr = + pci_dev->rom_base_addr; + pci_register_io_region((PCIDevice *)assigned_device, PCI_ROM_SLOT, + pci_dev->rom_size, PCI_ADDRESS_SPACE_MEM_PREFETCH, + pt_iomem_map); + + PT_LOG("Expansion ROM registered (size=0x%08x base_addr=0x%08x)\n", + (uint32_t)(pci_dev->rom_size), (uint32_t)(pci_dev->rom_base_addr)); + } + + return 0; +} + +struct pt_dev * register_real_device(PCIBus *e_bus, + const char *e_dev_name, int e_devfn, uint8_t r_bus, uint8_t r_dev, + uint8_t r_func, uint32_t machine_irq, struct pci_access *pci_access) +{ + int rc, i; + struct pt_dev *assigned_device = NULL; + struct pci_dev *pci_dev; + struct pci_config_cf8 machine_bdf; + uint8_t e_device, e_intx; + + PT_LOG("Assigning real physical device %02x:%02x.%x ...\n", + r_bus, r_dev, r_func); + + /* Find real device structure */ + for (pci_dev = pci_access->devices; pci_dev != NULL; + pci_dev = pci_dev->next) + { + if ((r_bus == pci_dev->bus) && (r_dev == pci_dev->dev) + && (r_func == pci_dev->func)) + break; + } + if ( pci_dev == NULL ) + { + PT_LOG("Error: couldn't locate device in libpci structures\n"); + return NULL; + } + + /* Register device */ + assigned_device = (struct pt_dev *) pci_register_device(e_bus, e_dev_name, + sizeof(struct pt_dev), e_devfn, + pt_pci_read_config, pt_pci_write_config); + if ( assigned_device == NULL ) + { + PT_LOG("Error: couldn't register real device\n"); + return NULL; + } + + assigned_device->pci_dev = pci_dev; + + /* Issue PCIe FLR */ + pdev_flr(pci_dev); + + /* Tell XEN vmm to change iommu settings */ + machine_bdf.reg = 0; + machine_bdf.bus = r_bus; + machine_bdf.dev = r_dev; + machine_bdf.func = r_func; + rc = xc_assign_device(xc_handle, domid, machine_bdf.value); + if ( rc < 0 ) + PT_LOG("Error: xc_domain_assign_device error %d\n", rc); + + /* Initialize virtualized PCI configuration (Extended 256 Bytes) */ + for ( i = 0; i < PCI_CONFIG_SIZE; i++ ) + assigned_device->dev.config[i] = pci_read_byte(pci_dev, i); + + /* Handle real device's MMIO/PIO BARs */ + pt_register_regions(assigned_device); + + /* Bind interrupt */ + e_device = (assigned_device->dev.devfn >> 3) & 0x1f; + e_intx = assigned_device->dev.config[0x3d]-1; + + if ( PT_MACHINE_IRQ_AUTO == machine_irq ) + machine_irq = pci_dev->irq; + + /* bind machine_irq to device */ + if ( 0 != machine_irq ) + { + rc = xc_domain_bind_pt_pci_irq(xc_handle, domid, machine_irq, 0, + e_device, e_intx); + if ( rc < 0 ) + { + /* TBD: unregister device in case of an error */ + PT_LOG("Error: Binding of interrupt failed! rc=%d\n", rc); + } + } + else { + /* Disable PCI intx assertion (turn on bit10 of devctl) */ + assigned_device->dev.config[0x05] |= 0x04; + pci_write_word(pci_dev, 0x04, + *(uint16_t *)(&assigned_device->dev.config[0x04])); + } + + PT_LOG("Real physical device %02x:%02x.%x registered successfuly!\n", + r_bus, r_dev, r_func); + + return assigned_device; +} + +int pt_init(PCIBus *e_bus, char *direct_pci) +{ + int i; + int seg, b, d, f; + struct pt_dev *pt_dev; + struct pci_access *pci_access; + int dev_count = pci_devs(direct_pci); + + /* Initialize libpci */ + pci_access = pci_alloc(); + if ( pci_access == NULL ) + { + PT_LOG("pci_access is NULL\n"); + return -1; + } + pci_init(pci_access); + pci_scan_bus(pci_access); + + /* Assign given devices to guest */ + for ( i = 0; i < dev_count; i++ ) + { + /* Get next device bdf (bus, device, function) */ + next_bdf(direct_pci, &seg, &b, &d, &f); + + /* Register real device with the emulated bus */ + pt_dev = register_real_device(e_bus, "DIRECT PCI", PT_VIRT_DEVFN_AUTO, + b, d, f, PT_MACHINE_IRQ_AUTO, pci_access); + if ( pt_dev == NULL ) + { + PT_LOG("Error: Registration failed (%02x:%02x.%x)\n", b, d, f); + return -1; + } + } + + /* Success */ + return 0; +} diff -r b3f681d71265 -r acfa9290746f tools/ioemu/hw/pass-through.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/ioemu/hw/pass-through.h Fri Sep 14 16:39:27 2007 +0100 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2007, Neocleus Corporation. + * Copyright (c) 2007, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __PASSTHROUGH_H__ +#define __PASSTHROUGH_H__ + +#include "vl.h" +#include "pci/header.h" +#include "pci/pci.h" + +/* Log acesss */ +#define PT_LOGGING_ENABLED + +#ifdef PT_LOGGING_ENABLED +#define PT_LOG(_f, _a...) fprintf(logfile, "%s: " _f, __func__, ##_a) +#else +#define PT_LOG(_f, _a...) +#endif + +/* Some compilation flags */ +// #define PT_DEBUG_PCI_CONFIG_ACCESS + +#define PT_MACHINE_IRQ_AUTO (0xFFFFFFFF) +#define PT_VIRT_DEVFN_AUTO (-1) + +/* Misc PCI constants that should be moved to a separate library :) */ +#define PCI_CONFIG_SIZE (256) +#define PCI_EXP_DEVCAP_FLR (1 << 28) +#define PCI_EXP_DEVCTL_FLR (0x1b) +#define PCI_BAR_ENTRIES (6) + +struct pt_region { + /* Virtual phys base & size */ + uint32_t e_physbase; + uint32_t e_size; + /* Index of region in qemu */ + uint32_t memory_index; + /* Translation of the emulated address */ + union { + uint32_t maddr; + uint32_t pio_base; + uint32_t u; + } access; +}; + +/* + This structure holds the context of the mapping functions + and data that is relevant for qemu device management. +*/ +struct pt_dev { + PCIDevice dev; + struct pci_dev *pci_dev; /* libpci struct */ + struct pt_region bases[PCI_NUM_REGIONS]; /* Access regions */ +}; + +/* Used for formatting PCI BDF into cf8 format */ +struct pci_config_cf8 { + union { + unsigned int value; + struct { + unsigned int reserved1:2; + unsigned int reg:6; + unsigned int func:3; + unsigned int dev:5; + unsigned int bus:8; + unsigned int reserved2:7; + unsigned int enable:1; + }; + }; +}; + +int pt_init(PCIBus * e_bus, char * direct_pci); + +#endif /* __PASSTHROUGH_H__ */ + diff -r b3f681d71265 -r acfa9290746f tools/ioemu/hw/pc.c --- a/tools/ioemu/hw/pc.c Fri Sep 14 16:10:08 2007 +0100 +++ b/tools/ioemu/hw/pc.c Fri Sep 14 16:39:27 2007 +0100 @@ -465,7 +465,7 @@ static void pc_init1(uint64_t ram_size, DisplayState *ds, const char **fd_filename, int snapshot, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, - int pci_enabled) + int pci_enabled, const char *direct_pci) { #ifndef NOBIOS char buf[1024]; @@ -480,6 +480,7 @@ static void pc_init1(uint64_t ram_size, int piix3_devfn = -1; CPUState *env; NICInfo *nd; + int rc; linux_boot = (kernel_filename != NULL); @@ -665,6 +666,19 @@ static void pc_init1(uint64_t ram_size, } } +#ifdef CONFIG_PASSTHROUGH + /* Pass-through Initialization */ + if ( pci_enabled && direct_pci ) + { + rc = pt_init(pci_bus, direct_pci); + if ( rc < 0 ) + { + fprintf(logfile, "Error: Initialization failed for pass-through devices\n"); + exit(1); + } + } +#endif + rtc_state = rtc_init(0x70, 8); register_ioport_read(0x92, 1, 1, ioport92_read, NULL); @@ -801,12 +815,14 @@ static void pc_init_pci(uint64_t ram_siz int snapshot, const char *kernel_filename, const char *kernel_cmdline, - const char *initrd_filename) + const char *initrd_filename, + const char *direct_pci) { pc_init1(ram_size, vga_ram_size, boot_device, ds, fd_filename, snapshot, kernel_filename, kernel_cmdline, - initrd_filename, 1); + initrd_filename, 1, + direct_pci); } static void pc_init_isa(uint64_t ram_size, int vga_ram_size, char *boot_device, @@ -814,12 +830,13 @@ static void pc_init_isa(uint64_t ram_siz int snapshot, const char *kernel_filename, const char *kernel_cmdline, - const char *initrd_filename) + const char *initrd_filename, + const char *unused) { pc_init1(ram_size, vga_ram_size, boot_device, ds, fd_filename, snapshot, kernel_filename, kernel_cmdline, - initrd_filename, 0); + initrd_filename, 0, NULL); } QEMUMachine pc_machine = { diff -r b3f681d71265 -r acfa9290746f tools/ioemu/vl.c --- a/tools/ioemu/vl.c Fri Sep 14 16:10:08 2007 +0100 +++ b/tools/ioemu/vl.c Fri Sep 14 16:39:27 2007 +0100 @@ -6513,6 +6513,7 @@ enum { QEMU_OPTION_acpi, QEMU_OPTION_vncviewer, QEMU_OPTION_vncunused, + QEMU_OPTION_pci, }; typedef struct QEMUOption { @@ -6610,6 +6611,7 @@ const QEMUOption qemu_options[] = { { "d", HAS_ARG, QEMU_OPTION_d }, { "vcpus", 1, QEMU_OPTION_vcpus }, { "acpi", 0, QEMU_OPTION_acpi }, + { "pci", HAS_ARG, QEMU_OPTION_pci}, { NULL }, }; @@ -7065,9 +7067,9 @@ int main(int argc, char **argv) extern void *buffered_pio_page; #endif sigset_t set; - char qemu_dm_logfilename[128]; - + const char *direct_pci = NULL; + /* Ensure that SIGUSR2 is blocked by default when a new thread is created, then only the threads that use the signal unblock it -- this fixes a race condition in Qcow support where the AIO signal is misdelivered. */ @@ -7560,6 +7562,9 @@ int main(int argc, char **argv) case QEMU_OPTION_vncunused: vncunused++; break; + case QEMU_OPTION_pci: + direct_pci = optarg; + break; } } } @@ -7926,7 +7931,8 @@ int main(int argc, char **argv) machine->init(ram_size, vga_ram_size, boot_device, ds, fd_filename, snapshot, - kernel_filename, kernel_cmdline, initrd_filename); + kernel_filename, kernel_cmdline, initrd_filename, + direct_pci); free(boot_device); /* init USB devices */ diff -r b3f681d71265 -r acfa9290746f tools/ioemu/vl.h --- a/tools/ioemu/vl.h Fri Sep 14 16:10:08 2007 +0100 +++ b/tools/ioemu/vl.h Fri Sep 14 16:39:27 2007 +0100 @@ -717,7 +717,7 @@ typedef void QEMUMachineInitFunc(uint64_ char *boot_device, DisplayState *ds, const char **fd_filename, int snapshot, const char *kernel_filename, const char *kernel_cmdline, - const char *initrd_filename); + const char *initrd_filename, const char *direct_pci); typedef struct QEMUMachine { const char *name; diff -r b3f681d71265 -r acfa9290746f tools/libxc/xc_domain.c --- a/tools/libxc/xc_domain.c Fri Sep 14 16:10:08 2007 +0100 +++ b/tools/libxc/xc_domain.c Fri Sep 14 16:39:27 2007 +0100 @@ -734,6 +734,114 @@ int xc_domain_setdebugging(int xc_handle return do_domctl(xc_handle, &domctl); } +int xc_assign_device( + int xc_handle, + uint32_t domid, + uint32_t machine_bdf) +{ + DECLARE_DOMCTL; + + domctl.cmd = XEN_DOMCTL_assign_device; + domctl.domain = domid; + domctl.u.assign_device.machine_bdf = machine_bdf; + + return do_domctl(xc_handle, &domctl); +} + +/* Pass-through: binds machine irq to guests irq */ +int xc_domain_bind_pt_irq( + int xc_handle, + uint32_t domid, + uint8_t machine_irq, + uint8_t irq_type, + uint8_t bus, + uint8_t device, + uint8_t intx, + uint8_t isa_irq) +{ + int rc; + xen_domctl_bind_pt_irq_t * bind; + DECLARE_DOMCTL; + + domctl.cmd = XEN_DOMCTL_bind_pt_irq; + domctl.domain = (domid_t)domid; + + bind = &(domctl.u.bind_pt_irq); + bind->hvm_domid = domid; + bind->irq_type = irq_type; + bind->machine_irq = machine_irq; + bind->u.pci.bus = bus; + bind->u.pci.device = device; + bind->u.pci.intx = intx; + bind->u.isa.isa_irq = isa_irq; + + rc = do_domctl(xc_handle, &domctl); + return rc; +} + +int xc_domain_bind_pt_pci_irq( + int xc_handle, + uint32_t domid, + uint8_t machine_irq, + uint8_t bus, + uint8_t device, + uint8_t intx) +{ + + return (xc_domain_bind_pt_irq(xc_handle, domid, machine_irq, + PT_IRQ_TYPE_PCI, bus, device, intx, 0)); +} + +int xc_domain_bind_pt_isa_irq( + int xc_handle, + uint32_t domid, + uint8_t machine_irq) +{ + + return (xc_domain_bind_pt_irq(xc_handle, domid, machine_irq, + PT_IRQ_TYPE_ISA, 0, 0, 0, machine_irq)); +} + +int xc_domain_memory_mapping( + int xc_handle, + uint32_t domid, + unsigned long first_gfn, + unsigned long first_mfn, + unsigned long nr_mfns, + uint32_t add_mapping) +{ + DECLARE_DOMCTL; + + domctl.cmd = XEN_DOMCTL_memory_mapping; + domctl.domain = domid; + domctl.u.memory_mapping.first_gfn = first_gfn; + domctl.u.memory_mapping.first_mfn = first_mfn; + domctl.u.memory_mapping.nr_mfns = nr_mfns; + domctl.u.memory_mapping.add_mapping = add_mapping; + + return do_domctl(xc_handle, &domctl); +} + +int xc_domain_ioport_mapping( + int xc_handle, + uint32_t domid, + uint32_t first_gport, + uint32_t first_mport, + uint32_t nr_ports, + uint32_t add_mapping) +{ + DECLARE_DOMCTL; + + domctl.cmd = XEN_DOMCTL_ioport_mapping; + domctl.domain = domid; + domctl.u.ioport_mapping.first_gport = first_gport; + domctl.u.ioport_mapping.first_mport = first_mport; + domctl.u.ioport_mapping.nr_ports = nr_ports; + domctl.u.ioport_mapping.add_mapping = add_mapping; + + return do_domctl(xc_handle, &domctl); +} + /* * Local variables: * mode: C diff -r b3f681d71265 -r acfa9290746f tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Fri Sep 14 16:10:08 2007 +0100 +++ b/tools/libxc/xenctrl.h Fri Sep 14 16:39:27 2007 +0100 @@ -897,4 +897,43 @@ int xc_ia64_save_to_nvram(int xc_handle, /* IA64 specific, nvram init */ int xc_ia64_nvram_init(int xc_handle, char *dom_name, uint32_t dom); +/* HVM guest pass-through */ +int xc_assign_device(int xc_handle, + uint32_t domid, + uint32_t machine_bdf); + +int xc_domain_memory_mapping(int xc_handle, + uint32_t domid, + unsigned long first_gfn, + unsigned long first_mfn, + unsigned long nr_mfns, + uint32_t add_mapping); + +int xc_domain_ioport_mapping(int xc_handle, + uint32_t domid, + uint32_t first_gport, + uint32_t first_mport, + uint32_t nr_ports, + uint32_t add_mapping); + +int xc_domain_bind_pt_irq(int xc_handle, + uint32_t domid, + uint8_t machine_irq, + uint8_t irq_type, + uint8_t bus, + uint8_t device, + uint8_t intx, + uint8_t isa_irq); + +int xc_domain_bind_pt_pci_irq(int xc_handle, + uint32_t domid, + uint8_t machine_irq, + uint8_t bus, + uint8_t device, + uint8_t intx); + +int xc_domain_bind_pt_isa_irq(int xc_handle, + uint32_t domid, + uint8_t machine_irq); + #endif /* XENCTRL_H */ diff -r b3f681d71265 -r acfa9290746f tools/python/xen/xend/XendConfig.py --- a/tools/python/xen/xend/XendConfig.py Fri Sep 14 16:10:08 2007 +0100 +++ b/tools/python/xen/xend/XendConfig.py Fri Sep 14 16:39:27 2007 +0100 @@ -127,7 +127,7 @@ XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 'nographic', 'pae', 'rtc_timeoffset', 'serial', 'sdl', 'soundhw','stdvga', 'usb', 'usbdevice', 'vnc', 'vncconsole', 'vncdisplay', 'vnclisten', - 'vncpasswd', 'vncunused', 'xauthority'] + 'vncpasswd', 'vncunused', 'xauthority', 'pci'] # Xen API console 'other_config' keys. XENAPI_CONSOLE_OTHER_CFG = ['vncunused', 'vncdisplay', 'vnclisten', @@ -168,6 +168,7 @@ XENAPI_CFG_TYPES = { 'tools_version': dict, 'other_config': dict, 'security_label': str, + 'pci': str, } # List of legacy configuration keys that have no equivalent in the diff -r b3f681d71265 -r acfa9290746f tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py Fri Sep 14 16:10:08 2007 +0100 +++ b/tools/python/xen/xend/image.py Fri Sep 14 16:39:27 2007 +0100 @@ -309,7 +309,7 @@ class HVMImageHandler(ImageHandler): def parseDeviceModelArgs(self, vmConfig): dmargs = [ 'boot', 'fda', 'fdb', 'soundhw', 'localtime', 'serial', 'stdvga', 'isa', - 'acpi', 'usb', 'usbdevice', 'keymap' ] + 'acpi', 'usb', 'usbdevice', 'keymap', 'pci' ] ret = ['-vcpus', str(self.vm.getVCpuCount())] diff -r b3f681d71265 -r acfa9290746f tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Fri Sep 14 16:10:08 2007 +0100 +++ b/tools/python/xen/xm/create.py Fri Sep 14 16:39:27 2007 +0100 @@ -721,7 +721,7 @@ def configure_hvm(config_image, vals): 'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'soundhw', 'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten', 'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor', - 'acpi', 'apic', 'usb', 'usbdevice', 'keymap' ] + 'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci' ] for a in args: if a in vals.__dict__ and vals.__dict__[a] is not None: config_image.append([a, vals.__dict__[a]]) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |