From ba25d977571e1551b7032d6104e49efd6f88f8ad Mon Sep 17 00:00:00 2001 From: Colin Xu Date: Thu, 9 Jul 2020 15:09:56 +0800 Subject: drm/i915/gvt: Do not destroy ppgtt_mm during vGPU D3->D0. When system enters S3 state, device enters D3 state while RAM remains powered. From vGPU/GVT perspective, ppgtt_mm is residual in guest memory during vGPU in D3 state, so that when guest state transits from S3->S0, ppgtt_mm can be re-used and no need rebuild. Previous implementation invalidate and destroy ppgtt_mm at DMLR, regardless the power state transition is S0->S3->S0 (guest suspend or resume) or OFF->S0 (normal boot/reboot), invalidate and destroy ppgtt_mm is unnecessary in the former transition case. The patch saves the vGPU D3/D0 transition state when guest writes the PCI_PM_CTRL in vGPU's configure space, then in later DMLR, GVT can decide whether or not invalidate and destroy ppgtt_mm is required. The d3_entered flags is reset after DMLR. To test this feature, make sure S3 is enabled in QEMU parameters: i440fx: PIIX4_PM.disable_s3=0 q35: ICH9-LPC.disable_s3=0 Also need enable sleep option in guest OS if it's disabled. v2: - Revise commit message to more accurate description. (Kevin) - Split patch by logic. (Zhenyu) Reviewed-by: Zhenyu Wang Signed-off-by: Hang Yuan Signed-off-by: Colin Xu Signed-off-by: Zhenyu Wang Link: http://patchwork.freedesktop.org/patch/msgid/20200709071002.247960-2-colin.xu@intel.com --- drivers/gpu/drm/i915/gvt/cfg_space.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers/gpu/drm/i915/gvt/cfg_space.c') diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c index 072725a448db..ad86c5eb5bba 100644 --- a/drivers/gpu/drm/i915/gvt/cfg_space.c +++ b/drivers/gpu/drm/i915/gvt/cfg_space.c @@ -70,6 +70,7 @@ static void vgpu_pci_cfg_mem_write(struct intel_vgpu *vgpu, unsigned int off, { u8 *cfg_base = vgpu_cfg_space(vgpu); u8 mask, new, old; + pci_power_t pwr; int i = 0; for (; i < bytes && (off + i < sizeof(pci_cfg_space_rw_bmp)); i++) { @@ -91,6 +92,15 @@ static void vgpu_pci_cfg_mem_write(struct intel_vgpu *vgpu, unsigned int off, /* For other configuration space directly copy as it is. */ if (i < bytes) memcpy(cfg_base + off + i, src + i, bytes - i); + + if (off == vgpu->cfg_space.pmcsr_off && vgpu->cfg_space.pmcsr_off) { + pwr = (pci_power_t __force)(*(u16*)(&vgpu_cfg_space(vgpu)[off]) + & PCI_PM_CTRL_STATE_MASK); + if (pwr == PCI_D3hot) + vgpu->d3_entered = true; + gvt_dbg_core("vgpu-%d power status changed to %d\n", + vgpu->id, pwr); + } } /** @@ -366,6 +376,7 @@ void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu, struct intel_gvt *gvt = vgpu->gvt; const struct intel_gvt_device_info *info = &gvt->device_info; u16 *gmch_ctl; + u8 next; memcpy(vgpu_cfg_space(vgpu), gvt->firmware.cfg_space, info->cfg_space_size); @@ -401,6 +412,19 @@ void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu, pci_resource_len(gvt->gt->i915->drm.pdev, 2); memset(vgpu_cfg_space(vgpu) + PCI_ROM_ADDRESS, 0, 4); + + /* PM Support */ + vgpu->cfg_space.pmcsr_off = 0; + if (vgpu_cfg_space(vgpu)[PCI_STATUS] & PCI_STATUS_CAP_LIST) { + next = vgpu_cfg_space(vgpu)[PCI_CAPABILITY_LIST]; + do { + if (vgpu_cfg_space(vgpu)[next + PCI_CAP_LIST_ID] == PCI_CAP_ID_PM) { + vgpu->cfg_space.pmcsr_off = next + PCI_PM_CTRL; + break; + } + next = vgpu_cfg_space(vgpu)[next + PCI_CAP_LIST_NEXT]; + } while (next); + } } /** -- cgit v1.2.3