mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-18 11:47:30 +00:00
DM: refuse passthrough PCIe without reset support
Check reset method for PCIe dev according to 'reset' in sysfs, which indicates reset capability, like FLR and secondary bus reset. PCIe dev without reset capability is refused for passthrough to avoid failure after UOS reboot. Signed-off-by: Edwin Zhai <edwin.zhai@intel.com> Acked-by: Kevin Tian <kevin.tian@intel.com>
This commit is contained in:
parent
c3793e19ed
commit
b19d936356
@ -37,6 +37,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
@ -102,6 +103,7 @@ struct passthru_dev {
|
||||
int capoff;
|
||||
int table_size;
|
||||
} msix;
|
||||
bool pcie_cap;
|
||||
struct pcisel sel;
|
||||
int phys_pin;
|
||||
uint16_t phys_bdf;
|
||||
@ -318,7 +320,7 @@ clear_mmc_mme(uint32_t *val)
|
||||
#endif
|
||||
|
||||
static int
|
||||
cfginitmsi(struct vmctx *ctx, struct passthru_dev *ptdev)
|
||||
cfginit_cap(struct vmctx *ctx, struct passthru_dev *ptdev)
|
||||
{
|
||||
int i, ptr, capptr, cap, sts, caplen, table_size;
|
||||
uint32_t u32;
|
||||
@ -393,7 +395,9 @@ cfginitmsi(struct vmctx *ctx, struct passthru_dev *ptdev)
|
||||
caplen -= 4;
|
||||
capptr += 4;
|
||||
}
|
||||
}
|
||||
} else if (cap == PCIY_EXPRESS)
|
||||
ptdev->pcie_cap = true;
|
||||
|
||||
ptr = read_config(phys_dev, ptr + PCICAP_NEXTPTR, 1);
|
||||
}
|
||||
}
|
||||
@ -439,11 +443,7 @@ cfginitmsi(struct vmctx *ctx, struct passthru_dev *ptdev)
|
||||
vm_set_ptdev_msix_info(ctx, &ptirq);
|
||||
}
|
||||
|
||||
/* Make sure one of the capabilities is present */
|
||||
if (ptdev->msi.capoff == 0 && ptdev->msix.capoff == 0)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
@ -809,18 +809,47 @@ cfginit(struct vmctx *ctx, struct passthru_dev *ptdev, int bus,
|
||||
int slot, int func)
|
||||
{
|
||||
int irq_type = IRQ_MSI;
|
||||
char reset_path[60];
|
||||
FILE *f;
|
||||
|
||||
bzero(&ptdev->sel, sizeof(struct pcisel));
|
||||
ptdev->sel.bus = bus;
|
||||
ptdev->sel.dev = slot;
|
||||
ptdev->sel.func = func;
|
||||
|
||||
if (cfginitmsi(ctx, ptdev) != 0) {
|
||||
if (cfginit_cap(ctx, ptdev) != 0) {
|
||||
warnx("Capability check fails for PCI %x/%x/%x",
|
||||
bus, slot, func);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check MSI or MSIX capabilities */
|
||||
if (ptdev->msi.capoff == 0 && ptdev->msix.capoff == 0) {
|
||||
warnx("MSI not supported for PCI %x/%x/%x",
|
||||
bus, slot, func);
|
||||
irq_type = IRQ_INTX;
|
||||
}
|
||||
|
||||
/* Check reset method for PCIe dev. If SOS kernel provides 'reset'
|
||||
* entry in sysfs, related dev has some reset capability, e.g. FLR, or
|
||||
* secondary bus reset. PCIe dev without any reset capability is
|
||||
* refused for passthrough.
|
||||
*/
|
||||
if (ptdev->pcie_cap) {
|
||||
snprintf(reset_path, 40,
|
||||
"/sys/bus/pci/devices/0000:%02x:%02x.%x/reset",
|
||||
bus, slot, func);
|
||||
|
||||
if ((f = fopen(reset_path, "r")))
|
||||
fclose(f);
|
||||
else if (errno == ENOENT) {
|
||||
warnx("No reset capability for PCIe %x/%x/%x, "
|
||||
"remove it from ptdev list!!\n",
|
||||
bus, slot, func);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (cfginitbar(ctx, ptdev) != 0) {
|
||||
warnx("failed to initialize BARs for PCI %x/%x/%x",
|
||||
bus, slot, func);
|
||||
|
Loading…
Reference in New Issue
Block a user