diff options
Diffstat (limited to 'drivers/gpu/drm/i915/gvt/gtt.c')
-rw-r--r-- | drivers/gpu/drm/i915/gvt/gtt.c | 290 |
1 files changed, 198 insertions, 92 deletions
diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index 7eaaf1c9ed2b..b832bea64e03 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -49,8 +49,8 @@ bool intel_gvt_ggtt_validate_range(struct intel_vgpu *vgpu, u64 addr, u32 size) { if ((!vgpu_gmadr_is_valid(vgpu, addr)) || (size && !vgpu_gmadr_is_valid(vgpu, addr + size - 1))) { - gvt_err("vgpu%d: invalid range gmadr 0x%llx size 0x%x\n", - vgpu->id, addr, size); + gvt_vgpu_err("invalid range gmadr 0x%llx size 0x%x\n", + addr, size); return false; } return true; @@ -240,15 +240,8 @@ static inline int get_pse_type(int type) static u64 read_pte64(struct drm_i915_private *dev_priv, unsigned long index) { void __iomem *addr = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + index; - u64 pte; -#ifdef readq - pte = readq(addr); -#else - pte = ioread32(addr); - pte |= (u64)ioread32(addr + 4) << 32; -#endif - return pte; + return readq(addr); } static void write_pte64(struct drm_i915_private *dev_priv, @@ -256,12 +249,8 @@ static void write_pte64(struct drm_i915_private *dev_priv, { void __iomem *addr = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + index; -#ifdef writeq writeq(pte, addr); -#else - iowrite32((u32)pte, addr); - iowrite32(pte >> 32, addr + 4); -#endif + I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); POSTING_READ(GFX_FLSH_CNTL_GEN6); } @@ -441,7 +430,7 @@ static int gtt_entry_p2m(struct intel_vgpu *vgpu, struct intel_gvt_gtt_entry *p, mfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gfn); if (mfn == INTEL_GVT_INVALID_ADDR) { - gvt_err("fail to translate gfn: 0x%lx\n", gfn); + gvt_vgpu_err("fail to translate gfn: 0x%lx\n", gfn); return -ENXIO; } @@ -617,21 +606,33 @@ struct intel_vgpu_guest_page *intel_vgpu_find_guest_page( static inline int init_shadow_page(struct intel_vgpu *vgpu, struct intel_vgpu_shadow_page *p, int type) { + struct device *kdev = &vgpu->gvt->dev_priv->drm.pdev->dev; + dma_addr_t daddr; + + daddr = dma_map_page(kdev, p->page, 0, 4096, PCI_DMA_BIDIRECTIONAL); + if (dma_mapping_error(kdev, daddr)) { + gvt_vgpu_err("fail to map dma addr\n"); + return -EINVAL; + } + p->vaddr = page_address(p->page); p->type = type; INIT_HLIST_NODE(&p->node); - p->mfn = intel_gvt_hypervisor_virt_to_mfn(p->vaddr); - if (p->mfn == INTEL_GVT_INVALID_ADDR) - return -EFAULT; - + p->mfn = daddr >> GTT_PAGE_SHIFT; hash_add(vgpu->gtt.shadow_page_hash_table, &p->node, p->mfn); return 0; } -static inline void clean_shadow_page(struct intel_vgpu_shadow_page *p) +static inline void clean_shadow_page(struct intel_vgpu *vgpu, + struct intel_vgpu_shadow_page *p) { + struct device *kdev = &vgpu->gvt->dev_priv->drm.pdev->dev; + + dma_unmap_page(kdev, p->mfn << GTT_PAGE_SHIFT, 4096, + PCI_DMA_BIDIRECTIONAL); + if (!hlist_unhashed(&p->node)) hash_del(&p->node); } @@ -681,7 +682,7 @@ static void ppgtt_free_shadow_page(struct intel_vgpu_ppgtt_spt *spt) { trace_spt_free(spt->vgpu->id, spt, spt->shadow_page.type); - clean_shadow_page(&spt->shadow_page); + clean_shadow_page(spt->vgpu, &spt->shadow_page); intel_vgpu_clean_guest_page(spt->vgpu, &spt->guest_page); list_del_init(&spt->post_shadow_list); @@ -734,7 +735,7 @@ retry: if (reclaim_one_mm(vgpu->gvt)) goto retry; - gvt_err("fail to allocate ppgtt shadow page\n"); + gvt_vgpu_err("fail to allocate ppgtt shadow page\n"); return ERR_PTR(-ENOMEM); } @@ -749,14 +750,14 @@ retry: */ ret = init_shadow_page(vgpu, &spt->shadow_page, type); if (ret) { - gvt_err("fail to initialize shadow page for spt\n"); + gvt_vgpu_err("fail to initialize shadow page for spt\n"); goto err; } ret = intel_vgpu_init_guest_page(vgpu, &spt->guest_page, gfn, ppgtt_write_protection_handler, NULL); if (ret) { - gvt_err("fail to initialize guest page for spt\n"); + gvt_vgpu_err("fail to initialize guest page for spt\n"); goto err; } @@ -775,8 +776,7 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_find_shadow_page( if (p) return shadow_page_to_ppgtt_spt(p); - gvt_err("vgpu%d: fail to find ppgtt shadow page: 0x%lx\n", - vgpu->id, mfn); + gvt_vgpu_err("fail to find ppgtt shadow page: 0x%lx\n", mfn); return NULL; } @@ -826,8 +826,8 @@ static int ppgtt_invalidate_shadow_page_by_shadow_entry(struct intel_vgpu *vgpu, } s = ppgtt_find_shadow_page(vgpu, ops->get_pfn(e)); if (!s) { - gvt_err("vgpu%d: fail to find shadow page: mfn: 0x%lx\n", - vgpu->id, ops->get_pfn(e)); + gvt_vgpu_err("fail to find shadow page: mfn: 0x%lx\n", + ops->get_pfn(e)); return -ENXIO; } return ppgtt_invalidate_shadow_page(s); @@ -835,6 +835,7 @@ static int ppgtt_invalidate_shadow_page_by_shadow_entry(struct intel_vgpu *vgpu, static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt) { + struct intel_vgpu *vgpu = spt->vgpu; struct intel_gvt_gtt_entry e; unsigned long index; int ret; @@ -853,7 +854,7 @@ static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt) for_each_present_shadow_entry(spt, &e, index) { if (!gtt_type_is_pt(get_next_pt_type(e.type))) { - gvt_err("GVT doesn't support pse bit for now\n"); + gvt_vgpu_err("GVT doesn't support pse bit for now\n"); return -EINVAL; } ret = ppgtt_invalidate_shadow_page_by_shadow_entry( @@ -867,8 +868,8 @@ release: ppgtt_free_shadow_page(spt); return 0; fail: - gvt_err("vgpu%d: fail: shadow page %p shadow entry 0x%llx type %d\n", - spt->vgpu->id, spt, e.val64, e.type); + gvt_vgpu_err("fail: shadow page %p shadow entry 0x%llx type %d\n", + spt, e.val64, e.type); return ret; } @@ -913,8 +914,8 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_populate_shadow_page_by_guest_entry( } return s; fail: - gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n", - vgpu->id, s, we->val64, we->type); + gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d\n", + s, we->val64, we->type); return ERR_PTR(ret); } @@ -952,7 +953,7 @@ static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt) for_each_present_guest_entry(spt, &ge, i) { if (!gtt_type_is_pt(get_next_pt_type(ge.type))) { - gvt_err("GVT doesn't support pse bit now\n"); + gvt_vgpu_err("GVT doesn't support pse bit now\n"); ret = -EINVAL; goto fail; } @@ -968,8 +969,8 @@ static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt) } return 0; fail: - gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n", - vgpu->id, spt, ge.val64, ge.type); + gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d\n", + spt, ge.val64, ge.type); return ret; } @@ -998,7 +999,7 @@ static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_guest_page *gpt, struct intel_vgpu_ppgtt_spt *s = ppgtt_find_shadow_page(vgpu, ops->get_pfn(&e)); if (!s) { - gvt_err("fail to find guest page\n"); + gvt_vgpu_err("fail to find guest page\n"); ret = -ENXIO; goto fail; } @@ -1010,8 +1011,8 @@ static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_guest_page *gpt, ppgtt_set_shadow_entry(spt, &e, index); return 0; fail: - gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n", - vgpu->id, spt, e.val64, e.type); + gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d\n", + spt, e.val64, e.type); return ret; } @@ -1045,8 +1046,8 @@ static int ppgtt_handle_guest_entry_add(struct intel_vgpu_guest_page *gpt, } return 0; fail: - gvt_err("vgpu%d: fail: spt %p guest entry 0x%llx type %d\n", vgpu->id, - spt, we->val64, we->type); + gvt_vgpu_err("fail: spt %p guest entry 0x%llx type %d\n", + spt, we->val64, we->type); return ret; } @@ -1249,8 +1250,8 @@ static int ppgtt_handle_guest_write_page_table( } return 0; fail: - gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d.\n", - vgpu->id, spt, we->val64, we->type); + gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d.\n", + spt, we->val64, we->type); return ret; } @@ -1380,8 +1381,7 @@ static int gen8_mm_alloc_page_table(struct intel_vgpu_mm *mm) info->gtt_entry_size; mem = kzalloc(mm->has_shadow_page_table ? mm->page_table_entry_size * 2 - : mm->page_table_entry_size, - GFP_ATOMIC); + : mm->page_table_entry_size, GFP_KERNEL); if (!mem) return -ENOMEM; mm->virtual_page_table = mem; @@ -1493,7 +1493,7 @@ static int shadow_mm(struct intel_vgpu_mm *mm) spt = ppgtt_populate_shadow_page_by_guest_entry(vgpu, &ge); if (IS_ERR(spt)) { - gvt_err("fail to populate guest root pointer\n"); + gvt_vgpu_err("fail to populate guest root pointer\n"); ret = PTR_ERR(spt); goto fail; } @@ -1532,7 +1532,7 @@ struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu, struct intel_vgpu_mm *mm; int ret; - mm = kzalloc(sizeof(*mm), GFP_ATOMIC); + mm = kzalloc(sizeof(*mm), GFP_KERNEL); if (!mm) { ret = -ENOMEM; goto fail; @@ -1566,7 +1566,7 @@ struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu, ret = gtt->mm_alloc_page_table(mm); if (ret) { - gvt_err("fail to allocate page table for mm\n"); + gvt_vgpu_err("fail to allocate page table for mm\n"); goto fail; } @@ -1584,7 +1584,7 @@ struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu, } return mm; fail: - gvt_err("fail to create mm\n"); + gvt_vgpu_err("fail to create mm\n"); if (mm) intel_gvt_mm_unreference(mm); return ERR_PTR(ret); @@ -1760,7 +1760,7 @@ unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma) mm->page_table_level, gma, gpa); return gpa; err: - gvt_err("invalid mm type: %d gma %lx\n", mm->type, gma); + gvt_vgpu_err("invalid mm type: %d gma %lx\n", mm->type, gma); return INTEL_GVT_INVALID_ADDR; } @@ -1825,11 +1825,8 @@ static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, gma = g_gtt_index << GTT_PAGE_SHIFT; /* the VM may configure the whole GM space when ballooning is used */ - if (WARN_ONCE(!vgpu_gmadr_is_valid(vgpu, gma), - "vgpu%d: found oob ggtt write, offset %x\n", - vgpu->id, off)) { + if (!vgpu_gmadr_is_valid(vgpu, gma)) return 0; - } ggtt_get_guest_entry(ggtt_mm, &e, g_gtt_index); @@ -1839,13 +1836,16 @@ static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, if (ops->test_present(&e)) { ret = gtt_entry_p2m(vgpu, &e, &m); if (ret) { - gvt_err("vgpu%d: fail to translate guest gtt entry\n", - vgpu->id); - return ret; + gvt_vgpu_err("fail to translate guest gtt 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_ggtt_mfn); } } else { m = e; - m.val64 = 0; + ops->set_pfn(&m, gvt->gtt.scratch_ggtt_mfn); } ggtt_set_shadow_entry(ggtt_mm, &m, g_gtt_index); @@ -1886,39 +1886,39 @@ static int alloc_scratch_pages(struct intel_vgpu *vgpu, struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; int page_entry_num = GTT_PAGE_SIZE >> vgpu->gvt->device_info.gtt_entry_size_shift; - struct page *scratch_pt; - unsigned long mfn; + void *scratch_pt; int i; - void *p; + struct device *dev = &vgpu->gvt->dev_priv->drm.pdev->dev; + dma_addr_t daddr; if (WARN_ON(type < GTT_TYPE_PPGTT_PTE_PT || type >= GTT_TYPE_MAX)) return -EINVAL; - scratch_pt = alloc_page(GFP_KERNEL | GFP_ATOMIC | __GFP_ZERO); + scratch_pt = (void *)get_zeroed_page(GFP_KERNEL); if (!scratch_pt) { - gvt_err("fail to allocate scratch page\n"); + gvt_vgpu_err("fail to allocate scratch page\n"); return -ENOMEM; } - p = kmap_atomic(scratch_pt); - mfn = intel_gvt_hypervisor_virt_to_mfn(p); - if (mfn == INTEL_GVT_INVALID_ADDR) { - gvt_err("fail to translate vaddr:0x%llx\n", (u64)p); - kunmap_atomic(p); - __free_page(scratch_pt); - return -EFAULT; + daddr = dma_map_page(dev, virt_to_page(scratch_pt), 0, + 4096, PCI_DMA_BIDIRECTIONAL); + if (dma_mapping_error(dev, daddr)) { + gvt_vgpu_err("fail to dmamap scratch_pt\n"); + __free_page(virt_to_page(scratch_pt)); + return -ENOMEM; } - gtt->scratch_pt[type].page_mfn = mfn; - gtt->scratch_pt[type].page = scratch_pt; + gtt->scratch_pt[type].page_mfn = + (unsigned long)(daddr >> GTT_PAGE_SHIFT); + gtt->scratch_pt[type].page = virt_to_page(scratch_pt); gvt_dbg_mm("vgpu%d create scratch_pt: type %d mfn=0x%lx\n", - vgpu->id, type, mfn); + vgpu->id, type, gtt->scratch_pt[type].page_mfn); /* Build the tree by full filled the scratch pt with the entries which * point to the next level scratch pt or scratch page. The * scratch_pt[type] indicate the scratch pt/scratch page used by the * 'type' pt. * e.g. scratch_pt[GTT_TYPE_PPGTT_PDE_PT] is used by - * GTT_TYPE_PPGTT_PDE_PT level pt, that means this scatch_pt it self + * GTT_TYPE_PPGTT_PDE_PT level pt, that means this scratch_pt it self * is GTT_TYPE_PPGTT_PTE_PT, and full filled by scratch page mfn. */ if (type > GTT_TYPE_PPGTT_PTE_PT && type < GTT_TYPE_MAX) { @@ -1936,20 +1936,23 @@ static int alloc_scratch_pages(struct intel_vgpu *vgpu, se.val64 |= PPAT_CACHED_INDEX; for (i = 0; i < page_entry_num; i++) - ops->set_entry(p, &se, i, false, 0, vgpu); + ops->set_entry(scratch_pt, &se, i, false, 0, vgpu); } - kunmap_atomic(p); - return 0; } static int release_scratch_page_tree(struct intel_vgpu *vgpu) { int i; + struct device *dev = &vgpu->gvt->dev_priv->drm.pdev->dev; + dma_addr_t daddr; for (i = GTT_TYPE_PPGTT_PTE_PT; i < GTT_TYPE_MAX; i++) { if (vgpu->gtt.scratch_pt[i].page != NULL) { + daddr = (dma_addr_t)(vgpu->gtt.scratch_pt[i].page_mfn << + GTT_PAGE_SHIFT); + dma_unmap_page(dev, daddr, 4096, PCI_DMA_BIDIRECTIONAL); __free_page(vgpu->gtt.scratch_pt[i].page); vgpu->gtt.scratch_pt[i].page = NULL; vgpu->gtt.scratch_pt[i].page_mfn = 0; @@ -1998,10 +2001,12 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu) INIT_LIST_HEAD(>t->oos_page_list_head); INIT_LIST_HEAD(>t->post_shadow_list_head); + intel_vgpu_reset_ggtt(vgpu); + ggtt_mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_GGTT, NULL, 1, 0); if (IS_ERR(ggtt_mm)) { - gvt_err("fail to create mm for ggtt.\n"); + gvt_vgpu_err("fail to create mm for ggtt.\n"); return PTR_ERR(ggtt_mm); } @@ -2010,6 +2015,22 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu) return create_scratch_page_tree(vgpu); } +static void intel_vgpu_free_mm(struct intel_vgpu *vgpu, int type) +{ + struct list_head *pos, *n; + struct intel_vgpu_mm *mm; + + list_for_each_safe(pos, n, &vgpu->gtt.mm_list_head) { + mm = container_of(pos, struct intel_vgpu_mm, list); + if (mm->type == type) { + vgpu->gvt->gtt.mm_free_page_table(mm); + list_del(&mm->list); + list_del(&mm->lru_list); + kfree(mm); + } + } +} + /** * intel_vgpu_clean_gtt - clean up per-vGPU graphics memory virulization * @vgpu: a vGPU @@ -2022,19 +2043,11 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu) */ void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu) { - struct list_head *pos, *n; - struct intel_vgpu_mm *mm; - ppgtt_free_all_shadow_page(vgpu); release_scratch_page_tree(vgpu); - list_for_each_safe(pos, n, &vgpu->gtt.mm_list_head) { - mm = container_of(pos, struct intel_vgpu_mm, list); - vgpu->gvt->gtt.mm_free_page_table(mm); - list_del(&mm->list); - list_del(&mm->lru_list); - kfree(mm); - } + intel_vgpu_free_mm(vgpu, INTEL_GVT_MM_PPGTT); + intel_vgpu_free_mm(vgpu, INTEL_GVT_MM_GGTT); } static void clean_spt_oos(struct intel_gvt *gvt) @@ -2066,7 +2079,6 @@ static int setup_spt_oos(struct intel_gvt *gvt) for (i = 0; i < preallocated_oos_pages; i++) { oos_page = kzalloc(sizeof(*oos_page), GFP_KERNEL); if (!oos_page) { - gvt_err("fail to pre-allocate oos page\n"); ret = -ENOMEM; goto fail; } @@ -2156,7 +2168,7 @@ int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu, mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_PPGTT, pdp, page_table_level, 0); if (IS_ERR(mm)) { - gvt_err("fail to create mm\n"); + gvt_vgpu_err("fail to create mm\n"); return PTR_ERR(mm); } } @@ -2186,7 +2198,7 @@ int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu, mm = intel_vgpu_find_ppgtt_mm(vgpu, page_table_level, pdp); if (!mm) { - gvt_err("fail to find ppgtt instance.\n"); + gvt_vgpu_err("fail to find ppgtt instance.\n"); return -EINVAL; } intel_gvt_mm_unreference(mm); @@ -2206,6 +2218,9 @@ int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu, int intel_gvt_init_gtt(struct intel_gvt *gvt) { int ret; + void *page; + struct device *dev = &gvt->dev_priv->drm.pdev->dev; + dma_addr_t daddr; gvt_dbg_core("init gtt\n"); @@ -2218,6 +2233,22 @@ int intel_gvt_init_gtt(struct intel_gvt *gvt) return -ENODEV; } + page = (void *)get_zeroed_page(GFP_KERNEL); + if (!page) { + gvt_err("fail to allocate scratch ggtt page\n"); + return -ENOMEM; + } + + daddr = dma_map_page(dev, virt_to_page(page), 0, + 4096, PCI_DMA_BIDIRECTIONAL); + if (dma_mapping_error(dev, daddr)) { + gvt_err("fail to dmamap scratch ggtt page\n"); + __free_page(virt_to_page(page)); + return -ENOMEM; + } + gvt->gtt.scratch_ggtt_page = virt_to_page(page); + gvt->gtt.scratch_ggtt_mfn = (unsigned long)(daddr >> GTT_PAGE_SHIFT); + if (enable_out_of_sync) { ret = setup_spt_oos(gvt); if (ret) { @@ -2239,6 +2270,81 @@ int intel_gvt_init_gtt(struct intel_gvt *gvt) */ void intel_gvt_clean_gtt(struct intel_gvt *gvt) { + struct device *dev = &gvt->dev_priv->drm.pdev->dev; + dma_addr_t daddr = (dma_addr_t)(gvt->gtt.scratch_ggtt_mfn << + GTT_PAGE_SHIFT); + + dma_unmap_page(dev, daddr, 4096, PCI_DMA_BIDIRECTIONAL); + + __free_page(gvt->gtt.scratch_ggtt_page); + if (enable_out_of_sync) clean_spt_oos(gvt); } + +/** + * intel_vgpu_reset_ggtt - reset the GGTT entry + * @vgpu: a vGPU + * + * This function is called at the vGPU create stage + * to reset all the GGTT entries. + * + */ +void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu) +{ + struct intel_gvt *gvt = vgpu->gvt; + struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; + u32 index; + u32 offset; + u32 num_entries; + struct intel_gvt_gtt_entry e; + + memset(&e, 0, sizeof(struct intel_gvt_gtt_entry)); + e.type = GTT_TYPE_GGTT_PTE; + ops->set_pfn(&e, gvt->gtt.scratch_ggtt_mfn); + e.val64 |= _PAGE_PRESENT; + + index = vgpu_aperture_gmadr_base(vgpu) >> PAGE_SHIFT; + num_entries = vgpu_aperture_sz(vgpu) >> PAGE_SHIFT; + for (offset = 0; offset < num_entries; offset++) + ops->set_entry(NULL, &e, index + offset, false, 0, vgpu); + + index = vgpu_hidden_gmadr_base(vgpu) >> PAGE_SHIFT; + num_entries = vgpu_hidden_sz(vgpu) >> PAGE_SHIFT; + for (offset = 0; offset < num_entries; offset++) + ops->set_entry(NULL, &e, index + offset, false, 0, vgpu); +} + +/** + * intel_vgpu_reset_gtt - reset the all GTT related status + * @vgpu: a vGPU + * @dmlr: true for vGPU Device Model Level Reset, false for GT Reset + * + * This function is called from vfio core to reset reset all + * GTT related status, including GGTT, PPGTT, scratch page. + * + */ +void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu, bool dmlr) +{ + int i; + + ppgtt_free_all_shadow_page(vgpu); + + /* Shadow pages are only created when there is no page + * table tracking data, so remove page tracking data after + * removing the shadow pages. + */ + intel_vgpu_free_mm(vgpu, INTEL_GVT_MM_PPGTT); + + if (!dmlr) + return; + + intel_vgpu_reset_ggtt(vgpu); + + /* clear scratch page for security */ + for (i = GTT_TYPE_PPGTT_PTE_PT; i < GTT_TYPE_MAX; i++) { + if (vgpu->gtt.scratch_pt[i].page != NULL) + memset(page_address(vgpu->gtt.scratch_pt[i].page), + 0, PAGE_SIZE); + } +} |