aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChangbin Du <changbin.du@intel.com>2018-01-30 06:19:48 -0500
committerZhenyu Wang <zhenyuw@linux.intel.com>2018-03-06 00:19:17 -0500
commit72f03d7ea16794c3ac4b7ae945510cf0015d3c3c (patch)
treee0dde2f0f99db250fb07d5e45eeeb300c70028d6
parentd861ca237df8f1ef7b6380cd61f403edfcfc2be1 (diff)
drm/i915/gvt: Refine pte shadowing process
Make the shadow PTE population code clear. Later we will add huge gtt support based on this. v2: - rebase to latest code. Signed-off-by: Changbin Du <changbin.du@intel.com> Reviewed-by: Zhi Wang <zhi.wang@intel.com> Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
-rw-r--r--drivers/gpu/drm/i915/gvt/gtt.c173
1 files changed, 94 insertions, 79 deletions
diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index b15b9e55a997..7b4a345a0d52 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 = {
453 .gma_to_pml4_index = gen8_gma_to_pml4_index, 453 .gma_to_pml4_index = gen8_gma_to_pml4_index,
454}; 454};
455 455
456static int gtt_entry_p2m(struct intel_vgpu *vgpu, struct intel_gvt_gtt_entry *p,
457 struct intel_gvt_gtt_entry *m)
458{
459 struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
460 unsigned long gfn, mfn;
461
462 *m = *p;
463
464 if (!ops->test_present(p))
465 return 0;
466
467 gfn = ops->get_pfn(p);
468
469 mfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gfn);
470 if (mfn == INTEL_GVT_INVALID_ADDR) {
471 gvt_vgpu_err("fail to translate gfn: 0x%lx\n", gfn);
472 return -ENXIO;
473 }
474
475 ops->set_pfn(m, mfn);
476 return 0;
477}
478
479/* 456/*
480 * MM helpers. 457 * MM helpers.
481 */ 458 */
@@ -943,8 +920,7 @@ static int ppgtt_invalidate_shadow_page_by_shadow_entry(struct intel_vgpu *vgpu,
943 struct intel_vgpu_ppgtt_spt *s; 920 struct intel_vgpu_ppgtt_spt *s;
944 intel_gvt_gtt_type_t cur_pt_type; 921 intel_gvt_gtt_type_t cur_pt_type;
945 922
946 if (WARN_ON(!gtt_type_is_pt(get_next_pt_type(e->type)))) 923 GEM_BUG_ON(!gtt_type_is_pt(get_next_pt_type(e->type)));
947 return -EINVAL;
948 924
949 if (e->type != GTT_TYPE_PPGTT_ROOT_L3_ENTRY 925 if (e->type != GTT_TYPE_PPGTT_ROOT_L3_ENTRY
950 && e->type != GTT_TYPE_PPGTT_ROOT_L4_ENTRY) { 926 && e->type != GTT_TYPE_PPGTT_ROOT_L4_ENTRY) {
@@ -982,14 +958,26 @@ static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
982 goto release; 958 goto release;
983 959
984 for_each_present_shadow_entry(spt, &e, index) { 960 for_each_present_shadow_entry(spt, &e, index) {
985 if (!gtt_type_is_pt(get_next_pt_type(e.type))) { 961 switch (e.type) {
986 gvt_vgpu_err("GVT doesn't support pse bit for now\n"); 962 case GTT_TYPE_PPGTT_PTE_4K_ENTRY:
987 return -EINVAL; 963 gvt_vdbg_mm("invalidate 4K entry\n");
964 continue;
965 case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
966 case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
967 WARN(1, "GVT doesn't support 2M/1GB page\n");
968 continue;
969 case GTT_TYPE_PPGTT_PML4_ENTRY:
970 case GTT_TYPE_PPGTT_PDP_ENTRY:
971 case GTT_TYPE_PPGTT_PDE_ENTRY:
972 gvt_vdbg_mm("invalidate PMUL4/PDP/PDE entry\n");
973 ret = ppgtt_invalidate_shadow_page_by_shadow_entry(
974 spt->vgpu, &e);
975 if (ret)
976 goto fail;
977 break;
978 default:
979 GEM_BUG_ON(1);
988 } 980 }
989 ret = ppgtt_invalidate_shadow_page_by_shadow_entry(
990 spt->vgpu, &e);
991 if (ret)
992 goto fail;
993 } 981 }
994release: 982release:
995 trace_spt_change(spt->vgpu->id, "release", spt, 983 trace_spt_change(spt->vgpu->id, "release", spt,
@@ -1013,10 +1001,7 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_populate_shadow_page_by_guest_entry(
1013 struct intel_vgpu_page_track *t; 1001 struct intel_vgpu_page_track *t;
1014 int ret; 1002 int ret;
1015 1003
1016 if (WARN_ON(!gtt_type_is_pt(get_next_pt_type(we->type)))) { 1004 GEM_BUG_ON(!gtt_type_is_pt(get_next_pt_type(we->type)));
1017 ret = -EINVAL;
1018 goto fail;
1019 }
1020 1005
1021 t = intel_vgpu_find_tracked_page(vgpu, ops->get_pfn(we)); 1006 t = intel_vgpu_find_tracked_page(vgpu, ops->get_pfn(we));
1022 if (t) { 1007 if (t) {
@@ -1062,6 +1047,41 @@ static inline void ppgtt_generate_shadow_entry(struct intel_gvt_gtt_entry *se,
1062 ops->set_pfn(se, s->shadow_page.mfn); 1047 ops->set_pfn(se, s->shadow_page.mfn);
1063} 1048}
1064 1049
1050static int ppgtt_populate_shadow_entry(struct intel_vgpu *vgpu,
1051 struct intel_vgpu_ppgtt_spt *spt, unsigned long index,
1052 struct intel_gvt_gtt_entry *ge)
1053{
1054 struct intel_gvt_gtt_pte_ops *pte_ops = vgpu->gvt->gtt.pte_ops;
1055 struct intel_gvt_gtt_entry se = *ge;
1056 unsigned long gfn, mfn;
1057
1058 if (!pte_ops->test_present(ge))
1059 return 0;
1060
1061 gfn = pte_ops->get_pfn(ge);
1062
1063 switch (ge->type) {
1064 case GTT_TYPE_PPGTT_PTE_4K_ENTRY:
1065 gvt_vdbg_mm("shadow 4K gtt entry\n");
1066 break;
1067 case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
1068 case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
1069 gvt_vgpu_err("GVT doesn't support 2M/1GB entry\n");
1070 return -EINVAL;
1071 default:
1072 GEM_BUG_ON(1);
1073 };
1074
1075 /* direct shadow */
1076 mfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gfn);
1077 if (mfn == INTEL_GVT_INVALID_ADDR)
1078 return -ENXIO;
1079
1080 pte_ops->set_pfn(&se, mfn);
1081 ppgtt_set_shadow_entry(spt, &se, index);
1082 return 0;
1083}
1084
1065static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt) 1085static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
1066{ 1086{
1067 struct intel_vgpu *vgpu = spt->vgpu; 1087 struct intel_vgpu *vgpu = spt->vgpu;
@@ -1075,32 +1095,29 @@ static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
1075 trace_spt_change(spt->vgpu->id, "born", spt, 1095 trace_spt_change(spt->vgpu->id, "born", spt,
1076 spt->guest_page.track.gfn, spt->shadow_page.type); 1096 spt->guest_page.track.gfn, spt->shadow_page.type);
1077 1097
1078 if (gtt_type_is_pte_pt(spt->shadow_page.type)) { 1098 for_each_present_guest_entry(spt, &ge, i) {
1079 for_each_present_guest_entry(spt, &ge, i) { 1099 if (gtt_type_is_pt(get_next_pt_type(ge.type))) {
1100 s = ppgtt_populate_shadow_page_by_guest_entry(vgpu,
1101 &ge);
1102 if (IS_ERR(s)) {
1103 ret = PTR_ERR(s);
1104 goto fail;
1105 }
1106 ppgtt_get_shadow_entry(spt, &se, i);
1107 ppgtt_generate_shadow_entry(&se, s, &ge);
1108 ppgtt_set_shadow_entry(spt, &se, i);
1109 } else {
1080 gfn = ops->get_pfn(&ge); 1110 gfn = ops->get_pfn(&ge);
1081 if (!intel_gvt_hypervisor_is_valid_gfn(vgpu, gfn) || 1111 if (!intel_gvt_hypervisor_is_valid_gfn(vgpu, gfn)) {
1082 gtt_entry_p2m(vgpu, &ge, &se))
1083 ops->set_pfn(&se, gvt->gtt.scratch_mfn); 1112 ops->set_pfn(&se, gvt->gtt.scratch_mfn);
1084 ppgtt_set_shadow_entry(spt, &se, i); 1113 ppgtt_set_shadow_entry(spt, &se, i);
1085 } 1114 continue;
1086 return 0; 1115 }
1087 }
1088
1089 for_each_present_guest_entry(spt, &ge, i) {
1090 if (!gtt_type_is_pt(get_next_pt_type(ge.type))) {
1091 gvt_vgpu_err("GVT doesn't support pse bit now\n");
1092 ret = -EINVAL;
1093 goto fail;
1094 }
1095 1116
1096 s = ppgtt_populate_shadow_page_by_guest_entry(vgpu, &ge); 1117 ret = ppgtt_populate_shadow_entry(vgpu, spt, i, &ge);
1097 if (IS_ERR(s)) { 1118 if (ret)
1098 ret = PTR_ERR(s); 1119 goto fail;
1099 goto fail;
1100 } 1120 }
1101 ppgtt_get_shadow_entry(spt, &se, i);
1102 ppgtt_generate_shadow_entry(&se, s, &ge);
1103 ppgtt_set_shadow_entry(spt, &se, i);
1104 } 1121 }
1105 return 0; 1122 return 0;
1106fail: 1123fail:
@@ -1175,10 +1192,9 @@ static int ppgtt_handle_guest_entry_add(struct intel_vgpu_guest_page *gpt,
1175 ppgtt_generate_shadow_entry(&m, s, we); 1192 ppgtt_generate_shadow_entry(&m, s, we);
1176 ppgtt_set_shadow_entry(spt, &m, index); 1193 ppgtt_set_shadow_entry(spt, &m, index);
1177 } else { 1194 } else {
1178 ret = gtt_entry_p2m(vgpu, we, &m); 1195 ret = ppgtt_populate_shadow_entry(vgpu, spt, index, we);
1179 if (ret) 1196 if (ret)
1180 goto fail; 1197 goto fail;
1181 ppgtt_set_shadow_entry(spt, &m, index);
1182 } 1198 }
1183 return 0; 1199 return 0;
1184fail: 1200fail:
@@ -1195,7 +1211,7 @@ static int sync_oos_page(struct intel_vgpu *vgpu,
1195 struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops; 1211 struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
1196 struct intel_vgpu_ppgtt_spt *spt = 1212 struct intel_vgpu_ppgtt_spt *spt =
1197 guest_page_to_ppgtt_spt(oos_page->guest_page); 1213 guest_page_to_ppgtt_spt(oos_page->guest_page);
1198 struct intel_gvt_gtt_entry old, new, m; 1214 struct intel_gvt_gtt_entry old, new;
1199 int index; 1215 int index;
1200 int ret; 1216 int ret;
1201 1217
@@ -1219,12 +1235,11 @@ static int sync_oos_page(struct intel_vgpu *vgpu,
1219 oos_page->guest_page, spt->guest_page_type, 1235 oos_page->guest_page, spt->guest_page_type,
1220 new.val64, index); 1236 new.val64, index);
1221 1237
1222 ret = gtt_entry_p2m(vgpu, &new, &m); 1238 ret = ppgtt_populate_shadow_entry(vgpu, spt, index, &new);
1223 if (ret) 1239 if (ret)
1224 return ret; 1240 return ret;
1225 1241
1226 ops->set_entry(oos_page->mem, &new, index, false, 0, vgpu); 1242 ops->set_entry(oos_page->mem, &new, index, false, 0, vgpu);
1227 ppgtt_set_shadow_entry(spt, &m, index);
1228 } 1243 }
1229 1244
1230 oos_page->guest_page->write_cnt = 0; 1245 oos_page->guest_page->write_cnt = 0;
@@ -1371,10 +1386,9 @@ static int ppgtt_handle_guest_write_page_table(
1371 struct intel_vgpu *vgpu = spt->vgpu; 1386 struct intel_vgpu *vgpu = spt->vgpu;
1372 int type = spt->shadow_page.type; 1387 int type = spt->shadow_page.type;
1373 struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; 1388 struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
1374 struct intel_gvt_gtt_entry se; 1389 struct intel_gvt_gtt_entry old_se;
1375
1376 int ret;
1377 int new_present; 1390 int new_present;
1391 int ret;
1378 1392
1379 new_present = ops->test_present(we); 1393 new_present = ops->test_present(we);
1380 1394
@@ -1383,7 +1397,7 @@ static int ppgtt_handle_guest_write_page_table(
1383 * guarantee the ppgtt table is validated during the window between 1397 * guarantee the ppgtt table is validated during the window between
1384 * adding and removal. 1398 * adding and removal.
1385 */ 1399 */
1386 ppgtt_get_shadow_entry(spt, &se, index); 1400 ppgtt_get_shadow_entry(spt, &old_se, index);
1387 1401
1388 if (new_present) { 1402 if (new_present) {
1389 ret = ppgtt_handle_guest_entry_add(gpt, we, index); 1403 ret = ppgtt_handle_guest_entry_add(gpt, we, index);
@@ -1391,13 +1405,13 @@ static int ppgtt_handle_guest_write_page_table(
1391 goto fail; 1405 goto fail;
1392 } 1406 }
1393 1407
1394 ret = ppgtt_handle_guest_entry_removal(gpt, &se, index); 1408 ret = ppgtt_handle_guest_entry_removal(gpt, &old_se, index);
1395 if (ret) 1409 if (ret)
1396 goto fail; 1410 goto fail;
1397 1411
1398 if (!new_present) { 1412 if (!new_present) {
1399 ops->set_pfn(&se, vgpu->gtt.scratch_pt[type].page_mfn); 1413 ops->set_pfn(&old_se, vgpu->gtt.scratch_pt[type].page_mfn);
1400 ppgtt_set_shadow_entry(spt, &se, index); 1414 ppgtt_set_shadow_entry(spt, &old_se, index);
1401 } 1415 }
1402 1416
1403 return 0; 1417 return 0;
@@ -1407,6 +1421,8 @@ fail:
1407 return ret; 1421 return ret;
1408} 1422}
1409 1423
1424
1425
1410static inline bool can_do_out_of_sync(struct intel_vgpu_guest_page *gpt) 1426static inline bool can_do_out_of_sync(struct intel_vgpu_guest_page *gpt)
1411{ 1427{
1412 return enable_out_of_sync 1428 return enable_out_of_sync
@@ -1924,9 +1940,8 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
1924 struct intel_vgpu_mm *ggtt_mm = vgpu->gtt.ggtt_mm; 1940 struct intel_vgpu_mm *ggtt_mm = vgpu->gtt.ggtt_mm;
1925 struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops; 1941 struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
1926 unsigned long g_gtt_index = off >> info->gtt_entry_size_shift; 1942 unsigned long g_gtt_index = off >> info->gtt_entry_size_shift;
1927 unsigned long gma, gfn; 1943 unsigned long gma, gfn, mfn;
1928 struct intel_gvt_gtt_entry e, m; 1944 struct intel_gvt_gtt_entry e, m;
1929 int ret;
1930 1945
1931 if (bytes != 4 && bytes != 8) 1946 if (bytes != 4 && bytes != 8)
1932 return -EINVAL; 1947 return -EINVAL;
@@ -1941,6 +1956,7 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
1941 1956
1942 memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data, 1957 memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data,
1943 bytes); 1958 bytes);
1959 m = e;
1944 1960
1945 if (ops->test_present(&e)) { 1961 if (ops->test_present(&e)) {
1946 gfn = ops->get_pfn(&e); 1962 gfn = ops->get_pfn(&e);
@@ -1953,19 +1969,18 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
1953 goto out; 1969 goto out;
1954 } 1970 }
1955 1971
1956 ret = gtt_entry_p2m(vgpu, &e, &m); 1972 mfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gfn);
1957 if (ret) { 1973 if (mfn == INTEL_GVT_INVALID_ADDR) {
1958 gvt_vgpu_err("fail to translate guest gtt entry\n"); 1974 gvt_vgpu_err("fail to populate guest ggtt entry\n");
1959 /* guest driver may read/write the entry when partial 1975 /* guest driver may read/write the entry when partial
1960 * update the entry in this situation p2m will fail 1976 * update the entry in this situation p2m will fail
1961 * settting the shadow entry to point to a scratch page 1977 * settting the shadow entry to point to a scratch page
1962 */ 1978 */
1963 ops->set_pfn(&m, gvt->gtt.scratch_mfn); 1979 ops->set_pfn(&m, gvt->gtt.scratch_mfn);
1964 } 1980 } else
1965 } else { 1981 ops->set_pfn(&m, mfn);
1966 m = e; 1982 } else
1967 ops->set_pfn(&m, gvt->gtt.scratch_mfn); 1983 ops->set_pfn(&m, gvt->gtt.scratch_mfn);
1968 }
1969 1984
1970out: 1985out:
1971 ggtt_set_host_entry(ggtt_mm, &m, g_gtt_index); 1986 ggtt_set_host_entry(ggtt_mm, &m, g_gtt_index);