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

Reply via email to