dm: pci: read dsm size from igd device for igd passthrough

Currently the DSM (Data of Stolen Memory) size was hardcoded to 64M in
ACRN, meaning that users must set "DVMT Pre-Allocated" to 64M in order
to make IGD passthrough (GVT-d) to work. This patch reads the BIOS-
configured memory size from GGC (GMCH Graphics Control, 0x50) register
and passthrough corresponding area to guest.

Tracked-On: #8432
Signed-off-by: Jiaqing Zhao <jiaqing.zhao@linux.intel.com>
Reviewed-by: Jian Jun Chen <jian.jun.chen@intel.com>
This commit is contained in:
Jiaqing Zhao 2023-07-18 07:30:30 +00:00 committed by acrnsi-robot
parent 3bbf99acbd
commit 75b031b63c
3 changed files with 38 additions and 5 deletions

View File

@ -63,6 +63,7 @@ extern uint64_t audio_nhlt_len;
uint64_t gpu_dsm_hpa = 0;
uint64_t gpu_dsm_gpa = 0;
uint32_t gpu_dsm_size = 0;
uint32_t gpu_opregion_hpa = 0;
uint32_t gpu_opregion_gpa = 0;
@ -553,7 +554,7 @@ get_gpu_rsvmem_base_gpa()
uint32_t
get_gpu_rsvmem_size()
{
return GPU_OPREGION_SIZE + GPU_DSM_SIZE;
return GPU_OPREGION_SIZE + gpu_dsm_size;
}
static const struct igd_device igd_device_tbl[] = {
@ -586,6 +587,31 @@ int igd_gen(uint16_t device) {
return 0;
}
uint32_t igd_dsm_region_size(struct pci_device *igddev)
{
uint16_t ggc;
uint8_t gms;
ggc = read_config(igddev, PCIR_GGC, 2);
gms = ggc >> PCIR_GGC_GMS_SHIFT;
switch (gms) {
case 0x00 ... 0x10:
return gms * 32 * MB;
case 0x20:
return 1024 * MB;
case 0x30:
return 1536 * MB;
case 0x40:
return 2048 * MB;
case 0xf0 ... 0xfe:
return (gms - 0xf0 + 1) * 4 * MB;
}
pr_err("%s: Invalid GMS value in GGC register. GGC = %04x\n", __func__, ggc);
return 0; /* Should never reach here */
}
/*
* passthrough GPU DSM(Data Stolen Memory) and Opregion to guest
*/
@ -607,6 +633,12 @@ passthru_gpu_dsm_opregion(struct vmctx *ctx, struct passthru_dev *ptdev,
gen = 11;
}
gpu_dsm_size = igd_dsm_region_size(ptdev->phys_dev);
if (!gpu_dsm_size) {
pr_err("Invalid igd dsm region size, check DVMT Pre-Allocated option in BIOS\n");
return;
}
if (gen >= 11) {
/* BDSM register has 64 bits.
* bits 63:20 contains the base address of stolen memory
@ -642,8 +674,8 @@ passthru_gpu_dsm_opregion(struct vmctx *ctx, struct passthru_dev *ptdev,
pci_set_cfgdata32(ptdev->dev, PCIR_ASLS_CTL, gpu_opregion_gpa | (opregion_phys & ~PCIM_ASLS_OPREGION_MASK));
/* initialize the EPT mapping for passthrough GPU dsm region */
vm_unmap_ptdev_mmio(ctx, 0, 2, 0, gpu_dsm_gpa, GPU_DSM_SIZE, gpu_dsm_hpa);
vm_map_ptdev_mmio(ctx, 0, 2, 0, gpu_dsm_gpa, GPU_DSM_SIZE, gpu_dsm_hpa);
vm_unmap_ptdev_mmio(ctx, 0, 2, 0, gpu_dsm_gpa, gpu_dsm_size, gpu_dsm_hpa);
vm_map_ptdev_mmio(ctx, 0, 2, 0, gpu_dsm_gpa, gpu_dsm_size, gpu_dsm_hpa);
/* initialize the EPT mapping for passthrough GPU opregion */
vm_unmap_ptdev_mmio(ctx, 0, 2, 0, gpu_opregion_gpa, GPU_OPREGION_SIZE, gpu_opregion_hpa);
@ -939,7 +971,7 @@ passthru_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
phys_bdf = ptdev->phys_bdf;
if (is_intel_graphics_dev(dev)) {
vm_unmap_ptdev_mmio(ctx, 0, 2, 0, gpu_dsm_gpa, GPU_DSM_SIZE, gpu_dsm_hpa);
vm_unmap_ptdev_mmio(ctx, 0, 2, 0, gpu_dsm_gpa, gpu_dsm_size, gpu_dsm_hpa);
vm_unmap_ptdev_mmio(ctx, 0, 2, 0, gpu_opregion_gpa, GPU_OPREGION_SIZE, gpu_opregion_hpa);
}

View File

@ -296,7 +296,6 @@ void destory_io_rsvd_rgns(struct pci_vdev *vdev);
* For OpRegion 2.0: ASLE.rvda = physical address, not support currently
*/
#define GPU_DSM_GPA 0x7C000000
#define GPU_DSM_SIZE 0x4000000
#define GPU_OPREGION_SIZE 0x5000
/*
* TODO: Forced DSM/OPREGION size requires native BIOS configuration.

View File

@ -1066,6 +1066,8 @@
#define PCIM_OSC_CTL_PCIE_CAP_STRUCT 0x10 /* Various Capability Structures */
/* Graphics definitions */
#define PCIR_GGC 0x50 /* GMCH Graphics Control */
#define PCIR_GGC_GMS_SHIFT 8 /* Bit 15:8 Graphics Memory Size (GMS) */
#define PCIR_BDSM 0x5C /* BDSM graphics base data of stolen memory register */
#define PCIR_GEN11_BDSM_DW0 0xC0
#define PCIR_GEN11_BDSM_DW1 0xC4