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 slotinfo *si;
struct funcinfo *fi; struct funcinfo *fi;
int bus, slot, func, i; int bus, slot, func, i;
int success_cnt = 0; int success_cnt[2] = {0}; /* 0 for passthru and 1 for others */
int error; int error;
uint64_t bus0_memlimit; uint64_t bus0_memlimit;
@ -1393,25 +1393,40 @@ init_pci(struct vmctx *ctx)
bi->membase32 = pci_emul_membase32; bi->membase32 = pci_emul_membase32;
bi->membase64 = pci_emul_membase64; bi->membase64 = pci_emul_membase64;
for (slot = 0; slot < MAXSLOTS; slot++) { /*
si = &bi->slotinfo[slot]; * Initialize pass-thru devices firstly to reserve PIO bar regions.
for (func = 0; func < MAXFUNCS; func++) { * For pass-thru devices, ACRN-DM need to ensure PIO bar regions identical mapping
fi = &si->si_funcs[func]; * (guest PIO bar start address equals to host PIO bar start address).
if (fi->fi_name == NULL) *
continue; * Then initialize non pass-thru devices.
ops = pci_emul_finddev(fi->fi_name); */
if (!ops) { for (i = 0; i < 2; i++) {
pr_warn("No driver for device [%s]\n", fi->fi_name); for (slot = 0; slot < MAXSLOTS; slot++) {
continue; 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; 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(); error = check_gsi_sharing_violation();
if (error < 0) if (error < 0)
goto pci_emul_init_fail; goto pci_emul_init_fail;
@ -1532,25 +1560,34 @@ init_pci(struct vmctx *ctx)
return 0; return 0;
pci_emul_init_fail: pci_emul_init_fail:
for (bus = 0; bus < MAXBUSES && success_cnt > 0; bus++) { for (i = 0; i < 2; i++) {
bi = pci_businfo[bus]; for (bus = 0; bus < MAXBUSES && success_cnt[i] > 0; bus++) {
if (bi == NULL) bi = pci_businfo[bus];
continue; if (bi == NULL)
for (slot = 0; slot < MAXSLOTS && success_cnt > 0; slot++) { continue;
si = &bi->slotinfo[slot]; for (slot = 0; slot < MAXSLOTS && success_cnt[i] > 0; slot++) {
for (func = 0; func < MAXFUNCS; func++) { si = &bi->slotinfo[slot];
fi = &si->si_funcs[func]; for (func = 0; func < MAXFUNCS; func++) {
if (fi->fi_name == NULL) fi = &si->si_funcs[func];
continue; if (fi->fi_name == NULL)
if (success_cnt-- <= 0) continue;
break; if (success_cnt[i]-- <= 0)
ops = pci_emul_finddev(fi->fi_name); break;
if (!ops) { ops = pci_emul_finddev(fi->fi_name);
pr_warn("No driver for device [%s]\n", fi->fi_name); if (!ops) {
continue; 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) if (size == 0)
continue; 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); error = pci_emul_alloc_pbar(dev, i, base, bartype, size);
if (error) if (error)
return -1; return -1;
@ -750,6 +755,8 @@ passthru_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
return; return;
} }
destory_io_rsvd_rgns(dev);
ptdev = (struct passthru_dev *) dev->arg; ptdev = (struct passthru_dev *) dev->arg;
pr_info("vm_reset_ptdev_intx:0x%x-%x, ioapic virpin=%d.\n", 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_MAX_SIZE 0x00800000UL
#define SOFTWARE_SRAM_BASE_GPA (PCI_EMUL_MEMBASE32 - SOFTWARE_SRAM_MAX_SIZE) #define SOFTWARE_SRAM_BASE_GPA (PCI_EMUL_MEMBASE32 - SOFTWARE_SRAM_MAX_SIZE)
/* Currently,only gvt need reserved bar regions, /* GVT BARs + PTDEV IO BARs */
* so just hardcode REGION_NUMS=5 here #define REGION_NUMS 32
*/
#define REGION_NUMS 5
struct vmctx; struct vmctx;
struct pci_vdev; struct pci_vdev;