drm/i915/gvt: Split ppgtt_alloc_spt into two parts
authorChangbin Du <changbin.du@intel.com>
Tue, 15 May 2018 02:35:39 +0000 (10:35 +0800)
committerZhenyu Wang <zhenyuw@linux.intel.com>
Mon, 9 Jul 2018 02:23:32 +0000 (10:23 +0800)
We need a interface to allocate a pure shadow page which doesn't have
a guest page associated with. Such shadow page is used to shadow 2M
huge gtt entry.

Signed-off-by: Changbin Du <changbin.du@intel.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
drivers/gpu/drm/i915/gvt/gtt.c

index d34dc9ab66e10e37024d7ab922b95077126bdbfb..15f6908fc648f31ec9f3a03ebb41a69531acefbb 100644 (file)
@@ -735,10 +735,12 @@ static void ppgtt_free_spt(struct intel_vgpu_ppgtt_spt *spt)
 
        radix_tree_delete(&spt->vgpu->gtt.spt_tree, spt->shadow_page.mfn);
 
-       if (spt->guest_page.oos_page)
-               detach_oos_page(spt->vgpu, spt->guest_page.oos_page);
+       if (spt->guest_page.gfn) {
+               if (spt->guest_page.oos_page)
+                       detach_oos_page(spt->vgpu, spt->guest_page.oos_page);
 
-       intel_vgpu_unregister_page_track(spt->vgpu, spt->guest_page.gfn);
+               intel_vgpu_unregister_page_track(spt->vgpu, spt->guest_page.gfn);
+       }
 
        list_del_init(&spt->post_shadow_list);
        free_spt(spt);
@@ -799,9 +801,9 @@ static inline struct intel_vgpu_ppgtt_spt *intel_vgpu_find_spt_by_mfn(
 
 static int reclaim_one_ppgtt_mm(struct intel_gvt *gvt);
 
+/* Allocate shadow page table without guest page. */
 static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt(
-               struct intel_vgpu *vgpu, int type, unsigned long gfn,
-               bool guest_pde_ips)
+               struct intel_vgpu *vgpu, intel_gvt_gtt_type_t type)
 {
        struct device *kdev = &vgpu->gvt->dev_priv->drm.pdev->dev;
        struct intel_vgpu_ppgtt_spt *spt = NULL;
@@ -836,27 +838,12 @@ retry:
        spt->shadow_page.vaddr = page_address(spt->shadow_page.page);
        spt->shadow_page.mfn = daddr >> I915_GTT_PAGE_SHIFT;
 
-       /*
-        * Init guest_page.
-        */
-       spt->guest_page.type = type;
-       spt->guest_page.gfn = gfn;
-       spt->guest_page.pde_ips = guest_pde_ips;
-
-       ret = intel_vgpu_register_page_track(vgpu, spt->guest_page.gfn,
-                                       ppgtt_write_protection_handler, spt);
-       if (ret)
-               goto err_unmap_dma;
-
        ret = radix_tree_insert(&vgpu->gtt.spt_tree, spt->shadow_page.mfn, spt);
        if (ret)
-               goto err_unreg_page_track;
+               goto err_unmap_dma;
 
-       trace_spt_alloc(vgpu->id, spt, type, spt->shadow_page.mfn, gfn);
        return spt;
 
-err_unreg_page_track:
-       intel_vgpu_unregister_page_track(vgpu, spt->guest_page.gfn);
 err_unmap_dma:
        dma_unmap_page(kdev, daddr, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 err_free_spt:
@@ -864,6 +851,37 @@ err_free_spt:
        return ERR_PTR(ret);
 }
 
+/* Allocate shadow page table associated with specific gfn. */
+static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt_gfn(
+               struct intel_vgpu *vgpu, intel_gvt_gtt_type_t type,
+               unsigned long gfn, bool guest_pde_ips)
+{
+       struct intel_vgpu_ppgtt_spt *spt;
+       int ret;
+
+       spt = ppgtt_alloc_spt(vgpu, type);
+       if (IS_ERR(spt))
+               return spt;
+
+       /*
+        * Init guest_page.
+        */
+       ret = intel_vgpu_register_page_track(vgpu, gfn,
+                       ppgtt_write_protection_handler, spt);
+       if (ret) {
+               ppgtt_free_spt(spt);
+               return ERR_PTR(ret);
+       }
+
+       spt->guest_page.type = type;
+       spt->guest_page.gfn = gfn;
+       spt->guest_page.pde_ips = guest_pde_ips;
+
+       trace_spt_alloc(vgpu->id, spt, type, spt->shadow_page.mfn, gfn);
+
+       return spt;
+}
+
 #define pt_entry_size_shift(spt) \
        ((spt)->vgpu->gvt->device_info.gtt_entry_size_shift)
 
@@ -1021,7 +1039,7 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_populate_spt_by_guest_entry(
                if (we->type == GTT_TYPE_PPGTT_PDE_ENTRY)
                        ips = vgpu_ips_enabled(vgpu) && ops->test_ips(we);
 
-               spt = ppgtt_alloc_spt(vgpu, type, ops->get_pfn(we), ips);
+               spt = ppgtt_alloc_spt_gfn(vgpu, type, ops->get_pfn(we), ips);
                if (IS_ERR(spt)) {
                        ret = PTR_ERR(spt);
                        goto fail;