aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChangbin Du <changbin.du@intel.com>2018-01-30 06:19:40 -0500
committerZhenyu Wang <zhenyuw@linux.intel.com>2018-03-06 00:19:13 -0500
commitede9d0cfcb789b6fd86ecb71b4721a19c53956e6 (patch)
treefa844b6b6c549c0d7b342cc7fed4e3777f520a80
parent1f267a572b573b0b155022750cba93001f4367a8 (diff)
drm/i915/gvt: Rework shadow graphic memory management code
This is a big one and the GVT shadow graphic memory management code is heavily refined. The new code is more straightforward with less code. The struct intel_vgpu_mm is restructured to be clearly defined, use accurate names and some of the original fields are removed which are really redundant. Now we only manage ppgtt mm object with mm->ppgtt_mm.lru_list. No need to mix ppgtt and ggtt together, since one vGPU only has one ggtt object. v4: Don't invoke ppgtt_free_all_shadow_page before intel_vgpu_destroy_all_ppgtt_mm. v3: Add GVT_RING_CTX_NR_PDPS to avoid confusing about the PDPs. v2: Split some changes into small standalone patches. Signed-off-by: Changbin Du <changbin.du@intel.com> Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
-rw-r--r--drivers/gpu/drm/i915/gvt/gtt.c520
-rw-r--r--drivers/gpu/drm/i915/gvt/gtt.h80
-rw-r--r--drivers/gpu/drm/i915/gvt/handlers.c15
-rw-r--r--drivers/gpu/drm/i915/gvt/mmio.c5
-rw-r--r--drivers/gpu/drm/i915/gvt/scheduler.c27
-rw-r--r--drivers/gpu/drm/i915/gvt/trace.h8
6 files changed, 299 insertions, 356 deletions
diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 8d5317d0122d..bd55fbb7910d 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -481,7 +481,10 @@ int intel_vgpu_mm_get_entry(struct intel_vgpu_mm *mm,
481 struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops; 481 struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
482 int ret; 482 int ret;
483 483
484 e->type = mm->page_table_entry_type; 484 if (mm->type == INTEL_GVT_MM_PPGTT)
485 e->type = mm->ppgtt_mm.root_entry_type;
486 else
487 e->type = GTT_TYPE_GGTT_PTE;
485 488
486 ret = ops->get_entry(page_table, e, index, false, 0, mm->vgpu); 489 ret = ops->get_entry(page_table, e, index, false, 0, mm->vgpu);
487 if (ret) 490 if (ret)
@@ -782,7 +785,7 @@ static int ppgtt_write_protection_handler(void *data, u64 pa,
782 return ret; 785 return ret;
783} 786}
784 787
785static int reclaim_one_mm(struct intel_gvt *gvt); 788static int reclaim_one_ppgtt_mm(struct intel_gvt *gvt);
786 789
787static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_shadow_page( 790static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_shadow_page(
788 struct intel_vgpu *vgpu, int type, unsigned long gfn) 791 struct intel_vgpu *vgpu, int type, unsigned long gfn)
@@ -793,7 +796,7 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_shadow_page(
793retry: 796retry:
794 spt = alloc_spt(GFP_KERNEL | __GFP_ZERO); 797 spt = alloc_spt(GFP_KERNEL | __GFP_ZERO);
795 if (!spt) { 798 if (!spt) {
796 if (reclaim_one_mm(vgpu->gvt)) 799 if (reclaim_one_ppgtt_mm(vgpu->gvt))
797 goto retry; 800 goto retry;
798 801
799 gvt_vgpu_err("fail to allocate ppgtt shadow page\n"); 802 gvt_vgpu_err("fail to allocate ppgtt shadow page\n");
@@ -1445,111 +1448,37 @@ static int ppgtt_handle_guest_write_page_table_bytes(
1445 return 0; 1448 return 0;
1446} 1449}
1447 1450
1448/* 1451static void invalidate_ppgtt_mm(struct intel_vgpu_mm *mm)
1449 * mm page table allocation policy for bdw+
1450 * - for ggtt, only virtual page table will be allocated.
1451 * - for ppgtt, dedicated virtual/shadow page table will be allocated.
1452 */
1453static int gen8_mm_alloc_page_table(struct intel_vgpu_mm *mm)
1454{
1455 struct intel_vgpu *vgpu = mm->vgpu;
1456 struct intel_gvt *gvt = vgpu->gvt;
1457 const struct intel_gvt_device_info *info = &gvt->device_info;
1458 void *mem;
1459
1460 if (mm->type == INTEL_GVT_MM_PPGTT) {
1461 mm->page_table_entry_cnt = 4;
1462 mm->page_table_entry_size = mm->page_table_entry_cnt *
1463 info->gtt_entry_size;
1464 mem = kzalloc(mm->has_shadow_page_table ?
1465 mm->page_table_entry_size * 2
1466 : mm->page_table_entry_size, GFP_KERNEL);
1467 if (!mem)
1468 return -ENOMEM;
1469 mm->virtual_page_table = mem;
1470 if (!mm->has_shadow_page_table)
1471 return 0;
1472 mm->shadow_page_table = mem + mm->page_table_entry_size;
1473 } else if (mm->type == INTEL_GVT_MM_GGTT) {
1474 mm->page_table_entry_cnt =
1475 (gvt_ggtt_gm_sz(gvt) >> I915_GTT_PAGE_SHIFT);
1476 mm->page_table_entry_size = mm->page_table_entry_cnt *
1477 info->gtt_entry_size;
1478 mem = vzalloc(mm->page_table_entry_size);
1479 if (!mem)
1480 return -ENOMEM;
1481 mm->virtual_page_table = mem;
1482 }
1483 return 0;
1484}
1485
1486static void gen8_mm_free_page_table(struct intel_vgpu_mm *mm)
1487{
1488 if (mm->type == INTEL_GVT_MM_PPGTT) {
1489 kfree(mm->virtual_page_table);
1490 } else if (mm->type == INTEL_GVT_MM_GGTT) {
1491 if (mm->virtual_page_table)
1492 vfree(mm->virtual_page_table);
1493 }
1494 mm->virtual_page_table = mm->shadow_page_table = NULL;
1495}
1496
1497static void invalidate_mm(struct intel_vgpu_mm *mm)
1498{ 1452{
1499 struct intel_vgpu *vgpu = mm->vgpu; 1453 struct intel_vgpu *vgpu = mm->vgpu;
1500 struct intel_gvt *gvt = vgpu->gvt; 1454 struct intel_gvt *gvt = vgpu->gvt;
1501 struct intel_gvt_gtt *gtt = &gvt->gtt; 1455 struct intel_gvt_gtt *gtt = &gvt->gtt;
1502 struct intel_gvt_gtt_pte_ops *ops = gtt->pte_ops; 1456 struct intel_gvt_gtt_pte_ops *ops = gtt->pte_ops;
1503 struct intel_gvt_gtt_entry se; 1457 struct intel_gvt_gtt_entry se;
1504 int i; 1458 int index;
1505 1459
1506 if (WARN_ON(!mm->has_shadow_page_table || !mm->shadowed)) 1460 if (!mm->ppgtt_mm.shadowed)
1507 return; 1461 return;
1508 1462
1509 for (i = 0; i < mm->page_table_entry_cnt; i++) { 1463 for (index = 0; index < ARRAY_SIZE(mm->ppgtt_mm.shadow_pdps); index++) {
1510 ppgtt_get_shadow_root_entry(mm, &se, i); 1464 ppgtt_get_shadow_root_entry(mm, &se, index);
1465
1511 if (!ops->test_present(&se)) 1466 if (!ops->test_present(&se))
1512 continue; 1467 continue;
1513 ppgtt_invalidate_shadow_page_by_shadow_entry( 1468
1514 vgpu, &se); 1469 ppgtt_invalidate_shadow_page_by_shadow_entry(vgpu, &se);
1515 se.val64 = 0; 1470 se.val64 = 0;
1516 ppgtt_set_shadow_root_entry(mm, &se, i); 1471 ppgtt_set_shadow_root_entry(mm, &se, index);
1517 1472
1518 trace_gpt_change(vgpu->id, "destroy root pointer", 1473 trace_gpt_change(vgpu->id, "destroy root pointer",
1519 NULL, se.type, se.val64, i); 1474 NULL, se.type, se.val64, index);
1520 } 1475 }
1521 mm->shadowed = false;
1522}
1523 1476
1524/** 1477 mm->ppgtt_mm.shadowed = false;
1525 * intel_vgpu_destroy_mm - destroy a mm object
1526 * @mm: a kref object
1527 *
1528 * This function is used to destroy a mm object for vGPU
1529 *
1530 */
1531void intel_vgpu_destroy_mm(struct kref *mm_ref)
1532{
1533 struct intel_vgpu_mm *mm = container_of(mm_ref, typeof(*mm), ref);
1534 struct intel_vgpu *vgpu = mm->vgpu;
1535 struct intel_gvt *gvt = vgpu->gvt;
1536 struct intel_gvt_gtt *gtt = &gvt->gtt;
1537
1538 if (!mm->initialized)
1539 goto out;
1540
1541 list_del(&mm->list);
1542 list_del(&mm->lru_list);
1543
1544 if (mm->has_shadow_page_table)
1545 invalidate_mm(mm);
1546
1547 gtt->mm_free_page_table(mm);
1548out:
1549 kfree(mm);
1550} 1478}
1551 1479
1552static int shadow_mm(struct intel_vgpu_mm *mm) 1480
1481static int shadow_ppgtt_mm(struct intel_vgpu_mm *mm)
1553{ 1482{
1554 struct intel_vgpu *vgpu = mm->vgpu; 1483 struct intel_vgpu *vgpu = mm->vgpu;
1555 struct intel_gvt *gvt = vgpu->gvt; 1484 struct intel_gvt *gvt = vgpu->gvt;
@@ -1557,21 +1486,21 @@ static int shadow_mm(struct intel_vgpu_mm *mm)
1557 struct intel_gvt_gtt_pte_ops *ops = gtt->pte_ops; 1486 struct intel_gvt_gtt_pte_ops *ops = gtt->pte_ops;
1558 struct intel_vgpu_ppgtt_spt *spt; 1487 struct intel_vgpu_ppgtt_spt *spt;
1559 struct intel_gvt_gtt_entry ge, se; 1488 struct intel_gvt_gtt_entry ge, se;
1560 int i; 1489 int index, ret;
1561 int ret;
1562 1490
1563 if (WARN_ON(!mm->has_shadow_page_table || mm->shadowed)) 1491 if (mm->ppgtt_mm.shadowed)
1564 return 0; 1492 return 0;
1565 1493
1566 mm->shadowed = true; 1494 mm->ppgtt_mm.shadowed = true;
1495
1496 for (index = 0; index < ARRAY_SIZE(mm->ppgtt_mm.guest_pdps); index++) {
1497 ppgtt_get_guest_root_entry(mm, &ge, index);
1567 1498
1568 for (i = 0; i < mm->page_table_entry_cnt; i++) {
1569 ppgtt_get_guest_root_entry(mm, &ge, i);
1570 if (!ops->test_present(&ge)) 1499 if (!ops->test_present(&ge))
1571 continue; 1500 continue;
1572 1501
1573 trace_gpt_change(vgpu->id, __func__, NULL, 1502 trace_gpt_change(vgpu->id, __func__, NULL,
1574 ge.type, ge.val64, i); 1503 ge.type, ge.val64, index);
1575 1504
1576 spt = ppgtt_populate_shadow_page_by_guest_entry(vgpu, &ge); 1505 spt = ppgtt_populate_shadow_page_by_guest_entry(vgpu, &ge);
1577 if (IS_ERR(spt)) { 1506 if (IS_ERR(spt)) {
@@ -1580,96 +1509,132 @@ static int shadow_mm(struct intel_vgpu_mm *mm)
1580 goto fail; 1509 goto fail;
1581 } 1510 }
1582 ppgtt_generate_shadow_entry(&se, spt, &ge); 1511 ppgtt_generate_shadow_entry(&se, spt, &ge);
1583 ppgtt_set_shadow_root_entry(mm, &se, i); 1512 ppgtt_set_shadow_root_entry(mm, &se, index);
1584 1513
1585 trace_gpt_change(vgpu->id, "populate root pointer", 1514 trace_gpt_change(vgpu->id, "populate root pointer",
1586 NULL, se.type, se.val64, i); 1515 NULL, se.type, se.val64, index);
1587 } 1516 }
1517
1588 return 0; 1518 return 0;
1589fail: 1519fail:
1590 invalidate_mm(mm); 1520 invalidate_ppgtt_mm(mm);
1591 return ret; 1521 return ret;
1592} 1522}
1593 1523
1524static struct intel_vgpu_mm *vgpu_alloc_mm(struct intel_vgpu *vgpu)
1525{
1526 struct intel_vgpu_mm *mm;
1527
1528 mm = kzalloc(sizeof(*mm), GFP_KERNEL);
1529 if (!mm)
1530 return NULL;
1531
1532 mm->vgpu = vgpu;
1533 kref_init(&mm->ref);
1534 atomic_set(&mm->pincount, 0);
1535
1536 return mm;
1537}
1538
1539static void vgpu_free_mm(struct intel_vgpu_mm *mm)
1540{
1541 kfree(mm);
1542}
1543
1594/** 1544/**
1595 * intel_vgpu_create_mm - create a mm object for a vGPU 1545 * intel_vgpu_create_ppgtt_mm - create a ppgtt mm object for a vGPU
1596 * @vgpu: a vGPU 1546 * @vgpu: a vGPU
1597 * @mm_type: mm object type, should be PPGTT or GGTT 1547 * @root_entry_type: ppgtt root entry type
1598 * @virtual_page_table: page table root pointers. Could be NULL if user wants 1548 * @pdps: guest pdps.
1599 * to populate shadow later.
1600 * @page_table_level: describe the page table level of the mm object
1601 * @pde_base_index: pde root pointer base in GGTT MMIO.
1602 * 1549 *
1603 * This function is used to create a mm object for a vGPU. 1550 * This function is used to create a ppgtt mm object for a vGPU.
1604 * 1551 *
1605 * Returns: 1552 * Returns:
1606 * Zero on success, negative error code in pointer if failed. 1553 * Zero on success, negative error code in pointer if failed.
1607 */ 1554 */
1608struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu, 1555struct intel_vgpu_mm *intel_vgpu_create_ppgtt_mm(struct intel_vgpu *vgpu,
1609 int mm_type, void *virtual_page_table, int page_table_level, 1556 intel_gvt_gtt_type_t root_entry_type, u64 pdps[])
1610 u32 pde_base_index)
1611{ 1557{
1612 struct intel_gvt *gvt = vgpu->gvt; 1558 struct intel_gvt *gvt = vgpu->gvt;
1613 struct intel_gvt_gtt *gtt = &gvt->gtt;
1614 struct intel_vgpu_mm *mm; 1559 struct intel_vgpu_mm *mm;
1615 int ret; 1560 int ret;
1616 1561
1617 mm = kzalloc(sizeof(*mm), GFP_KERNEL); 1562 mm = vgpu_alloc_mm(vgpu);
1618 if (!mm) { 1563 if (!mm)
1619 ret = -ENOMEM; 1564 return ERR_PTR(-ENOMEM);
1620 goto fail;
1621 }
1622 1565
1623 mm->type = mm_type; 1566 mm->type = INTEL_GVT_MM_PPGTT;
1624 1567
1625 if (page_table_level == 1) 1568 GEM_BUG_ON(root_entry_type != GTT_TYPE_PPGTT_ROOT_L3_ENTRY &&
1626 mm->page_table_entry_type = GTT_TYPE_GGTT_PTE; 1569 root_entry_type != GTT_TYPE_PPGTT_ROOT_L4_ENTRY);
1627 else if (page_table_level == 3) 1570 mm->ppgtt_mm.root_entry_type = root_entry_type;
1628 mm->page_table_entry_type = GTT_TYPE_PPGTT_ROOT_L3_ENTRY;
1629 else if (page_table_level == 4)
1630 mm->page_table_entry_type = GTT_TYPE_PPGTT_ROOT_L4_ENTRY;
1631 else {
1632 WARN_ON(1);
1633 ret = -EINVAL;
1634 goto fail;
1635 }
1636 1571
1637 mm->page_table_level = page_table_level; 1572 INIT_LIST_HEAD(&mm->ppgtt_mm.list);
1638 mm->pde_base_index = pde_base_index; 1573 INIT_LIST_HEAD(&mm->ppgtt_mm.lru_list);
1639 1574
1640 mm->vgpu = vgpu; 1575 if (root_entry_type == GTT_TYPE_PPGTT_ROOT_L4_ENTRY)
1641 mm->has_shadow_page_table = !!(mm_type == INTEL_GVT_MM_PPGTT); 1576 mm->ppgtt_mm.guest_pdps[0] = pdps[0];
1642 1577 else
1643 kref_init(&mm->ref); 1578 memcpy(mm->ppgtt_mm.guest_pdps, pdps,
1644 atomic_set(&mm->pincount, 0); 1579 sizeof(mm->ppgtt_mm.guest_pdps));
1645 INIT_LIST_HEAD(&mm->list);
1646 INIT_LIST_HEAD(&mm->lru_list);
1647 list_add_tail(&mm->list, &vgpu->gtt.mm_list_head);
1648 1580
1649 ret = gtt->mm_alloc_page_table(mm); 1581 ret = shadow_ppgtt_mm(mm);
1650 if (ret) { 1582 if (ret) {
1651 gvt_vgpu_err("fail to allocate page table for mm\n"); 1583 gvt_vgpu_err("failed to shadow ppgtt mm\n");
1652 goto fail; 1584 vgpu_free_mm(mm);
1585 return ERR_PTR(ret);
1653 } 1586 }
1654 1587
1655 mm->initialized = true; 1588 list_add_tail(&mm->ppgtt_mm.list, &vgpu->gtt.ppgtt_mm_list_head);
1589 list_add_tail(&mm->ppgtt_mm.lru_list, &gvt->gtt.ppgtt_mm_lru_list_head);
1590 return mm;
1591}
1656 1592
1657 if (virtual_page_table) 1593static struct intel_vgpu_mm *intel_vgpu_create_ggtt_mm(struct intel_vgpu *vgpu)
1658 memcpy(mm->virtual_page_table, virtual_page_table, 1594{
1659 mm->page_table_entry_size); 1595 struct intel_vgpu_mm *mm;
1596 unsigned long nr_entries;
1660 1597
1661 if (mm->has_shadow_page_table) { 1598 mm = vgpu_alloc_mm(vgpu);
1662 ret = shadow_mm(mm); 1599 if (!mm)
1663 if (ret) 1600 return ERR_PTR(-ENOMEM);
1664 goto fail; 1601
1665 list_add_tail(&mm->lru_list, &gvt->gtt.mm_lru_list_head); 1602 mm->type = INTEL_GVT_MM_GGTT;
1603
1604 nr_entries = gvt_ggtt_gm_sz(vgpu->gvt) >> I915_GTT_PAGE_SHIFT;
1605 mm->ggtt_mm.virtual_ggtt = vzalloc(nr_entries *
1606 vgpu->gvt->device_info.gtt_entry_size);
1607 if (!mm->ggtt_mm.virtual_ggtt) {
1608 vgpu_free_mm(mm);
1609 return ERR_PTR(-ENOMEM);
1666 } 1610 }
1611
1667 return mm; 1612 return mm;
1668fail: 1613}
1669 gvt_vgpu_err("fail to create mm\n"); 1614
1670 if (mm) 1615/**
1671 intel_gvt_mm_unreference(mm); 1616 * intel_vgpu_destroy_mm - destroy a mm object
1672 return ERR_PTR(ret); 1617 * @mm_ref: a kref object
1618 *
1619 * This function is used to destroy a mm object for vGPU
1620 *
1621 */
1622void intel_vgpu_destroy_mm(struct kref *mm_ref)
1623{
1624 struct intel_vgpu_mm *mm = container_of(mm_ref, typeof(*mm), ref);
1625
1626 if (GEM_WARN_ON(atomic_read(&mm->pincount)))
1627 gvt_err("vgpu mm pin count bug detected\n");
1628
1629 if (mm->type == INTEL_GVT_MM_PPGTT) {
1630 list_del(&mm->ppgtt_mm.list);
1631 list_del(&mm->ppgtt_mm.lru_list);
1632 invalidate_ppgtt_mm(mm);
1633 } else {
1634 vfree(mm->ggtt_mm.virtual_ggtt);
1635 }
1636
1637 vgpu_free_mm(mm);
1673} 1638}
1674 1639
1675/** 1640/**
@@ -1680,9 +1645,6 @@ fail:
1680 */ 1645 */
1681void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm) 1646void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm)
1682{ 1647{
1683 if (WARN_ON(mm->type != INTEL_GVT_MM_PPGTT))
1684 return;
1685
1686 atomic_dec(&mm->pincount); 1648 atomic_dec(&mm->pincount);
1687} 1649}
1688 1650
@@ -1701,36 +1663,34 @@ int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm)
1701{ 1663{
1702 int ret; 1664 int ret;
1703 1665
1704 if (WARN_ON(mm->type != INTEL_GVT_MM_PPGTT)) 1666 atomic_inc(&mm->pincount);
1705 return 0;
1706 1667
1707 if (!mm->shadowed) { 1668 if (mm->type == INTEL_GVT_MM_PPGTT) {
1708 ret = shadow_mm(mm); 1669 ret = shadow_ppgtt_mm(mm);
1709 if (ret) 1670 if (ret)
1710 return ret; 1671 return ret;
1672
1673 list_move_tail(&mm->ppgtt_mm.lru_list,
1674 &mm->vgpu->gvt->gtt.ppgtt_mm_lru_list_head);
1675
1711 } 1676 }
1712 1677
1713 atomic_inc(&mm->pincount);
1714 list_del_init(&mm->lru_list);
1715 list_add_tail(&mm->lru_list, &mm->vgpu->gvt->gtt.mm_lru_list_head);
1716 return 0; 1678 return 0;
1717} 1679}
1718 1680
1719static int reclaim_one_mm(struct intel_gvt *gvt) 1681static int reclaim_one_ppgtt_mm(struct intel_gvt *gvt)
1720{ 1682{
1721 struct intel_vgpu_mm *mm; 1683 struct intel_vgpu_mm *mm;
1722 struct list_head *pos, *n; 1684 struct list_head *pos, *n;
1723 1685
1724 list_for_each_safe(pos, n, &gvt->gtt.mm_lru_list_head) { 1686 list_for_each_safe(pos, n, &gvt->gtt.ppgtt_mm_lru_list_head) {
1725 mm = container_of(pos, struct intel_vgpu_mm, lru_list); 1687 mm = container_of(pos, struct intel_vgpu_mm, ppgtt_mm.lru_list);
1726 1688
1727 if (mm->type != INTEL_GVT_MM_PPGTT)
1728 continue;
1729 if (atomic_read(&mm->pincount)) 1689 if (atomic_read(&mm->pincount))
1730 continue; 1690 continue;
1731 1691
1732 list_del_init(&mm->lru_list); 1692 list_del_init(&mm->ppgtt_mm.lru_list);
1733 invalidate_mm(mm); 1693 invalidate_ppgtt_mm(mm);
1734 return 1; 1694 return 1;
1735 } 1695 }
1736 return 0; 1696 return 0;
@@ -1746,9 +1706,6 @@ static inline int ppgtt_get_next_level_entry(struct intel_vgpu_mm *mm,
1746 struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; 1706 struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
1747 struct intel_vgpu_ppgtt_spt *s; 1707 struct intel_vgpu_ppgtt_spt *s;
1748 1708
1749 if (WARN_ON(!mm->has_shadow_page_table))
1750 return -EINVAL;
1751
1752 s = ppgtt_find_shadow_page(vgpu, ops->get_pfn(e)); 1709 s = ppgtt_find_shadow_page(vgpu, ops->get_pfn(e));
1753 if (!s) 1710 if (!s)
1754 return -ENXIO; 1711 return -ENXIO;
@@ -1780,78 +1737,65 @@ unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma)
1780 unsigned long gpa = INTEL_GVT_INVALID_ADDR; 1737 unsigned long gpa = INTEL_GVT_INVALID_ADDR;
1781 unsigned long gma_index[4]; 1738 unsigned long gma_index[4];
1782 struct intel_gvt_gtt_entry e; 1739 struct intel_gvt_gtt_entry e;
1783 int i, index; 1740 int i, levels = 0;
1784 int ret; 1741 int ret;
1785 1742
1786 if (mm->type != INTEL_GVT_MM_GGTT && mm->type != INTEL_GVT_MM_PPGTT) 1743 GEM_BUG_ON(mm->type != INTEL_GVT_MM_GGTT &&
1787 return INTEL_GVT_INVALID_ADDR; 1744 mm->type != INTEL_GVT_MM_PPGTT);
1788 1745
1789 if (mm->type == INTEL_GVT_MM_GGTT) { 1746 if (mm->type == INTEL_GVT_MM_GGTT) {
1790 if (!vgpu_gmadr_is_valid(vgpu, gma)) 1747 if (!vgpu_gmadr_is_valid(vgpu, gma))
1791 goto err; 1748 goto err;
1792 1749
1793 ret = ggtt_get_guest_entry(mm, &e, 1750 ggtt_get_guest_entry(mm, &e,
1794 gma_ops->gma_to_ggtt_pte_index(gma)); 1751 gma_ops->gma_to_ggtt_pte_index(gma));
1795 if (ret) 1752
1796 goto err;
1797 gpa = (pte_ops->get_pfn(&e) << I915_GTT_PAGE_SHIFT) 1753 gpa = (pte_ops->get_pfn(&e) << I915_GTT_PAGE_SHIFT)
1798 + (gma & ~I915_GTT_PAGE_MASK); 1754 + (gma & ~I915_GTT_PAGE_MASK);
1799 1755
1800 trace_gma_translate(vgpu->id, "ggtt", 0, 0, gma, gpa); 1756 trace_gma_translate(vgpu->id, "ggtt", 0, 0, gma, gpa);
1801 return gpa; 1757 } else {
1802 } 1758 switch (mm->ppgtt_mm.root_entry_type) {
1803 1759 case GTT_TYPE_PPGTT_ROOT_L4_ENTRY:
1804 switch (mm->page_table_level) { 1760 ppgtt_get_shadow_root_entry(mm, &e, 0);
1805 case 4: 1761
1806 ret = ppgtt_get_shadow_root_entry(mm, &e, 0); 1762 gma_index[0] = gma_ops->gma_to_pml4_index(gma);
1807 if (ret) 1763 gma_index[1] = gma_ops->gma_to_l4_pdp_index(gma);
1808 goto err; 1764 gma_index[2] = gma_ops->gma_to_pde_index(gma);
1809 gma_index[0] = gma_ops->gma_to_pml4_index(gma); 1765 gma_index[3] = gma_ops->gma_to_pte_index(gma);
1810 gma_index[1] = gma_ops->gma_to_l4_pdp_index(gma); 1766 levels = 4;
1811 gma_index[2] = gma_ops->gma_to_pde_index(gma); 1767 break;
1812 gma_index[3] = gma_ops->gma_to_pte_index(gma); 1768 case GTT_TYPE_PPGTT_ROOT_L3_ENTRY:
1813 index = 4; 1769 ppgtt_get_shadow_root_entry(mm, &e,
1814 break; 1770 gma_ops->gma_to_l3_pdp_index(gma));
1815 case 3: 1771
1816 ret = ppgtt_get_shadow_root_entry(mm, &e, 1772 gma_index[0] = gma_ops->gma_to_pde_index(gma);
1817 gma_ops->gma_to_l3_pdp_index(gma)); 1773 gma_index[1] = gma_ops->gma_to_pte_index(gma);
1818 if (ret) 1774 levels = 2;
1819 goto err; 1775 break;
1820 gma_index[0] = gma_ops->gma_to_pde_index(gma); 1776 default:
1821 gma_index[1] = gma_ops->gma_to_pte_index(gma); 1777 GEM_BUG_ON(1);
1822 index = 2; 1778 }
1823 break;
1824 case 2:
1825 ret = ppgtt_get_shadow_root_entry(mm, &e,
1826 gma_ops->gma_to_pde_index(gma));
1827 if (ret)
1828 goto err;
1829 gma_index[0] = gma_ops->gma_to_pte_index(gma);
1830 index = 1;
1831 break;
1832 default:
1833 WARN_ON(1);
1834 goto err;
1835 }
1836 1779
1837 /* walk into the shadow page table and get gpa from guest entry */ 1780 /* walk the shadow page table and get gpa from guest entry */
1838 for (i = 0; i < index; i++) { 1781 for (i = 0; i < levels; i++) {
1839 ret = ppgtt_get_next_level_entry(mm, &e, gma_index[i], 1782 ret = ppgtt_get_next_level_entry(mm, &e, gma_index[i],
1840 (i == index - 1)); 1783 (i == levels - 1));
1841 if (ret) 1784 if (ret)
1842 goto err; 1785 goto err;
1843 1786
1844 if (!pte_ops->test_present(&e)) { 1787 if (!pte_ops->test_present(&e)) {
1845 gvt_dbg_core("GMA 0x%lx is not present\n", gma); 1788 gvt_dbg_core("GMA 0x%lx is not present\n", gma);
1846 goto err; 1789 goto err;
1790 }
1847 } 1791 }
1848 }
1849 1792
1850 gpa = (pte_ops->get_pfn(&e) << I915_GTT_PAGE_SHIFT) 1793 gpa = (pte_ops->get_pfn(&e) << I915_GTT_PAGE_SHIFT) +
1851 + (gma & ~I915_GTT_PAGE_MASK); 1794 (gma & ~I915_GTT_PAGE_MASK);
1795 trace_gma_translate(vgpu->id, "ppgtt", 0,
1796 mm->ppgtt_mm.root_entry_type, gma, gpa);
1797 }
1852 1798
1853 trace_gma_translate(vgpu->id, "ppgtt", 0,
1854 mm->page_table_level, gma, gpa);
1855 return gpa; 1799 return gpa;
1856err: 1800err:
1857 gvt_vgpu_err("invalid mm type: %d gma %lx\n", mm->type, gma); 1801 gvt_vgpu_err("invalid mm type: %d gma %lx\n", mm->type, gma);
@@ -2131,43 +2075,48 @@ err:
2131int intel_vgpu_init_gtt(struct intel_vgpu *vgpu) 2075int intel_vgpu_init_gtt(struct intel_vgpu *vgpu)
2132{ 2076{
2133 struct intel_vgpu_gtt *gtt = &vgpu->gtt; 2077 struct intel_vgpu_gtt *gtt = &vgpu->gtt;
2134 struct intel_vgpu_mm *ggtt_mm;
2135 2078
2136 hash_init(gtt->tracked_guest_page_hash_table); 2079 hash_init(gtt->tracked_guest_page_hash_table);
2137 hash_init(gtt->shadow_page_hash_table); 2080 hash_init(gtt->shadow_page_hash_table);
2138 2081
2139 INIT_LIST_HEAD(&gtt->mm_list_head); 2082 INIT_LIST_HEAD(&gtt->ppgtt_mm_list_head);
2140 INIT_LIST_HEAD(&gtt->oos_page_list_head); 2083 INIT_LIST_HEAD(&gtt->oos_page_list_head);
2141 INIT_LIST_HEAD(&gtt->post_shadow_list_head); 2084 INIT_LIST_HEAD(&gtt->post_shadow_list_head);
2142 2085
2143 intel_vgpu_reset_ggtt(vgpu); 2086 gtt->ggtt_mm = intel_vgpu_create_ggtt_mm(vgpu);
2144 2087 if (IS_ERR(gtt->ggtt_mm)) {
2145 ggtt_mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_GGTT,
2146 NULL, 1, 0);
2147 if (IS_ERR(ggtt_mm)) {
2148 gvt_vgpu_err("fail to create mm for ggtt.\n"); 2088 gvt_vgpu_err("fail to create mm for ggtt.\n");
2149 return PTR_ERR(ggtt_mm); 2089 return PTR_ERR(gtt->ggtt_mm);
2150 } 2090 }
2151 2091
2152 gtt->ggtt_mm = ggtt_mm; 2092 intel_vgpu_reset_ggtt(vgpu);
2153 2093
2154 return create_scratch_page_tree(vgpu); 2094 return create_scratch_page_tree(vgpu);
2155} 2095}
2156 2096
2157static void intel_vgpu_free_mm(struct intel_vgpu *vgpu, int type) 2097static void intel_vgpu_destroy_all_ppgtt_mm(struct intel_vgpu *vgpu)
2158{ 2098{
2159 struct list_head *pos, *n; 2099 struct list_head *pos, *n;
2160 struct intel_vgpu_mm *mm; 2100 struct intel_vgpu_mm *mm;
2161 2101
2162 list_for_each_safe(pos, n, &vgpu->gtt.mm_list_head) { 2102 list_for_each_safe(pos, n, &vgpu->gtt.ppgtt_mm_list_head) {
2163 mm = container_of(pos, struct intel_vgpu_mm, list); 2103 mm = container_of(pos, struct intel_vgpu_mm, ppgtt_mm.list);
2164 if (mm->type == type) { 2104 intel_vgpu_destroy_mm(&mm->ref);
2165 vgpu->gvt->gtt.mm_free_page_table(mm);
2166 list_del(&mm->list);
2167 list_del(&mm->lru_list);
2168 kfree(mm);
2169 }
2170 } 2105 }
2106
2107 if (GEM_WARN_ON(!list_empty(&vgpu->gtt.ppgtt_mm_list_head)))
2108 gvt_err("vgpu ppgtt mm is not fully destoried\n");
2109
2110 if (GEM_WARN_ON(!hlist_empty(vgpu->gtt.shadow_page_hash_table))) {
2111 gvt_err("Why we still has spt not freed?\n");
2112 ppgtt_free_all_shadow_page(vgpu);
2113 }
2114}
2115
2116static void intel_vgpu_destroy_ggtt_mm(struct intel_vgpu *vgpu)
2117{
2118 intel_vgpu_destroy_mm(&vgpu->gtt.ggtt_mm->ref);
2119 vgpu->gtt.ggtt_mm = NULL;
2171} 2120}
2172 2121
2173/** 2122/**
@@ -2182,11 +2131,9 @@ static void intel_vgpu_free_mm(struct intel_vgpu *vgpu, int type)
2182 */ 2131 */
2183void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu) 2132void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu)
2184{ 2133{
2185 ppgtt_free_all_shadow_page(vgpu); 2134 intel_vgpu_destroy_all_ppgtt_mm(vgpu);
2135 intel_vgpu_destroy_ggtt_mm(vgpu);
2186 release_scratch_page_tree(vgpu); 2136 release_scratch_page_tree(vgpu);
2187
2188 intel_vgpu_free_mm(vgpu, INTEL_GVT_MM_PPGTT);
2189 intel_vgpu_free_mm(vgpu, INTEL_GVT_MM_GGTT);
2190} 2137}
2191 2138
2192static void clean_spt_oos(struct intel_gvt *gvt) 2139static void clean_spt_oos(struct intel_gvt *gvt)
@@ -2248,32 +2195,26 @@ fail:
2248 * pointer to mm object on success, NULL if failed. 2195 * pointer to mm object on success, NULL if failed.
2249 */ 2196 */
2250struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu, 2197struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu,
2251 int page_table_level, void *root_entry) 2198 u64 pdps[])
2252{ 2199{
2253 struct list_head *pos;
2254 struct intel_vgpu_mm *mm; 2200 struct intel_vgpu_mm *mm;
2255 u64 *src, *dst; 2201 struct list_head *pos;
2256
2257 list_for_each(pos, &vgpu->gtt.mm_list_head) {
2258 mm = container_of(pos, struct intel_vgpu_mm, list);
2259 if (mm->type != INTEL_GVT_MM_PPGTT)
2260 continue;
2261
2262 if (mm->page_table_level != page_table_level)
2263 continue;
2264 2202
2265 src = root_entry; 2203 list_for_each(pos, &vgpu->gtt.ppgtt_mm_list_head) {
2266 dst = mm->virtual_page_table; 2204 mm = container_of(pos, struct intel_vgpu_mm, ppgtt_mm.list);
2267 2205
2268 if (page_table_level == 3) { 2206 switch (mm->ppgtt_mm.root_entry_type) {
2269 if (src[0] == dst[0] 2207 case GTT_TYPE_PPGTT_ROOT_L4_ENTRY:
2270 && src[1] == dst[1] 2208 if (pdps[0] == mm->ppgtt_mm.guest_pdps[0])
2271 && src[2] == dst[2]
2272 && src[3] == dst[3])
2273 return mm; 2209 return mm;
2274 } else { 2210 break;
2275 if (src[0] == dst[0]) 2211 case GTT_TYPE_PPGTT_ROOT_L3_ENTRY:
2212 if (!memcmp(pdps, mm->ppgtt_mm.guest_pdps,
2213 sizeof(mm->ppgtt_mm.guest_pdps)))
2276 return mm; 2214 return mm;
2215 break;
2216 default:
2217 GEM_BUG_ON(1);
2277 } 2218 }
2278 } 2219 }
2279 return NULL; 2220 return NULL;
@@ -2283,7 +2224,8 @@ struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu,
2283 * intel_vgpu_g2v_create_ppgtt_mm - create a PPGTT mm object from 2224 * intel_vgpu_g2v_create_ppgtt_mm - create a PPGTT mm object from
2284 * g2v notification 2225 * g2v notification
2285 * @vgpu: a vGPU 2226 * @vgpu: a vGPU
2286 * @page_table_level: PPGTT page table level 2227 * @root_entry_type: ppgtt root entry type
2228 * @pdps: guest pdps
2287 * 2229 *
2288 * This function is used to create a PPGTT mm object from a guest to GVT-g 2230 * This function is used to create a PPGTT mm object from a guest to GVT-g
2289 * notification. 2231 * notification.
@@ -2292,20 +2234,15 @@ struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu,
2292 * Zero on success, negative error code if failed. 2234 * Zero on success, negative error code if failed.
2293 */ 2235 */
2294int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu, 2236int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu,
2295 int page_table_level) 2237 intel_gvt_gtt_type_t root_entry_type, u64 pdps[])
2296{ 2238{
2297 u64 *pdp = (u64 *)&vgpu_vreg64_t(vgpu, vgtif_reg(pdp[0]));
2298 struct intel_vgpu_mm *mm; 2239 struct intel_vgpu_mm *mm;
2299 2240
2300 if (WARN_ON((page_table_level != 4) && (page_table_level != 3))) 2241 mm = intel_vgpu_find_ppgtt_mm(vgpu, pdps);
2301 return -EINVAL;
2302
2303 mm = intel_vgpu_find_ppgtt_mm(vgpu, page_table_level, pdp);
2304 if (mm) { 2242 if (mm) {
2305 intel_gvt_mm_reference(mm); 2243 intel_gvt_mm_reference(mm);
2306 } else { 2244 } else {
2307 mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_PPGTT, 2245 mm = intel_vgpu_create_ppgtt_mm(vgpu, root_entry_type, pdps);
2308 pdp, page_table_level, 0);
2309 if (IS_ERR(mm)) { 2246 if (IS_ERR(mm)) {
2310 gvt_vgpu_err("fail to create mm\n"); 2247 gvt_vgpu_err("fail to create mm\n");
2311 return PTR_ERR(mm); 2248 return PTR_ERR(mm);
@@ -2318,7 +2255,7 @@ int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu,
2318 * intel_vgpu_g2v_destroy_ppgtt_mm - destroy a PPGTT mm object from 2255 * intel_vgpu_g2v_destroy_ppgtt_mm - destroy a PPGTT mm object from
2319 * g2v notification 2256 * g2v notification
2320 * @vgpu: a vGPU 2257 * @vgpu: a vGPU
2321 * @page_table_level: PPGTT page table level 2258 * @pdps: guest pdps
2322 * 2259 *
2323 * This function is used to create a PPGTT mm object from a guest to GVT-g 2260 * This function is used to create a PPGTT mm object from a guest to GVT-g
2324 * notification. 2261 * notification.
@@ -2327,15 +2264,11 @@ int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu,
2327 * Zero on success, negative error code if failed. 2264 * Zero on success, negative error code if failed.
2328 */ 2265 */
2329int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu, 2266int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu,
2330 int page_table_level) 2267 u64 pdps[])
2331{ 2268{
2332 u64 *pdp = (u64 *)&vgpu_vreg64_t(vgpu, vgtif_reg(pdp[0]));
2333 struct intel_vgpu_mm *mm; 2269 struct intel_vgpu_mm *mm;
2334 2270
2335 if (WARN_ON((page_table_level != 4) && (page_table_level != 3))) 2271 mm = intel_vgpu_find_ppgtt_mm(vgpu, pdps);
2336 return -EINVAL;
2337
2338 mm = intel_vgpu_find_ppgtt_mm(vgpu, page_table_level, pdp);
2339 if (!mm) { 2272 if (!mm) {
2340 gvt_vgpu_err("fail to find ppgtt instance.\n"); 2273 gvt_vgpu_err("fail to find ppgtt instance.\n");
2341 return -EINVAL; 2274 return -EINVAL;
@@ -2367,8 +2300,6 @@ int intel_gvt_init_gtt(struct intel_gvt *gvt)
2367 || IS_KABYLAKE(gvt->dev_priv)) { 2300 || IS_KABYLAKE(gvt->dev_priv)) {
2368 gvt->gtt.pte_ops = &gen8_gtt_pte_ops; 2301 gvt->gtt.pte_ops = &gen8_gtt_pte_ops;
2369 gvt->gtt.gma_ops = &gen8_gtt_gma_ops; 2302 gvt->gtt.gma_ops = &gen8_gtt_gma_ops;
2370 gvt->gtt.mm_alloc_page_table = gen8_mm_alloc_page_table;
2371 gvt->gtt.mm_free_page_table = gen8_mm_free_page_table;
2372 } else { 2303 } else {
2373 return -ENODEV; 2304 return -ENODEV;
2374 } 2305 }
@@ -2399,7 +2330,7 @@ int intel_gvt_init_gtt(struct intel_gvt *gvt)
2399 return ret; 2330 return ret;
2400 } 2331 }
2401 } 2332 }
2402 INIT_LIST_HEAD(&gvt->gtt.mm_lru_list_head); 2333 INIT_LIST_HEAD(&gvt->gtt.ppgtt_mm_lru_list_head);
2403 return 0; 2334 return 0;
2404} 2335}
2405 2336
@@ -2471,13 +2402,10 @@ void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu)
2471 */ 2402 */
2472void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu) 2403void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu)
2473{ 2404{
2474 ppgtt_free_all_shadow_page(vgpu);
2475
2476 /* Shadow pages are only created when there is no page 2405 /* Shadow pages are only created when there is no page
2477 * table tracking data, so remove page tracking data after 2406 * table tracking data, so remove page tracking data after
2478 * removing the shadow pages. 2407 * removing the shadow pages.
2479 */ 2408 */
2480 intel_vgpu_free_mm(vgpu, INTEL_GVT_MM_PPGTT); 2409 intel_vgpu_destroy_all_ppgtt_mm(vgpu);
2481
2482 intel_vgpu_reset_ggtt(vgpu); 2410 intel_vgpu_reset_ggtt(vgpu);
2483} 2411}
diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h
index 4cc13b5934f1..037dcbd1c11b 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.h
+++ b/drivers/gpu/drm/i915/gvt/gtt.h
@@ -84,17 +84,12 @@ struct intel_gvt_gtt {
84 void (*mm_free_page_table)(struct intel_vgpu_mm *mm); 84 void (*mm_free_page_table)(struct intel_vgpu_mm *mm);
85 struct list_head oos_page_use_list_head; 85 struct list_head oos_page_use_list_head;
86 struct list_head oos_page_free_list_head; 86 struct list_head oos_page_free_list_head;
87 struct list_head mm_lru_list_head; 87 struct list_head ppgtt_mm_lru_list_head;
88 88
89 struct page *scratch_page; 89 struct page *scratch_page;
90 unsigned long scratch_mfn; 90 unsigned long scratch_mfn;
91}; 91};
92 92
93enum {
94 INTEL_GVT_MM_GGTT = 0,
95 INTEL_GVT_MM_PPGTT,
96};
97
98typedef enum { 93typedef enum {
99 GTT_TYPE_INVALID = -1, 94 GTT_TYPE_INVALID = -1,
100 95
@@ -125,26 +120,39 @@ typedef enum {
125 GTT_TYPE_MAX, 120 GTT_TYPE_MAX,
126} intel_gvt_gtt_type_t; 121} intel_gvt_gtt_type_t;
127 122
128struct intel_vgpu_mm { 123enum intel_gvt_mm_type {
129 int type; 124 INTEL_GVT_MM_GGTT,
130 bool initialized; 125 INTEL_GVT_MM_PPGTT,
131 bool shadowed; 126};
132 127
133 int page_table_entry_type; 128#define GVT_RING_CTX_NR_PDPS GEN8_3LVL_PDPES
134 u32 page_table_entry_size;
135 u32 page_table_entry_cnt;
136 void *virtual_page_table;
137 void *shadow_page_table;
138 129
139 int page_table_level; 130struct intel_vgpu_mm {
140 bool has_shadow_page_table; 131 enum intel_gvt_mm_type type;
141 u32 pde_base_index; 132 struct intel_vgpu *vgpu;
142 133
143 struct list_head list;
144 struct kref ref; 134 struct kref ref;
145 atomic_t pincount; 135 atomic_t pincount;
146 struct list_head lru_list; 136
147 struct intel_vgpu *vgpu; 137 union {
138 struct {
139 intel_gvt_gtt_type_t root_entry_type;
140 /*
141 * The 4 PDPs in ring context. For 48bit addressing,
142 * only PDP0 is valid and point to PML4. For 32it
143 * addressing, all 4 are used as true PDPs.
144 */
145 u64 guest_pdps[GVT_RING_CTX_NR_PDPS];
146 u64 shadow_pdps[GVT_RING_CTX_NR_PDPS];
147 bool shadowed;
148
149 struct list_head list;
150 struct list_head lru_list;
151 } ppgtt_mm;
152 struct {
153 void *virtual_ggtt;
154 } ggtt_mm;
155 };
148}; 156};
149 157
150extern int intel_vgpu_mm_get_entry( 158extern int intel_vgpu_mm_get_entry(
@@ -158,32 +166,31 @@ extern int intel_vgpu_mm_set_entry(
158 unsigned long index); 166 unsigned long index);
159 167
160#define ggtt_get_guest_entry(mm, e, index) \ 168#define ggtt_get_guest_entry(mm, e, index) \
161 intel_vgpu_mm_get_entry(mm, mm->virtual_page_table, e, index) 169 intel_vgpu_mm_get_entry(mm, mm->ggtt_mm.virtual_ggtt, e, index)
162 170
163#define ggtt_set_guest_entry(mm, e, index) \ 171#define ggtt_set_guest_entry(mm, e, index) \
164 intel_vgpu_mm_set_entry(mm, mm->virtual_page_table, e, index) 172 intel_vgpu_mm_set_entry(mm, mm->ggtt_mm.virtual_ggtt, e, index)
165 173
166#define ggtt_get_shadow_entry(mm, e, index) \ 174#define ggtt_get_shadow_entry(mm, e, index) \
167 intel_vgpu_mm_get_entry(mm, mm->shadow_page_table, e, index) 175 intel_vgpu_mm_get_entry(mm, mm->ggtt_mm.virtual_ggtt, e, index)
168 176
169#define ggtt_set_shadow_entry(mm, e, index) \ 177#define ggtt_set_shadow_entry(mm, e, index) \
170 intel_vgpu_mm_set_entry(mm, mm->shadow_page_table, e, index) 178 intel_vgpu_mm_set_entry(mm, mm->ggtt_mm.virtual_ggtt, e, index)
171 179
172#define ppgtt_get_guest_root_entry(mm, e, index) \ 180#define ppgtt_get_guest_root_entry(mm, e, index) \
173 intel_vgpu_mm_get_entry(mm, mm->virtual_page_table, e, index) 181 intel_vgpu_mm_get_entry(mm, mm->ppgtt_mm.guest_pdps, e, index)
174 182
175#define ppgtt_set_guest_root_entry(mm, e, index) \ 183#define ppgtt_set_guest_root_entry(mm, e, index) \
176 intel_vgpu_mm_set_entry(mm, mm->virtual_page_table, e, index) 184 intel_vgpu_mm_set_entry(mm, mm->ppgtt_mm.guest_pdps, e, index)
177 185
178#define ppgtt_get_shadow_root_entry(mm, e, index) \ 186#define ppgtt_get_shadow_root_entry(mm, e, index) \
179 intel_vgpu_mm_get_entry(mm, mm->shadow_page_table, e, index) 187 intel_vgpu_mm_get_entry(mm, mm->ppgtt_mm.shadow_pdps, e, index)
180 188
181#define ppgtt_set_shadow_root_entry(mm, e, index) \ 189#define ppgtt_set_shadow_root_entry(mm, e, index) \
182 intel_vgpu_mm_set_entry(mm, mm->shadow_page_table, e, index) 190 intel_vgpu_mm_set_entry(mm, mm->ppgtt_mm.shadow_pdps, e, index)
183 191
184extern struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu, 192struct intel_vgpu_mm *intel_vgpu_create_ppgtt_mm(struct intel_vgpu *vgpu,
185 int mm_type, void *virtual_page_table, int page_table_level, 193 intel_gvt_gtt_type_t root_entry_type, u64 pdps[]);
186 u32 pde_base_index);
187extern void intel_vgpu_destroy_mm(struct kref *mm_ref); 194extern void intel_vgpu_destroy_mm(struct kref *mm_ref);
188 195
189struct intel_vgpu_guest_page; 196struct intel_vgpu_guest_page;
@@ -196,7 +203,7 @@ struct intel_vgpu_scratch_pt {
196struct intel_vgpu_gtt { 203struct intel_vgpu_gtt {
197 struct intel_vgpu_mm *ggtt_mm; 204 struct intel_vgpu_mm *ggtt_mm;
198 unsigned long active_ppgtt_mm_bitmap; 205 unsigned long active_ppgtt_mm_bitmap;
199 struct list_head mm_list_head; 206 struct list_head ppgtt_mm_list_head;
200 DECLARE_HASHTABLE(shadow_page_hash_table, INTEL_GVT_GTT_HASH_BITS); 207 DECLARE_HASHTABLE(shadow_page_hash_table, INTEL_GVT_GTT_HASH_BITS);
201 DECLARE_HASHTABLE(tracked_guest_page_hash_table, INTEL_GVT_GTT_HASH_BITS); 208 DECLARE_HASHTABLE(tracked_guest_page_hash_table, INTEL_GVT_GTT_HASH_BITS);
202 atomic_t n_tracked_guest_page; 209 atomic_t n_tracked_guest_page;
@@ -294,13 +301,12 @@ unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm,
294 unsigned long gma); 301 unsigned long gma);
295 302
296struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu, 303struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu,
297 int page_table_level, void *root_entry); 304 u64 pdps[]);
298 305
299int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu, 306int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu,
300 int page_table_level); 307 intel_gvt_gtt_type_t root_entry_type, u64 pdps[]);
301 308
302int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu, 309int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu, u64 pdps[]);
303 int page_table_level);
304 310
305int intel_vgpu_emulate_gtt_mmio_read(struct intel_vgpu *vgpu, 311int intel_vgpu_emulate_gtt_mmio_read(struct intel_vgpu *vgpu,
306 unsigned int off, void *p_data, unsigned int bytes); 312 unsigned int off, void *p_data, unsigned int bytes);
diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c
index 9be639aa3b55..c51a5bd4e109 100644
--- a/drivers/gpu/drm/i915/gvt/handlers.c
+++ b/drivers/gpu/drm/i915/gvt/handlers.c
@@ -1139,20 +1139,27 @@ static int pvinfo_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
1139 1139
1140static int handle_g2v_notification(struct intel_vgpu *vgpu, int notification) 1140static int handle_g2v_notification(struct intel_vgpu *vgpu, int notification)
1141{ 1141{
1142 u64 *pdps;
1142 int ret = 0; 1143 int ret = 0;
1143 1144
1145 pdps = (u64 *)&vgpu_vreg64_t(vgpu, vgtif_reg(pdp[0]));
1146
1144 switch (notification) { 1147 switch (notification) {
1145 case VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE: 1148 case VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE:
1146 ret = intel_vgpu_g2v_create_ppgtt_mm(vgpu, 3); 1149 ret = intel_vgpu_g2v_create_ppgtt_mm(vgpu,
1150 GTT_TYPE_PPGTT_ROOT_L3_ENTRY,
1151 pdps);
1147 break; 1152 break;
1148 case VGT_G2V_PPGTT_L3_PAGE_TABLE_DESTROY: 1153 case VGT_G2V_PPGTT_L3_PAGE_TABLE_DESTROY:
1149 ret = intel_vgpu_g2v_destroy_ppgtt_mm(vgpu, 3); 1154 ret = intel_vgpu_g2v_destroy_ppgtt_mm(vgpu, pdps);
1150 break; 1155 break;
1151 case VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE: 1156 case VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE:
1152 ret = intel_vgpu_g2v_create_ppgtt_mm(vgpu, 4); 1157 ret = intel_vgpu_g2v_create_ppgtt_mm(vgpu,
1158 GTT_TYPE_PPGTT_ROOT_L4_ENTRY,
1159 pdps);
1153 break; 1160 break;
1154 case VGT_G2V_PPGTT_L4_PAGE_TABLE_DESTROY: 1161 case VGT_G2V_PPGTT_L4_PAGE_TABLE_DESTROY:
1155 ret = intel_vgpu_g2v_destroy_ppgtt_mm(vgpu, 4); 1162 ret = intel_vgpu_g2v_destroy_ppgtt_mm(vgpu, pdps);
1156 break; 1163 break;
1157 case VGT_G2V_EXECLIST_CONTEXT_CREATE: 1164 case VGT_G2V_EXECLIST_CONTEXT_CREATE:
1158 case VGT_G2V_EXECLIST_CONTEXT_DESTROY: 1165 case VGT_G2V_EXECLIST_CONTEXT_DESTROY:
diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c
index 5c869e3fdf3b..b8118cbeafe2 100644
--- a/drivers/gpu/drm/i915/gvt/mmio.c
+++ b/drivers/gpu/drm/i915/gvt/mmio.c
@@ -76,10 +76,9 @@ static void failsafe_emulate_mmio_rw(struct intel_vgpu *vgpu, uint64_t pa,
76 else 76 else
77 intel_vgpu_default_mmio_write(vgpu, offset, p_data, 77 intel_vgpu_default_mmio_write(vgpu, offset, p_data,
78 bytes); 78 bytes);
79 } else if (reg_is_gtt(gvt, offset) && 79 } else if (reg_is_gtt(gvt, offset)) {
80 vgpu->gtt.ggtt_mm->virtual_page_table) {
81 offset -= gvt->device_info.gtt_start_offset; 80 offset -= gvt->device_info.gtt_start_offset;
82 pt = vgpu->gtt.ggtt_mm->virtual_page_table + offset; 81 pt = vgpu->gtt.ggtt_mm->ggtt_mm.virtual_ggtt + offset;
83 if (read) 82 if (read)
84 memcpy(p_data, pt, bytes); 83 memcpy(p_data, pt, bytes);
85 else 84 else
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c
index 92df1b44fe1d..5668c3d0f542 100644
--- a/drivers/gpu/drm/i915/gvt/scheduler.c
+++ b/drivers/gpu/drm/i915/gvt/scheduler.c
@@ -113,7 +113,7 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload)
113#undef COPY_REG 113#undef COPY_REG
114 114
115 set_context_pdp_root_pointer(shadow_ring_context, 115 set_context_pdp_root_pointer(shadow_ring_context,
116 workload->shadow_mm->shadow_page_table); 116 (void *)workload->shadow_mm->ppgtt_mm.shadow_pdps);
117 117
118 intel_gvt_hypervisor_read_gpa(vgpu, 118 intel_gvt_hypervisor_read_gpa(vgpu,
119 workload->ring_context_gpa + 119 workload->ring_context_gpa +
@@ -1181,27 +1181,30 @@ static int prepare_mm(struct intel_vgpu_workload *workload)
1181 struct execlist_ctx_descriptor_format *desc = &workload->ctx_desc; 1181 struct execlist_ctx_descriptor_format *desc = &workload->ctx_desc;
1182 struct intel_vgpu_mm *mm; 1182 struct intel_vgpu_mm *mm;
1183 struct intel_vgpu *vgpu = workload->vgpu; 1183 struct intel_vgpu *vgpu = workload->vgpu;
1184 int page_table_level; 1184 intel_gvt_gtt_type_t root_entry_type;
1185 u32 pdp[8]; 1185 u64 pdps[GVT_RING_CTX_NR_PDPS];
1186 1186
1187 if (desc->addressing_mode == 1) { /* legacy 32-bit */ 1187 switch (desc->addressing_mode) {
1188 page_table_level = 3; 1188 case 1: /* legacy 32-bit */
1189 } else if (desc->addressing_mode == 3) { /* legacy 64 bit */ 1189 root_entry_type = GTT_TYPE_PPGTT_ROOT_L3_ENTRY;
1190 page_table_level = 4; 1190 break;
1191 } else { 1191 case 3: /* legacy 64-bit */
1192 root_entry_type = GTT_TYPE_PPGTT_ROOT_L4_ENTRY;
1193 break;
1194 default:
1192 gvt_vgpu_err("Advanced Context mode(SVM) is not supported!\n"); 1195 gvt_vgpu_err("Advanced Context mode(SVM) is not supported!\n");
1193 return -EINVAL; 1196 return -EINVAL;
1194 } 1197 }
1195 1198
1196 read_guest_pdps(workload->vgpu, workload->ring_context_gpa, pdp); 1199 read_guest_pdps(workload->vgpu, workload->ring_context_gpa, (void *)pdps);
1197 1200
1198 mm = intel_vgpu_find_ppgtt_mm(workload->vgpu, page_table_level, pdp); 1201 mm = intel_vgpu_find_ppgtt_mm(workload->vgpu, pdps);
1199 if (mm) { 1202 if (mm) {
1200 intel_gvt_mm_reference(mm); 1203 intel_gvt_mm_reference(mm);
1201 } else { 1204 } else {
1202 1205
1203 mm = intel_vgpu_create_mm(workload->vgpu, INTEL_GVT_MM_PPGTT, 1206 mm = intel_vgpu_create_ppgtt_mm(workload->vgpu, root_entry_type,
1204 pdp, page_table_level, 0); 1207 pdps);
1205 if (IS_ERR(mm)) { 1208 if (IS_ERR(mm)) {
1206 gvt_vgpu_err("fail to create mm object.\n"); 1209 gvt_vgpu_err("fail to create mm object.\n");
1207 return PTR_ERR(mm); 1210 return PTR_ERR(mm);
diff --git a/drivers/gpu/drm/i915/gvt/trace.h b/drivers/gpu/drm/i915/gvt/trace.h
index 7a2511538f34..5a060dacdb26 100644
--- a/drivers/gpu/drm/i915/gvt/trace.h
+++ b/drivers/gpu/drm/i915/gvt/trace.h
@@ -113,10 +113,10 @@ TRACE_EVENT(gma_index,
113); 113);
114 114
115TRACE_EVENT(gma_translate, 115TRACE_EVENT(gma_translate,
116 TP_PROTO(int id, char *type, int ring_id, int pt_level, 116 TP_PROTO(int id, char *type, int ring_id, int root_entry_type,
117 unsigned long gma, unsigned long gpa), 117 unsigned long gma, unsigned long gpa),
118 118
119 TP_ARGS(id, type, ring_id, pt_level, gma, gpa), 119 TP_ARGS(id, type, ring_id, root_entry_type, gma, gpa),
120 120
121 TP_STRUCT__entry( 121 TP_STRUCT__entry(
122 __array(char, buf, MAX_BUF_LEN) 122 __array(char, buf, MAX_BUF_LEN)
@@ -124,8 +124,8 @@ TRACE_EVENT(gma_translate,
124 124
125 TP_fast_assign( 125 TP_fast_assign(
126 snprintf(__entry->buf, MAX_BUF_LEN, 126 snprintf(__entry->buf, MAX_BUF_LEN,
127 "VM%d %s ring %d pt_level %d gma 0x%lx -> gpa 0x%lx\n", 127 "VM%d %s ring %d root_entry_type %d gma 0x%lx -> gpa 0x%lx\n",
128 id, type, ring_id, pt_level, gma, gpa); 128 id, type, ring_id, root_entry_type, gma, gpa);
129 ), 129 ),
130 130
131 TP_printk("%s", __entry->buf) 131 TP_printk("%s", __entry->buf)