| .. | .. |
|---|
| 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 | /** |
|---|