Skip to content

Commit eb3a353

Browse files
Changbin Duzhenyw
authored andcommitted
drm/i915/gvt: Add 64K huge gtt support
Finally, this add the first huge gtt support for GVTg - 64K pages. Since 64K page and 4K page cannot be mixed on the same page table, so we always split a 64K entry into small 4K page. And when unshadow guest 64K entry, we need ensure all the shadowed entries in shadow page table also get cleared. For page table which has 64K gtt entry, only PTE#0, PTE#16, PTE#32, ... PTE#496 are used. Unused PTEs update should be ignored. Signed-off-by: Changbin Du <[email protected]> Signed-off-by: Zhenyu Wang <[email protected]>
1 parent 4c9414d commit eb3a353

File tree

1 file changed

+80
-6
lines changed
  • drivers/gpu/drm/i915/gvt

1 file changed

+80
-6
lines changed

drivers/gpu/drm/i915/gvt/gtt.c

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -978,9 +978,12 @@ static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt)
978978
ppgtt_invalidate_pte(spt, &e);
979979
break;
980980
case GTT_TYPE_PPGTT_PTE_64K_ENTRY:
981+
/* We don't setup 64K shadow entry so far. */
982+
WARN(1, "suspicious 64K gtt entry\n");
983+
continue;
981984
case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
982985
case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
983-
WARN(1, "GVT doesn't support 64K/2M/1GB page\n");
986+
WARN(1, "GVT doesn't support 2M/1GB page\n");
984987
continue;
985988
case GTT_TYPE_PPGTT_PML4_ENTRY:
986989
case GTT_TYPE_PPGTT_PDP_ENTRY:
@@ -1075,9 +1078,44 @@ static inline void ppgtt_generate_shadow_entry(struct intel_gvt_gtt_entry *se,
10751078
se->type = ge->type;
10761079
se->val64 = ge->val64;
10771080

1081+
/* Because we always split 64KB pages, so clear IPS in shadow PDE. */
1082+
if (se->type == GTT_TYPE_PPGTT_PDE_ENTRY)
1083+
ops->clear_ips(se);
1084+
10781085
ops->set_pfn(se, s->shadow_page.mfn);
10791086
}
10801087

1088+
static int split_64KB_gtt_entry(struct intel_vgpu *vgpu,
1089+
struct intel_vgpu_ppgtt_spt *spt, unsigned long index,
1090+
struct intel_gvt_gtt_entry *se)
1091+
{
1092+
struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
1093+
struct intel_gvt_gtt_entry entry = *se;
1094+
unsigned long start_gfn;
1095+
dma_addr_t dma_addr;
1096+
int i, ret;
1097+
1098+
gvt_vdbg_mm("Split 64K gtt entry, index %lu\n", index);
1099+
1100+
GEM_BUG_ON(index % GTT_64K_PTE_STRIDE);
1101+
1102+
start_gfn = ops->get_pfn(se);
1103+
1104+
entry.type = GTT_TYPE_PPGTT_PTE_4K_ENTRY;
1105+
ops->set_64k_splited(&entry);
1106+
1107+
for (i = 0; i < GTT_64K_PTE_STRIDE; i++) {
1108+
ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu,
1109+
start_gfn + i, &dma_addr);
1110+
if (ret)
1111+
return ret;
1112+
1113+
ops->set_pfn(&entry, dma_addr >> PAGE_SHIFT);
1114+
ppgtt_set_shadow_entry(spt, &entry, index + i);
1115+
}
1116+
return 0;
1117+
}
1118+
10811119
static int ppgtt_populate_shadow_entry(struct intel_vgpu *vgpu,
10821120
struct intel_vgpu_ppgtt_spt *spt, unsigned long index,
10831121
struct intel_gvt_gtt_entry *ge)
@@ -1098,9 +1136,16 @@ static int ppgtt_populate_shadow_entry(struct intel_vgpu *vgpu,
10981136
gvt_vdbg_mm("shadow 4K gtt entry\n");
10991137
break;
11001138
case GTT_TYPE_PPGTT_PTE_64K_ENTRY:
1139+
gvt_vdbg_mm("shadow 64K gtt entry\n");
1140+
/*
1141+
* The layout of 64K page is special, the page size is
1142+
* controlled by uper PDE. To be simple, we always split
1143+
* 64K page to smaller 4K pages in shadow PT.
1144+
*/
1145+
return split_64KB_gtt_entry(vgpu, spt, index, &se);
11011146
case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
11021147
case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
1103-
gvt_vgpu_err("GVT doesn't support 64K/2M/1GB entry\n");
1148+
gvt_vgpu_err("GVT doesn't support 2M/1GB entry\n");
11041149
return -EINVAL;
11051150
default:
11061151
GEM_BUG_ON(1);
@@ -1190,8 +1235,12 @@ static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_ppgtt_spt *spt,
11901235
ret = ppgtt_invalidate_spt(s);
11911236
if (ret)
11921237
goto fail;
1193-
} else
1238+
} else {
1239+
/* We don't setup 64K shadow entry so far. */
1240+
WARN(se->type == GTT_TYPE_PPGTT_PTE_64K_ENTRY,
1241+
"suspicious 64K entry\n");
11941242
ppgtt_invalidate_pte(spt, se);
1243+
}
11951244

