dm: ensure identical mapping of pass-thru dev PIO bar

For pass-thru dev PIO bar,ensure it's identical mapping
(guest PIO bar start address equals to host PIO bar start address).
Then in HV side, set the corresponding VMCS io bitmap
to pass-thru these io ports for performance.

Tracked-On: #6508

Signed-off-by: Fei Li <fei1.li@intel.com>
Acked-by: Wang, Yu1 <yu1.wang@intel.com>
This commit is contained in:
Liu,Junming 2021-09-08 14:31:58 +00:00 committed by wenlingz
parent d700154c90
commit 30d2915309
3 changed files with 84 additions and 42 deletions

View File

@ -1371,7 +1371,7 @@ init_pci(struct vmctx *ctx)
struct slotinfo *si;
struct funcinfo *fi;
int bus, slot, func, i;
int success_cnt = 0;
int success_cnt[2] = {0}; /* 0 for passthru and 1 for others */
int error;
uint64_t bus0_memlimit;
@ -1393,25 +1393,40 @@ init_pci(struct vmctx *ctx)
bi->membase32 = pci_emul_membase32;
bi->membase64 = pci_emul_membase64;
for (slot = 0; slot < MAXSLOTS; slot++) {
si = &bi->slotinfo[slot];
for (func = 0; func < MAXFUNCS; func++) {
fi = &si->si_funcs[func];
if (fi->fi_name == NULL)
continue;
ops = pci_emul_finddev(fi->fi_name);
if (!ops) {
pr_warn("No driver for device [%s]\n", fi->fi_name);
continue;
/*
* Initialize pass-thru devices firstly to reserve PIO bar regions.
* For pass-thru devices, ACRN-DM need to ensure PIO bar regions identical mapping
* (guest PIO bar start address equals to host PIO bar start address).
*
* Then initialize non pass-thru devices.
*/
for (i = 0; i < 2; i++) {
for (slot = 0; slot < MAXSLOTS; slot++) {
si = &bi->slotinfo[slot];
for (func = 0; func < MAXFUNCS; func++) {
fi = &si->si_funcs[func];
if (fi->fi_name == NULL)
continue;
ops = pci_emul_finddev(fi->fi_name);
if (!ops) {
pr_warn("No driver for device [%s]\n", fi->fi_name);
continue;
}
if ((i == 0) && strcmp(ops->class_name, "passthru")) {
continue;
} else if ((i == 1) && !strcmp(ops->class_name, "passthru")) {
continue;
}
pr_notice("pci init %s\r\n", fi->fi_name);
error = pci_emul_init(ctx, ops, bus, slot, func, fi);
if (error) {
pr_err("pci %s init failed\n", fi->fi_name);
goto pci_emul_init_fail;
}
success_cnt[i]++;
}
pr_notice("pci init %s\r\n", fi->fi_name);
error = pci_emul_init(ctx, ops, bus, slot,
func, fi);
if (error) {
pr_err("pci %s init failed\n", fi->fi_name);
goto pci_emul_init_fail;
}
success_cnt++;
}
}
@ -1452,6 +1467,19 @@ init_pci(struct vmctx *ctx)
}
bi->memlimit32 = bus0_memlimit;
/* Update the PIO window in the guest ACPI DSDT table */
for (i = 0; i < REGION_NUMS; i++) {
if (reserved_bar_regions[i].vdev &&
reserved_bar_regions[i].bar_type == PCIBAR_IO) {
if (reserved_bar_regions[i].start < bi->iobase) {
bi->iobase = reserved_bar_regions[i].start;
}
if ((reserved_bar_regions[i].end + 1) > bi->iolimit) {
bi->iolimit = reserved_bar_regions[i].end + 1;
}
}
}
error = check_gsi_sharing_violation();
if (error < 0)
goto pci_emul_init_fail;
@ -1532,25 +1560,34 @@ init_pci(struct vmctx *ctx)
return 0;
pci_emul_init_fail:
for (bus = 0; bus < MAXBUSES && success_cnt > 0; bus++) {
bi = pci_businfo[bus];
if (bi == NULL)
continue;
for (slot = 0; slot < MAXSLOTS && success_cnt > 0; slot++) {
si = &bi->slotinfo[slot];
for (func = 0; func < MAXFUNCS; func++) {
fi = &si->si_funcs[func];
if (fi->fi_name == NULL)
continue;
if (success_cnt-- <= 0)
break;
ops = pci_emul_finddev(fi->fi_name);
if (!ops) {
pr_warn("No driver for device [%s]\n", fi->fi_name);
continue;
for (i = 0; i < 2; i++) {
for (bus = 0; bus < MAXBUSES && success_cnt[i] > 0; bus++) {
bi = pci_businfo[bus];
if (bi == NULL)
continue;
for (slot = 0; slot < MAXSLOTS && success_cnt[i] > 0; slot++) {
si = &bi->slotinfo[slot];
for (func = 0; func < MAXFUNCS; func++) {
fi = &si->si_funcs[func];
if (fi->fi_name == NULL)
continue;
if (success_cnt[i]-- <= 0)
break;
ops = pci_emul_finddev(fi->fi_name);
if (!ops) {
pr_warn("No driver for device [%s]\n", fi->fi_name);
continue;
}
if ((i == 0) && strcmp(ops->class_name, "passthru")) {
continue;
} else if ((i == 1) && !strcmp(ops->class_name, "passthru")) {
continue;
}
pci_emul_deinit(ctx, ops, bus, slot,
func, fi);
}
pci_emul_deinit(ctx, ops, bus, slot,
func, fi);
}
}
}

View File

@ -243,7 +243,12 @@ cfginitbar(struct vmctx *ctx, struct passthru_dev *ptdev)
if (size == 0)
continue;
/* Allocate the BAR in the guest I/O or MMIO space */
if (bartype == PCIBAR_IO)
error = reserve_io_rgn(base, base + size - 1, i, PCIBAR_IO, dev);
if (error)
return -1;
/* Allocate the BAR in the guest MMIO space */
error = pci_emul_alloc_pbar(dev, i, base, bartype, size);
if (error)
return -1;
@ -750,6 +755,8 @@ passthru_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
return;
}
destory_io_rsvd_rgns(dev);
ptdev = (struct passthru_dev *) dev->arg;
pr_info("vm_reset_ptdev_intx:0x%x-%x, ioapic virpin=%d.\n",

View File

@ -51,10 +51,8 @@
#define SOFTWARE_SRAM_MAX_SIZE 0x00800000UL
#define SOFTWARE_SRAM_BASE_GPA (PCI_EMUL_MEMBASE32 - SOFTWARE_SRAM_MAX_SIZE)
/* Currently,only gvt need reserved bar regions,
* so just hardcode REGION_NUMS=5 here
*/
#define REGION_NUMS 5
/* GVT BARs + PTDEV IO BARs */
#define REGION_NUMS 32
struct vmctx;
struct pci_vdev;