mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-09-01 00:47:23 +00:00
hv: vpci: pass through stolen memory and opregion memory for GVT-D
In order to add GVT-D support, we need pass through stolen memory and opregion memroy to the post-launched VM. To implement this, we first reserve the GPA for stolen memory and opregion memory through post-launched VM e820 table. Then we would build EPT mapping between the GPA and the stolen memory and opregion memory real HPA. The last, we need to return the GPA to post-launched VM if it wants to read the stolen memory and opregion memory address and prevent post-launched VM to write the stolen memory and opregion memory address register for now. We do the GPA reserve and GPA to HPA EPT mapping in ACRN-DM and the stolen memory and opregion memory CFG space register access emulation in ACRN-HV. Tracked-On: #4371 Signed-off-by: Li Fei1 <fei1.li@intel.com>
This commit is contained in:
@@ -57,6 +57,8 @@
|
||||
*/
|
||||
#define AUDIO_NHLT_HACK 1
|
||||
|
||||
#define PCI_BDF_GPU 0x00000010 /* 00:02.0 */
|
||||
|
||||
#define GPU_GSM_SIZE 0x4000000
|
||||
/* set gsm gpa=0xDB000000, which is reserved in e820 table */
|
||||
#define GPU_GSM_GPA 0xDB000000
|
||||
@@ -75,6 +77,9 @@ extern uint64_t audio_nhlt_len;
|
||||
static int pciaccess_ref_cnt;
|
||||
static pthread_mutex_t ref_cnt_mtx = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
uint32_t gsm_start_hpa = 0;
|
||||
uint32_t opregion_start_hpa = 0;
|
||||
|
||||
struct passthru_dev {
|
||||
struct pci_vdev *dev;
|
||||
struct pcibar bar[PCI_BARMAX + 1];
|
||||
@@ -412,6 +417,11 @@ passthru_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (is_rtvm && (PCI_BDF(bus, slot, func) == PCI_BDF_GPU)) {
|
||||
warnx("%s RTVM doesn't support GVT-D.", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while ((opt = strsep(&opts, ",")) != NULL) {
|
||||
if (!strncmp(opt, "keep_gsi", 8))
|
||||
keep_gsi = true;
|
||||
@@ -491,6 +501,24 @@ passthru_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
|
||||
if (error < 0)
|
||||
goto done;
|
||||
|
||||
if (ptdev->phys_bdf == PCI_BDF_GPU) {
|
||||
uint32_t gsm_phys, opregion_phys;
|
||||
/* get gsm hpa */
|
||||
gsm_phys = read_config(ptdev->phys_dev, PCIR_BDSM, 4);
|
||||
gsm_start_hpa = gsm_phys & 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_phys = read_config(ptdev->phys_dev, PCIR_ASLS_CTL, 4);
|
||||
opregion_start_hpa = opregion_phys & 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);
|
||||
|
||||
pcidev.rsvd2[0] = GPU_GSM_GPA | (gsm_phys & ~PCIM_BDSM_GSM_MASK) ;
|
||||
pcidev.rsvd2[1] = GPU_OPREGION_GPA | (opregion_phys & ~PCIM_ASLS_OPREGION_MASK);
|
||||
}
|
||||
|
||||
pcidev.virt_bdf = PCI_BDF(dev->bus, dev->slot, dev->func);
|
||||
pcidev.phys_bdf = ptdev->phys_bdf;
|
||||
for (idx = 0; idx <= PCI_BARMAX; idx++) {
|
||||
@@ -555,6 +583,11 @@ passthru_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
|
||||
vm_reset_ptdev_intx_info(ctx, virt_bdf, ptdev->phys_bdf, dev->lintr.ioapic_irq, false);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
pcidev.virt_bdf = PCI_BDF(dev->bus, dev->slot, dev->func);
|
||||
pcidev.phys_bdf = ptdev->phys_bdf;
|
||||
pciaccess_cleanup();
|
||||
|
Reference in New Issue
Block a user