.. | .. |
---|
53 | 53 | */ |
---|
54 | 54 | bool intel_gvt_ggtt_validate_range(struct intel_vgpu *vgpu, u64 addr, u32 size) |
---|
55 | 55 | { |
---|
56 | | - if ((!vgpu_gmadr_is_valid(vgpu, addr)) || (size |
---|
57 | | - && !vgpu_gmadr_is_valid(vgpu, addr + size - 1))) { |
---|
58 | | - gvt_vgpu_err("invalid range gmadr 0x%llx size 0x%x\n", |
---|
59 | | - addr, size); |
---|
60 | | - return false; |
---|
61 | | - } |
---|
62 | | - return true; |
---|
| 56 | + if (size == 0) |
---|
| 57 | + return vgpu_gmadr_is_valid(vgpu, addr); |
---|
| 58 | + |
---|
| 59 | + if (vgpu_gmadr_is_aperture(vgpu, addr) && |
---|
| 60 | + vgpu_gmadr_is_aperture(vgpu, addr + size - 1)) |
---|
| 61 | + return true; |
---|
| 62 | + else if (vgpu_gmadr_is_hidden(vgpu, addr) && |
---|
| 63 | + vgpu_gmadr_is_hidden(vgpu, addr + size - 1)) |
---|
| 64 | + return true; |
---|
| 65 | + |
---|
| 66 | + gvt_dbg_mm("Invalid ggtt range at 0x%llx, size: 0x%x\n", |
---|
| 67 | + addr, size); |
---|
| 68 | + return false; |
---|
63 | 69 | } |
---|
64 | 70 | |
---|
65 | 71 | /* translate a guest gmadr to host gmadr */ |
---|
66 | 72 | int intel_gvt_ggtt_gmadr_g2h(struct intel_vgpu *vgpu, u64 g_addr, u64 *h_addr) |
---|
67 | 73 | { |
---|
68 | | - if (WARN(!vgpu_gmadr_is_valid(vgpu, g_addr), |
---|
69 | | - "invalid guest gmadr %llx\n", g_addr)) |
---|
| 74 | + struct drm_i915_private *i915 = vgpu->gvt->gt->i915; |
---|
| 75 | + |
---|
| 76 | + if (drm_WARN(&i915->drm, !vgpu_gmadr_is_valid(vgpu, g_addr), |
---|
| 77 | + "invalid guest gmadr %llx\n", g_addr)) |
---|
70 | 78 | return -EACCES; |
---|
71 | 79 | |
---|
72 | 80 | if (vgpu_gmadr_is_aperture(vgpu, g_addr)) |
---|
.. | .. |
---|
81 | 89 | /* translate a host gmadr to guest gmadr */ |
---|
82 | 90 | int intel_gvt_ggtt_gmadr_h2g(struct intel_vgpu *vgpu, u64 h_addr, u64 *g_addr) |
---|
83 | 91 | { |
---|
84 | | - if (WARN(!gvt_gmadr_is_valid(vgpu->gvt, h_addr), |
---|
85 | | - "invalid host gmadr %llx\n", h_addr)) |
---|
| 92 | + struct drm_i915_private *i915 = vgpu->gvt->gt->i915; |
---|
| 93 | + |
---|
| 94 | + if (drm_WARN(&i915->drm, !gvt_gmadr_is_valid(vgpu->gvt, h_addr), |
---|
| 95 | + "invalid host gmadr %llx\n", h_addr)) |
---|
86 | 96 | return -EACCES; |
---|
87 | 97 | |
---|
88 | 98 | if (gvt_gmadr_is_aperture(vgpu->gvt, h_addr)) |
---|
.. | .. |
---|
269 | 279 | return gtt_type_table[type].pse_entry_type; |
---|
270 | 280 | } |
---|
271 | 281 | |
---|
272 | | -static u64 read_pte64(struct drm_i915_private *dev_priv, unsigned long index) |
---|
| 282 | +static u64 read_pte64(struct i915_ggtt *ggtt, unsigned long index) |
---|
273 | 283 | { |
---|
274 | | - void __iomem *addr = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + index; |
---|
| 284 | + void __iomem *addr = (gen8_pte_t __iomem *)ggtt->gsm + index; |
---|
275 | 285 | |
---|
276 | 286 | return readq(addr); |
---|
277 | 287 | } |
---|
278 | 288 | |
---|
279 | | -static void ggtt_invalidate(struct drm_i915_private *dev_priv) |
---|
| 289 | +static void ggtt_invalidate(struct intel_gt *gt) |
---|
280 | 290 | { |
---|
281 | | - mmio_hw_access_pre(dev_priv); |
---|
282 | | - I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); |
---|
283 | | - mmio_hw_access_post(dev_priv); |
---|
| 291 | + mmio_hw_access_pre(gt); |
---|
| 292 | + intel_uncore_write(gt->uncore, GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); |
---|
| 293 | + mmio_hw_access_post(gt); |
---|
284 | 294 | } |
---|
285 | 295 | |
---|
286 | | -static void write_pte64(struct drm_i915_private *dev_priv, |
---|
287 | | - unsigned long index, u64 pte) |
---|
| 296 | +static void write_pte64(struct i915_ggtt *ggtt, unsigned long index, u64 pte) |
---|
288 | 297 | { |
---|
289 | | - void __iomem *addr = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + index; |
---|
| 298 | + void __iomem *addr = (gen8_pte_t __iomem *)ggtt->gsm + index; |
---|
290 | 299 | |
---|
291 | 300 | writeq(pte, addr); |
---|
292 | 301 | } |
---|
.. | .. |
---|
309 | 318 | if (WARN_ON(ret)) |
---|
310 | 319 | return ret; |
---|
311 | 320 | } else if (!pt) { |
---|
312 | | - e->val64 = read_pte64(vgpu->gvt->dev_priv, index); |
---|
| 321 | + e->val64 = read_pte64(vgpu->gvt->gt->ggtt, index); |
---|
313 | 322 | } else { |
---|
314 | 323 | e->val64 = *((u64 *)pt + index); |
---|
315 | 324 | } |
---|
.. | .. |
---|
334 | 343 | if (WARN_ON(ret)) |
---|
335 | 344 | return ret; |
---|
336 | 345 | } else if (!pt) { |
---|
337 | | - write_pte64(vgpu->gvt->dev_priv, index, e->val64); |
---|
| 346 | + write_pte64(vgpu->gvt->gt->ggtt, index, e->val64); |
---|
338 | 347 | } else { |
---|
339 | 348 | *((u64 *)pt + index) = e->val64; |
---|
340 | 349 | } |
---|
.. | .. |
---|
728 | 737 | |
---|
729 | 738 | static void ppgtt_free_spt(struct intel_vgpu_ppgtt_spt *spt) |
---|
730 | 739 | { |
---|
731 | | - struct device *kdev = &spt->vgpu->gvt->dev_priv->drm.pdev->dev; |
---|
| 740 | + struct device *kdev = &spt->vgpu->gvt->gt->i915->drm.pdev->dev; |
---|
732 | 741 | |
---|
733 | 742 | trace_spt_free(spt->vgpu->id, spt, spt->guest_page.type); |
---|
734 | 743 | |
---|
.. | .. |
---|
750 | 759 | |
---|
751 | 760 | static void ppgtt_free_all_spt(struct intel_vgpu *vgpu) |
---|
752 | 761 | { |
---|
753 | | - struct intel_vgpu_ppgtt_spt *spt; |
---|
| 762 | + struct intel_vgpu_ppgtt_spt *spt, *spn; |
---|
754 | 763 | struct radix_tree_iter iter; |
---|
755 | | - void **slot; |
---|
| 764 | + LIST_HEAD(all_spt); |
---|
| 765 | + void __rcu **slot; |
---|
756 | 766 | |
---|
| 767 | + rcu_read_lock(); |
---|
757 | 768 | radix_tree_for_each_slot(slot, &vgpu->gtt.spt_tree, &iter, 0) { |
---|
758 | 769 | spt = radix_tree_deref_slot(slot); |
---|
759 | | - ppgtt_free_spt(spt); |
---|
| 770 | + list_move(&spt->post_shadow_list, &all_spt); |
---|
760 | 771 | } |
---|
| 772 | + rcu_read_unlock(); |
---|
| 773 | + |
---|
| 774 | + list_for_each_entry_safe(spt, spn, &all_spt, post_shadow_list) |
---|
| 775 | + ppgtt_free_spt(spt); |
---|
761 | 776 | } |
---|
762 | 777 | |
---|
763 | 778 | static int ppgtt_handle_guest_write_page_table_bytes( |
---|
.. | .. |
---|
805 | 820 | |
---|
806 | 821 | /* Allocate shadow page table without guest page. */ |
---|
807 | 822 | static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt( |
---|
808 | | - struct intel_vgpu *vgpu, intel_gvt_gtt_type_t type) |
---|
| 823 | + struct intel_vgpu *vgpu, enum intel_gvt_gtt_type type) |
---|
809 | 824 | { |
---|
810 | | - struct device *kdev = &vgpu->gvt->dev_priv->drm.pdev->dev; |
---|
| 825 | + struct device *kdev = &vgpu->gvt->gt->i915->drm.pdev->dev; |
---|
811 | 826 | struct intel_vgpu_ppgtt_spt *spt = NULL; |
---|
812 | 827 | dma_addr_t daddr; |
---|
813 | 828 | int ret; |
---|
.. | .. |
---|
855 | 870 | |
---|
856 | 871 | /* Allocate shadow page table associated with specific gfn. */ |
---|
857 | 872 | static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt_gfn( |
---|
858 | | - struct intel_vgpu *vgpu, intel_gvt_gtt_type_t type, |
---|
| 873 | + struct intel_vgpu *vgpu, enum intel_gvt_gtt_type type, |
---|
859 | 874 | unsigned long gfn, bool guest_pde_ips) |
---|
860 | 875 | { |
---|
861 | 876 | struct intel_vgpu_ppgtt_spt *spt; |
---|
.. | .. |
---|
928 | 943 | static int ppgtt_invalidate_spt_by_shadow_entry(struct intel_vgpu *vgpu, |
---|
929 | 944 | struct intel_gvt_gtt_entry *e) |
---|
930 | 945 | { |
---|
| 946 | + struct drm_i915_private *i915 = vgpu->gvt->gt->i915; |
---|
931 | 947 | struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; |
---|
932 | 948 | struct intel_vgpu_ppgtt_spt *s; |
---|
933 | | - intel_gvt_gtt_type_t cur_pt_type; |
---|
| 949 | + enum intel_gvt_gtt_type cur_pt_type; |
---|
934 | 950 | |
---|
935 | 951 | GEM_BUG_ON(!gtt_type_is_pt(get_next_pt_type(e->type))); |
---|
936 | 952 | |
---|
937 | 953 | if (e->type != GTT_TYPE_PPGTT_ROOT_L3_ENTRY |
---|
938 | 954 | && e->type != GTT_TYPE_PPGTT_ROOT_L4_ENTRY) { |
---|
939 | | - cur_pt_type = get_next_pt_type(e->type) + 1; |
---|
| 955 | + cur_pt_type = get_next_pt_type(e->type); |
---|
| 956 | + |
---|
| 957 | + if (!gtt_type_is_pt(cur_pt_type) || |
---|
| 958 | + !gtt_type_is_pt(cur_pt_type + 1)) { |
---|
| 959 | + drm_WARN(&i915->drm, 1, |
---|
| 960 | + "Invalid page table type, cur_pt_type is: %d\n", |
---|
| 961 | + cur_pt_type); |
---|
| 962 | + return -EINVAL; |
---|
| 963 | + } |
---|
| 964 | + |
---|
| 965 | + cur_pt_type += 1; |
---|
| 966 | + |
---|
940 | 967 | if (ops->get_pfn(e) == |
---|
941 | 968 | vgpu->gtt.scratch_pt[cur_pt_type].page_mfn) |
---|
942 | 969 | return 0; |
---|
.. | .. |
---|
1023 | 1050 | |
---|
1024 | 1051 | static bool vgpu_ips_enabled(struct intel_vgpu *vgpu) |
---|
1025 | 1052 | { |
---|
1026 | | - struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; |
---|
| 1053 | + struct drm_i915_private *dev_priv = vgpu->gvt->gt->i915; |
---|
1027 | 1054 | |
---|
1028 | 1055 | if (INTEL_GEN(dev_priv) == 9 || INTEL_GEN(dev_priv) == 10) { |
---|
1029 | 1056 | u32 ips = vgpu_vreg_t(vgpu, GEN8_GAMW_ECO_DEV_RW_IA) & |
---|
.. | .. |
---|
1070 | 1097 | } else { |
---|
1071 | 1098 | int type = get_next_pt_type(we->type); |
---|
1072 | 1099 | |
---|
| 1100 | + if (!gtt_type_is_pt(type)) { |
---|
| 1101 | + ret = -EINVAL; |
---|
| 1102 | + goto err; |
---|
| 1103 | + } |
---|
| 1104 | + |
---|
1073 | 1105 | spt = ppgtt_alloc_spt_gfn(vgpu, type, ops->get_pfn(we), ips); |
---|
1074 | 1106 | if (IS_ERR(spt)) { |
---|
1075 | 1107 | ret = PTR_ERR(spt); |
---|
.. | .. |
---|
1091 | 1123 | |
---|
1092 | 1124 | err_free_spt: |
---|
1093 | 1125 | ppgtt_free_spt(spt); |
---|
| 1126 | + spt = NULL; |
---|
1094 | 1127 | err: |
---|
1095 | 1128 | gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d\n", |
---|
1096 | 1129 | spt, we->val64, we->type); |
---|
.. | .. |
---|
1113 | 1146 | } |
---|
1114 | 1147 | |
---|
1115 | 1148 | /** |
---|
| 1149 | + * Check if can do 2M page |
---|
| 1150 | + * @vgpu: target vgpu |
---|
| 1151 | + * @entry: target pfn's gtt entry |
---|
| 1152 | + * |
---|
1116 | 1153 | * Return 1 if 2MB huge gtt shadowing is possilbe, 0 if miscondition, |
---|
1117 | 1154 | * negtive if found err. |
---|
1118 | 1155 | */ |
---|
.. | .. |
---|
1122 | 1159 | struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; |
---|
1123 | 1160 | unsigned long pfn; |
---|
1124 | 1161 | |
---|
1125 | | - if (!HAS_PAGE_SIZES(vgpu->gvt->dev_priv, I915_GTT_PAGE_SIZE_2M)) |
---|
| 1162 | + if (!HAS_PAGE_SIZES(vgpu->gvt->gt->i915, I915_GTT_PAGE_SIZE_2M)) |
---|
1126 | 1163 | return 0; |
---|
1127 | 1164 | |
---|
1128 | 1165 | pfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, ops->get_pfn(entry)); |
---|
.. | .. |
---|
1251 | 1288 | return -EINVAL; |
---|
1252 | 1289 | default: |
---|
1253 | 1290 | GEM_BUG_ON(1); |
---|
1254 | | - }; |
---|
| 1291 | + } |
---|
1255 | 1292 | |
---|
1256 | 1293 | /* direct shadow */ |
---|
1257 | 1294 | ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu, gfn, page_size, |
---|
.. | .. |
---|
1845 | 1882 | * Zero on success, negative error code in pointer if failed. |
---|
1846 | 1883 | */ |
---|
1847 | 1884 | struct intel_vgpu_mm *intel_vgpu_create_ppgtt_mm(struct intel_vgpu *vgpu, |
---|
1848 | | - intel_gvt_gtt_type_t root_entry_type, u64 pdps[]) |
---|
| 1885 | + enum intel_gvt_gtt_type root_entry_type, u64 pdps[]) |
---|
1849 | 1886 | { |
---|
1850 | 1887 | struct intel_gvt *gvt = vgpu->gvt; |
---|
1851 | 1888 | struct intel_vgpu_mm *mm; |
---|
.. | .. |
---|
1863 | 1900 | |
---|
1864 | 1901 | INIT_LIST_HEAD(&mm->ppgtt_mm.list); |
---|
1865 | 1902 | INIT_LIST_HEAD(&mm->ppgtt_mm.lru_list); |
---|
| 1903 | + INIT_LIST_HEAD(&mm->ppgtt_mm.link); |
---|
1866 | 1904 | |
---|
1867 | 1905 | if (root_entry_type == GTT_TYPE_PPGTT_ROOT_L4_ENTRY) |
---|
1868 | 1906 | mm->ppgtt_mm.guest_pdps[0] = pdps[0]; |
---|
.. | .. |
---|
1878 | 1916 | } |
---|
1879 | 1917 | |
---|
1880 | 1918 | list_add_tail(&mm->ppgtt_mm.list, &vgpu->gtt.ppgtt_mm_list_head); |
---|
| 1919 | + |
---|
| 1920 | + mutex_lock(&gvt->gtt.ppgtt_mm_lock); |
---|
1881 | 1921 | list_add_tail(&mm->ppgtt_mm.lru_list, &gvt->gtt.ppgtt_mm_lru_list_head); |
---|
| 1922 | + mutex_unlock(&gvt->gtt.ppgtt_mm_lock); |
---|
| 1923 | + |
---|
1882 | 1924 | return mm; |
---|
1883 | 1925 | } |
---|
1884 | 1926 | |
---|
.. | .. |
---|
1901 | 1943 | vgpu_free_mm(mm); |
---|
1902 | 1944 | return ERR_PTR(-ENOMEM); |
---|
1903 | 1945 | } |
---|
1904 | | - mm->ggtt_mm.last_partial_off = -1UL; |
---|
1905 | 1946 | |
---|
1906 | 1947 | return mm; |
---|
1907 | 1948 | } |
---|
.. | .. |
---|
1922 | 1963 | |
---|
1923 | 1964 | if (mm->type == INTEL_GVT_MM_PPGTT) { |
---|
1924 | 1965 | list_del(&mm->ppgtt_mm.list); |
---|
| 1966 | + |
---|
| 1967 | + mutex_lock(&mm->vgpu->gvt->gtt.ppgtt_mm_lock); |
---|
1925 | 1968 | list_del(&mm->ppgtt_mm.lru_list); |
---|
| 1969 | + mutex_unlock(&mm->vgpu->gvt->gtt.ppgtt_mm_lock); |
---|
| 1970 | + |
---|
1926 | 1971 | invalidate_ppgtt_mm(mm); |
---|
1927 | 1972 | } else { |
---|
1928 | 1973 | vfree(mm->ggtt_mm.virtual_ggtt); |
---|
1929 | | - mm->ggtt_mm.last_partial_off = -1UL; |
---|
1930 | 1974 | } |
---|
1931 | 1975 | |
---|
1932 | 1976 | vgpu_free_mm(mm); |
---|
.. | .. |
---|
1945 | 1989 | |
---|
1946 | 1990 | /** |
---|
1947 | 1991 | * intel_vgpu_pin_mm - increase the pin count of a vGPU mm object |
---|
1948 | | - * @vgpu: a vGPU |
---|
| 1992 | + * @mm: target vgpu mm |
---|
1949 | 1993 | * |
---|
1950 | 1994 | * This function is called when user wants to use a vGPU mm object. If this |
---|
1951 | 1995 | * mm object hasn't been shadowed yet, the shadow will be populated at this |
---|
.. | .. |
---|
1965 | 2009 | if (ret) |
---|
1966 | 2010 | return ret; |
---|
1967 | 2011 | |
---|
| 2012 | + mutex_lock(&mm->vgpu->gvt->gtt.ppgtt_mm_lock); |
---|
1968 | 2013 | list_move_tail(&mm->ppgtt_mm.lru_list, |
---|
1969 | 2014 | &mm->vgpu->gvt->gtt.ppgtt_mm_lru_list_head); |
---|
1970 | | - |
---|
| 2015 | + mutex_unlock(&mm->vgpu->gvt->gtt.ppgtt_mm_lock); |
---|
1971 | 2016 | } |
---|
1972 | 2017 | |
---|
1973 | 2018 | return 0; |
---|
.. | .. |
---|
1978 | 2023 | struct intel_vgpu_mm *mm; |
---|
1979 | 2024 | struct list_head *pos, *n; |
---|
1980 | 2025 | |
---|
| 2026 | + mutex_lock(&gvt->gtt.ppgtt_mm_lock); |
---|
| 2027 | + |
---|
1981 | 2028 | list_for_each_safe(pos, n, &gvt->gtt.ppgtt_mm_lru_list_head) { |
---|
1982 | 2029 | mm = container_of(pos, struct intel_vgpu_mm, ppgtt_mm.lru_list); |
---|
1983 | 2030 | |
---|
.. | .. |
---|
1985 | 2032 | continue; |
---|
1986 | 2033 | |
---|
1987 | 2034 | list_del_init(&mm->ppgtt_mm.lru_list); |
---|
| 2035 | + mutex_unlock(&gvt->gtt.ppgtt_mm_lock); |
---|
1988 | 2036 | invalidate_ppgtt_mm(mm); |
---|
1989 | 2037 | return 1; |
---|
1990 | 2038 | } |
---|
| 2039 | + mutex_unlock(&gvt->gtt.ppgtt_mm_lock); |
---|
1991 | 2040 | return 0; |
---|
1992 | 2041 | } |
---|
1993 | 2042 | |
---|
.. | .. |
---|
2103 | 2152 | struct intel_vgpu_mm *ggtt_mm = vgpu->gtt.ggtt_mm; |
---|
2104 | 2153 | const struct intel_gvt_device_info *info = &vgpu->gvt->device_info; |
---|
2105 | 2154 | unsigned long index = off >> info->gtt_entry_size_shift; |
---|
| 2155 | + unsigned long gma; |
---|
2106 | 2156 | struct intel_gvt_gtt_entry e; |
---|
2107 | 2157 | |
---|
2108 | 2158 | if (bytes != 4 && bytes != 8) |
---|
2109 | 2159 | return -EINVAL; |
---|
| 2160 | + |
---|
| 2161 | + gma = index << I915_GTT_PAGE_SHIFT; |
---|
| 2162 | + if (!intel_gvt_ggtt_validate_range(vgpu, |
---|
| 2163 | + gma, 1 << I915_GTT_PAGE_SHIFT)) { |
---|
| 2164 | + gvt_dbg_mm("read invalid ggtt at 0x%lx\n", gma); |
---|
| 2165 | + memset(p_data, 0, bytes); |
---|
| 2166 | + return 0; |
---|
| 2167 | + } |
---|
2110 | 2168 | |
---|
2111 | 2169 | ggtt_get_guest_entry(ggtt_mm, &e, index); |
---|
2112 | 2170 | memcpy(p_data, (void *)&e.val64 + (off & (info->gtt_entry_size - 1)), |
---|
.. | .. |
---|
2165 | 2223 | struct intel_gvt_gtt_entry m = {.val64 = 0, .type = GTT_TYPE_GGTT_PTE}; |
---|
2166 | 2224 | dma_addr_t dma_addr; |
---|
2167 | 2225 | int ret; |
---|
| 2226 | + struct intel_gvt_partial_pte *partial_pte, *pos, *n; |
---|
| 2227 | + bool partial_update = false; |
---|
2168 | 2228 | |
---|
2169 | 2229 | if (bytes != 4 && bytes != 8) |
---|
2170 | 2230 | return -EINVAL; |
---|
.. | .. |
---|
2175 | 2235 | if (!vgpu_gmadr_is_valid(vgpu, gma)) |
---|
2176 | 2236 | return 0; |
---|
2177 | 2237 | |
---|
2178 | | - ggtt_get_guest_entry(ggtt_mm, &e, g_gtt_index); |
---|
2179 | | - |
---|
| 2238 | + e.type = GTT_TYPE_GGTT_PTE; |
---|
2180 | 2239 | memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data, |
---|
2181 | 2240 | bytes); |
---|
2182 | 2241 | |
---|
2183 | 2242 | /* If ggtt entry size is 8 bytes, and it's split into two 4 bytes |
---|
2184 | | - * write, we assume the two 4 bytes writes are consecutive. |
---|
2185 | | - * Otherwise, we abort and report error |
---|
| 2243 | + * write, save the first 4 bytes in a list and update virtual |
---|
| 2244 | + * PTE. Only update shadow PTE when the second 4 bytes comes. |
---|
2186 | 2245 | */ |
---|
2187 | 2246 | if (bytes < info->gtt_entry_size) { |
---|
2188 | | - if (ggtt_mm->ggtt_mm.last_partial_off == -1UL) { |
---|
2189 | | - /* the first partial part*/ |
---|
2190 | | - ggtt_mm->ggtt_mm.last_partial_off = off; |
---|
2191 | | - ggtt_mm->ggtt_mm.last_partial_data = e.val64; |
---|
2192 | | - return 0; |
---|
2193 | | - } else if ((g_gtt_index == |
---|
2194 | | - (ggtt_mm->ggtt_mm.last_partial_off >> |
---|
2195 | | - info->gtt_entry_size_shift)) && |
---|
2196 | | - (off != ggtt_mm->ggtt_mm.last_partial_off)) { |
---|
2197 | | - /* the second partial part */ |
---|
| 2247 | + bool found = false; |
---|
2198 | 2248 | |
---|
2199 | | - int last_off = ggtt_mm->ggtt_mm.last_partial_off & |
---|
2200 | | - (info->gtt_entry_size - 1); |
---|
| 2249 | + list_for_each_entry_safe(pos, n, |
---|
| 2250 | + &ggtt_mm->ggtt_mm.partial_pte_list, list) { |
---|
| 2251 | + if (g_gtt_index == pos->offset >> |
---|
| 2252 | + info->gtt_entry_size_shift) { |
---|
| 2253 | + if (off != pos->offset) { |
---|
| 2254 | + /* the second partial part*/ |
---|
| 2255 | + int last_off = pos->offset & |
---|
| 2256 | + (info->gtt_entry_size - 1); |
---|
2201 | 2257 | |
---|
2202 | | - memcpy((void *)&e.val64 + last_off, |
---|
2203 | | - (void *)&ggtt_mm->ggtt_mm.last_partial_data + |
---|
2204 | | - last_off, bytes); |
---|
| 2258 | + memcpy((void *)&e.val64 + last_off, |
---|
| 2259 | + (void *)&pos->data + last_off, |
---|
| 2260 | + bytes); |
---|
2205 | 2261 | |
---|
2206 | | - ggtt_mm->ggtt_mm.last_partial_off = -1UL; |
---|
2207 | | - } else { |
---|
2208 | | - int last_offset; |
---|
| 2262 | + list_del(&pos->list); |
---|
| 2263 | + kfree(pos); |
---|
| 2264 | + found = true; |
---|
| 2265 | + break; |
---|
| 2266 | + } |
---|
2209 | 2267 | |
---|
2210 | | - gvt_vgpu_err("failed to populate guest ggtt entry: abnormal ggtt entry write sequence, last_partial_off=%lx, offset=%x, bytes=%d, ggtt entry size=%d\n", |
---|
2211 | | - ggtt_mm->ggtt_mm.last_partial_off, off, |
---|
2212 | | - bytes, info->gtt_entry_size); |
---|
| 2268 | + /* update of the first partial part */ |
---|
| 2269 | + pos->data = e.val64; |
---|
| 2270 | + ggtt_set_guest_entry(ggtt_mm, &e, g_gtt_index); |
---|
| 2271 | + return 0; |
---|
| 2272 | + } |
---|
| 2273 | + } |
---|
2213 | 2274 | |
---|
2214 | | - /* set host ggtt entry to scratch page and clear |
---|
2215 | | - * virtual ggtt entry as not present for last |
---|
2216 | | - * partially write offset |
---|
2217 | | - */ |
---|
2218 | | - last_offset = ggtt_mm->ggtt_mm.last_partial_off & |
---|
2219 | | - (~(info->gtt_entry_size - 1)); |
---|
2220 | | - |
---|
2221 | | - ggtt_get_host_entry(ggtt_mm, &m, last_offset); |
---|
2222 | | - ggtt_invalidate_pte(vgpu, &m); |
---|
2223 | | - ops->set_pfn(&m, gvt->gtt.scratch_mfn); |
---|
2224 | | - ops->clear_present(&m); |
---|
2225 | | - ggtt_set_host_entry(ggtt_mm, &m, last_offset); |
---|
2226 | | - ggtt_invalidate(gvt->dev_priv); |
---|
2227 | | - |
---|
2228 | | - ggtt_get_guest_entry(ggtt_mm, &e, last_offset); |
---|
2229 | | - ops->clear_present(&e); |
---|
2230 | | - ggtt_set_guest_entry(ggtt_mm, &e, last_offset); |
---|
2231 | | - |
---|
2232 | | - ggtt_mm->ggtt_mm.last_partial_off = off; |
---|
2233 | | - ggtt_mm->ggtt_mm.last_partial_data = e.val64; |
---|
2234 | | - |
---|
2235 | | - return 0; |
---|
| 2275 | + if (!found) { |
---|
| 2276 | + /* the first partial part */ |
---|
| 2277 | + partial_pte = kzalloc(sizeof(*partial_pte), GFP_KERNEL); |
---|
| 2278 | + if (!partial_pte) |
---|
| 2279 | + return -ENOMEM; |
---|
| 2280 | + partial_pte->offset = off; |
---|
| 2281 | + partial_pte->data = e.val64; |
---|
| 2282 | + list_add_tail(&partial_pte->list, |
---|
| 2283 | + &ggtt_mm->ggtt_mm.partial_pte_list); |
---|
| 2284 | + partial_update = true; |
---|
2236 | 2285 | } |
---|
2237 | 2286 | } |
---|
2238 | 2287 | |
---|
2239 | | - if (ops->test_present(&e)) { |
---|
| 2288 | + if (!partial_update && (ops->test_present(&e))) { |
---|
2240 | 2289 | gfn = ops->get_pfn(&e); |
---|
2241 | 2290 | m.val64 = e.val64; |
---|
2242 | 2291 | m.type = e.type; |
---|
.. | .. |
---|
2261 | 2310 | } else |
---|
2262 | 2311 | ops->set_pfn(&m, dma_addr >> PAGE_SHIFT); |
---|
2263 | 2312 | } else { |
---|
2264 | | - ggtt_get_host_entry(ggtt_mm, &m, g_gtt_index); |
---|
2265 | | - ggtt_invalidate_pte(vgpu, &m); |
---|
2266 | 2313 | ops->set_pfn(&m, gvt->gtt.scratch_mfn); |
---|
2267 | 2314 | ops->clear_present(&m); |
---|
2268 | 2315 | } |
---|
2269 | 2316 | |
---|
2270 | 2317 | out: |
---|
2271 | | - ggtt_set_host_entry(ggtt_mm, &m, g_gtt_index); |
---|
2272 | | - ggtt_invalidate(gvt->dev_priv); |
---|
2273 | 2318 | ggtt_set_guest_entry(ggtt_mm, &e, g_gtt_index); |
---|
| 2319 | + |
---|
| 2320 | + ggtt_get_host_entry(ggtt_mm, &e, g_gtt_index); |
---|
| 2321 | + ggtt_invalidate_pte(vgpu, &e); |
---|
| 2322 | + |
---|
| 2323 | + ggtt_set_host_entry(ggtt_mm, &m, g_gtt_index); |
---|
| 2324 | + ggtt_invalidate(gvt->gt); |
---|
2274 | 2325 | return 0; |
---|
2275 | 2326 | } |
---|
2276 | 2327 | |
---|
.. | .. |
---|
2291 | 2342 | { |
---|
2292 | 2343 | const struct intel_gvt_device_info *info = &vgpu->gvt->device_info; |
---|
2293 | 2344 | int ret; |
---|
| 2345 | + struct intel_vgpu_submission *s = &vgpu->submission; |
---|
| 2346 | + struct intel_engine_cs *engine; |
---|
| 2347 | + int i; |
---|
2294 | 2348 | |
---|
2295 | 2349 | if (bytes != 4 && bytes != 8) |
---|
2296 | 2350 | return -EINVAL; |
---|
2297 | 2351 | |
---|
2298 | 2352 | off -= info->gtt_start_offset; |
---|
2299 | 2353 | ret = emulate_ggtt_mmio_write(vgpu, off, p_data, bytes); |
---|
| 2354 | + |
---|
| 2355 | + /* if ggtt of last submitted context is written, |
---|
| 2356 | + * that context is probably got unpinned. |
---|
| 2357 | + * Set last shadowed ctx to invalid. |
---|
| 2358 | + */ |
---|
| 2359 | + for_each_engine(engine, vgpu->gvt->gt, i) { |
---|
| 2360 | + if (!s->last_ctx[i].valid) |
---|
| 2361 | + continue; |
---|
| 2362 | + |
---|
| 2363 | + if (s->last_ctx[i].lrca == (off >> info->gtt_entry_size_shift)) |
---|
| 2364 | + s->last_ctx[i].valid = false; |
---|
| 2365 | + } |
---|
2300 | 2366 | return ret; |
---|
2301 | 2367 | } |
---|
2302 | 2368 | |
---|
2303 | 2369 | static int alloc_scratch_pages(struct intel_vgpu *vgpu, |
---|
2304 | | - intel_gvt_gtt_type_t type) |
---|
| 2370 | + enum intel_gvt_gtt_type type) |
---|
2305 | 2371 | { |
---|
| 2372 | + struct drm_i915_private *i915 = vgpu->gvt->gt->i915; |
---|
2306 | 2373 | struct intel_vgpu_gtt *gtt = &vgpu->gtt; |
---|
2307 | 2374 | struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; |
---|
2308 | 2375 | int page_entry_num = I915_GTT_PAGE_SIZE >> |
---|
2309 | 2376 | vgpu->gvt->device_info.gtt_entry_size_shift; |
---|
2310 | 2377 | void *scratch_pt; |
---|
2311 | 2378 | int i; |
---|
2312 | | - struct device *dev = &vgpu->gvt->dev_priv->drm.pdev->dev; |
---|
| 2379 | + struct device *dev = &vgpu->gvt->gt->i915->drm.pdev->dev; |
---|
2313 | 2380 | dma_addr_t daddr; |
---|
2314 | 2381 | |
---|
2315 | | - if (WARN_ON(type < GTT_TYPE_PPGTT_PTE_PT || type >= GTT_TYPE_MAX)) |
---|
| 2382 | + if (drm_WARN_ON(&i915->drm, |
---|
| 2383 | + type < GTT_TYPE_PPGTT_PTE_PT || type >= GTT_TYPE_MAX)) |
---|
2316 | 2384 | return -EINVAL; |
---|
2317 | 2385 | |
---|
2318 | 2386 | scratch_pt = (void *)get_zeroed_page(GFP_KERNEL); |
---|
.. | .. |
---|
2366 | 2434 | static int release_scratch_page_tree(struct intel_vgpu *vgpu) |
---|
2367 | 2435 | { |
---|
2368 | 2436 | int i; |
---|
2369 | | - struct device *dev = &vgpu->gvt->dev_priv->drm.pdev->dev; |
---|
| 2437 | + struct device *dev = &vgpu->gvt->gt->i915->drm.pdev->dev; |
---|
2370 | 2438 | dma_addr_t daddr; |
---|
2371 | 2439 | |
---|
2372 | 2440 | for (i = GTT_TYPE_PPGTT_PTE_PT; i < GTT_TYPE_MAX; i++) { |
---|
.. | .. |
---|
2428 | 2496 | |
---|
2429 | 2497 | intel_vgpu_reset_ggtt(vgpu, false); |
---|
2430 | 2498 | |
---|
| 2499 | + INIT_LIST_HEAD(>t->ggtt_mm->ggtt_mm.partial_pte_list); |
---|
| 2500 | + |
---|
2431 | 2501 | return create_scratch_page_tree(vgpu); |
---|
2432 | 2502 | } |
---|
2433 | 2503 | |
---|
2434 | | -static void intel_vgpu_destroy_all_ppgtt_mm(struct intel_vgpu *vgpu) |
---|
| 2504 | +void intel_vgpu_destroy_all_ppgtt_mm(struct intel_vgpu *vgpu) |
---|
2435 | 2505 | { |
---|
2436 | 2506 | struct list_head *pos, *n; |
---|
2437 | 2507 | struct intel_vgpu_mm *mm; |
---|
.. | .. |
---|
2452 | 2522 | |
---|
2453 | 2523 | static void intel_vgpu_destroy_ggtt_mm(struct intel_vgpu *vgpu) |
---|
2454 | 2524 | { |
---|
| 2525 | + struct intel_gvt_partial_pte *pos, *next; |
---|
| 2526 | + |
---|
| 2527 | + list_for_each_entry_safe(pos, next, |
---|
| 2528 | + &vgpu->gtt.ggtt_mm->ggtt_mm.partial_pte_list, |
---|
| 2529 | + list) { |
---|
| 2530 | + gvt_dbg_mm("partial PTE update on hold 0x%lx : 0x%llx\n", |
---|
| 2531 | + pos->offset, pos->data); |
---|
| 2532 | + kfree(pos); |
---|
| 2533 | + } |
---|
2455 | 2534 | intel_vgpu_destroy_mm(vgpu->gtt.ggtt_mm); |
---|
2456 | 2535 | vgpu->gtt.ggtt_mm = NULL; |
---|
2457 | 2536 | } |
---|
.. | .. |
---|
2485 | 2564 | list_for_each_safe(pos, n, >t->oos_page_free_list_head) { |
---|
2486 | 2565 | oos_page = container_of(pos, struct intel_vgpu_oos_page, list); |
---|
2487 | 2566 | list_del(&oos_page->list); |
---|
| 2567 | + free_page((unsigned long)oos_page->mem); |
---|
2488 | 2568 | kfree(oos_page); |
---|
2489 | 2569 | } |
---|
2490 | 2570 | } |
---|
.. | .. |
---|
2505 | 2585 | ret = -ENOMEM; |
---|
2506 | 2586 | goto fail; |
---|
2507 | 2587 | } |
---|
| 2588 | + oos_page->mem = (void *)__get_free_pages(GFP_KERNEL, 0); |
---|
| 2589 | + if (!oos_page->mem) { |
---|
| 2590 | + ret = -ENOMEM; |
---|
| 2591 | + kfree(oos_page); |
---|
| 2592 | + goto fail; |
---|
| 2593 | + } |
---|
2508 | 2594 | |
---|
2509 | 2595 | INIT_LIST_HEAD(&oos_page->list); |
---|
2510 | 2596 | INIT_LIST_HEAD(&oos_page->vm_list); |
---|
.. | .. |
---|
2523 | 2609 | /** |
---|
2524 | 2610 | * intel_vgpu_find_ppgtt_mm - find a PPGTT mm object |
---|
2525 | 2611 | * @vgpu: a vGPU |
---|
2526 | | - * @page_table_level: PPGTT page table level |
---|
2527 | | - * @root_entry: PPGTT page table root pointers |
---|
| 2612 | + * @pdps: pdp root array |
---|
2528 | 2613 | * |
---|
2529 | 2614 | * This function is used to find a PPGTT mm object from mm object pool |
---|
2530 | 2615 | * |
---|
.. | .. |
---|
2569 | 2654 | * Zero on success, negative error code if failed. |
---|
2570 | 2655 | */ |
---|
2571 | 2656 | struct intel_vgpu_mm *intel_vgpu_get_ppgtt_mm(struct intel_vgpu *vgpu, |
---|
2572 | | - intel_gvt_gtt_type_t root_entry_type, u64 pdps[]) |
---|
| 2657 | + enum intel_gvt_gtt_type root_entry_type, u64 pdps[]) |
---|
2573 | 2658 | { |
---|
2574 | 2659 | struct intel_vgpu_mm *mm; |
---|
2575 | 2660 | |
---|
.. | .. |
---|
2621 | 2706 | { |
---|
2622 | 2707 | int ret; |
---|
2623 | 2708 | void *page; |
---|
2624 | | - struct device *dev = &gvt->dev_priv->drm.pdev->dev; |
---|
| 2709 | + struct device *dev = &gvt->gt->i915->drm.pdev->dev; |
---|
2625 | 2710 | dma_addr_t daddr; |
---|
2626 | 2711 | |
---|
2627 | 2712 | gvt_dbg_core("init gtt\n"); |
---|
.. | .. |
---|
2656 | 2741 | } |
---|
2657 | 2742 | } |
---|
2658 | 2743 | INIT_LIST_HEAD(&gvt->gtt.ppgtt_mm_lru_list_head); |
---|
| 2744 | + mutex_init(&gvt->gtt.ppgtt_mm_lock); |
---|
2659 | 2745 | return 0; |
---|
2660 | 2746 | } |
---|
2661 | 2747 | |
---|
.. | .. |
---|
2669 | 2755 | */ |
---|
2670 | 2756 | void intel_gvt_clean_gtt(struct intel_gvt *gvt) |
---|
2671 | 2757 | { |
---|
2672 | | - struct device *dev = &gvt->dev_priv->drm.pdev->dev; |
---|
| 2758 | + struct device *dev = &gvt->gt->i915->drm.pdev->dev; |
---|
2673 | 2759 | dma_addr_t daddr = (dma_addr_t)(gvt->gtt.scratch_mfn << |
---|
2674 | 2760 | I915_GTT_PAGE_SHIFT); |
---|
2675 | 2761 | |
---|
.. | .. |
---|
2696 | 2782 | list_for_each_safe(pos, n, &vgpu->gtt.ppgtt_mm_list_head) { |
---|
2697 | 2783 | mm = container_of(pos, struct intel_vgpu_mm, ppgtt_mm.list); |
---|
2698 | 2784 | if (mm->type == INTEL_GVT_MM_PPGTT) { |
---|
| 2785 | + mutex_lock(&vgpu->gvt->gtt.ppgtt_mm_lock); |
---|
2699 | 2786 | list_del_init(&mm->ppgtt_mm.lru_list); |
---|
| 2787 | + mutex_unlock(&vgpu->gvt->gtt.ppgtt_mm_lock); |
---|
2700 | 2788 | if (mm->ppgtt_mm.shadowed) |
---|
2701 | 2789 | invalidate_ppgtt_mm(mm); |
---|
2702 | 2790 | } |
---|
.. | .. |
---|
2715 | 2803 | void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu, bool invalidate_old) |
---|
2716 | 2804 | { |
---|
2717 | 2805 | struct intel_gvt *gvt = vgpu->gvt; |
---|
2718 | | - struct drm_i915_private *dev_priv = gvt->dev_priv; |
---|
2719 | 2806 | struct intel_gvt_gtt_pte_ops *pte_ops = vgpu->gvt->gtt.pte_ops; |
---|
2720 | 2807 | struct intel_gvt_gtt_entry entry = {.type = GTT_TYPE_GGTT_PTE}; |
---|
2721 | 2808 | struct intel_gvt_gtt_entry old_entry; |
---|
.. | .. |
---|
2745 | 2832 | ggtt_set_host_entry(vgpu->gtt.ggtt_mm, &entry, index++); |
---|
2746 | 2833 | } |
---|
2747 | 2834 | |
---|
2748 | | - ggtt_invalidate(dev_priv); |
---|
| 2835 | + ggtt_invalidate(gvt->gt); |
---|
2749 | 2836 | } |
---|
2750 | 2837 | |
---|
2751 | 2838 | /** |
---|