From: Zixuan Wang <zixuanwang@xxxxxxxxxx> 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 | 30 ++++++++++++++++++++++++++++++ lib/x86/amd_sev.h | 7 +++++++ lib/x86/setup.c | 12 ++++++++++++ 3 files changed, 49 insertions(+) diff --git a/lib/x86/amd_sev.c b/lib/x86/amd_sev.c index 88cf283..50352df 100644 --- a/lib/x86/amd_sev.c +++ b/lib/x86/amd_sev.c @@ -87,6 +87,36 @@ 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; + idt_entry_t vc_handler_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. Also update the #VC IDT code + * segment to use KVM-Unit-Tests segments, KERNEL_CS, so that we do not + * have to copy the UEFI GDT entries into KVM-Unit-Tests GDT. + * + * 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; + vc_handler_idt = idt[SEV_ES_VC_HANDLER_VECTOR]; + vc_handler_idt.selector = KERNEL_CS; + boot_idt[SEV_ES_VC_HANDLER_VECTOR] = vc_handler_idt; + + return EFI_SUCCESS; +} + unsigned long long get_amd_sev_c_bit_mask(void) { if (amd_sev_enabled()) { diff --git a/lib/x86/amd_sev.h b/lib/x86/amd_sev.h index fb51fc2..0ea1fda 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); unsigned long long get_amd_sev_c_bit_mask(void); unsigned long long get_amd_sev_addr_upperbound(void); diff --git a/lib/x86/setup.c b/lib/x86/setup.c index ad7f725..529c3d0 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -263,6 +263,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