dm:refine graphics data stolen memory passthru for EHL platform

EHL graphics data stolen memory(DSM) info has diff with KBL/WHL,
which includes two parts:
(1) DSM register location in pci config: on KBL/WHL, the register
locates on 0X5C, while on EHL, the register locates on 0xC0.
(2) DSM address length: On KBL/WHL,
DSM addr has 32 bits, while on EHL,DSM addr has 64 bits.

Here, refine graphics data stolen memory passthru to enable GVT-d on EHL platforms.

v3 -> v4:
        * add MICRO INTEL_ELKHARTLAKE
v2 -> v3:
	* refine discription,MICRO name
	* refine code style
v1 -> v2:
	* add callback functions for scalability

Tracked-On: projectacrn#4700

Signed-off-by: Junming Liu <junming.liu@intel.com>
Reviewed-by: Zhao Yakui <yakui.zhao@intel.com>
Reviewed-by: Liu XinYun <xinyun.liu@intel.com>
Reviewed-by: Xiaoguang Wu <xiaoguang.wu@intel.com>
Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
Junming Liu 2020-04-24 19:20:21 +08:00 committed by wenlingz
parent 795225d55e
commit 1da7e4145f
2 changed files with 52 additions and 11 deletions

View File

@ -98,6 +98,7 @@ struct passthru_dev {
* need_reset - reset dev before passthrough
*/
bool need_reset;
bool (*has_virt_pcicfg_regs)(int offset);
};
static uint32_t
@ -401,17 +402,57 @@ pciaccess_init(void)
return 0; /* success */
}
static bool
has_virt_pcicfg_regs_on_ehl_gpu(int offset)
{
return ((offset == PCIR_GEN11_BDSM_DW0) || (offset == PCIR_GEN11_BDSM_DW1) ||
(offset == PCIR_ASLS_CTL));
}
static bool
has_virt_pcicfg_regs_on_def_gpu(int offset)
{
return ((offset == PCIR_BDSM) || (offset == PCIR_ASLS_CTL));
}
/*
* passthrough GPU DSM(Data Stolen Memory) and Opregion to guest
*/
void
passthru_gpu_dsm_opregion(struct vmctx *ctx, struct passthru_dev *ptdev,
struct acrn_assign_pcidev *pcidev)
struct acrn_assign_pcidev *pcidev, uint16_t device)
{
uint32_t dsm_phys, opregion_phys;
/* get dsm hpa */
dsm_phys = read_config(ptdev->phys_dev, PCIR_BDSM, 4);
dsm_start_hpa = dsm_phys & PCIM_BDSM_MASK;
uint32_t opregion_phys, dsm_mask_val;
switch (device) {
case INTEL_ELKHARTLAKE:
/* 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;
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);
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;
pci_set_cfgdata32(ptdev->dev, PCIR_BDSM, GPU_DSM_GPA | dsm_mask_val);
ptdev->has_virt_pcicfg_regs = &has_virt_pcicfg_regs_on_def_gpu;
break;
}
/* 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);
@ -421,7 +462,6 @@ passthru_gpu_dsm_opregion(struct vmctx *ctx, struct passthru_dev *ptdev,
/* 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_BDSM, GPU_DSM_GPA | (dsm_phys & ~PCIM_BDSM_MASK));
pci_set_cfgdata32(ptdev->dev, PCIR_ASLS_CTL, GPU_OPREGION_GPA | (opregion_phys & ~PCIM_ASLS_OPREGION_MASK));
pcidev->type = QUIRK_PTDEV;
@ -550,7 +590,7 @@ passthru_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
goto done;
if (ptdev->phys_bdf == PCI_BDF_GPU)
passthru_gpu_dsm_opregion(ctx, ptdev, &pcidev);
passthru_gpu_dsm_opregion(ctx, ptdev, &pcidev, device);
pcidev.virt_bdf = PCI_BDF(dev->bus, dev->slot, dev->func);
pcidev.phys_bdf = ptdev->phys_bdf;
@ -663,8 +703,7 @@ passthru_cfgread(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
{
struct passthru_dev *ptdev = dev->arg;
if ((PCI_BDF(dev->bus, dev->slot, dev->func) == PCI_BDF_GPU) &&
((coff == PCIR_BDSM) || (coff == PCIR_ASLS_CTL)))
if (ptdev->has_virt_pcicfg_regs && ptdev->has_virt_pcicfg_regs(coff))
*rv = pci_get_cfgdata32(dev, coff);
else
*rv = read_config(ptdev->phys_dev, coff, bytes);
@ -678,8 +717,7 @@ passthru_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_vdev *dev,
{
struct passthru_dev *ptdev = dev->arg;
if (!((PCI_BDF(dev->bus, dev->slot, dev->func) == PCI_BDF_GPU) &&
((coff == PCIR_BDSM) || (coff == PCIR_ASLS_CTL))))
if (!(ptdev->has_virt_pcicfg_regs && ptdev->has_virt_pcicfg_regs(coff)))
write_config(ptdev->phys_dev, coff, bytes, val);
return 0;

View File

@ -1066,7 +1066,10 @@
#define PCIM_OSC_CTL_PCIE_CAP_STRUCT 0x10 /* Various Capability Structures */
/* Graphics definitions */
#define INTEL_ELKHARTLAKE 0x4551
#define PCIR_BDSM 0x5C /* BDSM graphics base data of stolen memory register */
#define PCIR_GEN11_BDSM_DW0 0xC0
#define PCIR_GEN11_BDSM_DW1 0xC4
#define PCIM_BDSM_MASK 0xFFF00000
#define PCIR_ASLS_CTL 0xFC /* Opregion start addr register */
#define PCIM_ASLS_OPREGION_MASK 0xFFFFF000 /* opregion need 4KB aligned */