@@ -326,6 +326,9 @@ static int pkvm_unmap_range(struct kvm *kvm, u64 start, u64 end)
326
326
327
327
mt_for_each (& kvm -> arch .pkvm .pinned_pages , entry , index , end - 1 ) {
328
328
struct kvm_pinned_page * ppage = entry ;
329
+
330
+ if (ppage == KVM_DUMMY_PPAGE )
331
+ continue ;
329
332
ret = pkvm_unmap_guest (kvm , ppage );
330
333
if (ret )
331
334
break ;
@@ -425,6 +428,8 @@ static void pkvm_stage2_flush(struct kvm *kvm)
425
428
mt_for_each (& kvm -> arch .pkvm .pinned_pages , entry , index , ULONG_MAX ) {
426
429
struct kvm_pinned_page * ppage = entry ;
427
430
431
+ if (ppage == KVM_DUMMY_PPAGE )
432
+ continue ;
428
433
__clean_dcache_guest_page (page_address (ppage -> page ), PAGE_SIZE );
429
434
cond_resched_rwlock_write (& kvm -> mmu_lock );
430
435
}
@@ -1284,7 +1289,11 @@ static int pkvm_wp_range(struct kvm *kvm, u64 start, u64 end)
1284
1289
1285
1290
mt_for_each (& kvm -> arch .pkvm .pinned_pages , entry , index , end - 1 ) {
1286
1291
struct kvm_pinned_page * ppage = entry ;
1287
- int ret = pkvm_call_hyp_nvhe_ppage (ppage , __pkvm_wrprotect_call ,
1292
+ int ret ;
1293
+
1294
+ if (ppage == KVM_DUMMY_PPAGE )
1295
+ continue ;
1296
+ ret = pkvm_call_hyp_nvhe_ppage (ppage , __pkvm_wrprotect_call ,
1288
1297
kvm , false);
1289
1298
1290
1299
if (ret )
@@ -1618,27 +1627,22 @@ find_ppage_or_above(struct kvm *kvm, phys_addr_t ipa)
1618
1627
unsigned long index = ipa ;
1619
1628
void * entry ;
1620
1629
1621
- mt_for_each (& kvm -> arch .pkvm .pinned_pages , entry , index , ULONG_MAX )
1630
+ mt_for_each (& kvm -> arch .pkvm .pinned_pages , entry , index , ULONG_MAX ) {
1631
+ if (entry == KVM_DUMMY_PPAGE )
1632
+ continue ;
1622
1633
return entry ;
1634
+ }
1623
1635
1624
1636
return NULL ;
1625
1637
}
1626
1638
1627
- static int insert_ppage (struct kvm * kvm , struct kvm_pinned_page * ppage )
1628
- {
1629
- size_t size = PAGE_SIZE << ppage -> order ;
1630
- unsigned long start = ppage -> ipa ;
1631
- unsigned long end = start + size - 1 ;
1632
-
1633
- return mtree_insert_range (& kvm -> arch .pkvm .pinned_pages , start , end ,
1634
- ppage , GFP_KERNEL );
1635
- }
1636
-
1637
1639
static struct kvm_pinned_page * find_ppage (struct kvm * kvm , u64 ipa )
1638
1640
{
1641
+ struct kvm_pinned_page * ppage ;
1639
1642
unsigned long index = ipa ;
1640
1643
1641
- return mt_find (& kvm -> arch .pkvm .pinned_pages , & index , ipa + PAGE_SIZE - 1 );
1644
+ ppage = mt_find (& kvm -> arch .pkvm .pinned_pages , & index , ipa + PAGE_SIZE - 1 );
1645
+ return ppage == KVM_DUMMY_PPAGE ? NULL : ppage ;
1642
1646
}
1643
1647
1644
1648
static int __pkvm_relax_perms_call (u64 pfn , u64 gfn , u8 order , void * args )
@@ -1690,10 +1694,11 @@ static int pkvm_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t *fault_ipa,
1690
1694
{
1691
1695
unsigned int flags = FOLL_HWPOISON | FOLL_LONGTERM | FOLL_WRITE ;
1692
1696
struct kvm_hyp_memcache * hyp_memcache = & vcpu -> arch .stage2_mc ;
1693
- unsigned long index , pmd_offset , page_size ;
1697
+ unsigned long index , pmd_offset , page_size , end ;
1694
1698
struct mm_struct * mm = current -> mm ;
1695
1699
struct kvm_pinned_page * ppage ;
1696
1700
struct kvm * kvm = vcpu -> kvm ;
1701
+ struct maple_tree * mt = & kvm -> arch .pkvm .pinned_pages ;
1697
1702
int ret , nr_pages ;
1698
1703
struct page * page ;
1699
1704
u64 pfn ;
@@ -1756,16 +1761,19 @@ static int pkvm_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t *fault_ipa,
1756
1761
if (ret )
1757
1762
goto unpin ;
1758
1763
1759
- write_lock (& kvm -> mmu_lock );
1764
+ index = * fault_ipa ;
1765
+ end = index + page_size - 1 ;
1766
+ ppage -> page = page ;
1767
+ ppage -> ipa = * fault_ipa ;
1768
+ ppage -> order = get_order (page_size );
1769
+ ppage -> pins = 1 << ppage -> order ;
1770
+
1760
1771
/*
1761
1772
* If we already have a mapping in the middle of the THP, we have no
1762
1773
* other choice than enforcing PAGE_SIZE for pkvm_host_map_guest() to
1763
1774
* succeed.
1764
1775
*/
1765
- index = * fault_ipa ;
1766
- if (page_size > PAGE_SIZE &&
1767
- mt_find (& kvm -> arch .pkvm .pinned_pages , & index , index + page_size - 1 )) {
1768
- write_unlock (& kvm -> mmu_lock );
1776
+ if (page_size > PAGE_SIZE && mt_find (mt , & index , end )) {
1769
1777
* fault_ipa += pmd_offset ;
1770
1778
pfn += pmd_offset >> PAGE_SHIFT ;
1771
1779
page = pfn_to_page (pfn );
@@ -1774,27 +1782,31 @@ static int pkvm_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t *fault_ipa,
1774
1782
goto retry ;
1775
1783
}
1776
1784
1777
- ret = pkvm_host_map_guest ( pfn , * fault_ipa >> PAGE_SHIFT ,
1778
- page_size >> PAGE_SHIFT , KVM_PGTABLE_PROT_R );
1785
+ /* Reserve space in the mtree */
1786
+ ret = mtree_insert_range ( mt , index , end , KVM_DUMMY_PPAGE , GFP_KERNEL );
1779
1787
if (ret ) {
1780
- if (ret == - EAGAIN )
1788
+ if (ret == - EEXIST )
1781
1789
ret = 0 ;
1782
-
1783
1790
goto dec_account ;
1784
1791
}
1785
1792
1786
- ppage -> page = page ;
1787
- ppage -> ipa = * fault_ipa ;
1788
- ppage -> order = get_order (page_size );
1789
- ppage -> pins = 1 << ppage -> order ;
1790
- WARN_ON (insert_ppage (kvm , ppage ));
1793
+ write_lock (& kvm -> mmu_lock );
1794
+ ret = pkvm_host_map_guest (pfn , * fault_ipa >> PAGE_SHIFT ,
1795
+ page_size >> PAGE_SHIFT , KVM_PGTABLE_PROT_R );
1796
+ if (ret ) {
1797
+ if (WARN_ON (ret == - EAGAIN ))
1798
+ ret = 0 ;
1791
1799
1800
+ goto err_unlock ;
1801
+ }
1802
+ WARN_ON (mtree_store_range (mt , index , end , ppage , GFP_ATOMIC ));
1792
1803
write_unlock (& kvm -> mmu_lock );
1793
1804
1794
1805
return 0 ;
1795
1806
1796
- dec_account :
1807
+ err_unlock :
1797
1808
write_unlock (& kvm -> mmu_lock );
1809
+ dec_account :
1798
1810
account_locked_vm (mm , page_size >> PAGE_SHIFT , false);
1799
1811
unpin :
1800
1812
unpin_user_pages (& page , 1 );
@@ -1825,7 +1837,7 @@ int pkvm_mem_abort_range(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, size_t si
1825
1837
ppage = find_ppage_or_above (vcpu -> kvm , fault_ipa );
1826
1838
1827
1839
while (fault_ipa < ipa_end ) {
1828
- if (ppage && ppage -> ipa == fault_ipa ) {
1840
+ if (ppage && ppage != KVM_DUMMY_PPAGE && ppage -> ipa == fault_ipa ) {
1829
1841
page_size = PAGE_SIZE << ppage -> order ;
1830
1842
ppage = mt_next (& vcpu -> kvm -> arch .pkvm .pinned_pages ,
1831
1843
ppage -> ipa , ULONG_MAX );
0 commit comments