Skip to content

Commit 0529c90

Browse files
Suzuki K PouloseMarc Zyngier
authored andcommitted
KVM: arm64: Unify handling THP backed host memory
We support mapping host memory backed by PMD transparent hugepages at stage2 as huge pages. However the checks are now spread across two different places. Let us unify the handling of the THPs to keep the code cleaner (and future proof for PUD THP support). This patch moves transparent_hugepage_adjust() closer to the caller to avoid a forward declaration for fault_supports_stage2_huge_mappings(). Also, since we already handle the case where the host VA and the guest PA may not be aligned, the explicit VM_BUG_ON() is not required. Signed-off-by: Suzuki K Poulose <[email protected]> Signed-off-by: Zenghui Yu <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 9f28361 commit 0529c90

File tree

1 file changed

+60
-55
lines changed

1 file changed

+60
-55
lines changed

arch/arm64/kvm/mmu.c

Lines changed: 60 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,47 +1375,6 @@ int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
13751375
return ret;
13761376
}
13771377

1378-
static bool transparent_hugepage_adjust(kvm_pfn_t *pfnp, phys_addr_t *ipap)
1379-
{
1380-
kvm_pfn_t pfn = *pfnp;
1381-
gfn_t gfn = *ipap >> PAGE_SHIFT;
1382-
1383-
if (kvm_is_transparent_hugepage(pfn)) {
1384-
unsigned long mask;
1385-
/*
1386-
* The address we faulted on is backed by a transparent huge
1387-
* page. However, because we map the compound huge page and
1388-
* not the individual tail page, we need to transfer the
1389-
* refcount to the head page. We have to be careful that the
1390-
* THP doesn't start to split while we are adjusting the
1391-
* refcounts.
1392-
*
1393-
* We are sure this doesn't happen, because mmu_notifier_retry
1394-
* was successful and we are holding the mmu_lock, so if this
1395-
* THP is trying to split, it will be blocked in the mmu
1396-
* notifier before touching any of the pages, specifically
1397-
* before being able to call __split_huge_page_refcount().
1398-
*
1399-
* We can therefore safely transfer the refcount from PG_tail
1400-
* to PG_head and switch the pfn from a tail page to the head
1401-
* page accordingly.
1402-
*/
1403-
mask = PTRS_PER_PMD - 1;
1404-
VM_BUG_ON((gfn & mask) != (pfn & mask));
1405-
if (pfn & mask) {
1406-
*ipap &= PMD_MASK;
1407-
kvm_release_pfn_clean(pfn);
1408-
pfn &= ~mask;
1409-
kvm_get_pfn(pfn);
1410-
*pfnp = pfn;
1411-
}
1412-
1413-
return true;
1414-
}
1415-
1416-
return false;
1417-
}
1418-
14191378
/**
14201379
* stage2_wp_ptes - write protect PMD range
14211380
* @pmd: pointer to pmd entry
@@ -1663,6 +1622,59 @@ static bool fault_supports_stage2_huge_mapping(struct kvm_memory_slot *memslot,
16631622
(hva & ~(map_size - 1)) + map_size <= uaddr_end;
16641623
}
16651624

1625+
/*
1626+
* Check if the given hva is backed by a transparent huge page (THP) and
1627+
* whether it can be mapped using block mapping in stage2. If so, adjust
1628+
* the stage2 PFN and IPA accordingly. Only PMD_SIZE THPs are currently
1629+
* supported. This will need to be updated to support other THP sizes.
1630+
*
1631+
* Returns the size of the mapping.
1632+
*/
1633+
static unsigned long
1634+
transparent_hugepage_adjust(struct kvm_memory_slot *memslot,
1635+
unsigned long hva, kvm_pfn_t *pfnp,
1636+
phys_addr_t *ipap)
1637+
{
1638+
kvm_pfn_t pfn = *pfnp;
1639+
1640+
/*
1641+
* Make sure the adjustment is done only for THP pages. Also make
1642+
* sure that the HVA and IPA are sufficiently aligned and that the
1643+
* block map is contained within the memslot.
1644+
*/
1645+
if (kvm_is_transparent_hugepage(pfn) &&
1646+
fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE)) {
1647+
/*
1648+
* The address we faulted on is backed by a transparent huge
1649+
* page. However, because we map the compound huge page and
1650+
* not the individual tail page, we need to transfer the
1651+
* refcount to the head page. We have to be careful that the
1652+
* THP doesn't start to split while we are adjusting the
1653+
* refcounts.
1654+
*
1655+
* We are sure this doesn't happen, because mmu_notifier_retry
1656+
* was successful and we are holding the mmu_lock, so if this
1657+
* THP is trying to split, it will be blocked in the mmu
1658+
* notifier before touching any of the pages, specifically
1659+
* before being able to call __split_huge_page_refcount().
1660+
*
1661+
* We can therefore safely transfer the refcount from PG_tail
1662+
* to PG_head and switch the pfn from a tail page to the head
1663+
* page accordingly.
1664+
*/
1665+
*ipap &= PMD_MASK;
1666+
kvm_release_pfn_clean(pfn);
1667+
pfn &= ~(PTRS_PER_PMD - 1);
1668+
kvm_get_pfn(pfn);
1669+
*pfnp = pfn;
1670+
1671+
return PMD_SIZE;
1672+
}
1673+
1674+
/* Use page mapping if we cannot use block mapping. */
1675+
return PAGE_SIZE;
1676+
}
1677+
16661678
static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
16671679
struct kvm_memory_slot *memslot, unsigned long hva,
16681680
unsigned long fault_status)
@@ -1776,20 +1788,13 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
17761788
if (mmu_notifier_retry(kvm, mmu_seq))
17771789
goto out_unlock;
17781790

1779-
if (vma_pagesize == PAGE_SIZE && !force_pte) {
1780-
/*
1781-
* Only PMD_SIZE transparent hugepages(THP) are
1782-
* currently supported. This code will need to be
1783-
* updated to support other THP sizes.
1784-
*
1785-
* Make sure the host VA and the guest IPA are sufficiently
1786-
* aligned and that the block is contained within the memslot.
1787-
*/
1788-
if (fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE) &&
1789-
transparent_hugepage_adjust(&pfn, &fault_ipa))
1790-
vma_pagesize = PMD_SIZE;
1791-
}
1792-
1791+
/*
1792+
* If we are not forced to use page mapping, check if we are
1793+
* backed by a THP and thus use block mapping if possible.
1794+
*/
1795+
if (vma_pagesize == PAGE_SIZE && !force_pte)
1796+
vma_pagesize = transparent_hugepage_adjust(memslot, hva,
1797+
&pfn, &fault_ipa);
17931798
if (writable)
17941799
kvm_set_pfn_dirty(pfn);
17951800

0 commit comments

Comments
 (0)