From 30d29153090b7450b0efbe9b5be337b2fee685b7 Mon Sep 17 00:00:00 2001 From: "Liu,Junming" Date: Wed, 8 Sep 2021 14:31:58 +0000 Subject: [PATCH] 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 Acked-by: Wang, Yu1 --- devicemodel/hw/pci/core.c | 111 ++++++++++++++++++++----------- devicemodel/hw/pci/passthrough.c | 9 ++- devicemodel/include/pci_core.h | 6 +- 3 files changed, 84 insertions(+), 42 deletions(-) diff --git a/devicemodel/hw/pci/core.c b/devicemodel/hw/pci/core.c index 2e21d28e2..66b0c0b0a 100644 --- a/devicemodel/hw/pci/core.c +++ b/devicemodel/hw/pci/core.c @@ -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); } } } diff --git a/devicemodel/hw/pci/passthrough.c b/devicemodel/hw/pci/passthrough.c index 00584a93c..39e6aa8ad 100644 --- a/devicemodel/hw/pci/passthrough.c +++ b/devicemodel/hw/pci/passthrough.c @@ -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", diff --git a/devicemodel/include/pci_core.h b/devicemodel/include/pci_core.h index 62cf4382c..f1fba5c59 100644 --- a/devicemodel/include/pci_core.h +++ b/devicemodel/include/pci_core.h @@ -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;