Could you consider applying the following patches?
They fix the bugs of PCI pass-through.
[PATCH] ioemu: Fix MSI/MSI-X capability structure virtualization code
[PATCH] ioemu: fix pt_chk_bar_overlap
[PATCH] ioemu: unmap INTx interrupt on hot-remove
Thanks,
--
Yuji Shimada
On Fri, 13 Mar 2009 13:57:58 +0900
Yuji Shimada <shimada-yxb@xxxxxxxxxxxxxxx> wrote:
> This patch fixes MSI/MSI-X capability structure virtualization code.
>
> Currently, xen does not support multiple message (multiple vector).
> So multiple message capable field should be emulated and fixed to 0
> (single vector).
>
> With the patch, my FC-HBA works when I assign it to guest domain where
> windows 2008 runs.
>
>
> In addition to this, initial values of emulated registers should be
> the same with initial values defined in PCI spec. If initial values
> are not defined, they should be 0. The emulated field mask and
> read-only field mask are also fixed.
>
> Thanks,
> --
> Yuji Shimada
>
>
> Signed-off-by: Yuji Shimada <shimada-yxb@xxxxxxxxxxxxxxx>
>
> diff --git a/hw/pass-through.c b/hw/pass-through.c
> index 308bcc3..487b08d 100644
> --- a/hw/pass-through.c
> +++ b/hw/pass-through.c
> @@ -73,8 +73,6 @@ static uint32_t pt_linkctrl2_reg_init(struct pt_dev *ptdev,
> struct pt_reg_info_tbl *reg, uint32_t real_offset);
> static uint32_t pt_msgctrl_reg_init(struct pt_dev *ptdev,
> struct pt_reg_info_tbl *reg, uint32_t real_offset);
> -static uint32_t pt_msgaddr32_reg_init(struct pt_dev *ptdev,
> - struct pt_reg_info_tbl *reg, uint32_t real_offset);
> static uint32_t pt_msgaddr64_reg_init(struct pt_dev *ptdev,
> struct pt_reg_info_tbl *reg, uint32_t real_offset);
> static uint32_t pt_msgdata_reg_init(struct pt_dev *ptdev,
> @@ -552,8 +550,8 @@ static struct pt_reg_info_tbl pt_emu_reg_msi_tbl[] = {
> .offset = PCI_MSI_FLAGS, // 2
> .size = 2,
> .init_val = 0x0000,
> - .ro_mask = 0x018E,
> - .emu_mask = 0xFFFF,
> + .ro_mask = 0xFF8E,
> + .emu_mask = 0x007F,
> .init = pt_msgctrl_reg_init,
> .u.w.read = pt_word_reg_read,
> .u.w.write = pt_msgctrl_reg_write,
> @@ -564,9 +562,9 @@ static struct pt_reg_info_tbl pt_emu_reg_msi_tbl[] = {
> .offset = PCI_MSI_ADDRESS_LO, // 4
> .size = 4,
> .init_val = 0x00000000,
> - .ro_mask = 0x00000FF0, /* bit 4~11 is reserved for MSI in x86
> */
> + .ro_mask = 0x00000003,
> .emu_mask = 0xFFFFFFFF,
> - .init = pt_msgaddr32_reg_init,
> + .init = pt_common_reg_init,
> .u.dw.read = pt_long_reg_read,
> .u.dw.write = pt_msgaddr32_reg_write,
> .u.dw.restore = NULL,
> @@ -588,7 +586,7 @@ static struct pt_reg_info_tbl pt_emu_reg_msi_tbl[] = {
> .offset = PCI_MSI_DATA_32, // 8
> .size = 2,
> .init_val = 0x0000,
> - .ro_mask = 0x3800,
> + .ro_mask = 0x0000,
> .emu_mask = 0xFFFF,
> .init = pt_msgdata_reg_init,
> .u.w.read = pt_word_reg_read,
> @@ -600,7 +598,7 @@ static struct pt_reg_info_tbl pt_emu_reg_msi_tbl[] = {
> .offset = PCI_MSI_DATA_64, // 12
> .size = 2,
> .init_val = 0x0000,
> - .ro_mask = 0x3800,
> + .ro_mask = 0x0000,
> .emu_mask = 0xFFFF,
> .init = pt_msgdata_reg_init,
> .u.w.read = pt_word_reg_read,
> @@ -2456,7 +2454,7 @@ static uint32_t pt_msgctrl_reg_init(struct pt_dev
> *ptdev,
> uint32_t reg_field = 0;
>
> /* use I/O device register's value as initial value */
> - reg_field |= *((uint16_t*)(d->config + real_offset));
> + reg_field = *((uint16_t*)(d->config + real_offset));
>
> if (reg_field & PCI_MSI_FLAGS_ENABLE)
> {
> @@ -2466,40 +2464,18 @@ static uint32_t pt_msgctrl_reg_init(struct pt_dev
> *ptdev,
> ptdev->msi->flags |= (reg_field | MSI_FLAG_UNINIT);
> ptdev->msi->ctrl_offset = real_offset;
>
> - /* All register is 0 after reset, except first 4 byte */
> - reg_field &= reg->ro_mask;
> -
> - return reg_field;
> -}
> -
> -/* initialize Message Address register */
> -static uint32_t pt_msgaddr32_reg_init(struct pt_dev *ptdev,
> - struct pt_reg_info_tbl *reg, uint32_t real_offset)
> -{
> - PCIDevice *d = (struct PCIDevice *)ptdev;
> - uint32_t reg_field = 0;
> -
> - /* use I/O device register's value as initial value */
> - reg_field |= *((uint32_t*)(d->config + real_offset));
> -
> - return reg_field;
> + return reg->init_val;
> }
>
> /* initialize Message Upper Address register */
> static uint32_t pt_msgaddr64_reg_init(struct pt_dev *ptdev,
> struct pt_reg_info_tbl *reg, uint32_t real_offset)
> {
> - PCIDevice *d = (struct PCIDevice *)ptdev;
> - uint32_t reg_field = 0;
> -
> /* no need to initialize in case of 32 bit type */
> if (!(ptdev->msi->flags & PCI_MSI_FLAGS_64BIT))
> return PT_INVALID_REG;
>
> - /* use I/O device register's value as initial value */
> - reg_field |= *((uint32_t*)(d->config + real_offset));
> -
> - return reg_field;
> + return reg->init_val;
> }
>
> /* this function will be called twice (for 32 bit and 64 bit type) */
> @@ -2507,14 +2483,13 @@ static uint32_t pt_msgaddr64_reg_init(struct pt_dev
> *ptdev,
> static uint32_t pt_msgdata_reg_init(struct pt_dev *ptdev,
> struct pt_reg_info_tbl *reg, uint32_t real_offset)
> {
> - PCIDevice *d = (struct PCIDevice *)ptdev;
> uint32_t flags = ptdev->msi->flags;
> uint32_t offset = reg->offset;
>
> /* check the offset whether matches the type or not */
> if (((offset == PCI_MSI_DATA_64) && (flags & PCI_MSI_FLAGS_64BIT)) ||
> ((offset == PCI_MSI_DATA_32) && !(flags & PCI_MSI_FLAGS_64BIT)))
> - return *((uint16_t*)(d->config + real_offset));
> + return reg->init_val;
> else
> return PT_INVALID_REG;
> }
> @@ -2528,18 +2503,17 @@ static uint32_t pt_msixctrl_reg_init(struct pt_dev
> *ptdev,
> uint16_t reg_field = 0;
>
> /* use I/O device register's value as initial value */
> - reg_field |= *((uint16_t*)(d->config + real_offset));
> + reg_field = *((uint16_t*)(d->config + real_offset));
>
> if (reg_field & PCI_MSIX_ENABLE)
> {
> PT_LOG("MSIX enabled already, disable first\n");
> pci_write_word(pdev, real_offset, reg_field & ~PCI_MSIX_ENABLE);
> - reg_field &= ~(PCI_MSIX_ENABLE | PCI_MSIX_MASK);
> }
>
> ptdev->msix->ctrl_offset = real_offset;
>
> - return reg_field;
> + return reg->init_val;
> }
>
> /* get register group size */
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|