@@ -421,18 +421,18 @@ pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
421
421
*/
422
422
pte_t * lookup_address (unsigned long address , unsigned int * level )
423
423
{
424
- return lookup_address_in_pgd (pgd_offset_k (address ), address , level );
424
+ return lookup_address_in_pgd (pgd_offset_k (address ), address , level );
425
425
}
426
426
EXPORT_SYMBOL_GPL (lookup_address );
427
427
428
428
static pte_t * _lookup_address_cpa (struct cpa_data * cpa , unsigned long address ,
429
429
unsigned int * level )
430
430
{
431
- if (cpa -> pgd )
431
+ if (cpa -> pgd )
432
432
return lookup_address_in_pgd (cpa -> pgd + pgd_index (address ),
433
433
address , level );
434
434
435
- return lookup_address (address , level );
435
+ return lookup_address (address , level );
436
436
}
437
437
438
438
/*
@@ -549,27 +549,22 @@ static pgprot_t pgprot_clear_protnone_bits(pgprot_t prot)
549
549
return prot ;
550
550
}
551
551
552
- static int
553
- try_preserve_large_page (pte_t * kpte , unsigned long address ,
554
- struct cpa_data * cpa )
552
+ static int __should_split_large_page (pte_t * kpte , unsigned long address ,
553
+ struct cpa_data * cpa )
555
554
{
556
- unsigned long nextpage_addr , numpages , pmask , psize , addr , pfn , old_pfn ;
557
- pte_t new_pte , old_pte , * tmp ;
555
+ unsigned long numpages , pmask , psize , lpaddr , addr , pfn , old_pfn ;
558
556
pgprot_t old_prot , new_prot , req_prot ;
559
- int i , do_split = 1 ;
557
+ pte_t new_pte , old_pte , * tmp ;
560
558
enum pg_level level ;
559
+ int i ;
561
560
562
- if (cpa -> force_split )
563
- return 1 ;
564
-
565
- spin_lock (& pgd_lock );
566
561
/*
567
562
* Check for races, another CPU might have split this page
568
563
* up already:
569
564
*/
570
565
tmp = _lookup_address_cpa (cpa , address , & level );
571
566
if (tmp != kpte )
572
- goto out_unlock ;
567
+ return 1 ;
573
568
574
569
switch (level ) {
575
570
case PG_LEVEL_2M :
@@ -581,8 +576,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
581
576
old_pfn = pud_pfn (* (pud_t * )kpte );
582
577
break ;
583
578
default :
584
- do_split = - EINVAL ;
585
- goto out_unlock ;
579
+ return - EINVAL ;
586
580
}
587
581
588
582
psize = page_level_size (level );
@@ -592,8 +586,8 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
592
586
* Calculate the number of pages, which fit into this large
593
587
* page starting at address:
594
588
*/
595
- nextpage_addr = (address + psize ) & pmask ;
596
- numpages = (nextpage_addr - address ) >> PAGE_SHIFT ;
589
+ lpaddr = (address + psize ) & pmask ;
590
+ numpages = (lpaddr - address ) >> PAGE_SHIFT ;
597
591
if (numpages < cpa -> numpages )
598
592
cpa -> numpages = numpages ;
599
593
@@ -620,57 +614,62 @@ try_preserve_large_page(pte_t *kpte, unsigned long address,
620
614
pgprot_val (req_prot ) |= _PAGE_PSE ;
621
615
622
616
/*
623
- * old_pfn points to the large page base pfn. So we need
624
- * to add the offset of the virtual address:
617
+ * old_pfn points to the large page base pfn. So we need to add the
618
+ * offset of the virtual address:
625
619
*/
626
620
pfn = old_pfn + ((address & (psize - 1 )) >> PAGE_SHIFT );
627
621
cpa -> pfn = pfn ;
628
622
629
- new_prot = static_protections (req_prot , address , pfn );
623
+ /*
624
+ * Calculate the large page base address and the number of 4K pages
625
+ * in the large page
626
+ */
627
+ lpaddr = address & pmask ;
628
+ numpages = psize >> PAGE_SHIFT ;
630
629
631
630
/*
632
- * We need to check the full range, whether
633
- * static_protection() requires a different pgprot for one of
634
- * the pages in the range we try to preserve:
631
+ * Make sure that the requested pgprot does not violate the static
632
+ * protections. Check the full large page whether one of the pages
633
+ * in it results in a different pgprot than the first one of the
634
+ * requested range. If yes, then the page needs to be split.
635
635
*/
636
- addr = address & pmask ;
636
+ new_prot = static_protections ( req_prot , address , pfn ) ;
637
637
pfn = old_pfn ;
638
- for (i = 0 ; i < ( psize >> PAGE_SHIFT ) ; i ++ , addr += PAGE_SIZE , pfn ++ ) {
638
+ for (i = 0 , addr = lpaddr ; i < numpages ; i ++ , addr += PAGE_SIZE , pfn ++ ) {
639
639
pgprot_t chk_prot = static_protections (req_prot , addr , pfn );
640
640
641
641
if (pgprot_val (chk_prot ) != pgprot_val (new_prot ))
642
- goto out_unlock ;
642
+ return 1 ;
643
643
}
644
644
645
- /*
646
- * If there are no changes, return. maxpages has been updated
647
- * above:
648
- */
649
- if (pgprot_val (new_prot ) == pgprot_val (old_prot )) {
650
- do_split = 0 ;
651
- goto out_unlock ;
652
- }
645
+ /* If there are no changes, return. */
646
+ if (pgprot_val (new_prot ) == pgprot_val (old_prot ))
647
+ return 0 ;
653
648
654
649
/*
655
- * We need to change the attributes. Check, whether we can
656
- * change the large page in one go. We request a split, when
657
- * the address is not aligned and the number of pages is
658
- * smaller than the number of pages in the large page. Note
659
- * that we limited the number of possible pages already to
660
- * the number of pages in the large page.
650
+ * Verify that the address is aligned and the number of pages
651
+ * covers the full page.
661
652
*/
662
- if (address == (address & pmask ) && cpa -> numpages == (psize >> PAGE_SHIFT )) {
663
- /*
664
- * The address is aligned and the number of pages
665
- * covers the full page.
666
- */
667
- new_pte = pfn_pte (old_pfn , new_prot );
668
- __set_pmd_pte (kpte , address , new_pte );
669
- cpa -> flags |= CPA_FLUSHTLB ;
670
- do_split = 0 ;
671
- }
653
+ if (address != lpaddr || cpa -> numpages != numpages )
654
+ return 1 ;
655
+
656
+ /* All checks passed. Update the large page mapping. */
657
+ new_pte = pfn_pte (old_pfn , new_prot );
658
+ __set_pmd_pte (kpte , address , new_pte );
659
+ cpa -> flags |= CPA_FLUSHTLB ;
660
+ return 0 ;
661
+ }
662
+
663
+ static int should_split_large_page (pte_t * kpte , unsigned long address ,
664
+ struct cpa_data * cpa )
665
+ {
666
+ int do_split ;
667
+
668
+ if (cpa -> force_split )
669
+ return 1 ;
672
670
673
- out_unlock :
671
+ spin_lock (& pgd_lock );
672
+ do_split = __should_split_large_page (kpte , address , cpa );
674
673
spin_unlock (& pgd_lock );
675
674
676
675
return do_split ;
@@ -1273,7 +1272,7 @@ static int __change_page_attr(struct cpa_data *cpa, int primary)
1273
1272
* Check, whether we can keep the large page intact
1274
1273
* and just change the pte:
1275
1274
*/
1276
- do_split = try_preserve_large_page (kpte , address , cpa );
1275
+ do_split = should_split_large_page (kpte , address , cpa );
1277
1276
/*
1278
1277
* When the range fits into the existing large page,
1279
1278
* return. cp->numpages and cpa->tlbflush have been updated in
@@ -1288,23 +1287,23 @@ static int __change_page_attr(struct cpa_data *cpa, int primary)
1288
1287
err = split_large_page (cpa , kpte , address );
1289
1288
if (!err ) {
1290
1289
/*
1291
- * Do a global flush tlb after splitting the large page
1292
- * and before we do the actual change page attribute in the PTE.
1293
- *
1294
- * With out this, we violate the TLB application note, that says
1295
- * "The TLBs may contain both ordinary and large-page
1290
+ * Do a global flush tlb after splitting the large page
1291
+ * and before we do the actual change page attribute in the PTE.
1292
+ *
1293
+ * With out this, we violate the TLB application note, that says
1294
+ * "The TLBs may contain both ordinary and large-page
1296
1295
* translations for a 4-KByte range of linear addresses. This
1297
1296
* may occur if software modifies the paging structures so that
1298
1297
* the page size used for the address range changes. If the two
1299
1298
* translations differ with respect to page frame or attributes
1300
1299
* (e.g., permissions), processor behavior is undefined and may
1301
1300
* be implementation-specific."
1302
- *
1303
- * We do this global tlb flush inside the cpa_lock, so that we
1301
+ *
1302
+ * We do this global tlb flush inside the cpa_lock, so that we
1304
1303
* don't allow any other cpu, with stale tlb entries change the
1305
1304
* page attribute in parallel, that also falls into the
1306
1305
* just split large page entry.
1307
- */
1306
+ */
1308
1307
flush_tlb_all ();
1309
1308
goto repeat ;
1310
1309
}
0 commit comments