Skip to content

Commit 9f674c8

Browse files
TinaZhangZWzhenyw
authored andcommitted
drm/i915/gvt: Pin vgpu dma address before using
Dma-buf display uses the vgpu dma address saved in the guest part GGTT table which is updated by vCPU thread. In host side, when the dma address is used by qemu ui thread, gvt-g must make sure the dma address is validated before letting it go to the HW. Invalid guest dma address will easily cause DMA fault and make GPU hang. v2: Rebase Fixes: e546e28 ("drm/i915/gvt: Dmabuf support for GVT-g") Acked-by: Zhenyu Wang <[email protected]> Signed-off-by: Tina Zhang <[email protected]> Signed-off-by: Zhenyu Wang <[email protected]> Link: http://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 4fc0a3c commit 9f674c8

File tree

4 files changed

+99
-4
lines changed

4 files changed

+99
-4
lines changed

drivers/gpu/drm/i915/gvt/dmabuf.c

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,32 @@
3636

3737
#define GEN8_DECODE_PTE(pte) (pte & GENMASK_ULL(63, 12))
3838

39+
static int vgpu_pin_dma_address(struct intel_vgpu *vgpu,
40+
unsigned long size,
41+
dma_addr_t dma_addr)
42+
{
43+
int ret = 0;
44+
45+
if (intel_gvt_hypervisor_dma_pin_guest_page(vgpu, dma_addr))
46+
ret = -EINVAL;
47+
48+
return ret;
49+
}
50+
51+
static void vgpu_unpin_dma_address(struct intel_vgpu *vgpu,
52+
dma_addr_t dma_addr)
53+
{
54+
intel_gvt_hypervisor_dma_unmap_guest_page(vgpu, dma_addr);
55+
}
56+
3957
static int vgpu_gem_get_pages(
4058
struct drm_i915_gem_object *obj)
4159
{
4260
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
61+
struct intel_vgpu *vgpu;
4362
struct sg_table *st;
4463
struct scatterlist *sg;
45-
int i, ret;
64+
int i, j, ret;
4665
gen8_pte_t __iomem *gtt_entries;
4766
struct intel_vgpu_fb_info *fb_info;
4867
u32 page_num;
@@ -51,6 +70,10 @@ static int vgpu_gem_get_pages(
5170
if (WARN_ON(!fb_info))
5271
return -ENODEV;
5372

73+
vgpu = fb_info->obj->vgpu;
74+
if (WARN_ON(!vgpu))
75+
return -ENODEV;
76+
5477
st = kmalloc(sizeof(*st), GFP_KERNEL);
5578
if (unlikely(!st))
5679
return -ENOMEM;
@@ -64,21 +87,53 @@ static int vgpu_gem_get_pages(
6487
gtt_entries = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm +
6588
(fb_info->start >> PAGE_SHIFT);
6689
for_each_sg(st->sgl, sg, page_num, i) {
90+
dma_addr_t dma_addr =
91+
GEN8_DECODE_PTE(readq(&gtt_entries[i]));
92+
if (vgpu_pin_dma_address(vgpu, PAGE_SIZE, dma_addr)) {
93+
ret = -EINVAL;
94+
goto out;
95+
}
96+
6797
sg->offset = 0;
6898
sg->length = PAGE_SIZE;
69-
sg_dma_address(sg) =
70-
GEN8_DECODE_PTE(readq(&gtt_entries[i]));
7199
sg_dma_len(sg) = PAGE_SIZE;
100+
sg_dma_address(sg) = dma_addr;
72101
}
73102

74103
__i915_gem_object_set_pages(obj, st, PAGE_SIZE);
104+
out:
105+
if (ret) {
106+
dma_addr_t dma_addr;
107+
108+
for_each_sg(st->sgl, sg, i, j) {
109+
dma_addr = sg_dma_address(sg);
110+
if (dma_addr)
111+
vgpu_unpin_dma_address(vgpu, dma_addr);
112+
}
113+
sg_free_table(st);
114+
kfree(st);
115+
}
116+
117+
return ret;
75118

76-
return 0;
77119
}
78120

79121
static void vgpu_gem_put_pages(struct drm_i915_gem_object *obj,
80122
struct sg_table *pages)
81123
{
124+
struct scatterlist *sg;
125+
126+
if (obj->base.dma_buf) {
127+
struct intel_vgpu_fb_info *fb_info = obj->gvt_info;
128+
struct intel_vgpu_dmabuf_obj *obj = fb_info->obj;
129+
struct intel_vgpu *vgpu = obj->vgpu;
130+
int i;
131+
132+
for_each_sg(pages->sgl, sg, fb_info->size, i)
133+
vgpu_unpin_dma_address(vgpu,
134+
sg_dma_address(sg));
135+
}
136+
82137
sg_free_table(pages);
83138
kfree(pages);
84139
}

drivers/gpu/drm/i915/gvt/hypercall.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ struct intel_gvt_mpt {
6262
unsigned long size, dma_addr_t *dma_addr);
6363
void (*dma_unmap_guest_page)(unsigned long handle, dma_addr_t dma_addr);
6464

65+
int (*dma_pin_guest_page)(unsigned long handle, dma_addr_t dma_addr);
66+
6567
int (*map_gfn_to_mfn)(unsigned long handle, unsigned long gfn,
6668
unsigned long mfn, unsigned int nr, bool map);
6769
int (*set_trap_area)(unsigned long handle, u64 start, u64 end,

drivers/gpu/drm/i915/gvt/kvmgt.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,6 +1916,28 @@ static int kvmgt_dma_map_guest_page(unsigned long handle, unsigned long gfn,
19161916
return ret;
19171917
}
19181918

1919+
static int kvmgt_dma_pin_guest_page(unsigned long handle, dma_addr_t dma_addr)
1920+
{
1921+
struct kvmgt_guest_info *info;
1922+
struct gvt_dma *entry;
1923+
int ret = 0;
1924+
1925+
if (!handle_valid(handle))
1926+
return -ENODEV;
1927+
1928+
info = (struct kvmgt_guest_info *)handle;
1929+
1930+
mutex_lock(&info->vgpu->vdev.cache_lock);
1931+
entry = __gvt_cache_find_dma_addr(info->vgpu, dma_addr);
1932+
if (entry)
1933+
kref_get(&entry->ref);
1934+
else
1935+
ret = -ENOMEM;
1936+
mutex_unlock(&info->vgpu->vdev.cache_lock);
1937+
1938+
return ret;
1939+
}
1940+
19191941
static void __gvt_dma_release(struct kref *ref)
19201942
{
19211943
struct gvt_dma *entry = container_of(ref, typeof(*entry), ref);
@@ -2027,6 +2049,7 @@ static struct intel_gvt_mpt kvmgt_mpt = {
20272049
.gfn_to_mfn = kvmgt_gfn_to_pfn,
20282050
.dma_map_guest_page = kvmgt_dma_map_guest_page,
20292051
.dma_unmap_guest_page = kvmgt_dma_unmap_guest_page,
2052+
.dma_pin_guest_page = kvmgt_dma_pin_guest_page,
20302053
.set_opregion = kvmgt_set_opregion,
20312054
.set_edid = kvmgt_set_edid,
20322055
.get_vfio_device = kvmgt_get_vfio_device,

drivers/gpu/drm/i915/gvt/mpt.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,21 @@ static inline void intel_gvt_hypervisor_dma_unmap_guest_page(
254254
intel_gvt_host.mpt->dma_unmap_guest_page(vgpu->handle, dma_addr);
255255
}
256256

257+
/**
258+
* intel_gvt_hypervisor_dma_pin_guest_page - pin guest dma buf
259+
* @vgpu: a vGPU
260+
* @dma_addr: guest dma addr
261+
*
262+
* Returns:
263+
* 0 on success, negative error code if failed.
264+
*/
265+
static inline int
266+
intel_gvt_hypervisor_dma_pin_guest_page(struct intel_vgpu *vgpu,
267+
dma_addr_t dma_addr)
268+
{
269+
return intel_gvt_host.mpt->dma_pin_guest_page(vgpu->handle, dma_addr);
270+
}
271+
257272
/**
258273
* intel_gvt_hypervisor_map_gfn_to_mfn - map a GFN region to MFN
259274
* @vgpu: a vGPU

0 commit comments

Comments
 (0)