DM: gvt: Identical mapping for GPU DSM

Windows graphic driver obtains DSM address from in-BAR mmio register
which has passthroughed. Not like the other platforms obtained from
pci configure space register which has virtualized. So TGL has to
keep identical mapping to avoid trap mmio BAR to do the emulation.

To keep simple, this patch hardcode the TGL DSM region in vE820
table, this will cause memory waste here. In the near future, we
need refine the entire vE820 logic as it is hard to maintained
due to many reserved regions have introduced in recently.

Signed-off-by: Sun Peng <peng.p.sun@intel.com>
Acked-by: Wang, Yu1 <yu1.wang@intel.com>
Tracked-On: #5461
This commit is contained in:
Sun Peng 2020-11-03 04:07:39 +00:00 committed by wenlingz
parent b02776a9d4
commit 73f21a41ad
3 changed files with 90 additions and 42 deletions

View File

@ -54,10 +54,13 @@ static char bootargs[BOOT_ARG_LEN];
* Begin Limit Type Length
* 0: 0 - 0xA0000 RAM 0xA0000
* 1: 0x100000 - lowmem part1 RAM 0x0
* 2: pSRAM_bottom - pSRAM_top (reserved) pSRAM_MAX_SIZE
* 3: lowmem part2 - 0x80000000 (reserved) 0x0
* 4: 0xE0000000 - 0x100000000 MCFG, MMIO 512MB
* 5: 0x140000000 - highmem RAM highmem - 5GB
* 2: gpu_rsvd_bot - gpu_rsvd_top (reserved) 0x4004000
* 3: pSRAM_bottom - pSRAM_top (reserved) pSRAM_MAX_SIZE
* 4: lowmem part2 - 0x80000000 (reserved) 0x0
* 5: 0xDB000000 - 0xDF000000 (reserved) 64MB
* 6: 0xDF000000 - 0xE0000000 (reserved) 16MB
* 7: 0xE0000000 - 0x100000000 MCFG, MMIO 512MB
* 8: 0x140000000 - highmem RAM highmem - 5GB
*
* FIXME: Do we need to reserve DSM and OPREGION for GVTD here.
*/
@ -74,6 +77,12 @@ const struct e820_entry e820_default_entries[NUM_E820_ENTRIES] = {
.type = E820_TYPE_RAM
},
{ /* TGL GPU DSM & OpRegion area */
.baseaddr = 0x3B800000,
.length = 0x4004000,
.type = E820_TYPE_RESERVED
},
{ /* pSRAM area */
.baseaddr = PSRAM_BASE_GPA,
.length = PSRAM_MAX_SIZE,
@ -208,21 +217,21 @@ acrn_create_e820_table(struct vmctx *ctx, struct e820_entry *e820)
uint32_t removed = 0, k;
memcpy(e820, e820_default_entries, sizeof(e820_default_entries));
if (ctx->lowmem <= e820[LOWRAM_E820_ENTRY+2].baseaddr) {
if (ctx->lowmem <= e820[LOWRAM_E820_ENTRY+3].baseaddr) {
e820[LOWRAM_E820_ENTRY].length =
(ctx->lowmem < e820[LOWRAM_E820_ENTRY+1].baseaddr ? ctx->lowmem :
e820[LOWRAM_E820_ENTRY+1].baseaddr) - e820[LOWRAM_E820_ENTRY].baseaddr;
memmove(&e820[LOWRAM_E820_ENTRY+2], &e820[LOWRAM_E820_ENTRY+3],
memmove(&e820[LOWRAM_E820_ENTRY+3], &e820[LOWRAM_E820_ENTRY+4],
sizeof(struct e820_entry) *
(NUM_E820_ENTRIES - (LOWRAM_E820_ENTRY+3)));
(NUM_E820_ENTRIES - (LOWRAM_E820_ENTRY+4)));
removed++;
} else {
e820[LOWRAM_E820_ENTRY].length = e820[LOWRAM_E820_ENTRY+1].baseaddr -
e820[LOWRAM_E820_ENTRY].baseaddr;
e820[LOWRAM_E820_ENTRY+2].length =
e820[LOWRAM_E820_ENTRY+3].length =
(ctx->lowmem < ctx->lowmem_limit ? ctx->lowmem : ctx->lowmem_limit) -
e820[LOWRAM_E820_ENTRY+2].baseaddr;
e820[LOWRAM_E820_ENTRY+3].baseaddr;
}
/* remove [5GB, highmem) if it's empty */

View File

@ -59,16 +59,18 @@
#define PCI_BDF_GPU 0x00000010 /* 00:02.0 */
/* Reserved [0x DF000000, 0x E0000000] 16M in e820 table for GVT
* [0xDB000000, 0xDF000000) 64M, DSM, used by native GOP and gfx driver
/* Reserved region in e820 table for GVT
* for GVT-g use:
* [0xDF000000, 0xDF800000) 8M, GOP FB, used OvmfPkg/GvtGopDxe for 1080p@30
* [0xDFFFD000, 0xDFFFF000) 8K, OpRegion, used by GvtGopDxe and GVT-g
* [0xDFFFF000, 0XE0000000) 4K, Reserved, not used
* for GVT-d use:
* for TGL GVT-d use:
* [0x3B800000, 0x3F800000) 64M, Date Stolen Memory
* [0x3F800000, 0X3F804000] 16K, OpRegion and Extended OpRegion
* for EHL/WHL/KBL GVT-d use:
* [0xDB000000, 0xDF000000) 64M, DSM, used by native GOP and gfx driver
* [0xDFFFC000, 0xDFFFE000) 8K, OpRegion, used by native GOP and gfx driver
* [0xDFFFE000, 0XE0000000] 8K, Extended OpRegion, store raw VBT
*
* OpRegion: 8KB(0x2000)
* [ OpRegion Header ] Offset: 0x0
* [ Mailbox #1: ACPI ] Offset: 0x100
@ -88,6 +90,14 @@
#define GPU_DSM_SIZE 0x4000000
#define GPU_OPREGION_GPA 0xDFFFC000
#define GPU_OPREGION_SIZE 0x4000
/*
* TODO: Forced DSM/OPREGION size requires native BIOS configuration.
* This limitation need remove in future
*/
uint32_t gpu_dsm_hpa = 0;
uint32_t gpu_dsm_gpa = 0;
uint32_t gpu_opregion_hpa = 0;
uint32_t gpu_opregion_gpa = 0;
extern uint64_t audio_nhlt_len;
@ -95,8 +105,6 @@ extern uint64_t audio_nhlt_len;
static int pciaccess_ref_cnt;
static pthread_mutex_t ref_cnt_mtx = PTHREAD_MUTEX_INITIALIZER;
uint32_t dsm_start_hpa = 0;
uint32_t opregion_start_hpa = 0;
struct passthru_dev {
struct pci_vdev *dev;
@ -473,46 +481,77 @@ passthru_gpu_dsm_opregion(struct vmctx *ctx, struct passthru_dev *ptdev,
{
uint32_t opregion_phys, dsm_mask_val;
/* get opregion hpa */
opregion_phys = read_config(ptdev->phys_dev, PCIR_ASLS_CTL, 4);
gpu_opregion_hpa = opregion_phys & PCIM_ASLS_OPREGION_MASK;
switch (device) {
case INTEL_ELKHARTLAKE:
/* BDSM register has 64 bits.
* bits 63:20 contains the base address of stolen memory
*/
gpu_dsm_hpa = read_config(ptdev->phys_dev, PCIR_GEN11_BDSM_DW0, 4);
dsm_mask_val = gpu_dsm_hpa & ~PCIM_BDSM_MASK;
gpu_dsm_hpa &= PCIM_BDSM_MASK;
gpu_dsm_hpa |= (uint64_t)read_config(ptdev->phys_dev, PCIR_GEN11_BDSM_DW1, 4) << 32;
gpu_dsm_gpa = GPU_DSM_GPA;
pci_set_cfgdata32(ptdev->dev, PCIR_GEN11_BDSM_DW0, gpu_dsm_gpa | dsm_mask_val);
/* write 0 to high 32-bits of BDSM on EHL platform */
pci_set_cfgdata32(ptdev->dev, PCIR_GEN11_BDSM_DW1, 0);
gpu_opregion_gpa = GPU_OPREGION_GPA;
ptdev->has_virt_pcicfg_regs = &has_virt_pcicfg_regs_on_ehl_gpu;
break;
case INTEL_TIGERLAKE:
/* BDSM register has 64 bits.
* bits 63:20 contains the base address of stolen memory
*/
dsm_start_hpa = read_config(ptdev->phys_dev, PCIR_GEN11_BDSM_DW0, 4);
dsm_mask_val = dsm_start_hpa & ~PCIM_BDSM_MASK;
dsm_start_hpa &= PCIM_BDSM_MASK;
dsm_start_hpa |= (uint64_t)read_config(ptdev->phys_dev, PCIR_GEN11_BDSM_DW1, 4) << 32;
gpu_dsm_hpa = read_config(ptdev->phys_dev, PCIR_GEN11_BDSM_DW0, 4);
dsm_mask_val = gpu_dsm_hpa & ~PCIM_BDSM_MASK;
gpu_dsm_hpa &= PCIM_BDSM_MASK;
gpu_dsm_hpa |= (uint64_t)read_config(ptdev->phys_dev, PCIR_GEN11_BDSM_DW1, 4) << 32;
/* Keep identical mapping for DSM region on TGL platform due to windows
* graphic driver obtain the DSM address from one mmio register locate
* in BAR instead of pci config space.
*/
gpu_dsm_gpa = gpu_dsm_hpa;
pci_set_cfgdata32(ptdev->dev, PCIR_GEN11_BDSM_DW0, GPU_DSM_GPA | dsm_mask_val);
pci_set_cfgdata32(ptdev->dev, PCIR_GEN11_BDSM_DW0, gpu_dsm_gpa | dsm_mask_val);
/* write 0 to high 32-bits of BDSM on EHL platform */
pci_set_cfgdata32(ptdev->dev, PCIR_GEN11_BDSM_DW1, 0);
gpu_opregion_gpa = gpu_dsm_gpa + GPU_DSM_SIZE;
ptdev->has_virt_pcicfg_regs = &has_virt_pcicfg_regs_on_ehl_gpu;
break;
/* If on default platforms, such as KBL,WHL */
default:
/* bits 31:20 contains the base address of stolen memory */
dsm_start_hpa = read_config(ptdev->phys_dev, PCIR_BDSM, 4);
dsm_mask_val = dsm_start_hpa & ~PCIM_BDSM_MASK;
dsm_start_hpa &= PCIM_BDSM_MASK;
gpu_dsm_hpa = read_config(ptdev->phys_dev, PCIR_BDSM, 4);
dsm_mask_val = gpu_dsm_hpa & ~PCIM_BDSM_MASK;
gpu_dsm_hpa &= PCIM_BDSM_MASK;
gpu_dsm_gpa = GPU_DSM_GPA;
pci_set_cfgdata32(ptdev->dev, PCIR_BDSM, GPU_DSM_GPA | dsm_mask_val);
pci_set_cfgdata32(ptdev->dev, PCIR_BDSM, gpu_dsm_gpa | dsm_mask_val);
gpu_opregion_gpa = GPU_OPREGION_GPA;
ptdev->has_virt_pcicfg_regs = &has_virt_pcicfg_regs_on_def_gpu;
break;
}
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_map_ptdev_mmio(ctx, 0, 2, 0, GPU_DSM_GPA, GPU_DSM_SIZE, dsm_start_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);
/* 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);
pci_set_cfgdata32(ptdev->dev, PCIR_ASLS_CTL, GPU_OPREGION_GPA | (opregion_phys & ~PCIM_ASLS_OPREGION_MASK));
vm_unmap_ptdev_mmio(ctx, 0, 2, 0, gpu_opregion_gpa, GPU_OPREGION_SIZE, gpu_opregion_hpa);
vm_map_ptdev_mmio(ctx, 0, 2, 0, gpu_opregion_gpa, GPU_OPREGION_SIZE, gpu_opregion_hpa);
pcidev->type = QUIRK_PTDEV;
}
@ -748,8 +787,8 @@ passthru_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
phys_bdf = ptdev->phys_bdf;
if (ptdev->phys_bdf == PCI_BDF_GPU) {
vm_unmap_ptdev_mmio(ctx, 0, 2, 0, GPU_DSM_GPA, GPU_DSM_SIZE, dsm_start_hpa);
vm_unmap_ptdev_mmio(ctx, 0, 2, 0, GPU_OPREGION_GPA, GPU_OPREGION_SIZE, opregion_start_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);
}
pcidev.virt_bdf = PCI_BDF(dev->bus, dev->slot, dev->func);

View File

@ -39,9 +39,9 @@
#define E820_TYPE_ACPI_NVS 4U /* EFI 10 */
#define E820_TYPE_UNUSABLE 5U /* EFI 8 */
#define NUM_E820_ENTRIES 6
#define NUM_E820_ENTRIES 9
#define LOWRAM_E820_ENTRY 1
#define HIGHRAM_E820_ENTRY 5
#define HIGHRAM_E820_ENTRY 6
/* Defines a single entry in an E820 memory map. */
struct e820_entry {