Skip to content

Commit cc753fb

Browse files
hyuan3rodrigovivi
authored andcommitted
drm/i915/gvt: validate gfn before set shadow page entry
GVT may receive partial write on one guest PTE update. Validate gfn not to translate incomplete gfn. This avoids some unnecessary error messages incurred by the incomplete gfn translating. Also fix the bug that the whole PPGTT shadow page update is aborted on any invalid gfn entry. gfn validation relys on hypervisor's help. Add one MPT module function to provide the function. Signed-off-by: Hang Yuan <hang.yuan@intel.com> Reviewed-by: Zhi Wang <zhi.a.wang@intel.com> Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com> Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
1 parent 03fa935 commit cc753fb

File tree

4 files changed

+53
-5
lines changed

4 files changed

+53
-5
lines changed

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

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -997,19 +997,22 @@ static inline void ppgtt_generate_shadow_entry(struct intel_gvt_gtt_entry *se,
997997
static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
998998
{
999999
struct intel_vgpu *vgpu = spt->vgpu;
1000+
struct intel_gvt *gvt = vgpu->gvt;
1001+
struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
10001002
struct intel_vgpu_ppgtt_spt *s;
10011003
struct intel_gvt_gtt_entry se, ge;
1002-
unsigned long i;
1004+
unsigned long gfn, i;
10031005
int ret;
10041006

10051007
trace_spt_change(spt->vgpu->id, "born", spt,
10061008
spt->guest_page.track.gfn, spt->shadow_page.type);
10071009

10081010
if (gtt_type_is_pte_pt(spt->shadow_page.type)) {
10091011
for_each_present_guest_entry(spt, &ge, i) {
1010-
ret = gtt_entry_p2m(vgpu, &ge, &se);
1011-
if (ret)
1012-
goto fail;
1012+
gfn = ops->get_pfn(&ge);
1013+
if (!intel_gvt_hypervisor_is_valid_gfn(vgpu, gfn) ||
1014+
gtt_entry_p2m(vgpu, &ge, &se))
1015+
ops->set_pfn(&se, gvt->gtt.scratch_mfn);
10131016
ppgtt_set_shadow_entry(spt, &se, i);
10141017
}
10151018
return 0;
@@ -1906,7 +1909,7 @@ static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
19061909
struct intel_vgpu_mm *ggtt_mm = vgpu->gtt.ggtt_mm;
19071910
struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
19081911
unsigned long g_gtt_index = off >> info->gtt_entry_size_shift;
1909-
unsigned long gma;
1912+
unsigned long gma, gfn;
19101913
struct intel_gvt_gtt_entry e, m;
19111914
int ret;
19121915

@@ -1925,6 +1928,16 @@ static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
19251928
bytes);
19261929

19271930
if (ops->test_present(&e)) {
1931+
gfn = ops->get_pfn(&e);
1932+
1933+
/* one PTE update may be issued in multiple writes and the
1934+
* first write may not construct a valid gfn
1935+
*/
1936+
if (!intel_gvt_hypervisor_is_valid_gfn(vgpu, gfn)) {
1937+
ops->set_pfn(&m, gvt->gtt.scratch_mfn);
1938+
goto out;
1939+
}
1940+
19281941
ret = gtt_entry_p2m(vgpu, &e, &m);
19291942
if (ret) {
19301943
gvt_vgpu_err("fail to translate guest gtt entry\n");
@@ -1939,6 +1952,7 @@ static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
19391952
ops->set_pfn(&m, gvt->gtt.scratch_mfn);
19401953
}
19411954

1955+
out:
19421956
ggtt_set_shadow_entry(ggtt_mm, &m, g_gtt_index);
19431957
gtt_invalidate(gvt->dev_priv);
19441958
ggtt_set_guest_entry(ggtt_mm, &e, g_gtt_index);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ struct intel_gvt_mpt {
5858
int (*set_opregion)(void *vgpu);
5959
int (*get_vfio_device)(void *vgpu);
6060
void (*put_vfio_device)(void *vgpu);
61+
bool (*is_valid_gfn)(unsigned long handle, unsigned long gfn);
6162
};
6263

6364
extern struct intel_gvt_mpt xengt_mpt;

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,6 +1570,21 @@ static unsigned long kvmgt_virt_to_pfn(void *addr)
15701570
return PFN_DOWN(__pa(addr));
15711571
}
15721572

1573+
static bool kvmgt_is_valid_gfn(unsigned long handle, unsigned long gfn)
1574+
{
1575+
struct kvmgt_guest_info *info;
1576+
struct kvm *kvm;
1577+
1578+
if (!handle_valid(handle))
1579+
return false;
1580+
1581+
info = (struct kvmgt_guest_info *)handle;
1582+
kvm = info->kvm;
1583+
1584+
return kvm_is_visible_gfn(kvm, gfn);
1585+
1586+
}
1587+
15731588
struct intel_gvt_mpt kvmgt_mpt = {
15741589
.host_init = kvmgt_host_init,
15751590
.host_exit = kvmgt_host_exit,
@@ -1585,6 +1600,7 @@ struct intel_gvt_mpt kvmgt_mpt = {
15851600
.set_opregion = kvmgt_set_opregion,
15861601
.get_vfio_device = kvmgt_get_vfio_device,
15871602
.put_vfio_device = kvmgt_put_vfio_device,
1603+
.is_valid_gfn = kvmgt_is_valid_gfn,
15881604
};
15891605
EXPORT_SYMBOL_GPL(kvmgt_mpt);
15901606

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,4 +339,21 @@ static inline void intel_gvt_hypervisor_put_vfio_device(struct intel_vgpu *vgpu)
339339
intel_gvt_host.mpt->put_vfio_device(vgpu);
340340
}
341341

342+
/**
343+
* intel_gvt_hypervisor_is_valid_gfn - check if a visible gfn
344+
* @vgpu: a vGPU
345+
* @gfn: guest PFN
346+
*
347+
* Returns:
348+
* true on valid gfn, false on not.
349+
*/
350+
static inline bool intel_gvt_hypervisor_is_valid_gfn(
351+
struct intel_vgpu *vgpu, unsigned long gfn)
352+
{
353+
if (!intel_gvt_host.mpt->is_valid_gfn)
354+
return true;
355+
356+
return intel_gvt_host.mpt->is_valid_gfn(vgpu->handle, gfn);
357+
}
358+
342359
#endif /* _GVT_MPT_H_ */

0 commit comments

Comments
 (0)