[PATCH 6/9] drm/i915/gvt: Refine pte shadowing process
Zhi Wang
zhi.a.wang at intel.com
Mon Dec 25 11:02:27 UTC 2017
Reviewed-by: Zhi Wang <zhi.wang at intel.com>
On 12/25/17 17:11, changbin.du at intel.com wrote:
> From: Changbin Du <changbin.du at intel.com>
>
> Make the shadow PTE population code clear. Later we will add huge gtt
> support based on this.
>
> Signed-off-by: Changbin Du <changbin.du at intel.com>
> ---
> drivers/gpu/drm/i915/gvt/gtt.c | 167 ++++++++++++++++++++++-------------------
> 1 file changed, 88 insertions(+), 79 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
> index 86636689..f8aff1d 100644
> --- a/drivers/gpu/drm/i915/gvt/gtt.c
> +++ b/drivers/gpu/drm/i915/gvt/gtt.c
> @@ -453,29 +453,6 @@ static struct intel_gvt_gtt_gma_ops gen8_gtt_gma_ops = {
> .gma_to_pml4_index = gen8_gma_to_pml4_index,
> };
>
> -static int gtt_entry_p2m(struct intel_vgpu *vgpu, struct intel_gvt_gtt_entry *p,
> - struct intel_gvt_gtt_entry *m)
> -{
> - struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
> - unsigned long gfn, mfn;
> -
> - *m = *p;
> -
> - if (!ops->test_present(p))
> - return 0;
> -
> - gfn = ops->get_pfn(p);
> -
> - mfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gfn);
> - if (mfn == INTEL_GVT_INVALID_ADDR) {
> - gvt_vgpu_err("fail to translate gfn: 0x%lx\n", gfn);
> - return -ENXIO;
> - }
> -
> - ops->set_pfn(m, mfn);
> - return 0;
> -}
> -
> /*
> * MM helpers.
> */
> @@ -941,8 +918,7 @@ static int ppgtt_invalidate_shadow_page_by_shadow_entry(struct intel_vgpu *vgpu,
> struct intel_vgpu_ppgtt_spt *s;
> intel_gvt_gtt_type_t cur_pt_type;
>
> - if (WARN_ON(!gtt_type_is_pt(get_next_pt_type(e->type))))
> - return -EINVAL;
> + GEM_BUG_ON(!gtt_type_is_pt(get_next_pt_type(e->type)));
>
> if (e->type != GTT_TYPE_PPGTT_ROOT_L3_ENTRY
> && e->type != GTT_TYPE_PPGTT_ROOT_L4_ENTRY) {
> @@ -980,14 +956,26 @@ static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
> goto release;
>
> for_each_present_shadow_entry(spt, &e, index) {
> - if (!gtt_type_is_pt(get_next_pt_type(e.type))) {
> - gvt_vgpu_err("GVT doesn't support pse bit for now\n");
> - return -EINVAL;
> + switch (e.type) {
> + case GTT_TYPE_PPGTT_PTE_4K_ENTRY:
> + gvt_vdbg_mm("invalidate 4K entry\n");
> + continue;
> + case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
> + case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
> + WARN(1, "GVT doesn't support 2M/1GB page\n");
> + continue;
> + case GTT_TYPE_PPGTT_PML4_ENTRY:
> + case GTT_TYPE_PPGTT_PDP_ENTRY:
> + case GTT_TYPE_PPGTT_PDE_ENTRY:
> + gvt_vdbg_mm("invalidate PMUL4/PDP/PDE entry\n");
> + ret = ppgtt_invalidate_shadow_page_by_shadow_entry(
> + spt->vgpu, &e);
> + if (ret)
> + goto fail;
> + break;
> + default:
> + GEM_BUG_ON(1);
> }
> - ret = ppgtt_invalidate_shadow_page_by_shadow_entry(
> - spt->vgpu, &e);
> - if (ret)
> - goto fail;
> }
> release:
> trace_spt_change(spt->vgpu->id, "release", spt,
> @@ -1011,10 +999,7 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_populate_shadow_page_by_guest_entry(
> struct intel_vgpu_page_track *t;
> int ret;
>
> - if (WARN_ON(!gtt_type_is_pt(get_next_pt_type(we->type)))) {
> - ret = -EINVAL;
> - goto fail;
> - }
> + GEM_BUG_ON(!gtt_type_is_pt(get_next_pt_type(we->type)));
>
> t = intel_vgpu_find_tracked_page(vgpu, ops->get_pfn(we));
> if (t) {
> @@ -1060,6 +1045,41 @@ static inline void ppgtt_generate_shadow_entry(struct intel_gvt_gtt_entry *se,
> ops->set_pfn(se, s->shadow_page.mfn);
> }
>
> +static int ppgtt_populate_shadow_entry(struct intel_vgpu *vgpu,
> + struct intel_vgpu_ppgtt_spt *spt, unsigned long index,
> + struct intel_gvt_gtt_entry *ge)
> +{
> + struct intel_gvt_gtt_pte_ops *pte_ops = vgpu->gvt->gtt.pte_ops;
> + struct intel_gvt_gtt_entry se = *ge;
> + unsigned long gfn, mfn;
> +
> + if (!pte_ops->test_present(ge))
> + return 0;
> +
> + gfn = pte_ops->get_pfn(ge);
> +
> + switch (ge->type) {
> + case GTT_TYPE_PPGTT_PTE_4K_ENTRY:
> + gvt_vdbg_mm("shadow 4K gtt entry\n");
> + break;
> + case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
> + case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
> + gvt_vgpu_err("GVT doesn't support 2M/1GB entry\n");
> + return -EINVAL;
> + default:
> + GEM_BUG_ON(1);
> + };
> +
> + /* direct shadow */
> + mfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gfn);
> + if (mfn == INTEL_GVT_INVALID_ADDR)
> + return -ENXIO;
> +
> + pte_ops->set_pfn(&se, mfn);
> + ppgtt_set_shadow_entry(spt, &se, index);
> + return 0;
> +}
> +
> static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
> {
> struct intel_vgpu *vgpu = spt->vgpu;
> @@ -1071,31 +1091,22 @@ static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
> trace_spt_change(spt->vgpu->id, "born", spt,
> spt->guest_page.track.gfn, spt->shadow_page.type);
>
> - if (gtt_type_is_pte_pt(spt->shadow_page.type)) {
> - for_each_present_guest_entry(spt, &ge, i) {
> - ret = gtt_entry_p2m(vgpu, &ge, &se);
> - if (ret)
> + for_each_present_guest_entry(spt, &ge, i) {
> + if (gtt_type_is_pt(get_next_pt_type(ge.type))) {
> + s = ppgtt_populate_shadow_page_by_guest_entry(vgpu,
> + &ge);
> + if (IS_ERR(s)) {
> + ret = PTR_ERR(s);
> goto fail;
> + }
> + ppgtt_get_shadow_entry(spt, &se, i);
> + ppgtt_generate_shadow_entry(&se, s, &ge);
> ppgtt_set_shadow_entry(spt, &se, i);
> + } else {
> + ret = ppgtt_populate_shadow_entry(vgpu, spt, i, &ge);
> + if (ret)
> + goto fail;
> }
> - return 0;
> - }
> -
> - for_each_present_guest_entry(spt, &ge, i) {
> - if (!gtt_type_is_pt(get_next_pt_type(ge.type))) {
> - gvt_vgpu_err("GVT doesn't support pse bit now\n");
> - ret = -EINVAL;
> - goto fail;
> - }
> -
> - s = ppgtt_populate_shadow_page_by_guest_entry(vgpu, &ge);
> - if (IS_ERR(s)) {
> - ret = PTR_ERR(s);
> - goto fail;
> - }
> - ppgtt_get_shadow_entry(spt, &se, i);
> - ppgtt_generate_shadow_entry(&se, s, &ge);
> - ppgtt_set_shadow_entry(spt, &se, i);
> }
> return 0;
> fail:
> @@ -1170,10 +1181,9 @@ static int ppgtt_handle_guest_entry_add(struct intel_vgpu_guest_page *gpt,
> ppgtt_generate_shadow_entry(&m, s, we);
> ppgtt_set_shadow_entry(spt, &m, index);
> } else {
> - ret = gtt_entry_p2m(vgpu, we, &m);
> + ret = ppgtt_populate_shadow_entry(vgpu, spt, index, we);
> if (ret)
> goto fail;
> - ppgtt_set_shadow_entry(spt, &m, index);
> }
> return 0;
> fail:
> @@ -1190,7 +1200,7 @@ static int sync_oos_page(struct intel_vgpu *vgpu,
> struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
> struct intel_vgpu_ppgtt_spt *spt =
> guest_page_to_ppgtt_spt(oos_page->guest_page);
> - struct intel_gvt_gtt_entry old, new, m;
> + struct intel_gvt_gtt_entry old, new;
> int index;
> int ret;
>
> @@ -1214,12 +1224,11 @@ static int sync_oos_page(struct intel_vgpu *vgpu,
> oos_page->guest_page, spt->guest_page_type,
> new.val64, index);
>
> - ret = gtt_entry_p2m(vgpu, &new, &m);
> + ret = ppgtt_populate_shadow_entry(vgpu, spt, index, &new);
> if (ret)
> return ret;
>
> ops->set_entry(oos_page->mem, &new, index, false, 0, vgpu);
> - ppgtt_set_shadow_entry(spt, &m, index);
> }
>
> oos_page->guest_page->write_cnt = 0;
> @@ -1366,10 +1375,9 @@ static int ppgtt_handle_guest_write_page_table(
> struct intel_vgpu *vgpu = spt->vgpu;
> int type = spt->shadow_page.type;
> struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
> - struct intel_gvt_gtt_entry se;
> -
> - int ret;
> + struct intel_gvt_gtt_entry old_se;
> int new_present;
> + int ret;
>
> new_present = ops->test_present(we);
>
> @@ -1378,7 +1386,7 @@ static int ppgtt_handle_guest_write_page_table(
> * guarantee the ppgtt table is validated during the window between
> * adding and removal.
> */
> - ppgtt_get_shadow_entry(spt, &se, index);
> + ppgtt_get_shadow_entry(spt, &old_se, index);
>
> if (new_present) {
> ret = ppgtt_handle_guest_entry_add(gpt, we, index);
> @@ -1386,13 +1394,13 @@ static int ppgtt_handle_guest_write_page_table(
> goto fail;
> }
>
> - ret = ppgtt_handle_guest_entry_removal(gpt, &se, index);
> + ret = ppgtt_handle_guest_entry_removal(gpt, &old_se, index);
> if (ret)
> goto fail;
>
> if (!new_present) {
> - ops->set_pfn(&se, vgpu->gtt.scratch_pt[type].page_mfn);
> - ppgtt_set_shadow_entry(spt, &se, index);
> + ops->set_pfn(&old_se, vgpu->gtt.scratch_pt[type].page_mfn);
> + ppgtt_set_shadow_entry(spt, &old_se, index);
> }
>
> return 0;
> @@ -1402,6 +1410,8 @@ static int ppgtt_handle_guest_write_page_table(
> return ret;
> }
>
> +
> +
> static inline bool can_do_out_of_sync(struct intel_vgpu_guest_page *gpt)
> {
> return enable_out_of_sync
> @@ -1912,9 +1922,8 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
> struct intel_vgpu_mm *ggtt_mm = vgpu->gtt.ggtt_mm;
> struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
> unsigned long g_gtt_index = off >> info->gtt_entry_size_shift;
> - unsigned long gma;
> + unsigned long mfn, gma;
> struct intel_gvt_gtt_entry e, m;
> - int ret;
>
> if (bytes != 4 && bytes != 8)
> return -EINVAL;
> @@ -1929,21 +1938,21 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
>
> memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data,
> bytes);
> + m = e;
>
> if (ops->test_present(&e)) {
> - ret = gtt_entry_p2m(vgpu, &e, &m);
> - if (ret) {
> - gvt_vgpu_err("fail to translate guest gtt entry\n");
> + mfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, ops->get_pfn(&e));
> + if (mfn == INTEL_GVT_INVALID_ADDR) {
> + gvt_vgpu_err("fail to populate guest ggtt entry\n");
> /* guest driver may read/write the entry when partial
> * update the entry in this situation p2m will fail
> * settting the shadow entry to point to a scratch page
> */
> ops->set_pfn(&m, gvt->gtt.scratch_mfn);
> - }
> - } else {
> - m = e;
> + } else
> + ops->set_pfn(&m, mfn);
> + } else
> ops->set_pfn(&m, gvt->gtt.scratch_mfn);
> - }
>
> ggtt_set_host_entry(ggtt_mm, &m, g_gtt_index);
> ggtt_invalidate(gvt->dev_priv);
More information about the intel-gvt-dev
mailing list