Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

x86/sev: Pass SVSM calling area down to early page state change API

The early page state change API is mostly only used very early, when only the
boot time SVSM calling area is in use. However, this API is also called by the
kexec finishing code, which runs very late, and potentially from a different
CPU (which uses a different calling area).

To avoid pulling the per-CPU SVSM calling area pointers and related SEV state
into the startup code, refactor the page state change API so the SVSM calling
area virtual and physical addresses can be provided by the caller.

No functional change intended.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/20250828102202.1849035-32-ardb+git@google.com

authored by

Ard Biesheuvel and committed by
Borislav Petkov (AMD)
00d25566 d5949ea5

+57 -21
+21 -3
arch/x86/boot/compressed/sev.c
··· 62 62 63 63 void snp_set_page_private(unsigned long paddr) 64 64 { 65 + struct psc_desc d = { 66 + SNP_PAGE_STATE_PRIVATE, 67 + (struct svsm_ca *)boot_svsm_caa_pa, 68 + boot_svsm_caa_pa 69 + }; 70 + 65 71 if (!sev_snp_enabled()) 66 72 return; 67 73 68 - __page_state_change(paddr, paddr, SNP_PAGE_STATE_PRIVATE); 74 + __page_state_change(paddr, paddr, &d); 69 75 } 70 76 71 77 void snp_set_page_shared(unsigned long paddr) 72 78 { 79 + struct psc_desc d = { 80 + SNP_PAGE_STATE_SHARED, 81 + (struct svsm_ca *)boot_svsm_caa_pa, 82 + boot_svsm_caa_pa 83 + }; 84 + 73 85 if (!sev_snp_enabled()) 74 86 return; 75 87 76 - __page_state_change(paddr, paddr, SNP_PAGE_STATE_SHARED); 88 + __page_state_change(paddr, paddr, &d); 77 89 } 78 90 79 91 bool early_setup_ghcb(void) ··· 110 98 111 99 void snp_accept_memory(phys_addr_t start, phys_addr_t end) 112 100 { 101 + struct psc_desc d = { 102 + SNP_PAGE_STATE_PRIVATE, 103 + (struct svsm_ca *)boot_svsm_caa_pa, 104 + boot_svsm_caa_pa 105 + }; 106 + 113 107 for (phys_addr_t pa = start; pa < end; pa += PAGE_SIZE) 114 - __page_state_change(pa, pa, SNP_PAGE_STATE_PRIVATE); 108 + __page_state_change(pa, pa, &d); 115 109 } 116 110 117 111 void sev_es_shutdown_ghcb(void)
+12 -11
arch/x86/boot/startup/sev-shared.c
··· 602 602 return ret; 603 603 } 604 604 605 - static void __head svsm_pval_4k_page(unsigned long paddr, bool validate) 605 + static void __head svsm_pval_4k_page(unsigned long paddr, bool validate, 606 + struct svsm_ca *caa, u64 caa_pa) 606 607 { 607 608 struct svsm_pvalidate_call *pc; 608 609 struct svsm_call call = {}; ··· 616 615 */ 617 616 flags = native_local_irq_save(); 618 617 619 - call.caa = svsm_get_caa(); 618 + call.caa = caa; 620 619 621 620 pc = (struct svsm_pvalidate_call *)call.caa->svsm_buffer; 622 - pc_pa = svsm_get_caa_pa() + offsetof(struct svsm_ca, svsm_buffer); 621 + pc_pa = caa_pa + offsetof(struct svsm_ca, svsm_buffer); 623 622 624 623 pc->num_entries = 1; 625 624 pc->cur_index = 0; ··· 645 644 } 646 645 647 646 static void __head pvalidate_4k_page(unsigned long vaddr, unsigned long paddr, 648 - bool validate) 647 + bool validate, struct svsm_ca *caa, u64 caa_pa) 649 648 { 650 649 int ret; 651 650 652 651 if (snp_vmpl) { 653 - svsm_pval_4k_page(paddr, validate); 652 + svsm_pval_4k_page(paddr, validate, caa, caa_pa); 654 653 } else { 655 654 ret = pvalidate(vaddr, RMP_PG_SIZE_4K, validate); 656 655 if (ret) ··· 666 665 } 667 666 668 667 static void __head __page_state_change(unsigned long vaddr, unsigned long paddr, 669 - enum psc_op op) 668 + const struct psc_desc *desc) 670 669 { 671 670 u64 val, msr; 672 671 ··· 674 673 * If private -> shared then invalidate the page before requesting the 675 674 * state change in the RMP table. 676 675 */ 677 - if (op == SNP_PAGE_STATE_SHARED) 678 - pvalidate_4k_page(vaddr, paddr, false); 676 + if (desc->op == SNP_PAGE_STATE_SHARED) 677 + pvalidate_4k_page(vaddr, paddr, false, desc->ca, desc->caa_pa); 679 678 680 679 /* Save the current GHCB MSR value */ 681 680 msr = sev_es_rd_ghcb_msr(); 682 681 683 682 /* Issue VMGEXIT to change the page state in RMP table. */ 684 - sev_es_wr_ghcb_msr(GHCB_MSR_PSC_REQ_GFN(paddr >> PAGE_SHIFT, op)); 683 + sev_es_wr_ghcb_msr(GHCB_MSR_PSC_REQ_GFN(paddr >> PAGE_SHIFT, desc->op)); 685 684 VMGEXIT(); 686 685 687 686 /* Read the response of the VMGEXIT. */ ··· 696 695 * Now that page state is changed in the RMP table, validate it so that it is 697 696 * consistent with the RMP entry. 698 697 */ 699 - if (op == SNP_PAGE_STATE_PRIVATE) 700 - pvalidate_4k_page(vaddr, paddr, true); 698 + if (desc->op == SNP_PAGE_STATE_PRIVATE) 699 + pvalidate_4k_page(vaddr, paddr, true, desc->ca, desc->caa_pa); 701 700 } 702 701 703 702 /*
+12 -4
arch/x86/boot/startup/sev-startup.c
··· 132 132 133 133 void __head 134 134 early_set_pages_state(unsigned long vaddr, unsigned long paddr, 135 - unsigned long npages, enum psc_op op) 135 + unsigned long npages, const struct psc_desc *desc) 136 136 { 137 137 unsigned long paddr_end; 138 138 ··· 142 142 paddr_end = paddr + (npages << PAGE_SHIFT); 143 143 144 144 while (paddr < paddr_end) { 145 - __page_state_change(vaddr, paddr, op); 145 + __page_state_change(vaddr, paddr, desc); 146 146 147 147 vaddr += PAGE_SIZE; 148 148 paddr += PAGE_SIZE; ··· 152 152 void __head early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr, 153 153 unsigned long npages) 154 154 { 155 + struct psc_desc d = { 156 + SNP_PAGE_STATE_PRIVATE, svsm_get_caa(), svsm_get_caa_pa() 157 + }; 158 + 155 159 /* 156 160 * This can be invoked in early boot while running identity mapped, so 157 161 * use an open coded check for SNP instead of using cc_platform_has(). ··· 169 165 * Ask the hypervisor to mark the memory pages as private in the RMP 170 166 * table. 171 167 */ 172 - early_set_pages_state(vaddr, paddr, npages, SNP_PAGE_STATE_PRIVATE); 168 + early_set_pages_state(vaddr, paddr, npages, &d); 173 169 } 174 170 175 171 void __head early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr, 176 172 unsigned long npages) 177 173 { 174 + struct psc_desc d = { 175 + SNP_PAGE_STATE_SHARED, svsm_get_caa(), svsm_get_caa_pa() 176 + }; 177 + 178 178 /* 179 179 * This can be invoked in early boot while running identity mapped, so 180 180 * use an open coded check for SNP instead of using cc_platform_has(). ··· 189 181 return; 190 182 191 183 /* Ask hypervisor to mark the memory pages shared in the RMP table. */ 192 - early_set_pages_state(vaddr, paddr, npages, SNP_PAGE_STATE_SHARED); 184 + early_set_pages_state(vaddr, paddr, npages, &d); 193 185 } 194 186 195 187 /*
+5 -2
arch/x86/coco/sev/core.c
··· 607 607 unsigned long vaddr_end; 608 608 609 609 /* Use the MSR protocol when a GHCB is not available. */ 610 - if (!boot_ghcb) 611 - return early_set_pages_state(vaddr, __pa(vaddr), npages, op); 610 + if (!boot_ghcb) { 611 + struct psc_desc d = { op, svsm_get_caa(), svsm_get_caa_pa() }; 612 + 613 + return early_set_pages_state(vaddr, __pa(vaddr), npages, &d); 614 + } 612 615 613 616 vaddr = vaddr & PAGE_MASK; 614 617 vaddr_end = vaddr + (npages << PAGE_SHIFT);
+1 -1
arch/x86/include/asm/sev-internal.h
··· 55 55 DECLARE_PER_CPU(struct sev_es_save_area *, sev_vmsa); 56 56 57 57 void early_set_pages_state(unsigned long vaddr, unsigned long paddr, 58 - unsigned long npages, enum psc_op op); 58 + unsigned long npages, const struct psc_desc *desc); 59 59 60 60 DECLARE_PER_CPU(struct svsm_ca *, svsm_caa); 61 61 DECLARE_PER_CPU(u64, svsm_caa_pa);
+6
arch/x86/include/asm/sev.h
··· 570 570 extern struct ghcb *boot_ghcb; 571 571 extern bool sev_snp_needs_sfw; 572 572 573 + struct psc_desc { 574 + enum psc_op op; 575 + struct svsm_ca *ca; 576 + u64 caa_pa; 577 + }; 578 + 573 579 #else /* !CONFIG_AMD_MEM_ENCRYPT */ 574 580 575 581 #define snp_vmpl 0