aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/mem_encrypt.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/mm/mem_encrypt.c')
-rw-r--r--arch/x86/mm/mem_encrypt.c123
1 files changed, 107 insertions, 16 deletions
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 35f38caa1fa3..e74a1722d438 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -469,6 +469,7 @@ struct sme_populate_pgd_data {
469 pgd_t *pgd; 469 pgd_t *pgd;
470 470
471 pmdval_t pmd_flags; 471 pmdval_t pmd_flags;
472 pteval_t pte_flags;
472 unsigned long paddr; 473 unsigned long paddr;
473 474
474 unsigned long vaddr; 475 unsigned long vaddr;
@@ -493,6 +494,7 @@ static void __init sme_clear_pgd(struct sme_populate_pgd_data *ppd)
493#define PGD_FLAGS _KERNPG_TABLE_NOENC 494#define PGD_FLAGS _KERNPG_TABLE_NOENC
494#define P4D_FLAGS _KERNPG_TABLE_NOENC 495#define P4D_FLAGS _KERNPG_TABLE_NOENC
495#define PUD_FLAGS _KERNPG_TABLE_NOENC 496#define PUD_FLAGS _KERNPG_TABLE_NOENC
497#define PMD_FLAGS _KERNPG_TABLE_NOENC
496 498
497#define PMD_FLAGS_LARGE (__PAGE_KERNEL_LARGE_EXEC & ~_PAGE_GLOBAL) 499#define PMD_FLAGS_LARGE (__PAGE_KERNEL_LARGE_EXEC & ~_PAGE_GLOBAL)
498 500
@@ -502,7 +504,15 @@ static void __init sme_clear_pgd(struct sme_populate_pgd_data *ppd)
502 504
503#define PMD_FLAGS_ENC (PMD_FLAGS_LARGE | _PAGE_ENC) 505#define PMD_FLAGS_ENC (PMD_FLAGS_LARGE | _PAGE_ENC)
504 506
505static void __init sme_populate_pgd_large(struct sme_populate_pgd_data *ppd) 507#define PTE_FLAGS (__PAGE_KERNEL_EXEC & ~_PAGE_GLOBAL)
508
509#define PTE_FLAGS_DEC PTE_FLAGS
510#define PTE_FLAGS_DEC_WP ((PTE_FLAGS_DEC & ~_PAGE_CACHE_MASK) | \
511 (_PAGE_PAT | _PAGE_PWT))
512
513#define PTE_FLAGS_ENC (PTE_FLAGS | _PAGE_ENC)
514
515static pmd_t __init *sme_prepare_pgd(struct sme_populate_pgd_data *ppd)
506{ 516{
507 pgd_t *pgd_p; 517 pgd_t *pgd_p;
508 p4d_t *p4d_p; 518 p4d_t *p4d_p;
@@ -553,7 +563,7 @@ static void __init sme_populate_pgd_large(struct sme_populate_pgd_data *ppd)
553 pud_p += pud_index(ppd->vaddr); 563 pud_p += pud_index(ppd->vaddr);
554 if (native_pud_val(*pud_p)) { 564 if (native_pud_val(*pud_p)) {
555 if (native_pud_val(*pud_p) & _PAGE_PSE) 565 if (native_pud_val(*pud_p) & _PAGE_PSE)
556 return; 566 return NULL;
557 567
558 pmd_p = (pmd_t *)(native_pud_val(*pud_p) & ~PTE_FLAGS_MASK); 568 pmd_p = (pmd_t *)(native_pud_val(*pud_p) & ~PTE_FLAGS_MASK);
559 } else { 569 } else {
@@ -567,16 +577,55 @@ static void __init sme_populate_pgd_large(struct sme_populate_pgd_data *ppd)
567 native_set_pud(pud_p, pud); 577 native_set_pud(pud_p, pud);
568 } 578 }
569 579
580 return pmd_p;
581}
582
583static void __init sme_populate_pgd_large(struct sme_populate_pgd_data *ppd)
584{
585 pmd_t *pmd_p;
586
587 pmd_p = sme_prepare_pgd(ppd);
588 if (!pmd_p)
589 return;
590
570 pmd_p += pmd_index(ppd->vaddr); 591 pmd_p += pmd_index(ppd->vaddr);
571 if (!native_pmd_val(*pmd_p) || !(native_pmd_val(*pmd_p) & _PAGE_PSE)) 592 if (!native_pmd_val(*pmd_p) || !(native_pmd_val(*pmd_p) & _PAGE_PSE))
572 native_set_pmd(pmd_p, native_make_pmd(ppd->paddr | ppd->pmd_flags)); 593 native_set_pmd(pmd_p, native_make_pmd(ppd->paddr | ppd->pmd_flags));
573} 594}
574 595
575static void __init __sme_map_range(struct sme_populate_pgd_data *ppd, 596static void __init sme_populate_pgd(struct sme_populate_pgd_data *ppd)
576 pmdval_t pmd_flags)
577{ 597{
578 ppd->pmd_flags = pmd_flags; 598 pmd_t *pmd_p;
599 pte_t *pte_p;
600
601 pmd_p = sme_prepare_pgd(ppd);
602 if (!pmd_p)
603 return;
604
605 pmd_p += pmd_index(ppd->vaddr);
606 if (native_pmd_val(*pmd_p)) {
607 if (native_pmd_val(*pmd_p) & _PAGE_PSE)
608 return;
609
610 pte_p = (pte_t *)(native_pmd_val(*pmd_p) & ~PTE_FLAGS_MASK);
611 } else {
612 pmd_t pmd;
579 613
614 pte_p = ppd->pgtable_area;
615 memset(pte_p, 0, sizeof(*pte_p) * PTRS_PER_PTE);
616 ppd->pgtable_area += sizeof(*pte_p) * PTRS_PER_PTE;
617
618 pmd = native_make_pmd((pteval_t)pte_p + PMD_FLAGS);
619 native_set_pmd(pmd_p, pmd);
620 }
621
622 pte_p += pte_index(ppd->vaddr);
623 if (!native_pte_val(*pte_p))
624 native_set_pte(pte_p, native_make_pte(ppd->paddr | ppd->pte_flags));
625}
626
627static void __init __sme_map_range_pmd(struct sme_populate_pgd_data *ppd)
628{
580 while (ppd->vaddr < ppd->vaddr_end) { 629 while (ppd->vaddr < ppd->vaddr_end) {
581 sme_populate_pgd_large(ppd); 630 sme_populate_pgd_large(ppd);
582 631
@@ -585,33 +634,71 @@ static void __init __sme_map_range(struct sme_populate_pgd_data *ppd,
585 } 634 }
586} 635}
587 636
637static void __init __sme_map_range_pte(struct sme_populate_pgd_data *ppd)
638{
639 while (ppd->vaddr < ppd->vaddr_end) {
640 sme_populate_pgd(ppd);
641
642 ppd->vaddr += PAGE_SIZE;
643 ppd->paddr += PAGE_SIZE;
644 }
645}
646
647static void __init __sme_map_range(struct sme_populate_pgd_data *ppd,
648 pmdval_t pmd_flags, pteval_t pte_flags)
649{
650 unsigned long vaddr_end;
651
652 ppd->pmd_flags = pmd_flags;
653 ppd->pte_flags = pte_flags;
654
655 /* Save original end value since we modify the struct value */
656 vaddr_end = ppd->vaddr_end;
657
658 /* If start is not 2MB aligned, create PTE entries */
659 ppd->vaddr_end = ALIGN(ppd->vaddr, PMD_PAGE_SIZE);
660 __sme_map_range_pte(ppd);
661
662 /* Create PMD entries */
663 ppd->vaddr_end = vaddr_end & PMD_PAGE_MASK;
664 __sme_map_range_pmd(ppd);
665
666 /* If end is not 2MB aligned, create PTE entries */
667 ppd->vaddr_end = vaddr_end;
668 __sme_map_range_pte(ppd);
669}
670
588static void __init sme_map_range_encrypted(struct sme_populate_pgd_data *ppd) 671static void __init sme_map_range_encrypted(struct sme_populate_pgd_data *ppd)
589{ 672{
590 __sme_map_range(ppd, PMD_FLAGS_ENC); 673 __sme_map_range(ppd, PMD_FLAGS_ENC, PTE_FLAGS_ENC);
591} 674}
592 675
593static void __init sme_map_range_decrypted(struct sme_populate_pgd_data *ppd) 676static void __init sme_map_range_decrypted(struct sme_populate_pgd_data *ppd)
594{ 677{
595 __sme_map_range(ppd, PMD_FLAGS_DEC); 678 __sme_map_range(ppd, PMD_FLAGS_DEC, PTE_FLAGS_DEC);
596} 679}
597 680
598static void __init sme_map_range_decrypted_wp(struct sme_populate_pgd_data *ppd) 681static void __init sme_map_range_decrypted_wp(struct sme_populate_pgd_data *ppd)
599{ 682{
600 __sme_map_range(ppd, PMD_FLAGS_DEC_WP); 683 __sme_map_range(ppd, PMD_FLAGS_DEC_WP, PTE_FLAGS_DEC_WP);
601} 684}
602 685
603static unsigned long __init sme_pgtable_calc(unsigned long len) 686static unsigned long __init sme_pgtable_calc(unsigned long len)
604{ 687{
605 unsigned long p4d_size, pud_size, pmd_size; 688 unsigned long p4d_size, pud_size, pmd_size, pte_size;
606 unsigned long total; 689 unsigned long total;
607 690
608 /* 691 /*
609 * Perform a relatively simplistic calculation of the pagetable 692 * Perform a relatively simplistic calculation of the pagetable
610 * entries that are needed. That mappings will be covered by 2MB 693 * entries that are needed. Those mappings will be covered mostly
611 * PMD entries so we can conservatively calculate the required 694 * by 2MB PMD entries so we can conservatively calculate the required
612 * number of P4D, PUD and PMD structures needed to perform the 695 * number of P4D, PUD and PMD structures needed to perform the
613 * mappings. Incrementing the count for each covers the case where 696 * mappings. For mappings that are not 2MB aligned, PTE mappings
614 * the addresses cross entries. 697 * would be needed for the start and end portion of the address range
698 * that fall outside of the 2MB alignment. This results in, at most,
699 * two extra pages to hold PTE entries for each range that is mapped.
700 * Incrementing the count for each covers the case where the addresses
701 * cross entries.
615 */ 702 */
616 if (IS_ENABLED(CONFIG_X86_5LEVEL)) { 703 if (IS_ENABLED(CONFIG_X86_5LEVEL)) {
617 p4d_size = (ALIGN(len, PGDIR_SIZE) / PGDIR_SIZE) + 1; 704 p4d_size = (ALIGN(len, PGDIR_SIZE) / PGDIR_SIZE) + 1;
@@ -625,8 +712,9 @@ static unsigned long __init sme_pgtable_calc(unsigned long len)
625 } 712 }
626 pmd_size = (ALIGN(len, PUD_SIZE) / PUD_SIZE) + 1; 713 pmd_size = (ALIGN(len, PUD_SIZE) / PUD_SIZE) + 1;
627 pmd_size *= sizeof(pmd_t) * PTRS_PER_PMD; 714 pmd_size *= sizeof(pmd_t) * PTRS_PER_PMD;
715 pte_size = 2 * sizeof(pte_t) * PTRS_PER_PTE;
628 716
629 total = p4d_size + pud_size + pmd_size; 717 total = p4d_size + pud_size + pmd_size + pte_size;
630 718
631 /* 719 /*
632 * Now calculate the added pagetable structures needed to populate 720 * Now calculate the added pagetable structures needed to populate
@@ -709,10 +797,13 @@ void __init sme_encrypt_kernel(void)
709 797
710 /* 798 /*
711 * The total workarea includes the executable encryption area and 799 * The total workarea includes the executable encryption area and
712 * the pagetable area. 800 * the pagetable area. The start of the workarea is already 2MB
801 * aligned, align the end of the workarea on a 2MB boundary so that
802 * we don't try to create/allocate PTE entries from the workarea
803 * before it is mapped.
713 */ 804 */
714 workarea_len = execute_len + pgtable_area_len; 805 workarea_len = execute_len + pgtable_area_len;
715 workarea_end = workarea_start + workarea_len; 806 workarea_end = ALIGN(workarea_start + workarea_len, PMD_PAGE_SIZE);
716 807
717 /* 808 /*
718 * Set the address to the start of where newly created pagetable 809 * Set the address to the start of where newly created pagetable