Skip to content

Commit

Permalink
Support early pvalidation in startup_64
Browse files Browse the repository at this point in the history
The previous SNP VM boot is slow majorly due to the expensive PSP
command LAUNCH_UPDATE per 4K page. With this patch, launch_update only
need to validate memory pages used before startup_64 and optinally
choose to launch_update other memory pages.

The early pvalidate assumes the E820 table does not cover
invalid memory pages and then will do on-demand validation and extend
the table.
  • Loading branch information
ziqiaozhou authored and wdcui committed Feb 14, 2022
1 parent f874f2f commit 1c18d85
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
8 changes: 8 additions & 0 deletions arch/x86/boot/compressed/head_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,14 @@ SYM_CODE_START(startup_64)
cld
cli

#ifdef CONFIG_AMD_MEM_ENCRYPT
/* pvalidate memory on demand if SNP is enabled. */
pushq %rsi
movq %rsi, %rdi
call pvalidate_for_startup_64
popq %rsi
#endif

/* Setup data segments. */
xorl %eax, %eax
movl %eax, %ds
Expand Down
60 changes: 60 additions & 0 deletions arch/x86/boot/compressed/sev-snp.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "misc.h"
#include "error.h"

#include <asm/e820/types.h>
#include <asm/msr-index.h>
#include <asm/sev-snp.h>
#include <asm/sev-es.h>
Expand Down Expand Up @@ -139,3 +140,62 @@ void sev_snp_register_ghcb(unsigned long paddr)
/* Restore the GHCB MSR value */
sev_es_wr_ghcb_msr(old);
}

static void extend_e820_on_demand(struct boot_e820_entry *e820_entry,
u64 needed_ram_end)
{
u64 end, paddr;
if (!e820_entry) {
return;
}
// Validated memory must be aligned by PAGE_SIZE
end = ALIGN(e820_entry->addr + e820_entry->size, PAGE_SIZE);
if (needed_ram_end > end && e820_entry->type == E820_TYPE_RAM) {
for (paddr = end; paddr < needed_ram_end; paddr += PAGE_SIZE) {
sev_snp_issue_pvalidate_page(paddr, true);
}
e820_entry->size = needed_ram_end - e820_entry->addr;
}
}

/*
* Explictly pvalidate needed pages for decompressing the kernel.
* The E820_TYPE_RAM entry includes only validated memory. The kernel
* expects that the RAM entry's addr is fixed while the entry size is to be
* extended to cover addresses to the start of next entry.
* The function increases the RAM entry size to cover all possilble memory
* addresses until init_size.
* For example, init_end = 0x4000000,
* [RAM: 0x0 - 0x0], M[RAM: 0x0 - 0xa0000]
* [RSVD: 0xa0000 - 0x10000] [RSVD: 0xa0000 - 0x10000]
* [ACPI: 0x10000 - 0x20000] ==> [ACPI: 0x10000 - 0x20000]
* [RSVD: 0x800000 - 0x900000] [RSVD: 0x800000 - 0x900000]
* [RAM: 0x1000000 - 0x2000000] M[RAM: 0x1000000 - 0x2001000]
* [RAM: 0x2001000 - 0x2007000] M[RAM: 0x2001000 - 0x4000000]
Other RAM memory after init_end is pvalidated by ms_hyperv_init_platform
*/
__visible void pvalidate_for_startup_64(struct boot_params *boot_params)
{
struct boot_e820_entry *e820_entry;
u64 init_end =
boot_params->hdr.pref_address + boot_params->hdr.init_size;
u64 needed_end;
u8 i, nr_entries = boot_params->e820_entries;
if (!sev_snp_enabled()) {
return;
}
for (i = 0; i < nr_entries; ++i) {
/* Pvalidate memory holes in e820 RAM entries. */
e820_entry = &boot_params->e820_table[i];
if (i < nr_entries - 1) {
needed_end = boot_params->e820_table[i + 1].addr;
if (needed_end < e820_entry->addr) {
error("e820 table is not sorted.");
}
} else {
needed_end = init_end;
}
extend_e820_on_demand(e820_entry, needed_end);
}
}

0 comments on commit 1c18d85

Please sign in to comment.