@@ -453,7 +453,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
453
453
* Check for races, another CPU might have split this page
454
454
* up already:
455
455
*/
456
- tmp = lookup_address ( address , & level );
456
+ tmp = _lookup_address_cpa ( cpa , address , & level );
457
457
if (tmp != kpte )
458
458
goto out_unlock ;
459
459
@@ -559,7 +559,8 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
559
559
}
560
560
561
561
static int
562
- __split_large_page (pte_t * kpte , unsigned long address , struct page * base )
562
+ __split_large_page (struct cpa_data * cpa , pte_t * kpte , unsigned long address ,
563
+ struct page * base )
563
564
{
564
565
pte_t * pbase = (pte_t * )page_address (base );
565
566
unsigned long pfn , pfninc = 1 ;
@@ -572,7 +573,7 @@ __split_large_page(pte_t *kpte, unsigned long address, struct page *base)
572
573
* Check for races, another CPU might have split this page
573
574
* up for us already:
574
575
*/
575
- tmp = lookup_address ( address , & level );
576
+ tmp = _lookup_address_cpa ( cpa , address , & level );
576
577
if (tmp != kpte ) {
577
578
spin_unlock (& pgd_lock );
578
579
return 1 ;
@@ -648,7 +649,8 @@ __split_large_page(pte_t *kpte, unsigned long address, struct page *base)
648
649
return 0 ;
649
650
}
650
651
651
- static int split_large_page (pte_t * kpte , unsigned long address )
652
+ static int split_large_page (struct cpa_data * cpa , pte_t * kpte ,
653
+ unsigned long address )
652
654
{
653
655
struct page * base ;
654
656
@@ -660,7 +662,7 @@ static int split_large_page(pte_t *kpte, unsigned long address)
660
662
if (!base )
661
663
return - ENOMEM ;
662
664
663
- if (__split_large_page (kpte , address , base ))
665
+ if (__split_large_page (cpa , kpte , address , base ))
664
666
__free_page (base );
665
667
666
668
return 0 ;
@@ -1041,6 +1043,9 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr)
1041
1043
static int __cpa_process_fault (struct cpa_data * cpa , unsigned long vaddr ,
1042
1044
int primary )
1043
1045
{
1046
+ if (cpa -> pgd )
1047
+ return populate_pgd (cpa , vaddr );
1048
+
1044
1049
/*
1045
1050
* Ignore all non primary paths.
1046
1051
*/
@@ -1085,7 +1090,7 @@ static int __change_page_attr(struct cpa_data *cpa, int primary)
1085
1090
else
1086
1091
address = * cpa -> vaddr ;
1087
1092
repeat :
1088
- kpte = lookup_address ( address , & level );
1093
+ kpte = _lookup_address_cpa ( cpa , address , & level );
1089
1094
if (!kpte )
1090
1095
return __cpa_process_fault (cpa , address , primary );
1091
1096
@@ -1149,7 +1154,7 @@ static int __change_page_attr(struct cpa_data *cpa, int primary)
1149
1154
/*
1150
1155
* We have to split the large page:
1151
1156
*/
1152
- err = split_large_page (kpte , address );
1157
+ err = split_large_page (cpa , kpte , address );
1153
1158
if (!err ) {
1154
1159
/*
1155
1160
* Do a global flush tlb after splitting the large page
@@ -1298,6 +1303,8 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages,
1298
1303
int ret , cache , checkalias ;
1299
1304
unsigned long baddr = 0 ;
1300
1305
1306
+ memset (& cpa , 0 , sizeof (cpa ));
1307
+
1301
1308
/*
1302
1309
* Check, if we are requested to change a not supported
1303
1310
* feature:
@@ -1744,6 +1751,7 @@ static int __set_pages_p(struct page *page, int numpages)
1744
1751
{
1745
1752
unsigned long tempaddr = (unsigned long ) page_address (page );
1746
1753
struct cpa_data cpa = { .vaddr = & tempaddr ,
1754
+ .pgd = NULL ,
1747
1755
.numpages = numpages ,
1748
1756
.mask_set = __pgprot (_PAGE_PRESENT | _PAGE_RW ),
1749
1757
.mask_clr = __pgprot (0 ),
@@ -1762,6 +1770,7 @@ static int __set_pages_np(struct page *page, int numpages)
1762
1770
{
1763
1771
unsigned long tempaddr = (unsigned long ) page_address (page );
1764
1772
struct cpa_data cpa = { .vaddr = & tempaddr ,
1773
+ .pgd = NULL ,
1765
1774
.numpages = numpages ,
1766
1775
.mask_set = __pgprot (0 ),
1767
1776
.mask_clr = __pgprot (_PAGE_PRESENT | _PAGE_RW ),
@@ -1822,6 +1831,36 @@ bool kernel_page_present(struct page *page)
1822
1831
1823
1832
#endif /* CONFIG_DEBUG_PAGEALLOC */
1824
1833
1834
+ int kernel_map_pages_in_pgd (pgd_t * pgd , u64 pfn , unsigned long address ,
1835
+ unsigned numpages , unsigned long page_flags )
1836
+ {
1837
+ int retval = - EINVAL ;
1838
+
1839
+ struct cpa_data cpa = {
1840
+ .vaddr = & address ,
1841
+ .pfn = pfn ,
1842
+ .pgd = pgd ,
1843
+ .numpages = numpages ,
1844
+ .mask_set = __pgprot (0 ),
1845
+ .mask_clr = __pgprot (0 ),
1846
+ .flags = 0 ,
1847
+ };
1848
+
1849
+ if (!(__supported_pte_mask & _PAGE_NX ))
1850
+ goto out ;
1851
+
1852
+ if (!(page_flags & _PAGE_NX ))
1853
+ cpa .mask_clr = __pgprot (_PAGE_NX );
1854
+
1855
+ cpa .mask_set = __pgprot (_PAGE_PRESENT | page_flags );
1856
+
1857
+ retval = __change_page_attr_set_clr (& cpa , 0 );
1858
+ __flush_tlb_all ();
1859
+
1860
+ out :
1861
+ return retval ;
1862
+ }
1863
+
1825
1864
/*
1826
1865
* The testcases use internal knowledge of the implementation that shouldn't
1827
1866
* be exposed to the rest of the kernel. Include these directly here.
0 commit comments