[EMAIL PROTECTED] wrote: > From: Muli Ben-Yehuda <[EMAIL PROTECTED]> > > This patch has been contributed to by the following people: > > Or Sagi <[EMAIL PROTECTED]> > Nir Peleg <[EMAIL PROTECTED]> > Amit Shah <[EMAIL PROTECTED]> > Ben-Ami Yassour <[EMAIL PROTECTED]> > Weidong Han <[EMAIL PROTECTED]> > Glauber de Oliveira Costa <[EMAIL PROTECTED]> > Muli Ben-Yehuda <[EMAIL PROTECTED]> > > With this patch, we can assign a device on the host machine to a > guest. > > A new command-line option, -pcidevice is added. > To invoke it for a device sitting at PCI bus:dev.fn 04:08.0, use this: > > -pcidevice host=04:08.0 > > * The host driver for the device, if any, is to be removed before > assigning the device (else device assignment will fail). > > * A device that shares IRQ with another host device cannot currently > be assigned. > > * The RAW_IO capability is needed for this to work > > This works only with the in-kernel irqchip method; to use the > userspace irqchip, a kernel module (irqhook) and some extra changes > are needed. > > [muli: lots of small fixes from Muli and Weidong Han addressing all v7 > review comments] > > Signed-off-by: Amit Shah <[EMAIL PROTECTED]> > Signed-off-by: Muli Ben-Yehuda <[EMAIL PROTECTED]> > --- > qemu/Makefile.target | 3 + > qemu/hw/device-assignment.c | 641 > +++++++++++++++++++++++++++++++++++++++++++ > qemu/hw/device-assignment.h | 117 ++++++++ qemu/hw/pc.c > | 16 + qemu/hw/pci.c | 7 + > qemu/qemu-kvm.c | 14 + > qemu/qemu-kvm.h | 8 + > qemu/vl.c | 28 ++ > 8 files changed, 834 insertions(+), 0 deletions(-) > create mode 100644 qemu/hw/device-assignment.c > create mode 100644 qemu/hw/device-assignment.h > > diff --git a/qemu/Makefile.target b/qemu/Makefile.target > index d9bdeca..5d44e08 100644 > --- a/qemu/Makefile.target > +++ b/qemu/Makefile.target > @@ -621,6 +621,9 @@ OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o > OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o > OBJS+= cirrus_vga.o apic.o parallel.o acpi.o piix_pci.o > OBJS+= usb-uhci.o vmmouse.o vmport.o vmware_vga.o extboot.o > +ifeq ($(USE_KVM), 1) > +OBJS+= device-assignment.o > +endif > ifeq ($(USE_KVM_PIT), 1) > OBJS+= i8254-kvm.o > endif > diff --git a/qemu/hw/device-assignment.c b/qemu/hw/device-assignment.c > new file mode 100644 > index 0000000..89b05f9 > --- /dev/null > +++ b/qemu/hw/device-assignment.c > @@ -0,0 +1,641 @@ > +/* > + * Copyright (c) 2007, Neocleus 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. + * > + * > + * Assign a PCI device from the host to a guest VM. > + * > + * Adapted for KVM by Qumranet. > + * > + * Copyright (c) 2007, Neocleus, Alex Novik ([EMAIL PROTECTED]) > + * Copyright (c) 2007, Neocleus, Guy Zana ([EMAIL PROTECTED]) > + * Copyright (C) 2008, Qumranet, Amit Shah ([EMAIL PROTECTED]) > + * Copyright (C) 2008, Red Hat, Amit Shah ([EMAIL PROTECTED]) > + * Copyright (C) 2008, IBM, Muli Ben-Yehuda ([EMAIL PROTECTED]) > + */ > +#include <stdio.h> > +#include <sys/io.h> > +#include "qemu-kvm.h" > +#include "hw.h" > +#include "pc.h" > +#include "sysemu.h" > +#include "console.h" > +#include "device-assignment.h" > + > +/* From linux/ioport.h */ > +#define IORESOURCE_IO 0x00000100 /* Resource type */ > +#define IORESOURCE_MEM 0x00000200 > +#define IORESOURCE_IRQ 0x00000400 > +#define IORESOURCE_DMA 0x00000800 > +#define IORESOURCE_PREFETCH 0x00001000 /* No side effects */ > + > +/* #define DEVICE_ASSIGNMENT_DEBUG 1 */ > + > +#ifdef DEVICE_ASSIGNMENT_DEBUG > +#define DEBUG(fmt, ...) \ > + do { \ > + fprintf(stderr, "%s: " fmt, __func__ , __VA_ARGS__); \ > + } while (0) > +#else > +#define DEBUG(fmt, ...) do { } while(0) > +#endif > + > +static uint32_t guest_to_host_ioport(AssignedDevRegion *region, > uint32_t addr) +{ > + return region->u.r_baseport + (addr - region->e_physbase); > +} > + > +static void assigned_dev_ioport_writeb(void *opaque, uint32_t addr, > + uint32_t value) > +{ > + AssignedDevRegion *r_access = opaque; > + uint32_t r_pio = guest_to_host_ioport(r_access, addr); > + > + DEBUG("r_pio=%08x e_physbase=%08x r_virtbase=%08lx value=%08x\n", > + r_pio, (int)r_access->e_physbase, > + (unsigned long)r_access->r_virtbase, value);
should be (unsigned long)r_access->u.r_virtbase > + > + outb(value, r_pio); > +} > + > +static void assigned_dev_ioport_writew(void *opaque, uint32_t addr, > + uint32_t value) > +{ > + AssignedDevRegion *r_access = opaque; > + uint32_t r_pio = guest_to_host_ioport(r_access, addr); > + > + DEBUG("r_pio=%08x e_physbase=%08x r_virtbase=%08lx value=%08x\n", > + __func__, r_pio, (int)r_access->e_physbase, > + (unsigned long)r_access->r_virtbase, value); (unsigned long)r_access->u.r_virtbase > + > + outw(value, r_pio); > +} > + > +static void assigned_dev_ioport_writel(void *opaque, uint32_t addr, > + uint32_t value) > +{ > + AssignedDevRegion *r_access = opaque; > + uint32_t r_pio = guest_to_host_ioport(r_access, addr); > + > + DEBUG("%s: r_pio=%08x e_physbase=%08x r_virtbase=%08lx > value=%08x\n", + r_pio, (int)r_access->e_physbase, > + (unsigned long)r_access->r_virtbase, value); (unsigned long)r_access->u.r_virtbase > + > + outl(value, r_pio); > +} > + > +static uint32_t assigned_dev_ioport_readb(void *opaque, uint32_t > addr) +{ > + AssignedDevRegion *r_access = opaque; > + uint32_t r_pio = guest_to_host_ioport(r_access, addr); > + uint32_t value; > + > + value = inb(r_pio); > + > + DEBUG("r_pio=%08x e_physbase=%08x r_virtbase=%08lx value=%08x\n", > + r_pio, (int)r_access->e_physbase, > + (unsigned long)r_access->r_virtbase, value); (unsigned long)r_access->u.r_virtbase > + > + return value; > +} > + > +static uint32_t assigned_dev_ioport_readw(void *opaque, uint32_t > addr) +{ > + AssignedDevRegion *r_access = opaque; > + uint32_t r_pio = guest_to_host_ioport(r_access, addr); > + uint32_t value; > + > + value = inw(r_pio); > + > + DEBUG("r_pio=%08x e_physbase=%08x r_virtbase=%08lx value=%08x\n", > + r_pio, (int)r_access->e_physbase, > + (unsigned long)r_access->r_virtbase, value); (unsigned long)r_access->u.r_virtbase > + > + return value; > +} > + > +static uint32_t assigned_dev_ioport_readl(void *opaque, uint32_t > addr) +{ > + AssignedDevRegion *r_access = opaque; > + uint32_t r_pio = guest_to_host_ioport(r_access, addr); > + uint32_t value; > + > + value = inl(r_pio); > + > + DEBUG("r_pio=%08x e_physbase=%08x r_virtbase=%08lx value=%08x\n", > + r_pio, (int)r_access->e_physbase, > + (unsigned long)r_access->r_virtbase, value); (unsigned long)r_access->u.r_virtbase > + > + return value; > +} > + > +static void assigned_dev_iomem_map(PCIDevice *pci_dev, int > region_num, + uint32_t e_phys, > uint32_t e_size, int type) +{ > + AssignedDevice *r_dev = (AssignedDevice *) pci_dev; > + AssignedDevRegion *region = &r_dev->v_addrs[region_num]; > + uint32_t old_ephys = region->e_physbase; > + uint32_t old_esize = region->e_size; > + int first_map = (region->e_size == 0); > + int ret = 0; > + > + DEBUG("e_phys=%08x r_virt=%x type=%d len=%08x region_num=%d \n", > + e_phys, (uint32_t)region->r_virtbase, type, e_size, (uint32_t)r_access->u.r_virtbase Regards, Weidong -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html