11961245
return 0;
11971246
fail:
@@ -1414,7 +1463,7 @@ static int ppgtt_handle_guest_write_page_table(
14141463
struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
14151464
struct intel_gvt_gtt_entry old_se;
14161465
int new_present;
1417-
int ret;
1466+
int i, ret;
14181467

14191468
new_present = ops->test_present(we);
14201469

@@ -1436,8 +1485,21 @@ static int ppgtt_handle_guest_write_page_table(
14361485
goto fail;
14371486

14381487
if (!new_present) {
1439-
ops->set_pfn(&old_se, vgpu->gtt.scratch_pt[type].page_mfn);
1440-
ppgtt_set_shadow_entry(spt, &old_se, index);
1488+
/* For 64KB splited entries, we need clear them all. */
1489+
if (ops->test_64k_splited(&old_se) &&
1490+
!(index % GTT_64K_PTE_STRIDE)) {
1491+
gvt_vdbg_mm("remove splited 64K shadow entries\n");
1492+
for (i = 0; i < GTT_64K_PTE_STRIDE; i++) {
1493+
ops->clear_64k_splited(&old_se);
1494+
ops->set_pfn(&old_se,
1495+
vgpu->gtt.scratch_pt[type].page_mfn);
1496+
ppgtt_set_shadow_entry(spt, &old_se, index + i);
1497+
}
1498+
} else {
1499+
ops->set_pfn(&old_se,
1500+
vgpu->gtt.scratch_pt[type].page_mfn);
1501+
ppgtt_set_shadow_entry(spt, &old_se, index);
1502+
}
14411503
}
14421504

14431505
return 0;
@@ -1519,6 +1581,18 @@ static int ppgtt_handle_guest_write_page_table_bytes(
15191581

15201582
ppgtt_get_guest_entry(spt, &we, index);
15211583

1584+
/*
1585+
* For page table which has 64K gtt entry, only PTE#0, PTE#16,
1586+
* PTE#32, ... PTE#496 are used. Unused PTEs update should be
1587+
* ignored.
1588+
*/
1589+
if (we.type == GTT_TYPE_PPGTT_PTE_64K_ENTRY &&
1590+
(index % GTT_64K_PTE_STRIDE)) {
1591+
gvt_vdbg_mm("Ignore write to unused PTE entry, index %lu\n",
1592+
index);
1593+
return 0;
1594+
}
1595+
15221596
if (bytes == info->gtt_entry_size) {
15231597
ret = ppgtt_handle_guest_write_page_table(spt, &we, index);
15241598
if (ret)

0 commit comments

Comments
 (0)