Skip to content

Commit d54d610

Browse files
ardbiesheuvelIngo Molnar
authored and
Ingo Molnar
committed
x86/boot/sev: Avoid shared GHCB page for early memory acceptance
Communicating with the hypervisor using the shared GHCB page requires clearing the C bit in the mapping of that page. When executing in the context of the EFI boot services, the page tables are owned by the firmware, and this manipulation is not possible. So switch to a different API for accepting memory in SEV-SNP guests, one which is actually supported at the point during boot where the EFI stub may need to accept memory, but the SEV-SNP init code has not executed yet. For simplicity, also switch the memory acceptance carried out by the decompressor when not booting via EFI - this only involves the allocation for the decompressed kernel, and is generally only called after kexec, as normal boot will jump straight into the kernel from the EFI stub. Fixes: 6c32117 ("x86/sev: Add SNP-specific unaccepted memory support") Tested-by: Tom Lendacky <[email protected]> Co-developed-by: Tom Lendacky <[email protected]> Signed-off-by: Tom Lendacky <[email protected]> Signed-off-by: Ard Biesheuvel <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Cc: <[email protected]> Cc: Dionna Amalie Glaze <[email protected]> Cc: Kevin Loughlin <[email protected]> Cc: Kirill A. Shutemov <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/[email protected] # discussion thread #1 Link: https://lore.kernel.org/r/[email protected] # discussion thread #2 Link: https://lore.kernel.org/r/[email protected] # final submission
1 parent 263e559 commit d54d610

File tree

3 files changed

+21
-53
lines changed

3 files changed

+21
-53
lines changed

arch/x86/boot/compressed/mem.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,14 @@ static bool early_is_tdx_guest(void)
3434

3535
void arch_accept_memory(phys_addr_t start, phys_addr_t end)
3636
{
37+
static bool sevsnp;
38+
3739
/* Platform-specific memory-acceptance call goes here */
3840
if (early_is_tdx_guest()) {
3941
if (!tdx_accept_memory(start, end))
4042
panic("TDX: Failed to accept memory\n");
41-
} else if (sev_snp_enabled()) {
43+
} else if (sevsnp || (sev_get_status() & MSR_AMD64_SEV_SNP_ENABLED)) {
44+
sevsnp = true;
4245
snp_accept_memory(start, end);
4346
} else {
4447
error("Cannot accept memory: unknown platform\n");

arch/x86/boot/compressed/sev.c

Lines changed: 15 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,7 @@ bool sev_snp_enabled(void)
164164

165165
static void __page_state_change(unsigned long paddr, enum psc_op op)
166166
{
167-
u64 val;
168-
169-
if (!sev_snp_enabled())
170-
return;
167+
u64 val, msr;
171168

172169
/*
173170
* If private -> shared then invalidate the page before requesting the
@@ -176,6 +173,9 @@ static void __page_state_change(unsigned long paddr, enum psc_op op)
176173
if (op == SNP_PAGE_STATE_SHARED)
177174
pvalidate_4k_page(paddr, paddr, false);
178175

176+
/* Save the current GHCB MSR value */
177+
msr = sev_es_rd_ghcb_msr();
178+
179179
/* Issue VMGEXIT to change the page state in RMP table. */
180180
sev_es_wr_ghcb_msr(GHCB_MSR_PSC_REQ_GFN(paddr >> PAGE_SHIFT, op));
181181
VMGEXIT();
@@ -185,6 +185,9 @@ static void __page_state_change(unsigned long paddr, enum psc_op op)
185185
if ((GHCB_RESP_CODE(val) != GHCB_MSR_PSC_RESP) || GHCB_MSR_PSC_RESP_VAL(val))
186186
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC);
187187

188+
/* Restore the GHCB MSR value */
189+
sev_es_wr_ghcb_msr(msr);
190+
188191
/*
189192
* Now that page state is changed in the RMP table, validate it so that it is
190193
* consistent with the RMP entry.
@@ -195,11 +198,17 @@ static void __page_state_change(unsigned long paddr, enum psc_op op)
195198

196199
void snp_set_page_private(unsigned long paddr)
197200
{
201+
if (!sev_snp_enabled())
202+
return;
203+
198204
__page_state_change(paddr, SNP_PAGE_STATE_PRIVATE);
199205
}
200206

201207
void snp_set_page_shared(unsigned long paddr)
202208
{
209+
if (!sev_snp_enabled())
210+
return;
211+
203212
__page_state_change(paddr, SNP_PAGE_STATE_SHARED);
204213
}
205214

@@ -223,56 +232,10 @@ static bool early_setup_ghcb(void)
223232
return true;
224233
}
225234

226-
static phys_addr_t __snp_accept_memory(struct snp_psc_desc *desc,
227-
phys_addr_t pa, phys_addr_t pa_end)
228-
{
229-
struct psc_hdr *hdr;
230-
struct psc_entry *e;
231-
unsigned int i;
232-
233-
hdr = &desc->hdr;
234-
memset(hdr, 0, sizeof(*hdr));
235-
236-
e = desc->entries;
237-
238-
i = 0;
239-
while (pa < pa_end && i < VMGEXIT_PSC_MAX_ENTRY) {
240-
hdr->end_entry = i;
241-
242-
e->gfn = pa >> PAGE_SHIFT;
243-
e->operation = SNP_PAGE_STATE_PRIVATE;
244-
if (IS_ALIGNED(pa, PMD_SIZE) && (pa_end - pa) >= PMD_SIZE) {
245-
e->pagesize = RMP_PG_SIZE_2M;
246-
pa += PMD_SIZE;
247-
} else {
248-
e->pagesize = RMP_PG_SIZE_4K;
249-
pa += PAGE_SIZE;
250-
}
251-
252-
e++;
253-
i++;
254-
}
255-
256-
if (vmgexit_psc(boot_ghcb, desc))
257-
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC);
258-
259-
pvalidate_pages(desc);
260-
261-
return pa;
262-
}
263-
264235
void snp_accept_memory(phys_addr_t start, phys_addr_t end)
265236
{
266-
struct snp_psc_desc desc = {};
267-
unsigned int i;
268-
phys_addr_t pa;
269-
270-
if (!boot_ghcb && !early_setup_ghcb())
271-
sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC);
272-
273-
pa = start;
274-
while (pa < end)
275-
pa = __snp_accept_memory(&desc, pa, end);
237+
for (phys_addr_t pa = start; pa < end; pa += PAGE_SIZE)
238+
__page_state_change(pa, SNP_PAGE_STATE_PRIVATE);
276239
}
277240

278241
void sev_es_shutdown_ghcb(void)

arch/x86/boot/compressed/sev.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212

1313
bool sev_snp_enabled(void);
1414
void snp_accept_memory(phys_addr_t start, phys_addr_t end);
15+
u64 sev_get_status(void);
1516

1617
#else
1718

1819
static inline bool sev_snp_enabled(void) { return false; }
1920
static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { }
21+
static inline u64 sev_get_status(void) { return 0; }
2022

2123
#endif
2224

0 commit comments

Comments
 (0)