[PATCH] drm/i915/gvt: Fix aperture read/write emulation when enable x-no-mmap=on
Du, Changbin
changbin.du at intel.com
Tue Jan 30 04:04:18 UTC 2018
On Tue, Jan 30, 2018 at 10:56:30AM +0800, Zhenyu Wang wrote:
> On 2018.01.26 14:58:48 +0800, changbin.du at intel.com wrote:
> > From: Changbin Du <changbin.du at intel.com>
> >
> > When add 'x-no-mmap=on' for vfio-pci option, aperture access in guest
> > is emulated. But the vgpu_aperture_rw() function take wrong offset when
> > do memcpy, since vgpu->gm.aperture_va is not the base of entire aperture.
> > This mistake cause GPU command in guest get lost and so the seqno is not
> > updated in engine HWSP.
> >
> > This patch fix this, and it also move the emulation code to kvmgt.
> > Because only vfio need to emulate it. Put aperture rw to MMIO emulation
> > path breaks assumptions in xengt.
> >
> > Fixes: f090a00df9ec ("drm/i915/gvt: Add emulation for BAR2 (aperture) with normal file RW approach")
> > Signed-off-by: Changbin Du <changbin.du at intel.com>
> > ---
> > drivers/gpu/drm/i915/gvt/cfg_space.c | 15 +------------
> > drivers/gpu/drm/i915/gvt/gvt.h | 1 -
> > drivers/gpu/drm/i915/gvt/kvmgt.c | 36 +++++++++++++++++++++++++++++--
> > drivers/gpu/drm/i915/gvt/mmio.c | 42 ------------------------------------
> > 4 files changed, 35 insertions(+), 59 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c
> > index 97bfc00..c62346f 100644
> > --- a/drivers/gpu/drm/i915/gvt/cfg_space.c
> > +++ b/drivers/gpu/drm/i915/gvt/cfg_space.c
> > @@ -119,16 +119,6 @@ static int map_aperture(struct intel_vgpu *vgpu, bool map)
> > if (map == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked)
> > return 0;
> >
> > - if (map) {
> > - vgpu->gm.aperture_va = memremap(aperture_pa, aperture_sz,
> > - MEMREMAP_WC);
> > - if (!vgpu->gm.aperture_va)
> > - return -ENOMEM;
> > - } else {
> > - memunmap(vgpu->gm.aperture_va);
> > - vgpu->gm.aperture_va = NULL;
> > - }
> > -
> > val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_2];
> > if (val & PCI_BASE_ADDRESS_MEM_TYPE_64)
> > val = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2);
> > @@ -141,11 +131,8 @@ static int map_aperture(struct intel_vgpu *vgpu, bool map)
> > aperture_pa >> PAGE_SHIFT,
> > aperture_sz >> PAGE_SHIFT,
> > map);
> > - if (ret) {
> > - memunmap(vgpu->gm.aperture_va);
> > - vgpu->gm.aperture_va = NULL;
> > + if (ret)
> > return ret;
> > - }
> >
> > vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked = map;
> > return 0;
> > diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
> > index 7dc7a80..84b04f6 100644
> > --- a/drivers/gpu/drm/i915/gvt/gvt.h
> > +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> > @@ -82,7 +82,6 @@ struct intel_gvt_device_info {
> > struct intel_vgpu_gm {
> > u64 aperture_sz;
> > u64 hidden_sz;
> > - void *aperture_va;
> > struct drm_mm_node low_gm_node;
> > struct drm_mm_node high_gm_node;
> > };
> > diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
> > index 70f03e9..3c68727 100644
> > --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> > +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> > @@ -651,6 +651,39 @@ static int intel_vgpu_bar_rw(struct intel_vgpu *vgpu, int bar, uint64_t off,
> > return ret;
> > }
> >
> > +static inline bool intel_vgpu_in_aperture(struct intel_vgpu *vgpu, uint64_t off)
> > +{
> > + return off >= vgpu_aperture_offset(vgpu) &&
> > + off < vgpu_aperture_offset(vgpu) + vgpu_aperture_sz(vgpu);
> > +}
> > +
> > +static int intel_vgpu_aperture_rw(struct intel_vgpu *vgpu, uint64_t off,
> > + void *buf, unsigned long count, bool is_write)
> > +{
> > + void *aperture_va;
> > +
> > + if (!intel_vgpu_in_aperture(vgpu, off) ||
> > + !intel_vgpu_in_aperture(vgpu, off + count)) {
> > + gvt_vgpu_err("Invalid aperture offset %llu\n", off);
> > + return -EINVAL;
> > + }
> > +
> > + aperture_va = io_mapping_map_wc(&vgpu->gvt->dev_priv->ggtt.iomap,
> > + ALIGN_DOWN(off, PAGE_SIZE),
> > + PAGE_ALIGN(count + offset_in_page(off)));
>
> I don't think we need page aligned size? Other looks fine to me.
>
'Using an offset which is not page aligned yields an undefined result.' This is
from the document, though it is not a problem on x86 arch.
> > + if (!aperture_va)
> > + return -EIO;
> > +
> > + if (is_write)
> > + memcpy(aperture_va + offset_in_page(off), buf, count);
> > + else
> > + memcpy(buf, aperture_va + offset_in_page(off), count);
> > +
> > + io_mapping_unmap(aperture_va);
> > +
> > + return 0;
> > +}
> > +
> > static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf,
> > size_t count, loff_t *ppos, bool is_write)
> > {
> > @@ -679,8 +712,7 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf,
> > buf, count, is_write);
> > break;
> > case VFIO_PCI_BAR2_REGION_INDEX:
> > - ret = intel_vgpu_bar_rw(vgpu, PCI_BASE_ADDRESS_2, pos,
> > - buf, count, is_write);
> > + ret = intel_vgpu_aperture_rw(vgpu, pos, buf, count, is_write);
> > break;
> > case VFIO_PCI_BAR1_REGION_INDEX:
> > case VFIO_PCI_BAR3_REGION_INDEX:
> > diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c
> > index 562b5ad..5c869e3 100644
> > --- a/drivers/gpu/drm/i915/gvt/mmio.c
> > +++ b/drivers/gpu/drm/i915/gvt/mmio.c
> > @@ -56,38 +56,6 @@ int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa)
> > (reg >= gvt->device_info.gtt_start_offset \
> > && reg < gvt->device_info.gtt_start_offset + gvt_ggtt_sz(gvt))
> >
> > -static bool vgpu_gpa_is_aperture(struct intel_vgpu *vgpu, uint64_t gpa)
> > -{
> > - u64 aperture_gpa = intel_vgpu_get_bar_gpa(vgpu, PCI_BASE_ADDRESS_2);
> > - u64 aperture_sz = vgpu_aperture_sz(vgpu);
> > -
> > - return gpa >= aperture_gpa && gpa < aperture_gpa + aperture_sz;
> > -}
> > -
> > -static int vgpu_aperture_rw(struct intel_vgpu *vgpu, uint64_t gpa,
> > - void *pdata, unsigned int size, bool is_read)
> > -{
> > - u64 aperture_gpa = intel_vgpu_get_bar_gpa(vgpu, PCI_BASE_ADDRESS_2);
> > - u64 offset = gpa - aperture_gpa;
> > -
> > - if (!vgpu_gpa_is_aperture(vgpu, gpa + size - 1)) {
> > - gvt_vgpu_err("Aperture rw out of range, offset %llx, size %d\n",
> > - offset, size);
> > - return -EINVAL;
> > - }
> > -
> > - if (!vgpu->gm.aperture_va) {
> > - gvt_vgpu_err("BAR is not enabled\n");
> > - return -ENXIO;
> > - }
> > -
> > - if (is_read)
> > - memcpy(pdata, vgpu->gm.aperture_va + offset, size);
> > - else
> > - memcpy(vgpu->gm.aperture_va + offset, pdata, size);
> > - return 0;
> > -}
> > -
> > static void failsafe_emulate_mmio_rw(struct intel_vgpu *vgpu, uint64_t pa,
> > void *p_data, unsigned int bytes, bool read)
> > {
> > @@ -144,11 +112,6 @@ int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa,
> > }
> > mutex_lock(&gvt->lock);
> >
> > - if (vgpu_gpa_is_aperture(vgpu, pa)) {
> > - ret = vgpu_aperture_rw(vgpu, pa, p_data, bytes, true);
> > - goto out;
> > - }
> > -
> > offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa);
> >
> > if (WARN_ON(bytes > 8))
> > @@ -222,11 +185,6 @@ int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, uint64_t pa,
> >
> > mutex_lock(&gvt->lock);
> >
> > - if (vgpu_gpa_is_aperture(vgpu, pa)) {
> > - ret = vgpu_aperture_rw(vgpu, pa, p_data, bytes, false);
> > - goto out;
> > - }
> > -
> > offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa);
> >
> > if (WARN_ON(bytes > 8))
> > --
> > 2.7.4
> >
> > _______________________________________________
> > intel-gvt-dev mailing list
> > intel-gvt-dev at lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gvt-dev
>
> --
> Open Source Technology Center, Intel ltd.
>
> $gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827
--
Thanks,
Changbin Du
More information about the intel-gvt-dev
mailing list