HV: Fix VPCI bugs found in integration testing for partition mode

Tracked-On: #1126
Signed-off-by: dongshen <dongsheng.x.zhang@intel.com>
This commit is contained in:
dongshen 2018-08-28 16:47:55 -07:00 committed by lijinxia
parent 308910ebf7
commit 36c4a27abc
3 changed files with 31 additions and 21 deletions

View File

@ -115,7 +115,9 @@ static int vdev_hostbridge_cfgwrite(struct pci_vdev *vdev, uint32_t offset,
return -EINVAL; return -EINVAL;
} }
pci_vdev_write_cfg(vdev, offset, bytes, val); if (!pci_bar_access(offset)) {
pci_vdev_write_cfg(vdev, offset, bytes, val);
}
return 0; return 0;
} }

View File

@ -42,7 +42,6 @@
#define PCIR_VENDOR 0x00U #define PCIR_VENDOR 0x00U
#define PCIR_DEVICE 0x02U #define PCIR_DEVICE 0x02U
#define PCIR_COMMAND 0x04U #define PCIR_COMMAND 0x04U
#define PCIM_CMD_MEMEN 0x0002U
#define PCIR_REVID 0x08U #define PCIR_REVID 0x08U
#define PCIR_SUBCLASS 0x0AU #define PCIR_SUBCLASS 0x0AU
#define PCIR_CLASS 0x0BU #define PCIR_CLASS 0x0BU

View File

@ -131,6 +131,7 @@ static int vdev_pt_init(struct pci_vdev *vdev)
{ {
int ret; int ret;
struct vm *vm = vdev->vpci->vm; struct vm *vm = vdev->vpci->vm;
uint16_t pci_command;
ret = vdev_pt_init_validate(vdev); ret = vdev_pt_init_validate(vdev);
if (ret != 0) { if (ret != 0) {
@ -150,6 +151,11 @@ static int vdev_pt_init(struct pci_vdev *vdev)
ret = assign_iommu_device(vm->iommu, vdev->pdev.bdf.bits.b, ret = assign_iommu_device(vm->iommu, vdev->pdev.bdf.bits.b,
(uint8_t)(vdev->pdev.bdf.value & 0xFFU)); (uint8_t)(vdev->pdev.bdf.value & 0xFFU));
pci_command = pci_pdev_read_cfg(&vdev->pdev, PCIR_COMMAND, 2U);
/* Disable INTX */
pci_command |= 0x400U;
pci_pdev_write_cfg(&vdev->pdev, PCIR_COMMAND, 2U, pci_command);
return ret; return ret;
} }
@ -212,44 +218,47 @@ static int vdev_pt_remap_bar(struct pci_vdev *vdev, uint32_t idx,
return error; return error;
} }
static uint32_t memen(struct pci_vdev *vdev)
{
return pci_pdev_read_cfg(&vdev->pdev, PCIR_COMMAND, 2U)
& PCIM_CMD_MEMEN;
}
static void vdev_pt_cfgwrite_bar(struct pci_vdev *vdev, uint32_t offset, static void vdev_pt_cfgwrite_bar(struct pci_vdev *vdev, uint32_t offset,
uint32_t bytes, uint32_t new_bar_uos) uint32_t bytes, uint32_t new_bar_uos)
{ {
uint32_t idx; uint32_t idx;
uint32_t new_bar, mask; uint32_t new_bar, mask;
bool bar_update_normal = 1; bool bar_update_normal;
bool do_map;
int error; int error;
if ((bytes != 4U) || ((offset & 0x3U) != 0U)) { if ((bytes != 4U) || ((offset & 0x3U) != 0U)) {
return; return;
} }
new_bar = 0U;
idx = (offset - pci_bar_offset(0U)) >> 2U; idx = (offset - pci_bar_offset(0U)) >> 2U;
mask = ~(vdev->bar[idx].size - 1U); mask = ~(vdev->bar[idx].size - 1U);
bar_update_normal = (new_bar_uos != (uint32_t)~0U);
new_bar = new_bar_uos & mask;
if (pci_bar_base(new_bar) == vdev->bar[idx].base) { switch (vdev->bar[idx].type) {
return; case PCIBAR_NONE:
} vdev->bar[idx].base = 0UL;
break;
do_map = (memen(vdev)) && bar_update_normal; case PCIBAR_MEM32:
if (do_map) { bar_update_normal = (new_bar_uos != (uint32_t)~0U);
error = vdev_pt_remap_bar(vdev, idx, pci_bar_base(new_bar)); new_bar = new_bar_uos & mask;
if (error != 0) { if (bar_update_normal) {
pr_err("vdev_pt_remap_bar failed: %d", idx); error = vdev_pt_remap_bar(vdev, idx,
pci_bar_base(new_bar));
if (error != 0) {
pr_err("vdev_pt_remap_bar failed: %d", idx);
}
vdev->bar[idx].base = pci_bar_base(new_bar);
} }
break;
default:
pr_err("Unknown bar type, idx=%d", idx);
break;
} }
pci_vdev_write_cfg_u32(vdev, offset, new_bar); pci_vdev_write_cfg_u32(vdev, offset, new_bar);
vdev->bar[idx].base = pci_bar_base(new_bar);
} }
static int vdev_pt_cfgwrite(struct pci_vdev *vdev, uint32_t offset, static int vdev_pt_cfgwrite(struct pci_vdev *vdev, uint32_t offset,