AMD SEV-ES introduces a new #VC exception that handles the communication between guest and host. UEFI already implements a #VC handler so there is no need to re-implement it in KVM-Unit-Tests. To reuse this #VC handler, this commit reads UEFI's IDT, copy the #VC IDT entry into KVM-Unit-Tests' IDT. Reusing UEFI #VC handler is a temporary workaround, and the long-term solution is to implement a #VC handler in KVM-Unit-Tests so it does not depend on specific UEFI's #VC handler. However, we still believe that the current approach is good as an intermediate solution, because it unlocks a lot of testing and we do not expect that testing to be inherently tied to the UEFI's #VC handler. In this commit, load_idt() can work and now guest crashes in setup_page_table(), which will be fixed by follow-up commits. Signed-off-by: Zixuan Wang <zixuanwang@xxxxxxxxxx> --- lib/x86/amd_sev.c | 25 +++++++++++++++++++++++++ lib/x86/amd_sev.h | 7 +++++++ lib/x86/setup.c | 12 ++++++++++++ 3 files changed, 44 insertions(+) diff --git a/lib/x86/amd_sev.c b/lib/x86/amd_sev.c index c9fabc4..d1e43ae 100644 --- a/lib/x86/amd_sev.c +++ b/lib/x86/amd_sev.c @@ -91,6 +91,31 @@ bool amd_sev_es_enabled(void) return sev_es_enabled; } +efi_status_t setup_amd_sev_es(void) +{ + struct descriptor_table_ptr idtr; + idt_entry_t *idt; + + if (!amd_sev_es_enabled()) { + return EFI_UNSUPPORTED; + } + + /* + * Copy UEFI's #VC IDT entry, so KVM-Unit-Tests can reuse it and does + * not have to re-implement a #VC handler. + * + * TODO: Reusing UEFI #VC handler is a temporary workaround to simplify + * the boot up process, the long-term solution is to implement a #VC + * handler in KVM-Unit-Tests and load it, so that KVM-Unit-Tests does + * not depend on specific UEFI #VC handler implementation. + */ + sidt(&idtr); + idt = (idt_entry_t *)idtr.base; + boot_idt[SEV_ES_VC_HANDLER_VECTOR] = idt[SEV_ES_VC_HANDLER_VECTOR]; + + return EFI_SUCCESS; +} + static void copy_gdt_entry(gdt_entry_t *dst, gdt_entry_t *src, unsigned segment) { unsigned index; diff --git a/lib/x86/amd_sev.h b/lib/x86/amd_sev.h index 0b4ff8c..aaa4806 100644 --- a/lib/x86/amd_sev.h +++ b/lib/x86/amd_sev.h @@ -39,7 +39,14 @@ bool amd_sev_enabled(void); efi_status_t setup_amd_sev(void); +/* + * AMD Programmer's Manual Volume 2 + * - Section "#VC Exception" + */ +#define SEV_ES_VC_HANDLER_VECTOR 29 + bool amd_sev_es_enabled(void); +efi_status_t setup_amd_sev_es(void); void copy_uefi_segments(void); unsigned long long get_amd_sev_c_bit_mask(void); diff --git a/lib/x86/setup.c b/lib/x86/setup.c index c6eb3e9..9075a22 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -227,6 +227,18 @@ efi_status_t setup_efi_pre_boot(unsigned long *mapkey, efi_bootinfo_t *efi_booti } } + status = setup_amd_sev_es(); + if (status != EFI_SUCCESS) { + switch (status) { + case EFI_UNSUPPORTED: + /* Continue if AMD SEV-ES is not supported */ + break; + default: + printf("Set up AMD SEV-ES failed\n"); + return status; + } + } + return EFI_SUCCESS; } -- 2.33.0.259.gc128427fd7-goog