diff --git a/devicemodel/hw/pci/passthrough.c b/devicemodel/hw/pci/passthrough.c index 580cca58d..2efd4e90b 100644 --- a/devicemodel/hw/pci/passthrough.c +++ b/devicemodel/hw/pci/passthrough.c @@ -73,6 +73,14 @@ /* set gsm gpa=0xDB000000, which is reserved in e820 table */ #define GPU_GSM_GPA 0xDB000000 +#define GPU_OPREGION_SIZE 0x3000 +/* set opregion gpa=0xDFFFD000, which is reserved in e820 table. + * [0xDFFFD000, 0XE0000000] 12K opregion has reserved for GVT-g, + * because GVT-d is not compatible with GVT-g, + * so here can use [0xDFFFD000, 0XE0000000] region. + */ +#define GPU_OPREGION_GPA 0xDFFFD000 + extern uint64_t audio_nhlt_len; /* reference count for libpciaccess init/deinit */ @@ -86,6 +94,7 @@ struct mmio_map { }; uint32_t gsm_start_hpa = 0; +uint32_t opregion_start_hpa = 0; struct passthru_dev { struct pci_vdev *dev; @@ -873,6 +882,12 @@ passthru_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts) gsm_start_hpa &= PCIM_BDSM_GSM_MASK; /* initialize the EPT mapping for passthrough GPU gsm region */ vm_map_ptdev_mmio(ctx, 0, 2, 0, GPU_GSM_GPA, GPU_GSM_SIZE, gsm_start_hpa); + + /* get opregion hpa */ + opregion_start_hpa = read_config(ptdev->phys_dev, PCIR_ASLS_CTL, 4); + opregion_start_hpa &= PCIM_ASLS_OPREGION_MASK; + /* initialize the EPT mapping for passthrough GPU opregion */ + vm_map_ptdev_mmio(ctx, 0, 2, 0, GPU_OPREGION_GPA, GPU_OPREGION_SIZE, opregion_start_hpa); } /* If ptdev support MSI/MSIX, stop here to skip virtual INTx setup. @@ -962,6 +977,7 @@ passthru_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts) if (ptdev->phys_bdf == PCI_BDF_GPU) { vm_unmap_ptdev_mmio(ctx, 0, 2, 0, GPU_GSM_GPA, GPU_GSM_SIZE, gsm_start_hpa); + vm_unmap_ptdev_mmio(ctx, 0, 2, 0, GPU_OPREGION_GPA, GPU_OPREGION_SIZE, opregion_start_hpa); } pciaccess_cleanup(); @@ -1066,6 +1082,18 @@ passthru_cfgread(struct vmctx *ctx, int vcpu, struct pci_vdev *dev, *rv |= GPU_GSM_GPA; } + /* passthru_init has initialized the EPT mapping + * for GPU opregion. + * So uos GPU can passthrough physical opregion now. + * Here, only need return opregion gpa value for uos. + */ + if ((PCI_BDF(dev->bus, dev->slot, dev->func) == PCI_BDF_GPU) + && (coff == PCIR_ASLS_CTL)) { + /* reserve opregion start addr offset to 4KB page */ + *rv &= ~PCIM_ASLS_OPREGION_MASK; + *rv |= GPU_OPREGION_GPA; + } + return 0; } diff --git a/devicemodel/include/pcireg.h b/devicemodel/include/pcireg.h index 3857d8325..e2d8594c1 100644 --- a/devicemodel/include/pcireg.h +++ b/devicemodel/include/pcireg.h @@ -1068,4 +1068,6 @@ /* Graphics definitions */ #define PCIR_BDSM 0x5C /* BDSM graphics base data of stolen memory register */ #define PCIM_BDSM_GSM_MASK 0xFFF00000 /* bits 31:20 contains the base address of stolen memory */ +#define PCIR_ASLS_CTL 0xFC /* Opregion start addr register */ +#define PCIM_ASLS_OPREGION_MASK 0xFFFFF000 /* opregion need 4KB aligned */ #endif