Su, Disheng wrote: > Amit Shah wrote: >> This patch has been contributed to by the following people: >> >> From: Or Sagi <[EMAIL PROTECTED]> >> From: Nir Peleg <[EMAIL PROTECTED]> >> From: Amit Shah <[EMAIL PROTECTED]> >> From: Ben-Ami Yassour <[EMAIL PROTECTED]> >> From: Weidong Han <[EMAIL PROTECTED]> >> From: Glauber de Oliveira Costa <[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. >> >> Signed-off-by: Amit Shah <[EMAIL PROTECTED]> >> --- >> qemu/Makefile.target | 1 + >> qemu/hw/device-assignment.c | 619 >> +++++++++++++++++++++++++++++++++++++++++++ >> qemu/hw/device-assignment.h | 98 +++++++ qemu/hw/pc.c >> | 6 + qemu/hw/pci.c | 7 + >> qemu/vl.c | 18 ++ >> 6 files changed, 749 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..05a1d84 100644 >> --- a/qemu/Makefile.target >> +++ b/qemu/Makefile.target >> @@ -621,6 +621,7 @@ 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 +OBJS+= >> device-assignment.o 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..5ba21a0 --- /dev/null >> +++ b/qemu/hw/device-assignment.c >> @@ -0,0 +1,619 @@ >> +/* >> + * 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]) + >> */ +#include <stdio.h> >> +#include <sys/io.h> >> +#include "qemu-kvm.h" >> +#include "hw.h" >> +#include "pc.h" >> +#include "sysemu.h" >> +#include "console.h" >> +#include <linux/kvm_para.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, args...) \ >> + do { \ >> + fprintf(stderr, "%s: " fmt, __func__ , ## args); \ + } >> while (0) +#else >> +#define DEBUG(fmt, args...) do { } while(0) >> +#endif >> + >> +static void assigned_dev_ioport_writeb(void *opaque, uint32_t addr, >> + uint32_t value) +{ >> + AssignedDevRegion *r_access = (AssignedDevRegion *)opaque; >> + uint32_t r_pio = (unsigned long)r_access->r_virtbase >> + + (addr - r_access->e_physbase); >> + >> + DEBUG(stderr, "%s: 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); + >> outb(value, r_pio); +} >> + >> +static void assigned_dev_ioport_writew(void *opaque, uint32_t addr, >> + uint32_t value) +{ >> + AssignedDevRegion *r_access = (AssignedDevRegion *)opaque; >> + uint32_t r_pio = (unsigned long)r_access->r_virtbase >> + + (addr - r_access->e_physbase); >> + >> + DEBUG(stderr, "%s: 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); + >> outw(value, r_pio); +} >> + >> +static void assigned_dev_ioport_writel(void *opaque, uint32_t addr, >> + uint32_t value) >> +{ >> + AssignedDevRegion *r_access = (AssignedDevRegion *)opaque; >> + uint32_t r_pio = (unsigned long)r_access->r_virtbase >> + + (addr - r_access->e_physbase); >> + >> + DEBUG(stderr, "%s: 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); + >> outl(value, r_pio); +} >> + >> +static uint32_t assigned_dev_ioport_readb(void *opaque, uint32_t >> addr) +{ + AssignedDevRegion *r_access = (AssignedDevRegion >> *)opaque; + uint32_t r_pio = (addr - r_access->e_physbase) >> + + (unsigned long)r_access->r_virtbase; >> + uint32_t value; >> + >> + value = inb(r_pio); >> + DEBUG(stderr, "%s: 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); + return >> value; +} >> + >> +static uint32_t assigned_dev_ioport_readw(void *opaque, uint32_t >> addr) +{ + AssignedDevRegion *r_access = (AssignedDevRegion >> *)opaque; + uint32_t r_pio = (addr - r_access->e_physbase) >> + + (unsigned long)r_access->r_virtbase; >> + uint32_t value; >> + >> + value = inw(r_pio); >> + DEBUG(stderr, "%s: 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); + return >> value; +} >> + >> +static uint32_t assigned_dev_ioport_readl(void *opaque, uint32_t >> addr) +{ + AssignedDevRegion *r_access = (AssignedDevRegion >> *)opaque; + uint32_t r_pio = (addr - r_access->e_physbase) >> + + (unsigned long)r_access->r_virtbase; >> + uint32_t value; >> + >> + value = inl(r_pio); >> + DEBUG(stderr, "%s: 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); + 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]; + int first_map = (region->e_size == >> 0); + int ret = 0; >> + >> + DEBUG("%s: e_phys=%08x r_virt=%x type=%d len=%08x region_num=%d >> \n", + __func__, e_phys, (uint32_t)region->r_virtbase, type, >> e_size, + region_num); >> + >> + region->e_physbase = e_phys; >> + region->e_size = e_size; >> + >> + /* FIXME: Add support for emulated MMIO for non-kvm guests */ + >> if (kvm_enabled()) { + if (!first_map) >> + kvm_destroy_phys_mem(kvm_context, e_phys, e_size); > A typo? Need to destory orignal registered address?
Yes, it's buggy. It should like: uint32_t old_ephys = region->e_physbase; uint32_t old_esize = region->e_size; ... kvm_destroy_phys_mem(kvm_context, old_ephys, old_esize); ... 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