From patchwork Fri Aug 27 03:12:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12461125 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C9141C4320E for ; Fri, 27 Aug 2021 03:12:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A976560F6C for ; Fri, 27 Aug 2021 03:12:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244101AbhH0DNY (ORCPT ); Thu, 26 Aug 2021 23:13:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36128 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232208AbhH0DNU (ORCPT ); Thu, 26 Aug 2021 23:13:20 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5714FC061757 for ; Thu, 26 Aug 2021 20:12:27 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id s8-20020a17090a0748b0290177ecd83711so1106035pje.2 for ; Thu, 26 Aug 2021 20:12:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=aLzm4dekRioPMrmtNvuPvPmAgcYSaNAkSnHk+thr8ec=; b=Nb7tY1L9i6gX7oM8oYxTga0eBp3KnktIgRe8+csaFQvtoEM373pubeQxRMLv7FRtaq hn6dGbz2YPH21+JF9BCkH/PtyuoHkT/62lr0uqaxV1NvmNnGqK4znJQoQ9TqBarh3S6/ bYwJbgDAKmiC+ko6tt7OsXqf8X+jblv0Uzn4+6mOHUZwLVtSUIt0PFg6Ks6ivyCm0Rb+ 3PDkeTjHIbwpWpZtmG5QMnfV3OK38i0QjeKCUZoMfFptUVP61Fs7gFn/K90eNpxQoL4R b+4+0BwBSjD7f8Qcy5cHgFRB4keEyvGzgt9ErW01MiebH7EWz3Pw2mfi6iw+3f2UzyeS fbfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=aLzm4dekRioPMrmtNvuPvPmAgcYSaNAkSnHk+thr8ec=; b=KAxtRf1hzx5D3T9kgYL+wNPFU898+ntoldXHpXgs2j7pEIAm8fN1ITkCHmQcks3fX3 XhbfW9ac23OHP/W0mquuT+d6kJ/n/MPLVb7/VwKY9w9+0zZDjd7Tr1qNn9Px1gNd6Uht orHm5EosoukVL7aCsp88xgTnlpmdxtUl2WOMBtJOQ1AMRtihGN/QWnU+JkSK8EKvdo9k HMGF4lSEHzyU8LFSwEjdjAwtxWl9LfEjIlRJzJ0BJSbDuTt42sqnq+2r6PpkocohuoOw dyIgkyqHe3WqZligkGuqxlBROsuR/pdDMgSUuHgKGxKdDwlYO35w4tiGlFJuaixuOaXW GDXA== X-Gm-Message-State: AOAM53288zPkdzhfFYPsbNuUuyJFGy1h9ZtMxRLg2BoKP2KvqFnutTNN 4iuPPg+Yrd07zNP/KhkVkFLXfpBUqiuDR2xZmCrehCuS2UbD1Yr8L8ow4fBlfZ9Ogr8mPG5UxQu c5rOYjYdlYdhvBwQOD35KxVMz3x3AJHMynTOIDfjh+QgWcjcHmSMkWlP540c3Wkv+8fIS X-Google-Smtp-Source: ABdhPJxS+gN8lAUXJaNzos4wQ4FIzx13by5vzeqKBbl+d3+jDsKvDiiotC82i7exiyvWF5hhFsATtRNoxE89/NSj X-Received: from zxwang42.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2936]) (user=zixuanwang job=sendgmr) by 2002:a17:90b:ed7:: with SMTP id gz23mr297578pjb.1.1630033946324; Thu, 26 Aug 2021 20:12:26 -0700 (PDT) Date: Fri, 27 Aug 2021 03:12:06 +0000 In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com> Message-Id: <20210827031222.2778522-2-zixuanwang@google.com> Mime-Version: 1.0 References: <20210827031222.2778522-1-zixuanwang@google.com> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog Subject: [kvm-unit-tests PATCH v2 01/17] x86 UEFI: Copy code from Linux From: Zixuan Wang To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com, erdemaktas@google.com, rientjes@google.com, seanjc@google.com, brijesh.singh@amd.com, Thomas.Lendacky@amd.com, varad.gautam@suse.com, jroedel@suse.de, bp@suse.de Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Varad Gautam Copy UEFI-related definitions from Linux, so the follow-up commits can develop UEFI function calls based on these definitions, without relying on GNU-EFI library. Signed-off-by: Varad Gautam --- lib/linux/uefi.h | 518 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 518 insertions(+) create mode 100644 lib/linux/uefi.h diff --git a/lib/linux/uefi.h b/lib/linux/uefi.h new file mode 100644 index 0000000..567cddc --- /dev/null +++ b/lib/linux/uefi.h @@ -0,0 +1,518 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Relevant definitions from linux/efi.h. */ + +#ifndef __LINUX_UEFI_H +#define __LINUX_UEFI_H + +#define BITS_PER_LONG 64 + +#define EFI_SUCCESS 0 +#define EFI_LOAD_ERROR ( 1 | (1UL << (BITS_PER_LONG-1))) +#define EFI_INVALID_PARAMETER ( 2 | (1UL << (BITS_PER_LONG-1))) +#define EFI_UNSUPPORTED ( 3 | (1UL << (BITS_PER_LONG-1))) +#define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << (BITS_PER_LONG-1))) +#define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << (BITS_PER_LONG-1))) +#define EFI_NOT_READY ( 6 | (1UL << (BITS_PER_LONG-1))) +#define EFI_DEVICE_ERROR ( 7 | (1UL << (BITS_PER_LONG-1))) +#define EFI_WRITE_PROTECTED ( 8 | (1UL << (BITS_PER_LONG-1))) +#define EFI_OUT_OF_RESOURCES ( 9 | (1UL << (BITS_PER_LONG-1))) +#define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1))) +#define EFI_TIMEOUT (18 | (1UL << (BITS_PER_LONG-1))) +#define EFI_ABORTED (21 | (1UL << (BITS_PER_LONG-1))) +#define EFI_SECURITY_VIOLATION (26 | (1UL << (BITS_PER_LONG-1))) + +typedef unsigned long efi_status_t; +typedef u8 efi_bool_t; +typedef u16 efi_char16_t; /* UNICODE character */ +typedef u64 efi_physical_addr_t; +typedef void *efi_handle_t; + +#define __efiapi __attribute__((ms_abi)) + +/* + * The UEFI spec and EDK2 reference implementation both define EFI_GUID as + * struct { u32 a; u16; b; u16 c; u8 d[8]; }; and so the implied alignment + * is 32 bits not 8 bits like our guid_t. In some cases (i.e., on 32-bit ARM), + * this means that firmware services invoked by the kernel may assume that + * efi_guid_t* arguments are 32-bit aligned, and use memory accessors that + * do not tolerate misalignment. So let's set the minimum alignment to 32 bits. + * + * Note that the UEFI spec as well as some comments in the EDK2 code base + * suggest that EFI_GUID should be 64-bit aligned, but this appears to be + * a mistake, given that no code seems to exist that actually enforces that + * or relies on it. + */ +typedef struct { + u8 b[16]; +} guid_t; +typedef guid_t efi_guid_t; + +#define EFI_GUID(a, b, c, d...) (efi_guid_t){ { \ + (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \ + (b) & 0xff, ((b) >> 8) & 0xff, \ + (c) & 0xff, ((c) >> 8) & 0xff, d } } + +/* + * Generic EFI table header + */ +typedef struct { + u64 signature; + u32 revision; + u32 headersize; + u32 crc32; + u32 reserved; +} efi_table_hdr_t; + +/* + * Memory map descriptor: + */ + +/* Memory types: */ +#define EFI_RESERVED_TYPE 0 +#define EFI_LOADER_CODE 1 +#define EFI_LOADER_DATA 2 +#define EFI_BOOT_SERVICES_CODE 3 +#define EFI_BOOT_SERVICES_DATA 4 +#define EFI_RUNTIME_SERVICES_CODE 5 +#define EFI_RUNTIME_SERVICES_DATA 6 +#define EFI_CONVENTIONAL_MEMORY 7 +#define EFI_UNUSABLE_MEMORY 8 +#define EFI_ACPI_RECLAIM_MEMORY 9 +#define EFI_ACPI_MEMORY_NVS 10 +#define EFI_MEMORY_MAPPED_IO 11 +#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12 +#define EFI_PAL_CODE 13 +#define EFI_PERSISTENT_MEMORY 14 +#define EFI_MAX_MEMORY_TYPE 15 + +/* Attribute values: */ +#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */ +#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */ +#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */ +#define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */ +#define EFI_MEMORY_UCE ((u64)0x0000000000000010ULL) /* uncached, exported */ +#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */ +#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */ +#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */ +#define EFI_MEMORY_NV ((u64)0x0000000000008000ULL) /* non-volatile */ +#define EFI_MEMORY_MORE_RELIABLE \ + ((u64)0x0000000000010000ULL) /* higher reliability */ +#define EFI_MEMORY_RO ((u64)0x0000000000020000ULL) /* read-only */ +#define EFI_MEMORY_SP ((u64)0x0000000000040000ULL) /* soft reserved */ +#define EFI_MEMORY_CPU_CRYPTO ((u64)0x0000000000080000ULL) /* supports encryption */ +#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */ +#define EFI_MEMORY_DESCRIPTOR_VERSION 1 + +#define EFI_PAGE_SHIFT 12 +#define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) +#define EFI_PAGES_MAX (U64_MAX >> EFI_PAGE_SHIFT) + +typedef struct { + u32 type; + u32 pad; + u64 phys_addr; + u64 virt_addr; + u64 num_pages; + u64 attribute; +} efi_memory_desc_t; + +typedef struct { + efi_guid_t guid; + u32 headersize; + u32 flags; + u32 imagesize; +} efi_capsule_header_t; + +/* + * EFI capsule flags + */ +#define EFI_CAPSULE_PERSIST_ACROSS_RESET 0x00010000 +#define EFI_CAPSULE_POPULATE_SYSTEM_TABLE 0x00020000 +#define EFI_CAPSULE_INITIATE_RESET 0x00040000 + +struct capsule_info { + efi_capsule_header_t header; + efi_capsule_header_t *capsule; + int reset_type; + long index; + size_t count; + size_t total_size; + struct page **pages; + phys_addr_t *phys; + size_t page_bytes_remain; +}; + +int __efi_capsule_setup_info(struct capsule_info *cap_info); + +/* + * Types and defines for Time Services + */ +#define EFI_TIME_ADJUST_DAYLIGHT 0x1 +#define EFI_TIME_IN_DAYLIGHT 0x2 +#define EFI_UNSPECIFIED_TIMEZONE 0x07ff + +typedef struct { + u16 year; + u8 month; + u8 day; + u8 hour; + u8 minute; + u8 second; + u8 pad1; + u32 nanosecond; + s16 timezone; + u8 daylight; + u8 pad2; +} efi_time_t; + +typedef struct { + u32 resolution; + u32 accuracy; + u8 sets_to_zero; +} efi_time_cap_t; + +typedef void *efi_event_t; +/* Note that notifications won't work in mixed mode */ +typedef void (__efiapi *efi_event_notify_t)(efi_event_t, void *); + +typedef enum { + EfiTimerCancel, + EfiTimerPeriodic, + EfiTimerRelative +} EFI_TIMER_DELAY; + +/* + * EFI Device Path information + */ +#define EFI_DEV_HW 0x01 +#define EFI_DEV_PCI 1 +#define EFI_DEV_PCCARD 2 +#define EFI_DEV_MEM_MAPPED 3 +#define EFI_DEV_VENDOR 4 +#define EFI_DEV_CONTROLLER 5 +#define EFI_DEV_ACPI 0x02 +#define EFI_DEV_BASIC_ACPI 1 +#define EFI_DEV_EXPANDED_ACPI 2 +#define EFI_DEV_MSG 0x03 +#define EFI_DEV_MSG_ATAPI 1 +#define EFI_DEV_MSG_SCSI 2 +#define EFI_DEV_MSG_FC 3 +#define EFI_DEV_MSG_1394 4 +#define EFI_DEV_MSG_USB 5 +#define EFI_DEV_MSG_USB_CLASS 15 +#define EFI_DEV_MSG_I20 6 +#define EFI_DEV_MSG_MAC 11 +#define EFI_DEV_MSG_IPV4 12 +#define EFI_DEV_MSG_IPV6 13 +#define EFI_DEV_MSG_INFINIBAND 9 +#define EFI_DEV_MSG_UART 14 +#define EFI_DEV_MSG_VENDOR 10 +#define EFI_DEV_MEDIA 0x04 +#define EFI_DEV_MEDIA_HARD_DRIVE 1 +#define EFI_DEV_MEDIA_CDROM 2 +#define EFI_DEV_MEDIA_VENDOR 3 +#define EFI_DEV_MEDIA_FILE 4 +#define EFI_DEV_MEDIA_PROTOCOL 5 +#define EFI_DEV_BIOS_BOOT 0x05 +#define EFI_DEV_END_PATH 0x7F +#define EFI_DEV_END_PATH2 0xFF +#define EFI_DEV_END_INSTANCE 0x01 +#define EFI_DEV_END_ENTIRE 0xFF + +struct efi_generic_dev_path { + u8 type; + u8 sub_type; + u16 length; +} __packed; + +typedef struct efi_generic_dev_path efi_device_path_protocol_t; + +/* + * EFI Boot Services table + */ +union efi_boot_services { + struct { + efi_table_hdr_t hdr; + void *raise_tpl; + void *restore_tpl; + efi_status_t (__efiapi *allocate_pages)(int, int, unsigned long, + efi_physical_addr_t *); + efi_status_t (__efiapi *free_pages)(efi_physical_addr_t, + unsigned long); + efi_status_t (__efiapi *get_memory_map)(unsigned long *, void *, + unsigned long *, + unsigned long *, u32 *); + efi_status_t (__efiapi *allocate_pool)(int, unsigned long, + void **); + efi_status_t (__efiapi *free_pool)(void *); + efi_status_t (__efiapi *create_event)(u32, unsigned long, + efi_event_notify_t, void *, + efi_event_t *); + efi_status_t (__efiapi *set_timer)(efi_event_t, + EFI_TIMER_DELAY, u64); + efi_status_t (__efiapi *wait_for_event)(unsigned long, + efi_event_t *, + unsigned long *); + void *signal_event; + efi_status_t (__efiapi *close_event)(efi_event_t); + void *check_event; + void *install_protocol_interface; + void *reinstall_protocol_interface; + void *uninstall_protocol_interface; + efi_status_t (__efiapi *handle_protocol)(efi_handle_t, + efi_guid_t *, void **); + void *__reserved; + void *register_protocol_notify; + efi_status_t (__efiapi *locate_handle)(int, efi_guid_t *, + void *, unsigned long *, + efi_handle_t *); + efi_status_t (__efiapi *locate_device_path)(efi_guid_t *, + efi_device_path_protocol_t **, + efi_handle_t *); + efi_status_t (__efiapi *install_configuration_table)(efi_guid_t *, + void *); + void *load_image; + void *start_image; + efi_status_t (__efiapi *exit)(efi_handle_t, + efi_status_t, + unsigned long, + efi_char16_t *); + void *unload_image; + efi_status_t (__efiapi *exit_boot_services)(efi_handle_t, + unsigned long); + void *get_next_monotonic_count; + efi_status_t (__efiapi *stall)(unsigned long); + void *set_watchdog_timer; + void *connect_controller; + efi_status_t (__efiapi *disconnect_controller)(efi_handle_t, + efi_handle_t, + efi_handle_t); + void *open_protocol; + void *close_protocol; + void *open_protocol_information; + void *protocols_per_handle; + void *locate_handle_buffer; + efi_status_t (__efiapi *locate_protocol)(efi_guid_t *, void *, + void **); + void *install_multiple_protocol_interfaces; + void *uninstall_multiple_protocol_interfaces; + void *calculate_crc32; + void *copy_mem; + void *set_mem; + void *create_event_ex; + }; + struct { + efi_table_hdr_t hdr; + u32 raise_tpl; + u32 restore_tpl; + u32 allocate_pages; + u32 free_pages; + u32 get_memory_map; + u32 allocate_pool; + u32 free_pool; + u32 create_event; + u32 set_timer; + u32 wait_for_event; + u32 signal_event; + u32 close_event; + u32 check_event; + u32 install_protocol_interface; + u32 reinstall_protocol_interface; + u32 uninstall_protocol_interface; + u32 handle_protocol; + u32 __reserved; + u32 register_protocol_notify; + u32 locate_handle; + u32 locate_device_path; + u32 install_configuration_table; + u32 load_image; + u32 start_image; + u32 exit; + u32 unload_image; + u32 exit_boot_services; + u32 get_next_monotonic_count; + u32 stall; + u32 set_watchdog_timer; + u32 connect_controller; + u32 disconnect_controller; + u32 open_protocol; + u32 close_protocol; + u32 open_protocol_information; + u32 protocols_per_handle; + u32 locate_handle_buffer; + u32 locate_protocol; + u32 install_multiple_protocol_interfaces; + u32 uninstall_multiple_protocol_interfaces; + u32 calculate_crc32; + u32 copy_mem; + u32 set_mem; + u32 create_event_ex; + } mixed_mode; +}; + +typedef union efi_boot_services efi_boot_services_t; + +/* + * Types and defines for EFI ResetSystem + */ +#define EFI_RESET_COLD 0 +#define EFI_RESET_WARM 1 +#define EFI_RESET_SHUTDOWN 2 + +/* + * EFI Runtime Services table + */ +#define EFI_RUNTIME_SERVICES_SIGNATURE ((u64)0x5652453544e5552ULL) +#define EFI_RUNTIME_SERVICES_REVISION 0x00010000 + +typedef struct { + efi_table_hdr_t hdr; + u32 get_time; + u32 set_time; + u32 get_wakeup_time; + u32 set_wakeup_time; + u32 set_virtual_address_map; + u32 convert_pointer; + u32 get_variable; + u32 get_next_variable; + u32 set_variable; + u32 get_next_high_mono_count; + u32 reset_system; + u32 update_capsule; + u32 query_capsule_caps; + u32 query_variable_info; +} efi_runtime_services_32_t; + +typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc); +typedef efi_status_t efi_set_time_t (efi_time_t *tm); +typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t *pending, + efi_time_t *tm); +typedef efi_status_t efi_set_wakeup_time_t (efi_bool_t enabled, efi_time_t *tm); +typedef efi_status_t efi_get_variable_t (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, + unsigned long *data_size, void *data); +typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char16_t *name, + efi_guid_t *vendor); +typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor, + u32 attr, unsigned long data_size, + void *data); +typedef efi_status_t efi_get_next_high_mono_count_t (u32 *count); +typedef void efi_reset_system_t (int reset_type, efi_status_t status, + unsigned long data_size, efi_char16_t *data); +typedef efi_status_t efi_set_virtual_address_map_t (unsigned long memory_map_size, + unsigned long descriptor_size, + u32 descriptor_version, + efi_memory_desc_t *virtual_map); +typedef efi_status_t efi_query_variable_info_t(u32 attr, + u64 *storage_space, + u64 *remaining_space, + u64 *max_variable_size); +typedef efi_status_t efi_update_capsule_t(efi_capsule_header_t **capsules, + unsigned long count, + unsigned long sg_list); +typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, + unsigned long count, + u64 *max_size, + int *reset_type); +typedef efi_status_t efi_query_variable_store_t(u32 attributes, + unsigned long size, + bool nonblocking); + +typedef union { + struct { + efi_table_hdr_t hdr; + efi_get_time_t __efiapi *get_time; + efi_set_time_t __efiapi *set_time; + efi_get_wakeup_time_t __efiapi *get_wakeup_time; + efi_set_wakeup_time_t __efiapi *set_wakeup_time; + efi_set_virtual_address_map_t __efiapi *set_virtual_address_map; + void *convert_pointer; + efi_get_variable_t __efiapi *get_variable; + efi_get_next_variable_t __efiapi *get_next_variable; + efi_set_variable_t __efiapi *set_variable; + efi_get_next_high_mono_count_t __efiapi *get_next_high_mono_count; + efi_reset_system_t __efiapi *reset_system; + efi_update_capsule_t __efiapi *update_capsule; + efi_query_capsule_caps_t __efiapi *query_capsule_caps; + efi_query_variable_info_t __efiapi *query_variable_info; + }; + efi_runtime_services_32_t mixed_mode; +} efi_runtime_services_t; + +#define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL) + +#define EFI_2_30_SYSTEM_TABLE_REVISION ((2 << 16) | (30)) +#define EFI_2_20_SYSTEM_TABLE_REVISION ((2 << 16) | (20)) +#define EFI_2_10_SYSTEM_TABLE_REVISION ((2 << 16) | (10)) +#define EFI_2_00_SYSTEM_TABLE_REVISION ((2 << 16) | (00)) +#define EFI_1_10_SYSTEM_TABLE_REVISION ((1 << 16) | (10)) +#define EFI_1_02_SYSTEM_TABLE_REVISION ((1 << 16) | (02)) + +typedef struct { + efi_table_hdr_t hdr; + u64 fw_vendor; /* physical addr of CHAR16 vendor string */ + u32 fw_revision; + u32 __pad1; + u64 con_in_handle; + u64 con_in; + u64 con_out_handle; + u64 con_out; + u64 stderr_handle; + u64 stderr; + u64 runtime; + u64 boottime; + u32 nr_tables; + u32 __pad2; + u64 tables; +} efi_system_table_64_t; + +typedef struct { + efi_table_hdr_t hdr; + u32 fw_vendor; /* physical addr of CHAR16 vendor string */ + u32 fw_revision; + u32 con_in_handle; + u32 con_in; + u32 con_out_handle; + u32 con_out; + u32 stderr_handle; + u32 stderr; + u32 runtime; + u32 boottime; + u32 nr_tables; + u32 tables; +} efi_system_table_32_t; + +typedef union efi_simple_text_input_protocol efi_simple_text_input_protocol_t; +typedef union efi_simple_text_output_protocol efi_simple_text_output_protocol_t; + +typedef union { + struct { + efi_table_hdr_t hdr; + unsigned long fw_vendor; /* physical addr of CHAR16 vendor string */ + u32 fw_revision; + unsigned long con_in_handle; + efi_simple_text_input_protocol_t *con_in; + unsigned long con_out_handle; + efi_simple_text_output_protocol_t *con_out; + unsigned long stderr_handle; + unsigned long stderr; + efi_runtime_services_t *runtime; + efi_boot_services_t *boottime; + unsigned long nr_tables; + unsigned long tables; + }; + efi_system_table_32_t mixed_mode; +} efi_system_table_t; + +struct efi_boot_memmap { + efi_memory_desc_t **map; + unsigned long *map_size; + unsigned long *desc_size; + u32 *desc_ver; + unsigned long *key_ptr; + unsigned long *buff_size; +}; + +#define efi_bs_call(func, ...) \ + efi_system_table->boottime->func(__VA_ARGS__) + +#endif /* __LINUX_UEFI_H */ From patchwork Fri Aug 27 03:12:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12461127 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AE6F3C43214 for ; Fri, 27 Aug 2021 03:12:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9744460F5C for ; Fri, 27 Aug 2021 03:12:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244108AbhH0DNY (ORCPT ); Thu, 26 Aug 2021 23:13:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36132 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244082AbhH0DNU (ORCPT ); Thu, 26 Aug 2021 23:13:20 -0400 Received: from mail-pl1-x64a.google.com (mail-pl1-x64a.google.com [IPv6:2607:f8b0:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C8158C0613CF for ; Thu, 26 Aug 2021 20:12:28 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id f17-20020a170902ab91b029012c3bac8d81so619532plr.23 for ; Thu, 26 Aug 2021 20:12:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=TV3XBKvgeVZ3rwCRmDSJpEdlUJZvgFVJ0BSDevfpb6Q=; b=HfshYIuZYAIUjDw0eK+CBhq0gXsFxZ+zx+WurVoTsURhuDQPVj+FAfp5gDzHyggXmk clyO4CmxMmmQl8WTR30u8ZicWI8TR55uCpP6jS/i4yOPinOJ416zCxNJ8rKagszlOFF9 2Nq47A2XZ3s7/dGa9Kjlu2RHkniEWL1aUTeCENJbfpPg/m747e4puQgHzyi9RfAbGhsE 7ezwMUy45b33JD5QThcTOhrMSJfw1+c5yr3p2EpHpDFJsiqC6lM+xV3423LL53ySvrpD V8Cs+l8Ldg2VrkqovWpF3BX13CopdOO/duUXvcQyObClN2AZwPwk4iHi/i6Yj3+NPKUH 1p8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=TV3XBKvgeVZ3rwCRmDSJpEdlUJZvgFVJ0BSDevfpb6Q=; b=e1FqA/y0RVpvTWy4XSky6XvrnMoSslYh2jwpDICphoKiYOwXTcr4WvLvbvCJAImosg I1W3w7Pwvj6SBrtoFXH7LwQEExAJtzWi3GLI8FZD/pscY7p3YEEVfhWtBG4p89XAkloS ikhQE9Vy6kQ4Y85k8MXWNm4ruyFGTp9sK+iQ2M5AX3c2NG+t7kvWlvlx5RVm4XHND948 TE6+lJcCEkn1KazW19iZY0kE87NOk+/At6HlN+jEe6exjRNBusT9C7DVhTP4bYi9Varu UqR5HcEODpF5wGF0vjCjw1X3G0kgxr+lscb+RJAtfcDsvu9Dqq2rDHuPqgU6pj4MJmPQ 1Wbg== X-Gm-Message-State: AOAM533U/GWNggyYfu9ROfiwaMATncZzkTL0X1eZYBKTUygWmhZ76U15 kQPddBWaMyFCxkFdi7yycFJVYs2LRvkvt7uQI/34RvXqar+5Ov2duR41APfGb684YIXdow2E0a9 d8fn13BC5jHTPxrI75XanEEDSv+dqRGLaYa9Qf+mBtpHusbqx8nMHVX5mPGCRoBZBJw6g X-Google-Smtp-Source: ABdhPJyHsYrPyzUKegLg9DRMzuDfhDJgQ2CV9dLSDePVFZOQm5T3GHpdkVxbLx7pQKj9vvL+lWmIMN5VuvqVVuQR X-Received: from zxwang42.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2936]) (user=zixuanwang job=sendgmr) by 2002:aa7:8d46:0:b029:3cd:c2fd:fea5 with SMTP id s6-20020aa78d460000b02903cdc2fdfea5mr6836271pfe.31.1630033948101; Thu, 26 Aug 2021 20:12:28 -0700 (PDT) Date: Fri, 27 Aug 2021 03:12:07 +0000 In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com> Message-Id: <20210827031222.2778522-3-zixuanwang@google.com> Mime-Version: 1.0 References: <20210827031222.2778522-1-zixuanwang@google.com> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog Subject: [kvm-unit-tests PATCH v2 02/17] x86 UEFI: Implement UEFI function calls From: Zixuan Wang To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com, erdemaktas@google.com, rientjes@google.com, seanjc@google.com, brijesh.singh@amd.com, Thomas.Lendacky@amd.com, varad.gautam@suse.com, jroedel@suse.de, bp@suse.de Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Varad Gautam This commit implements helper functions that call UEFI services and assist the boot up process. Signed-off-by: Varad Gautam Reviewed-by: Andrew Jones --- lib/efi.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 lib/efi.c diff --git a/lib/efi.c b/lib/efi.c new file mode 100644 index 0000000..9711354 --- /dev/null +++ b/lib/efi.c @@ -0,0 +1,58 @@ +#include + +unsigned long __efiapi efi_main(efi_handle_t handle, efi_system_table_t *sys_tab); +efi_system_table_t *efi_system_table = NULL; + +static void efi_free_pool(void *ptr) +{ + efi_bs_call(free_pool, ptr); +} + +static efi_status_t efi_get_memory_map(struct efi_boot_memmap *map) +{ + efi_memory_desc_t *m = NULL; + efi_status_t status; + unsigned long key = 0, map_size = 0, desc_size = 0; + + status = efi_bs_call(get_memory_map, &map_size, + NULL, &key, &desc_size, NULL); + if (status != EFI_BUFFER_TOO_SMALL || map_size == 0) + goto out; + + /* Pad map_size with additional descriptors so we don't need to + * retry. */ + map_size += 4 * desc_size; + *map->buff_size = map_size; + status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, + map_size, (void **)&m); + if (status != EFI_SUCCESS) + goto out; + + /* Get the map. */ + status = efi_bs_call(get_memory_map, &map_size, + m, &key, &desc_size, NULL); + if (status != EFI_SUCCESS) { + efi_free_pool(m); + goto out; + } + + *map->desc_size = desc_size; + *map->map_size = map_size; + *map->key_ptr = key; +out: + *map->map = m; + return status; +} + +static efi_status_t efi_exit_boot_services(void *handle, + struct efi_boot_memmap *map) +{ + return efi_bs_call(exit_boot_services, handle, *map->key_ptr); +} + +unsigned long __efiapi efi_main(efi_handle_t handle, efi_system_table_t *sys_tab) +{ + efi_system_table = sys_tab; + + return 0; +} From patchwork Fri Aug 27 03:12:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12461129 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2F519C43216 for ; Fri, 27 Aug 2021 03:12:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0E31960F6F for ; Fri, 27 Aug 2021 03:12:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244116AbhH0DNZ (ORCPT ); Thu, 26 Aug 2021 23:13:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36134 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244083AbhH0DNV (ORCPT ); Thu, 26 Aug 2021 23:13:21 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9881DC0613D9 for ; Thu, 26 Aug 2021 20:12:30 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id g6-20020a655946000000b00255ef826275so692032pgu.23 for ; Thu, 26 Aug 2021 20:12:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=HskK1EYbvxi4RkT5lCVHXcak9FXd6Yo7D0JVVrhS90k=; b=M1s2NYsY2AP7twKSK6TLE8jY+DX9DcEOuPE9oiclVU4eMAS5nQxPqsy3lXaYt3WkuC msqsU9nsRDwrxbva1Qup/3STJo5RfdPbyRewqfFUlM5xbCudv1gLjUvYWfMIpkM0mveT yMLw9bJFzoOFpaWO35udUqzvWjbnxhjBaN7BUel5Rk0TaH151MBAJGpcuTUMmx5denhH 4C8OsyHwiv4hgh1s/PsJ2UyRrABPhKRKgyJNwExpMUt0Yn98nGOkhce+ySbv+5UPUJxs 9gzfCCpp1qvCRxno2ZBHFPexkoqjQiQg2bM8i+39d4CFQG2KLgzHZWBZG2mZiA7ZOy8u 6Htw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=HskK1EYbvxi4RkT5lCVHXcak9FXd6Yo7D0JVVrhS90k=; b=nfVABilxY2lNZ90uxMFxi40OvBsxbu8unOgxSjlMgz+YBRPsdq5Q9mdyaraKaarNcz oGe8UXFycRutF3Y7M6YflvJhBAKq0okagN4OuSqeCcvLEvxxl2yqPc4P2KxbaswFZ/uM WSIUA0digNrVrb6Ph0wBk8y3LvgZ/eroLIPxFJD3EQWSe2PDsCm5lxNizzoUagGsI/YC vMsBw8Et+qwoTjDokwSPv/eFY1euq+nN4WW76wVzeGhsiwgW3/hMzJ8vD0aamPb0PzBS kYv8OKkTlELVdZ486Fu3W7bvDKNm9itHUE7GBZZ/LKn7MEo3bSJr99eSDG6coV4dvphA yLpg== X-Gm-Message-State: AOAM532PWvXlqdLARU1tsg5p0ItA3nz0jBJzOCzy7uaDDTI6KU9E0xdH m8OXoBhjTC7nkVcLuMEiYybprharJVxiyh0VuvCoEsEvx49Q5q6PqVOjjLzZzMXKR0D+Foy3Vac nlmxAO/bFEsDkD9HA4t4W3O4BEzTWUydxyF568VINhiyd8JR2a7keRqeUviMUHGi9FCgI X-Google-Smtp-Source: ABdhPJzT36w361U6aZEWiCsS9nyY2+3FNe0qSraPHwJUSycLHuYfw29DFCVKP6Nqimsizufps7GROl5OBicYcYKS X-Received: from zxwang42.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2936]) (user=zixuanwang job=sendgmr) by 2002:a62:ea1a:0:b029:329:a95a:fab with SMTP id t26-20020a62ea1a0000b0290329a95a0fabmr6790372pfh.31.1630033949875; Thu, 26 Aug 2021 20:12:29 -0700 (PDT) Date: Fri, 27 Aug 2021 03:12:08 +0000 In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com> Message-Id: <20210827031222.2778522-4-zixuanwang@google.com> Mime-Version: 1.0 References: <20210827031222.2778522-1-zixuanwang@google.com> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog Subject: [kvm-unit-tests PATCH v2 03/17] x86 UEFI: Copy code from GNU-EFI From: Zixuan Wang To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com, erdemaktas@google.com, rientjes@google.com, seanjc@google.com, brijesh.singh@amd.com, Thomas.Lendacky@amd.com, varad.gautam@suse.com, jroedel@suse.de, bp@suse.de Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org To build x86 test cases with UEFI, we need to borrow some source code from GNU-EFI, which includes the initialization code and linker scripts. This commit only copies the source code, without any modification. These source code files are not used by KVM-Unit-Tests in this commit. The following source code is copied from GNU-EFI: 1. x86/efi/elf_x86_64_efi.lds 2. x86/efi/reloc_x86_64.c 3. x86/efi/crt0-efi-x86_64.S We put these EFI-related files under a new dir `x86/efi` because: 1. EFI-related code is easy to find 2. EFI-related code is separated from the original code in `x86/` 3. EFI-related code can still reuse the Makefile and test case code in its parent dir `x86/` GNU-EFI repo and version: GIT URL: https://git.code.sf.net/p/gnu-efi/code Commit ID: 4fe83e102674 Website: https://sourceforge.net/p/gnu-efi/code/ci/4fe83e/tree/ Co-developed-by: Varad Gautam Signed-off-by: Varad Gautam Signed-off-by: Zixuan Wang --- x86/efi/README.md | 25 ++++++++++ x86/efi/crt0-efi-x86_64.S | 79 +++++++++++++++++++++++++++++ x86/efi/elf_x86_64_efi.lds | 77 ++++++++++++++++++++++++++++ x86/efi/reloc_x86_64.c | 100 +++++++++++++++++++++++++++++++++++++ 4 files changed, 281 insertions(+) create mode 100644 x86/efi/README.md create mode 100644 x86/efi/crt0-efi-x86_64.S create mode 100644 x86/efi/elf_x86_64_efi.lds create mode 100644 x86/efi/reloc_x86_64.c diff --git a/x86/efi/README.md b/x86/efi/README.md new file mode 100644 index 0000000..256ef8c --- /dev/null +++ b/x86/efi/README.md @@ -0,0 +1,25 @@ +# EFI Startup Code and Linker Script + +This dir contains source code and linker script copied from +[GNU-EFI](https://sourceforge.net/projects/gnu-efi/): + - crt0-efi-x86_64.S: startup code of an EFI application + - elf_x86_64_efi.lds: linker script to build an EFI application + - reloc_x86_64.c: position independent x86_64 ELF shared object relocator + +EFI application binaries should be relocatable as UEFI loads binaries to dynamic +runtime addresses. To build such relocatable binaries, GNU-EFI utilizes the +above-mentioned files in its build process: + + 1. build an ELF shared object and link it using linker script + `elf_x86_64_efi.lds` to organize the sections in a way UEFI recognizes + 2. link the shared object with self-relocator `reloc_x86_64.c` that applies + dynamic relocations that may be present in the shared object + 3. link the entry point code `crt0-efi-x86_64.S` that invokes self-relocator + and then jumps to EFI application's `efi_main()` function + 4. convert the shared object to an EFI binary + +More details can be found in `GNU-EFI/README.gnuefi`, section "Building +Relocatable Binaries". + +KVM-Unit-Tests follows a similar build process, but does not link with GNU-EFI +library. diff --git a/x86/efi/crt0-efi-x86_64.S b/x86/efi/crt0-efi-x86_64.S new file mode 100644 index 0000000..eaf1656 --- /dev/null +++ b/x86/efi/crt0-efi-x86_64.S @@ -0,0 +1,79 @@ +/* The following code is copied from GNU-EFI/gnuefi/crt0-efi-x86_64.S + + crt0-efi-x86_64.S - x86_64 EFI startup code. + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger . + Copyright (C) 2005 Intel Co. + Contributed by Fenghua Yu . + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + .text + .align 4 + + .globl _start +_start: + subq $8, %rsp + pushq %rcx + pushq %rdx + +0: + lea ImageBase(%rip), %rdi + lea _DYNAMIC(%rip), %rsi + + popq %rcx + popq %rdx + pushq %rcx + pushq %rdx + call _relocate + + popq %rdi + popq %rsi + + call efi_main + addq $8, %rsp + +.exit: + ret + + // hand-craft a dummy .reloc section so EFI knows it's a relocatable executable: + + .data +dummy: .long 0 + +#define IMAGE_REL_ABSOLUTE 0 + .section .reloc, "a" +label1: + .long dummy-label1 // Page RVA + .long 12 // Block Size (2*4+2*2), must be aligned by 32 Bits + .word (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy + .word (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy + diff --git a/x86/efi/elf_x86_64_efi.lds b/x86/efi/elf_x86_64_efi.lds new file mode 100644 index 0000000..5eae376 --- /dev/null +++ b/x86/efi/elf_x86_64_efi.lds @@ -0,0 +1,77 @@ +/* Copied from GNU-EFI/gnuefi/elf_x86_64_efi.lds, licensed under GNU GPL */ +/* Same as elf_x86_64_fbsd_efi.lds, except for OUTPUT_FORMAT below - KEEP IN SYNC */ +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +ENTRY(_start) +SECTIONS +{ + . = 0; + ImageBase = .; + /* .hash and/or .gnu.hash MUST come first! */ + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + . = ALIGN(4096); + .eh_frame : + { + *(.eh_frame) + } + . = ALIGN(4096); + .text : + { + _text = .; + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + . = ALIGN(16); + } + _etext = .; + _text_size = . - _text; + . = ALIGN(4096); + .reloc : + { + *(.reloc) + } + . = ALIGN(4096); + .data : + { + _data = .; + *(.rodata*) + *(.got.plt) + *(.got) + *(.data*) + *(.sdata) + /* the EFI loader doesn't seem to like a .bss section, so we stick + it all into .data: */ + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + *(.rel.local) + } + .note.gnu.build-id : { *(.note.gnu.build-id) } + + _edata = .; + _data_size = . - _etext; + . = ALIGN(4096); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + .rela : + { + *(.rela.data*) + *(.rela.got) + *(.rela.stab) + } + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .ignored.reloc : + { + *(.rela.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} diff --git a/x86/efi/reloc_x86_64.c b/x86/efi/reloc_x86_64.c new file mode 100644 index 0000000..d13b53e --- /dev/null +++ b/x86/efi/reloc_x86_64.c @@ -0,0 +1,100 @@ +/* This file is copied from GNU-EFI/gnuefi/reloc_x86_64.c + + reloc_x86_64.c - position independent x86_64 ELF shared object relocator + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger . + Copyright (C) 2005 Intel Co. + Contributed by Fenghua Yu . + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include +#include + +#include + +EFI_STATUS _relocate (long ldbase, Elf64_Dyn *dyn, + EFI_HANDLE image EFI_UNUSED, + EFI_SYSTEM_TABLE *systab EFI_UNUSED) +{ + long relsz = 0, relent = 0; + Elf64_Rel *rel = 0; + unsigned long *addr; + int i; + + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { + switch (dyn[i].d_tag) { + case DT_RELA: + rel = (Elf64_Rel*) + ((unsigned long)dyn[i].d_un.d_ptr + + ldbase); + break; + + case DT_RELASZ: + relsz = dyn[i].d_un.d_val; + break; + + case DT_RELAENT: + relent = dyn[i].d_un.d_val; + break; + + default: + break; + } + } + + if (!rel && relent == 0) + return EFI_SUCCESS; + + if (!rel || relent == 0) + return EFI_LOAD_ERROR; + + while (relsz > 0) { + /* apply the relocs */ + switch (ELF64_R_TYPE (rel->r_info)) { + case R_X86_64_NONE: + break; + + case R_X86_64_RELATIVE: + addr = (unsigned long *) + (ldbase + rel->r_offset); + *addr += ldbase; + break; + + default: + break; + } + rel = (Elf64_Rel*) ((char *) rel + relent); + relsz -= relent; + } + return EFI_SUCCESS; +} From patchwork Fri Aug 27 03:12:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12461123 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-31.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,MENTIONS_GIT_HOSTING, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3A550C432BE for ; Fri, 27 Aug 2021 03:12:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 151D760F6F for ; Fri, 27 Aug 2021 03:12:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244096AbhH0DNX (ORCPT ); Thu, 26 Aug 2021 23:13:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36138 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244086AbhH0DNW (ORCPT ); Thu, 26 Aug 2021 23:13:22 -0400 Received: from mail-pl1-x649.google.com (mail-pl1-x649.google.com [IPv6:2607:f8b0:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E510DC061796 for ; Thu, 26 Aug 2021 20:12:32 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id q11-20020a170902c9cb00b0013346a0d4e6so813861pld.14 for ; Thu, 26 Aug 2021 20:12:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=KDQYFbO0Y9LKELxixiMj806YyD4L+mEIABWJ+4FhoGs=; b=hYAV+/asDnOyXAc6Q+scLrdSlQ35jn4w8NwqKtr2voAUrI1pR7X6kcM3NhbM9jtA2j NgKGj8UwGrU1A33g0hQqsKvo6Sh1iXFyH1b7oPeXSheLRcyfobM7KxtwUs0W5jGBtV1z FFVXYHNzpQz0Yqn+xViKk1rzkP0kRfVy0u4sq8tB8ENg+aFXEl8pH1tMJ7dmAiBz4s1i AANoPaFqrpQmjyWxW5bC0SWQqg5M8YSnaCN9w/U4i5flYEQ9vG72O18sDKPnZ2C/fC6k cTKKWn2/sTGPbC3yvLVRgkjndBlYWG8VoyRdV1BtDoiyHQQY9SbV6ItC1lOBvJvlU3gj dEQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=KDQYFbO0Y9LKELxixiMj806YyD4L+mEIABWJ+4FhoGs=; b=gIpnidsidSjcYZ7FLSkff6Xio88hXwUGmnK2u54vCURFA6ZJCThLSMJC0siJ46Tj66 9RYYVgpmmHRtRsspEZD9lvuWqwbmDeY96bdcltSyTYte3jjqvTOeBXsdomrY5ye7Qyo3 nJG/0zH45BvV5XuezPheZuNa+ePRuJUq8Bp94q10Xj+9WWjwvcHQqPeGA0DIxsXac3QC 9vNr8Q8yP9gFIiHPbdZ60PmsN9Hy4YeZ9tGzlv5+aL5sSZKpD1rACqiYoMes2bisrH4n WSeIjva+utCkRpVw8kg9SlNHW096VeO5lP65MeEYFIjWlp7lSuME3Xub1f6gXj6cS7k7 qu0w== X-Gm-Message-State: AOAM530CIiwdE46shDEleaNBoCS3Gcy0lKaATrSxtdTGtS8H9Flb7kKQ vIIQB3vVOgrYZ8LLj2DPsE5wMDi2FMBORpNQWDCFgURWT/57he0fP94+FrmA5e32Dn65r9KNBsV YIOKUIXv9ToPLXEKVdvKbzrscdWDI5wl2yKIf8uNduq4b9/XyaPUurnOhlWCv9GhkGroC X-Google-Smtp-Source: ABdhPJxDZuAyvP/hquM8HLdiVLRDEFH8Vg7BX80RIsJ9NyNmgbJXUnLJyVNSAKR1Apt+3s79nDHRn7mjA6hgwe1b X-Received: from zxwang42.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2936]) (user=zixuanwang job=sendgmr) by 2002:a62:1d0a:0:b0:3e2:7dd6:e4b0 with SMTP id d10-20020a621d0a000000b003e27dd6e4b0mr6934547pfd.27.1630033951704; Thu, 26 Aug 2021 20:12:31 -0700 (PDT) Date: Fri, 27 Aug 2021 03:12:09 +0000 In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com> Message-Id: <20210827031222.2778522-5-zixuanwang@google.com> Mime-Version: 1.0 References: <20210827031222.2778522-1-zixuanwang@google.com> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog Subject: [kvm-unit-tests PATCH v2 04/17] x86 UEFI: Boot from UEFI From: Zixuan Wang To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com, erdemaktas@google.com, rientjes@google.com, seanjc@google.com, brijesh.singh@amd.com, Thomas.Lendacky@amd.com, varad.gautam@suse.com, jroedel@suse.de, bp@suse.de Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This commit provides initial support for x86 test cases to boot from UEFI: 1. UEFI compiler flags are added to Makefile 2. A new TARGET_EFI macro is added to turn on/off UEFI startup code 3. Previous Multiboot setup code is refactored and updated for supporting UEFI, including the following changes: 1. x86/efi/crt0-efi-x86_64.S: provides entry point and jumps to setup code in lib/efi.c. 2. lib/efi.c: performs UEFI setup, calls arch-related setup functions, then jumps to test case main() function 3. lib/x86/setup.c: provides arch-related setup under UEFI To build test cases for UEFI, please first install the GNU-EFI library. Check x86/efi/README.md for more details. This commit is tested by a simple test calling report() and report_summayr(). This commit does not include such a test to avoid unnecessary files added into git history. To build and run this test in UEFI (assuming file name is x86/dummy.c): ./configure --target-efi make x86/dummy.efi ./x86/efi/run ./x86/dummy.efi To use the default Multiboot instead of UEFI: ./configure make x86/dummy.flat ./x86/run ./x86/dummy.flat Some x86 test cases require additional fixes to work in UEFI, e.g., converting to position independent code (PIC), setting up page tables, etc. This commit does not provide these fixes, so compiling and running UEFI test cases other than x86/dummy.c may trigger compiler errors or QEMU crashes. These test cases will be fixed by the follow-up commits in this series. The following code is ported from github.com/rhdrjones/kvm-unit-tests - ./configure: 'target-efi'-related code See original code: - Repo: https://github.com/rhdrjones/kvm-unit-tests - Branch: target-efi Co-developed-by: Varad Gautam Signed-off-by: Varad Gautam Signed-off-by: Zixuan Wang --- .gitignore | 3 ++ Makefile | 29 +++++++++++++++++- README.md | 6 ++++ configure | 6 ++++ lib/efi.c | 38 ++++++++++++++++++++---- lib/efi.h | 17 +++++++++++ lib/linux/uefi.h | 10 +++++-- lib/x86/asm/setup.h | 11 +++++++ lib/x86/setup.c | 15 ++++++++++ x86/Makefile.common | 67 +++++++++++++++++++++++++++++++----------- x86/Makefile.i386 | 5 ++-- x86/Makefile.x86_64 | 54 ++++++++++++++++++++++------------ x86/efi/README.md | 40 ++++++++++++++++++++++++- x86/efi/reloc_x86_64.c | 9 ++---- x86/efi/run | 63 +++++++++++++++++++++++++++++++++++++++ x86/run | 16 ++++++++-- 16 files changed, 333 insertions(+), 56 deletions(-) create mode 100644 lib/efi.h create mode 100644 lib/x86/asm/setup.h create mode 100755 x86/efi/run diff --git a/.gitignore b/.gitignore index b3cf2cb..dca6d29 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,9 @@ tags *.a *.d *.o +*.so *.flat +*.efi *.elf .pc patches @@ -24,3 +26,4 @@ cscope.* /api/dirty-log-perf /s390x/*.bin /s390x/snippets/*/*.gbin +/efi-tests/* diff --git a/Makefile b/Makefile index f7b9f28..c4a3905 100644 --- a/Makefile +++ b/Makefile @@ -38,6 +38,29 @@ LIBFDT_archive = $(LIBFDT_objdir)/libfdt.a OBJDIRS += $(LIBFDT_objdir) +# EFI App +ifeq ($(TARGET_EFI),y) +ifeq ($(ARCH_NAME),x86_64) +EFI_ARCH = x86_64 +else +$(error Cannot build $(ARCH_NAME) tests as EFI apps) +endif +EFI_CFLAGS := -DTARGET_EFI +# The following CFLAGS and LDFLAGS come from: +# - GNU-EFI/Makefile.defaults +# - GNU-EFI/apps/Makefile +# Function calls must include the number of arguments passed to the functions +# More details: https://wiki.osdev.org/GNU-EFI +EFI_CFLAGS += -maccumulate-outgoing-args +# GCC defines wchar to be 32 bits, but EFI expects 16 bits +EFI_CFLAGS += -fshort-wchar +# EFI applications use PIC as they are loaded to dynamic addresses, not a fixed +# starting address +EFI_CFLAGS += -fPIC +# Create shared library +EFI_LDFLAGS := -Bsymbolic -shared -nostdlib +endif + #include architecture specific make rules include $(SRCDIR)/$(TEST_DIR)/Makefile @@ -62,7 +85,11 @@ COMMON_CFLAGS += $(fno_stack_protector) COMMON_CFLAGS += $(fno_stack_protector_all) COMMON_CFLAGS += $(wno_frame_address) COMMON_CFLAGS += $(if $(U32_LONG_FMT),-D__U32_LONG_FMT__,) +ifeq ($(TARGET_EFI),y) +COMMON_CFLAGS += $(EFI_CFLAGS) +else COMMON_CFLAGS += $(fno_pic) $(no_pie) +endif COMMON_CFLAGS += $(wclobbered) COMMON_CFLAGS += $(wunused_but_set_parameter) @@ -113,7 +140,7 @@ clean: arch_clean libfdt_clean distclean: clean $(RM) lib/asm lib/config.h config.mak $(TEST_DIR)-run msr.out cscope.* build-head - $(RM) -r tests logs logs.old + $(RM) -r tests logs logs.old efi-tests cscope: cscope_dirs = lib lib/libfdt lib/linux $(TEST_DIR) $(ARCH_LIBDIRS) lib/asm-generic cscope: diff --git a/README.md b/README.md index b498aaf..6edacfe 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ in this directory. Test images are created in ./ARCH/\*.flat NOTE: GCC cross-compiler is required for [build on macOS](README.macOS.md). +To build with UEFI, check [build and run with UEFI](./x86/efi/README.md). + ## Standalone tests The tests can be built as standalone. To create and use standalone tests do: @@ -54,6 +56,10 @@ ACCEL=name environment variable: ACCEL=kvm ./x86-run ./x86/msr.flat +## Running the tests with UEFI + +Check [build and run with UEFI](./x86/efi/README.md). + # Tests configuration file The test case may need specific runtime configurations, for diff --git a/configure b/configure index 1d4d855..b6c09b3 100755 --- a/configure +++ b/configure @@ -28,6 +28,7 @@ erratatxt="$srcdir/errata.txt" host_key_document= page_size= earlycon= +target_efi= usage() { cat <<-EOF @@ -69,6 +70,7 @@ usage() { pl011,mmio32,ADDR Specify a PL011 compatible UART at address ADDR. Supported register stride is 32 bit only. + --target-efi Boot and run from UEFI EOF exit 1 } @@ -133,6 +135,9 @@ while [[ "$1" = -* ]]; do --earlycon) earlycon="$arg" ;; + --target-efi) + target_efi=y + ;; --help) usage ;; @@ -341,6 +346,7 @@ U32_LONG_FMT=$u32_long WA_DIVIDE=$wa_divide GENPROTIMG=${GENPROTIMG-genprotimg} HOST_KEY_DOCUMENT=$host_key_document +TARGET_EFI=$target_efi EOF if [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then echo "TARGET=$target" >> config.mak diff --git a/lib/efi.c b/lib/efi.c index 9711354..99307db 100644 --- a/lib/efi.c +++ b/lib/efi.c @@ -1,6 +1,24 @@ +/* + * efi_main() function to set up and run test cases in EFI + * + * Copyright (c) 2021, SUSE, Varad Gautam + * Copyright (c) 2021, Google Inc, Zixuan Wang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + #include +#include +#include +#include "efi.h" + +/* From lib/argv.c */ +extern int __argc, __envc; +extern char *__argv[100]; +extern char *__environ[200]; + +extern int main(int argc, char **argv, char **envp); -unsigned long __efiapi efi_main(efi_handle_t handle, efi_system_table_t *sys_tab); efi_system_table_t *efi_system_table = NULL; static void efi_free_pool(void *ptr) @@ -8,7 +26,7 @@ static void efi_free_pool(void *ptr) efi_bs_call(free_pool, ptr); } -static efi_status_t efi_get_memory_map(struct efi_boot_memmap *map) +efi_status_t efi_get_memory_map(struct efi_boot_memmap *map) { efi_memory_desc_t *m = NULL; efi_status_t status; @@ -44,15 +62,23 @@ out: return status; } -static efi_status_t efi_exit_boot_services(void *handle, - struct efi_boot_memmap *map) +efi_status_t efi_exit_boot_services(void *handle, struct efi_boot_memmap *map) { return efi_bs_call(exit_boot_services, handle, *map->key_ptr); } -unsigned long __efiapi efi_main(efi_handle_t handle, efi_system_table_t *sys_tab) +efi_status_t efi_main(efi_handle_t handle, efi_system_table_t *sys_tab) { + int ret; + efi_system_table = sys_tab; - return 0; + setup_efi(); + ret = main(__argc, __argv, __environ); + + /* Shutdown the guest VM */ + efi_rs_call(reset_system, EFI_RESET_SHUTDOWN, ret, 0, NULL); + + /* Unreachable */ + return EFI_UNSUPPORTED; } diff --git a/lib/efi.h b/lib/efi.h new file mode 100644 index 0000000..60cdb6f --- /dev/null +++ b/lib/efi.h @@ -0,0 +1,17 @@ +#ifndef _EFI_H_ +#define _EFI_H_ + +/* + * EFI-related functions in KVM-Unit-Tests. This file's name "efi.h" is in + * conflict with GNU-EFI library's "efi.h", but KVM-Unit-Tests does not include + * GNU-EFI headers or links against GNU-EFI. + */ +#include "linux/uefi.h" +#include + +efi_status_t _relocate(long ldbase, Elf64_Dyn *dyn, efi_handle_t handle, efi_system_table_t *sys_tab); +efi_status_t efi_get_memory_map(struct efi_boot_memmap *map); +efi_status_t efi_exit_boot_services(void *handle, struct efi_boot_memmap *map); +efi_status_t efi_main(efi_handle_t handle, efi_system_table_t *sys_tab); + +#endif /* _EFI_H_ */ diff --git a/lib/linux/uefi.h b/lib/linux/uefi.h index 567cddc..9adc7ab 100644 --- a/lib/linux/uefi.h +++ b/lib/linux/uefi.h @@ -4,6 +4,12 @@ #ifndef __LINUX_UEFI_H #define __LINUX_UEFI_H +#include "libcflat.h" + +#ifndef __packed +# define __packed __attribute__((__packed__)) +#endif + #define BITS_PER_LONG 64 #define EFI_SUCCESS 0 @@ -512,7 +518,7 @@ struct efi_boot_memmap { unsigned long *buff_size; }; -#define efi_bs_call(func, ...) \ - efi_system_table->boottime->func(__VA_ARGS__) +#define efi_bs_call(func, ...) efi_system_table->boottime->func(__VA_ARGS__) +#define efi_rs_call(func, ...) efi_system_table->runtime->func(__VA_ARGS__) #endif /* __LINUX_UEFI_H */ diff --git a/lib/x86/asm/setup.h b/lib/x86/asm/setup.h new file mode 100644 index 0000000..eb1cf73 --- /dev/null +++ b/lib/x86/asm/setup.h @@ -0,0 +1,11 @@ +#ifndef _X86_ASM_SETUP_H_ +#define _X86_ASM_SETUP_H_ + +#ifdef TARGET_EFI +#include "x86/apic.h" +#include "x86/smp.h" + +void setup_efi(void); +#endif /* TARGET_EFI */ + +#endif /* _X86_ASM_SETUP_H_ */ diff --git a/lib/x86/setup.c b/lib/x86/setup.c index 7befe09..efb5ecd 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -2,6 +2,7 @@ * Initialize machine setup information * * Copyright (C) 2017, Red Hat Inc, Andrew Jones + * Copyright (C) 2021, Google Inc, Zixuan Wang * * This work is licensed under the terms of the GNU LGPL, version 2. */ @@ -9,6 +10,7 @@ #include "fwcfg.h" #include "alloc_phys.h" #include "argv.h" +#include "asm/setup.h" extern char edata; @@ -118,6 +120,19 @@ void setup_multiboot(struct mbi_bootinfo *bi) initrd_size = mods->end - mods->start; } +#ifdef TARGET_EFI + +void setup_efi(void) +{ + reset_apic(); + mask_pic_interrupts(); + enable_apic(); + enable_x2apic(); + smp_init(); +} + +#endif /* TARGET_EFI */ + void setup_libcflat(void) { if (initrd) { diff --git a/x86/Makefile.common b/x86/Makefile.common index 52bb7aa..4859bf3 100644 --- a/x86/Makefile.common +++ b/x86/Makefile.common @@ -22,6 +22,11 @@ cflatobjs += lib/x86/acpi.o cflatobjs += lib/x86/stack.o cflatobjs += lib/x86/fault_test.o cflatobjs += lib/x86/delay.o +ifeq ($(TARGET_EFI),y) +cflatobjs += lib/x86/setup.o +cflatobjs += lib/efi.o +cflatobjs += x86/efi/reloc_x86_64.o +endif OBJDIRS += lib/x86 @@ -37,10 +42,25 @@ COMMON_CFLAGS += -O1 # stack.o relies on frame pointers. KEEP_FRAME_POINTER := y -# We want to keep intermediate file: %.elf and %.o +FLATLIBS = lib/libcflat.a + +ifeq ($(TARGET_EFI),y) +.PRECIOUS: %.efi %.so + +%.so: %.o $(FLATLIBS) $(SRCDIR)/x86/efi/elf_x86_64_efi.lds $(cstart.o) + $(LD) -T $(SRCDIR)/x86/efi/elf_x86_64_efi.lds $(EFI_LDFLAGS) -o $@ \ + $(filter %.o, $^) $(FLATLIBS) + @chmod a-x $@ + +%.efi: %.so + $(OBJCOPY) \ + -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \ + -j .rela -j .reloc -S --target=$(FORMAT) $< $@ + @chmod a-x $@ +else +# We want to keep intermediate file: %.elf and %.o .PRECIOUS: %.elf %.o -FLATLIBS = lib/libcflat.a %.elf: %.o $(FLATLIBS) $(SRCDIR)/x86/flat.lds $(cstart.o) $(CC) $(CFLAGS) -nostdlib -o $@ -Wl,-T,$(SRCDIR)/x86/flat.lds \ $(filter %.o, $^) $(FLATLIBS) @@ -49,18 +69,29 @@ FLATLIBS = lib/libcflat.a %.flat: %.elf $(OBJCOPY) -O elf32-i386 $^ $@ @chmod a-x $@ +endif -tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \ - $(TEST_DIR)/smptest.flat \ - $(TEST_DIR)/realmode.flat $(TEST_DIR)/msr.flat \ - $(TEST_DIR)/hypercall.flat $(TEST_DIR)/sieve.flat \ - $(TEST_DIR)/kvmclock_test.flat $(TEST_DIR)/eventinj.flat \ - $(TEST_DIR)/s3.flat $(TEST_DIR)/pmu.flat $(TEST_DIR)/setjmp.flat \ - $(TEST_DIR)/tsc_adjust.flat $(TEST_DIR)/asyncpf.flat \ - $(TEST_DIR)/init.flat $(TEST_DIR)/smap.flat \ - $(TEST_DIR)/hyperv_synic.flat $(TEST_DIR)/hyperv_stimer.flat \ - $(TEST_DIR)/hyperv_connections.flat \ - $(TEST_DIR)/umip.flat $(TEST_DIR)/tsx-ctrl.flat +tests-common = $(TEST_DIR)/vmexit.$(exe) $(TEST_DIR)/tsc.$(exe) \ + $(TEST_DIR)/smptest.$(exe) \ + $(TEST_DIR)/msr.$(exe) \ + $(TEST_DIR)/hypercall.$(exe) $(TEST_DIR)/sieve.$(exe) \ + $(TEST_DIR)/kvmclock_test.$(exe) \ + $(TEST_DIR)/s3.$(exe) $(TEST_DIR)/pmu.$(exe) $(TEST_DIR)/setjmp.$(exe) \ + $(TEST_DIR)/tsc_adjust.$(exe) $(TEST_DIR)/asyncpf.$(exe) \ + $(TEST_DIR)/init.$(exe) \ + $(TEST_DIR)/hyperv_synic.$(exe) $(TEST_DIR)/hyperv_stimer.$(exe) \ + $(TEST_DIR)/hyperv_connections.$(exe) \ + $(TEST_DIR)/tsx-ctrl.$(exe) + +# The following test cases are disabled when building EFI tests because they +# use absolute addresses in their inline assembly code, which cannot compile +# with the '-fPIC' flag +ifneq ($(TARGET_EFI),y) +tests-common += $(TEST_DIR)/eventinj.$(exe) \ + $(TEST_DIR)/smap.$(exe) \ + $(TEST_DIR)/realmode.$(exe) \ + $(TEST_DIR)/umip.$(exe) +endif test_cases: $(tests-common) $(tests) @@ -72,14 +103,16 @@ $(TEST_DIR)/realmode.elf: $(TEST_DIR)/realmode.o $(TEST_DIR)/realmode.o: bits = $(if $(call cc-option,-m16,""),16,32) -$(TEST_DIR)/kvmclock_test.elf: $(TEST_DIR)/kvmclock.o +$(TEST_DIR)/kvmclock_test.$(bin): $(TEST_DIR)/kvmclock.o -$(TEST_DIR)/hyperv_synic.elf: $(TEST_DIR)/hyperv.o +$(TEST_DIR)/hyperv_synic.$(bin): $(TEST_DIR)/hyperv.o -$(TEST_DIR)/hyperv_stimer.elf: $(TEST_DIR)/hyperv.o +$(TEST_DIR)/hyperv_stimer.$(bin): $(TEST_DIR)/hyperv.o -$(TEST_DIR)/hyperv_connections.elf: $(TEST_DIR)/hyperv.o +$(TEST_DIR)/hyperv_connections.$(bin): $(TEST_DIR)/hyperv.o arch_clean: $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \ $(TEST_DIR)/.*.d lib/x86/.*.d \ + $(TEST_DIR)/efi/*.o $(TEST_DIR)/efi/.*.d \ + $(TEST_DIR)/*.so $(TEST_DIR)/*.efi diff --git a/x86/Makefile.i386 b/x86/Makefile.i386 index 960e274..340c561 100644 --- a/x86/Makefile.i386 +++ b/x86/Makefile.i386 @@ -1,11 +1,12 @@ cstart.o = $(TEST_DIR)/cstart.o bits = 32 ldarch = elf32-i386 +exe = flat COMMON_CFLAGS += -mno-sse -mno-sse2 cflatobjs += lib/x86/setjmp32.o lib/ldiv32.o -tests = $(TEST_DIR)/taskswitch.flat $(TEST_DIR)/taskswitch2.flat \ - $(TEST_DIR)/cmpxchg8b.flat $(TEST_DIR)/la57.flat +tests = $(TEST_DIR)/taskswitch.$(exe) $(TEST_DIR)/taskswitch2.$(exe) \ + $(TEST_DIR)/cmpxchg8b.$(exe) $(TEST_DIR)/la57.$(exe) include $(SRCDIR)/$(TEST_DIR)/Makefile.common diff --git a/x86/Makefile.x86_64 b/x86/Makefile.x86_64 index 8134952..a5f8923 100644 --- a/x86/Makefile.x86_64 +++ b/x86/Makefile.x86_64 @@ -1,6 +1,15 @@ cstart.o = $(TEST_DIR)/cstart64.o bits = 64 ldarch = elf64-x86-64 +ifeq ($(TARGET_EFI),y) +exe = efi +bin = so +FORMAT = efi-app-x86_64 +cstart.o = x86/efi/crt0-efi-x86_64.o +else +exe = flat +bin = elf +endif fcf_protection_full := $(call cc-option, -fcf-protection=full,) COMMON_CFLAGS += -mno-red-zone -mno-sse -mno-sse2 $(fcf_protection_full) @@ -9,29 +18,36 @@ cflatobjs += lib/x86/setjmp64.o cflatobjs += lib/x86/intel-iommu.o cflatobjs += lib/x86/usermode.o -tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \ - $(TEST_DIR)/emulator.flat $(TEST_DIR)/idt_test.flat \ - $(TEST_DIR)/xsave.flat $(TEST_DIR)/rmap_chain.flat \ - $(TEST_DIR)/pcid.flat $(TEST_DIR)/debug.flat \ - $(TEST_DIR)/ioapic.flat $(TEST_DIR)/memory.flat \ - $(TEST_DIR)/pku.flat $(TEST_DIR)/hyperv_clock.flat -tests += $(TEST_DIR)/syscall.flat -tests += $(TEST_DIR)/svm.flat -tests += $(TEST_DIR)/vmx.flat -tests += $(TEST_DIR)/tscdeadline_latency.flat -tests += $(TEST_DIR)/intel-iommu.flat -tests += $(TEST_DIR)/vmware_backdoors.flat -tests += $(TEST_DIR)/rdpru.flat -tests += $(TEST_DIR)/pks.flat -tests += $(TEST_DIR)/pmu_lbr.flat +tests = $(TEST_DIR)/apic.$(exe) \ + $(TEST_DIR)/idt_test.$(exe) \ + $(TEST_DIR)/xsave.$(exe) $(TEST_DIR)/rmap_chain.$(exe) \ + $(TEST_DIR)/pcid.$(exe) $(TEST_DIR)/debug.$(exe) \ + $(TEST_DIR)/ioapic.$(exe) $(TEST_DIR)/memory.$(exe) \ + $(TEST_DIR)/pku.$(exe) $(TEST_DIR)/hyperv_clock.$(exe) +tests += $(TEST_DIR)/syscall.$(exe) +tests += $(TEST_DIR)/tscdeadline_latency.$(exe) +tests += $(TEST_DIR)/intel-iommu.$(exe) +tests += $(TEST_DIR)/rdpru.$(exe) +tests += $(TEST_DIR)/pks.$(exe) +tests += $(TEST_DIR)/pmu_lbr.$(exe) +# The following test cases are disabled when building EFI tests because they +# use absolute addresses in their inline assembly code, which cannot compile +# with the '-fPIC' flag +ifneq ($(TARGET_EFI),y) +tests += $(TEST_DIR)/access.$(exe) +tests += $(TEST_DIR)/emulator.$(exe) +tests += $(TEST_DIR)/svm.$(exe) +tests += $(TEST_DIR)/vmx.$(exe) +tests += $(TEST_DIR)/vmware_backdoors.$(exe) ifneq ($(fcf_protection_full),) -tests += $(TEST_DIR)/cet.flat +tests += $(TEST_DIR)/cet.$(exe) +endif endif include $(SRCDIR)/$(TEST_DIR)/Makefile.common -$(TEST_DIR)/hyperv_clock.elf: $(TEST_DIR)/hyperv_clock.o +$(TEST_DIR)/hyperv_clock.$(bin): $(TEST_DIR)/hyperv_clock.o -$(TEST_DIR)/vmx.elf: $(TEST_DIR)/vmx_tests.o -$(TEST_DIR)/svm.elf: $(TEST_DIR)/svm_tests.o +$(TEST_DIR)/vmx.$(bin): $(TEST_DIR)/vmx_tests.o +$(TEST_DIR)/svm.$(bin): $(TEST_DIR)/svm_tests.o diff --git a/x86/efi/README.md b/x86/efi/README.md index 256ef8c..befe9cc 100644 --- a/x86/efi/README.md +++ b/x86/efi/README.md @@ -1,4 +1,38 @@ -# EFI Startup Code and Linker Script +# Build KVM-Unit-Tests and run under UEFI + +## Introduction + +This dir provides code to build KVM-Unit-Tests test cases and run them under +QEMU and UEFI. + +### Install dependencies + +The following dependencies should be installed: + +- [UEFI firmware](https://github.com/tianocore/edk2): to run test cases in QEMU + +### Build + +To build: + + ./configure --target-efi + make + +### Run test cases with UEFI + +To run a test case with UEFI: + + ./x86/efi/run ./x86/dummy.efi + +By default the runner script loads the UEFI firmware `/usr/share/ovmf/OVMF.fd`; +please install UEFI firmware to this path, or specify the correct path through +the env variable `EFI_UEFI`: + + EFI_UEFI=/path/to/OVMF.fd ./x86/efi/run ./x86/dummy.efi + +## Code structure + +### Code from GNU-EFI This dir contains source code and linker script copied from [GNU-EFI](https://sourceforge.net/projects/gnu-efi/): @@ -23,3 +57,7 @@ Relocatable Binaries". KVM-Unit-Tests follows a similar build process, but does not link with GNU-EFI library. +### Startup code for KVM-Unit-Tests in UEFI + +This dir also contains KVM-Unit-Tests startup code in UEFI: + - efistart64.S: startup code for KVM-Unit-Tests in UEFI diff --git a/x86/efi/reloc_x86_64.c b/x86/efi/reloc_x86_64.c index d13b53e..511ef82 100644 --- a/x86/efi/reloc_x86_64.c +++ b/x86/efi/reloc_x86_64.c @@ -37,14 +37,11 @@ SUCH DAMAGE. */ -#include -#include - +#include "linux/uefi.h" +#include "efi.h" #include -EFI_STATUS _relocate (long ldbase, Elf64_Dyn *dyn, - EFI_HANDLE image EFI_UNUSED, - EFI_SYSTEM_TABLE *systab EFI_UNUSED) +efi_status_t _relocate(long ldbase, Elf64_Dyn *dyn, efi_handle_t handle, efi_system_table_t *sys_tab) { long relsz = 0, relent = 0; Elf64_Rel *rel = 0; diff --git a/x86/efi/run b/x86/efi/run new file mode 100755 index 0000000..72ad4a9 --- /dev/null +++ b/x86/efi/run @@ -0,0 +1,63 @@ +#!/bin/bash + +set -e + +if [ $# -eq 0 ]; then + echo "Usage $0 TEST_CASE [QEMU_ARGS]" + exit 2 +fi + +if [ ! -f config.mak ]; then + echo "run './configure --target-efi && make' first. See ./configure -h" + exit 2 +fi +source config.mak + +: "${EFI_SRC:=$(realpath "$(dirname "$0")/../")}" +: "${EFI_UEFI:=/usr/share/ovmf/OVMF.fd}" +: "${EFI_TEST:=efi-tests}" +: "${EFI_SMP:=1}" +: "${EFI_CASE:=$(basename $1 .efi)}" + +if [ ! -f "$EFI_UEFI" ]; then + echo "UEFI firmware not found: $EFI_UEFI" + echo "Please install the UEFI firmware to this path" + echo "Or specify the correct path with the env variable EFI_UEFI" + exit 2 +fi + +# Remove the TEST_CASE from $@ +shift 1 + +# Prepare EFI boot file system +# - Copy .efi file to host dir $EFI_TEST/$EFI_CASE/ +# This host dir will be loaded by QEMU as a FAT32 image +# - Make UEFI startup script that runs the .efi on boot +mkdir -p "$EFI_TEST/$EFI_CASE/" +cp "$EFI_SRC/$EFI_CASE.efi" "$EFI_TEST/$EFI_CASE/" + +pushd "$EFI_TEST/$EFI_CASE" || exit 2 +# 'startup.nsh' is the default script executed by UEFI on boot +# Use this script to run the test binary automatically +cat << EOF >startup.nsh +@echo -off +fs0: +"$EFI_CASE.efi" +EOF +popd || exit 2 + +# Run test case with 256MiB QEMU memory. QEMU default memory size is 128MiB. +# After UEFI boot up and we call `LibMemoryMap()`, the largest consecutive +# memory region is ~42MiB. Although this is sufficient for many test cases to +# run in UEFI, some test cases, e.g. `x86/pmu.c`, require more free memory. A +# simple fix is to increase the QEMU default memory size to 256MiB so that +# UEFI's largest allocatable memory region is large enough. +EFI_RUN=y \ +"$TEST_DIR/run" \ + -drive file="$EFI_UEFI",format=raw,if=pflash \ + -drive file.dir="$EFI_TEST/$EFI_CASE/",file.driver=vvfat,file.rw=on,format=raw \ + -net none \ + -nographic \ + -smp "$EFI_SMP" \ + -m 256 \ + "$@" diff --git a/x86/run b/x86/run index 8b2425f..4eba2b9 100755 --- a/x86/run +++ b/x86/run @@ -38,7 +38,19 @@ else fi command="${qemu} --no-reboot -nodefaults $pc_testdev -vnc none -serial stdio $pci_testdev" -command+=" -machine accel=$ACCEL -kernel" +command+=" -machine accel=$ACCEL" +if ! [ "$EFI_RUN" ]; then + command+=" -kernel" +fi command="$(timeout_cmd) $command" -run_qemu ${command} "$@" +if [ "$EFI_RUN" ]; then + # Set ENVIRON_DEFAULT=n to remove '-initrd' flag for QEMU (see + # 'scripts/arch-run.bash' for more details). This is because when using + # UEFI, the test case binaries are passed to QEMU through the disk + # image, not through the '-kernel' flag. And QEMU reports an error if it + # gets '-initrd' without a '-kernel' + ENVIRON_DEFAULT=n run_qemu ${command} "$@" +else + run_qemu ${command} "$@" +fi From patchwork Fri Aug 27 03:12:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12461137 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C0310C00143 for ; Fri, 27 Aug 2021 03:12:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A27E960F6C for ; Fri, 27 Aug 2021 03:12:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244120AbhH0DN0 (ORCPT ); Thu, 26 Aug 2021 23:13:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36146 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232254AbhH0DNW (ORCPT ); Thu, 26 Aug 2021 23:13:22 -0400 Received: from mail-pl1-x649.google.com (mail-pl1-x649.google.com [IPv6:2607:f8b0:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2EF6BC06179A for ; Thu, 26 Aug 2021 20:12:34 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id q11-20020a170902c9cb00b0013346a0d4e6so813931pld.14 for ; Thu, 26 Aug 2021 20:12:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=7ltC4LZo1AcY0S785rbycN7qIa7ski/y0jqVxQdf//g=; b=LYE1laivzODuZsXoshmJAtzheodVE2wwS8bkF9cHWqmMDcCBsKcl+w4+x9dFffcuzf w5FU6go/6Jwok8enOr/d2pGjShsKPReeuuVyQWT7w419tOPcxUUQl3dKRK+rnG+Mua2H 1mBzkdfqe5nbhmQDZd5IfPBiXLdDF2cR613UU5UgcK5VhM3TUmY0QkeR+0hbua6KYCM8 dYcyx4kLa3rmpLzo/GkB24OHESdShWZ+4rR4hkHXsonwUGD3imXvgqJtTbmLJBYh9rk4 tXnRW+r7mfWxerft/N9Sit/QTNDfWYffQWXOQb0gAFldO6XLUJ/dmWaUGzv9MtO8EajJ UlwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=7ltC4LZo1AcY0S785rbycN7qIa7ski/y0jqVxQdf//g=; b=Av2ju32YxfeQRIoyN2CZOn7e/qwb4eE16+tS232AZc8aPhG9WY+zJYeDTOdG7MWfay 5yyfbloeKKzDcSCbxQhbjCUF7UnuPHQU9j/voWEH5K+cx57tQMqOeR/9ZjijrVpSl+RJ A4OZH7Us6pq34gOfdMCwPS0/xEy1LvmMfmtA+oU2QHT3yCZ1eOUUTzruSn2W4HTDU3iN fMZ+DdRo+FrsG1LvshFj7LkV+goHGcUOz3BxxeWVKxLGFmSrMCHb9VCiZZVeXY0YydHT 5msW3ngWacqbGqNi3CU3h/xKMltoFUF4bJdKCUmgsGbK/T5svbIwidMpBvSiCX6M9Cjy koww== X-Gm-Message-State: AOAM533NK0qT9v9gH+XTDKzTXXNkN3wva1EeJ0Wm+cnkU1t6K/sLyw1L KsU76tB1KjkDINPEYb/kfREkQihaKXPdxb3pRXEeOf9/Og0Kvd5c7lWPdTqCuunxffJw6cC8z8N uI2g5V4Y+M4AzL1TYLOdmLVwVv2Btrlv5oNMsAnWF5LL6tfZ+V5hataDzQzS2Izsoubif X-Google-Smtp-Source: ABdhPJys1F+IiVgX0Px/VLafA4eGGvfLR/Gd068xwtfS4zriSzQhRWWClkaefTPD2Emo10msKLXMscD2SaLaxyhu X-Received: from zxwang42.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2936]) (user=zixuanwang job=sendgmr) by 2002:a62:5c7:0:b029:3e0:dd9c:8fd2 with SMTP id 190-20020a6205c70000b02903e0dd9c8fd2mr6993660pff.28.1630033953505; Thu, 26 Aug 2021 20:12:33 -0700 (PDT) Date: Fri, 27 Aug 2021 03:12:10 +0000 In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com> Message-Id: <20210827031222.2778522-6-zixuanwang@google.com> Mime-Version: 1.0 References: <20210827031222.2778522-1-zixuanwang@google.com> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog Subject: [kvm-unit-tests PATCH v2 05/17] x86 UEFI: Load IDT after UEFI boot up From: Zixuan Wang To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com, erdemaktas@google.com, rientjes@google.com, seanjc@google.com, brijesh.singh@amd.com, Thomas.Lendacky@amd.com, varad.gautam@suse.com, jroedel@suse.de, bp@suse.de Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Interrupt descriptor table (IDT) is used by x86 arch to describe the interrupt handlers. UEFI already setup an IDT before running the test binaries, but this IDT is not compatible with the existing KVM-Unit-Tests test cases, e.g., x86/msr.c triggers a #GP fault when using UEFI IDT. This is because test cases setup new interrupt handlers and register them into KVM-Unit-Tests' IDT, but it takes no effect if we do not load KVM-Unit-Tests' IDT. This commit fixes this issue: 1. Port the IDT definition from cstart64.S to efistart64.S 2. Update IDT descriptor with runtime IDT address and load it In this commit, the x86/msr.c can run in UEFI and generates same output as the default Seabios version. Co-developed-by: Varad Gautam Signed-off-by: Varad Gautam Signed-off-by: Zixuan Wang --- lib/x86/setup.c | 6 ++++++ x86/Makefile.x86_64 | 2 +- x86/efi/README.md | 4 ++-- x86/efi/efistart64.S | 34 ++++++++++++++++++++++++++++++++++ x86/efi/elf_x86_64_efi.lds | 6 +++++- 5 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 x86/efi/efistart64.S diff --git a/lib/x86/setup.c b/lib/x86/setup.c index efb5ecd..5e369ea 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -10,6 +10,7 @@ #include "fwcfg.h" #include "alloc_phys.h" #include "argv.h" +#include "x86/desc.h" #include "asm/setup.h" extern char edata; @@ -122,9 +123,14 @@ void setup_multiboot(struct mbi_bootinfo *bi) #ifdef TARGET_EFI +/* From x86/efi/efistart64.S */ +extern void load_idt(void); + void setup_efi(void) { reset_apic(); + setup_idt(); + load_idt(); mask_pic_interrupts(); enable_apic(); enable_x2apic(); diff --git a/x86/Makefile.x86_64 b/x86/Makefile.x86_64 index a5f8923..aa23b22 100644 --- a/x86/Makefile.x86_64 +++ b/x86/Makefile.x86_64 @@ -5,7 +5,7 @@ ifeq ($(TARGET_EFI),y) exe = efi bin = so FORMAT = efi-app-x86_64 -cstart.o = x86/efi/crt0-efi-x86_64.o +cstart.o = $(TEST_DIR)/efi/efistart64.o else exe = flat bin = elf diff --git a/x86/efi/README.md b/x86/efi/README.md index befe9cc..360f9fe 100644 --- a/x86/efi/README.md +++ b/x86/efi/README.md @@ -22,13 +22,13 @@ To build: To run a test case with UEFI: - ./x86/efi/run ./x86/dummy.efi + ./x86/efi/run ./x86/msr.efi By default the runner script loads the UEFI firmware `/usr/share/ovmf/OVMF.fd`; please install UEFI firmware to this path, or specify the correct path through the env variable `EFI_UEFI`: - EFI_UEFI=/path/to/OVMF.fd ./x86/efi/run ./x86/dummy.efi + EFI_UEFI=/path/to/OVMF.fd ./x86/efi/run ./x86/msr.efi ## Code structure diff --git a/x86/efi/efistart64.S b/x86/efi/efistart64.S new file mode 100644 index 0000000..ec607da --- /dev/null +++ b/x86/efi/efistart64.S @@ -0,0 +1,34 @@ +/* Startup code and pre-defined data structures */ + +#include "crt0-efi-x86_64.S" + +.globl boot_idt +.globl idt_descr + +.data + +boot_idt: + .rept 256 + .quad 0 + .quad 0 + .endr +end_boot_idt: + +idt_descr: + .word end_boot_idt - boot_idt - 1 + .quad 0 /* To be filled with runtime addr of boot_idt(%rip) */ + +.section .init +.code64 +.text + +.globl load_idt +load_idt: + /* Set IDT runtime address */ + lea boot_idt(%rip), %rax + mov %rax, idt_descr+2(%rip) + + /* Load IDT */ + lidtq idt_descr(%rip) + + retq diff --git a/x86/efi/elf_x86_64_efi.lds b/x86/efi/elf_x86_64_efi.lds index 5eae376..3d92c86 100644 --- a/x86/efi/elf_x86_64_efi.lds +++ b/x86/efi/elf_x86_64_efi.lds @@ -1,4 +1,4 @@ -/* Copied from GNU-EFI/gnuefi/elf_x86_64_efi.lds, licensed under GNU GPL */ +/* Developed based on GNU-EFI/gnuefi/elf_x86_64_efi.lds, licensed under GNU GPL */ /* Same as elf_x86_64_fbsd_efi.lds, except for OUTPUT_FORMAT below - KEEP IN SYNC */ OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") OUTPUT_ARCH(i386:x86-64) @@ -38,6 +38,10 @@ SECTIONS *(.rodata*) *(.got.plt) *(.got) + /* Expected by lib/x86/desc.c to store exception_table */ + exception_table_start = .; + *(.data.ex) + exception_table_end = .; *(.data*) *(.sdata) /* the EFI loader doesn't seem to like a .bss section, so we stick From patchwork Fri Aug 27 03:12:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12461131 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 58D14C432BE for ; Fri, 27 Aug 2021 03:12:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 43BBF60F6C for ; Fri, 27 Aug 2021 03:12:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244122AbhH0DN1 (ORCPT ); Thu, 26 Aug 2021 23:13:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36150 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244100AbhH0DNY (ORCPT ); Thu, 26 Aug 2021 23:13:24 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E26F9C061757 for ; Thu, 26 Aug 2021 20:12:35 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id q23-20020a6562570000b029023cbfb4fd73so2584921pgv.14 for ; Thu, 26 Aug 2021 20:12:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=Gka1dI7P9lBEiuUdPc0CEpOt/++HLm6/PwfPOTzYM3w=; b=tlfMhVaYZoAVW30vTZlQaIKPt+70XCyCGQNXMcfNgYYwZn0fCX/6ZzjK8gI99uhw17 gexcVZ2YdM+f+5+zAy9a2+Blxne8AikeLCZoADtR34opQ/7b/8+KW4tTdj75b2xGlXF7 1/SLaF89pAQn1188fZxV3IHy7rDucxkg1o+oeKICpwbt4cd7YwkuYFTWFiqPkETF+q9i XoFsVBmQb/0cfCIWolwAQAjJKRQ1w0mms7idksc6YQs6awqRQw4UP5y6FFxlJPsJ2KRd wzmyHGEkWmxZst70CUa3dZRbD8p9uSKniQQmgC3m8bP3uOn4WyLmp1lTvh/aIdwJCxoB /oEA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=Gka1dI7P9lBEiuUdPc0CEpOt/++HLm6/PwfPOTzYM3w=; b=YgKiUv7ByFUIpUoq04LtO9UpI1zk+6zOwpZmRybXLZx/FthxPbielzLT1UJyndceFC SLLjvPATK8JtkWfo2JH8hPog0Ek0AfgHitcsdwLvDmnoaOeIuCz4MwDFIJgQm0kx0lv9 MitwQERI0/ITKuZ+vddHkQgyjfbn7sn0Bfcv+HitqYg06MuJpFtdT2MPusp9M1pSNQo2 vYIiWjxRZ5HxJXXERI1gmd+a7U/shfcJrPOIWRekq/DTTdDKj7pJl3kbrcBdZVuYqnwk P7/w3nCbt3blXldtqkS8fX68hlr+E60YvKi+Kh01AnYOAk8unHVgAOpOFvlipZdGVOs5 NDYw== X-Gm-Message-State: AOAM532qAbPAbXa+dbVocKB55SAWQ9uhG6+8DH2Pmma0n7ag18G9r0n4 gEMaJbgaP6ZGgQZKaLS19Ba8V4etqDYtuhZPZI+n7RH5mM22opbv9LUl9/w2umQ/nr215woukqC VNJf6vzvdmUh8ihE9s7CGEP082WjsDDCgHNM1Y5D0P+NG/gQ3kLJbWGC6shfiR1dKpzp3 X-Google-Smtp-Source: ABdhPJxVz0IYCgfoc97yWjYgpmf9Tk101wMzGjAPDmw/Z8jaDEIPkPvtcrtK1+5nySDWw1J3kY+Oe5xqo5ePv3uE X-Received: from zxwang42.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2936]) (user=zixuanwang job=sendgmr) by 2002:a17:90a:2e0e:: with SMTP id q14mr20437134pjd.16.1630033955274; Thu, 26 Aug 2021 20:12:35 -0700 (PDT) Date: Fri, 27 Aug 2021 03:12:11 +0000 In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com> Message-Id: <20210827031222.2778522-7-zixuanwang@google.com> Mime-Version: 1.0 References: <20210827031222.2778522-1-zixuanwang@google.com> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog Subject: [kvm-unit-tests PATCH v2 06/17] x86 UEFI: Load GDT and TSS after UEFI boot up From: Zixuan Wang To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com, erdemaktas@google.com, rientjes@google.com, seanjc@google.com, brijesh.singh@amd.com, Thomas.Lendacky@amd.com, varad.gautam@suse.com, jroedel@suse.de, bp@suse.de Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Global Descriptor Table (GDT) defines x86 memory areas, e.g. memory area for data or code. UEFI has a different GDT compared to KVM-Unit-Tests, e.g., in UEFI, 3rd GDT entry defines a code segment, while in KVM-Unit-Tests, 3rd GDT entry is data segment. Without loading KVM-Unit-Tests GDT, the UEFI GDT is used and is incompatible with KVM-Unit-Tests. This causes QEMU to silently crash when a test case changes segments. This commit fixes this issue by loading KVM-Unit-Tests GDT to replace UEFI GDT. And since Task State Segment (TSS) is tightly coupled with GDT, this commit also loads TSS on boot-up. The GDT and TSS loading function is originally written in assembly code, see cstart64.S load_tss function. This commit provides a similar C function setup_gdt_tss() which is more readable and easier to modify. In this commit, x86/debug.c can run in UEFI and pass all sub-tests. Co-developed-by: Varad Gautam Signed-off-by: Varad Gautam Signed-off-by: Zixuan Wang --- lib/x86/setup.c | 44 ++++++++++++++++++++++ x86/efi/efistart64.S | 88 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) diff --git a/lib/x86/setup.c b/lib/x86/setup.c index 5e369ea..0a065fe 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -125,10 +125,54 @@ void setup_multiboot(struct mbi_bootinfo *bi) /* From x86/efi/efistart64.S */ extern void load_idt(void); +extern void load_gdt_tss(size_t tss_offset); +extern phys_addr_t tss_descr; +extern phys_addr_t ring0stacktop; +extern gdt_entry_t gdt64[]; +extern size_t ring0stacksize; + +static void setup_gdt_tss(void) +{ + gdt_entry_t *tss_lo, *tss_hi; + tss64_t *curr_tss; + phys_addr_t curr_tss_addr; + u32 id; + size_t tss_offset; + size_t pre_tss_entries; + + /* Get APIC ID, see also x86/cstart64.S:load_tss */ + id = apic_id(); + + /* Get number of GDT entries before TSS-related GDT entry */ + pre_tss_entries = (size_t)((u8 *)&(tss_descr) - (u8 *)gdt64) / sizeof(gdt_entry_t); + + /* Each TSS descriptor takes up 2 GDT entries */ + tss_offset = (pre_tss_entries + id * 2) * sizeof(gdt_entry_t); + tss_lo = &(gdt64[pre_tss_entries + id * 2 + 0]); + tss_hi = &(gdt64[pre_tss_entries + id * 2 + 1]); + + /* Runtime address of current TSS */ + curr_tss_addr = (((phys_addr_t)&tss) + (phys_addr_t)(id * sizeof(tss64_t))); + + /* Use runtime address for ring0stacktop, see also x86/cstart64.S:tss */ + curr_tss = (tss64_t *)curr_tss_addr; + curr_tss->rsp0 = (u64)((u8*)&ring0stacktop - id * ring0stacksize); + + /* Update TSS descriptors */ + tss_lo->limit_low = sizeof(tss64_t); + tss_lo->base_low = (u16)(curr_tss_addr & 0xffff); + tss_lo->base_middle = (u8)((curr_tss_addr >> 16) & 0xff); + tss_lo->base_high = (u8)((curr_tss_addr >> 24) & 0xff); + tss_hi->limit_low = (u16)((curr_tss_addr >> 32) & 0xffff); + tss_hi->base_low = (u16)((curr_tss_addr >> 48) & 0xffff); + + load_gdt_tss(tss_offset); +} void setup_efi(void) { reset_apic(); + setup_gdt_tss(); setup_idt(); load_idt(); mask_pic_interrupts(); diff --git a/x86/efi/efistart64.S b/x86/efi/efistart64.S index ec607da..a14bd46 100644 --- a/x86/efi/efistart64.S +++ b/x86/efi/efistart64.S @@ -1,9 +1,24 @@ /* Startup code and pre-defined data structures */ +#include "apic-defs.h" +#include "asm-generic/page.h" #include "crt0-efi-x86_64.S" .globl boot_idt .globl idt_descr +.globl tss_descr +.globl gdt64_desc +.globl ring0stacksize + +max_cpus = MAX_TEST_CPUS +ring0stacksize = PAGE_SIZE + +.bss + +.globl ring0stacktop + . = . + ring0stacksize * max_cpus + .align 16 +ring0stacktop: .data @@ -18,6 +33,48 @@ idt_descr: .word end_boot_idt - boot_idt - 1 .quad 0 /* To be filled with runtime addr of boot_idt(%rip) */ +gdt64_desc: + .word gdt64_end - gdt64 - 1 + .quad 0 /* To be filled with runtime addr of gdt64(%rip) */ + +.globl gdt64 +gdt64: + .quad 0 + .quad 0x00af9b000000ffff /* 64-bit code segment */ + .quad 0x00cf93000000ffff /* 32/64-bit data segment */ + .quad 0x00af1b000000ffff /* 64-bit code segment, not present */ + .quad 0x00cf9b000000ffff /* 32-bit code segment */ + .quad 0x008f9b000000FFFF /* 16-bit code segment */ + .quad 0x008f93000000FFFF /* 16-bit data segment */ + .quad 0x00cffb000000ffff /* 32-bit code segment (user) */ + .quad 0x00cff3000000ffff /* 32/64-bit data segment (user) */ + .quad 0x00affb000000ffff /* 64-bit code segment (user) */ + + .quad 0 /* 6 spare selectors */ + .quad 0 + .quad 0 + .quad 0 + .quad 0 + .quad 0 + +tss_descr: + .rept max_cpus + .quad 0x000089000000ffff /* 64-bit avail tss */ + .quad 0 /* tss high addr */ + .endr +gdt64_end: + +.globl tss +tss: + .rept max_cpus + .long 0 + .quad 0 + .quad 0, 0 + .quad 0, 0, 0, 0, 0, 0, 0, 0 + .long 0, 0, 0 + .endr +tss_end: + .section .init .code64 .text @@ -32,3 +89,34 @@ load_idt: lidtq idt_descr(%rip) retq + +.globl load_gdt_tss +load_gdt_tss: + /* Set GDT runtime address */ + lea gdt64(%rip), %rax + mov %rax, gdt64_desc+2(%rip) + + /* Load GDT */ + lgdt gdt64_desc(%rip) + + /* Load TSS */ + mov %rdi, %rax + ltr %ax + + /* Update data segments */ + mov $0x10, %ax /* 3rd entry in gdt64: 32/64-bit data segment */ + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + mov %ax, %ss + + /* + * Update the code segment by putting it on the stack before the return + * address, then doing a far return: this will use the new code segment + * along with the address. + */ + popq %rdi + pushq $0x08 /* 2nd entry in gdt64: 64-bit code segment */ + pushq %rdi + lretq From patchwork Fri Aug 27 03:12:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12461133 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E875EC4320E for ; Fri, 27 Aug 2021 03:12:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CE7AC60F6C for ; Fri, 27 Aug 2021 03:12:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244125AbhH0DN2 (ORCPT ); Thu, 26 Aug 2021 23:13:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36158 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244117AbhH0DNZ (ORCPT ); Thu, 26 Aug 2021 23:13:25 -0400 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CC0F6C061757 for ; Thu, 26 Aug 2021 20:12:37 -0700 (PDT) Received: by mail-pj1-x1049.google.com with SMTP id s2-20020a17090a948200b001927a323769so1306641pjo.9 for ; Thu, 26 Aug 2021 20:12:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=t39Mv0ccoM5NmVCSCdog5kXFGY+iF5gUOM0LhYajG54=; b=KBNz29sATJ6f5pkNlzcQbGiPG9ZqJPAFkiALxlwQQ4yw/aEx+l5OGnMc1iuBvlk3BT 3hcz3sirD+OdbvDDf7imDbLUusnySs7TQzbbKy2R48FJ6jezH0bFjw1BzMRjyS3EsM2H LAAPxTYtyIQhCfQmZMY+6maGi/tTbkP4tf+Vs0cfLy4ZS5ZMCONZRlEKkQRSsH+smU14 c1pra1OIhTR5tBbB2Icv2D8SDEdHocK9fwDZUwsoyVcO9DC2qlfG/r4PpJqvfK29f6u1 bIEvXBm09dauFDRxEPOQ/7gVRmHNVd0mSY0kczRBCau/RBxgreIgOYrO7R9N1OQZlF/E t/1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=t39Mv0ccoM5NmVCSCdog5kXFGY+iF5gUOM0LhYajG54=; b=fKcnTRv6A/xbeoBgrajkeHqAqkqOsjeaf9OBRtU98uFWBWSIiZBG5XPC9I8QrLqxZm hdr44Yv0rG4Diy1VOf24JPT6FFR1vlh7T73jWv37GUAnHJW6L4/uY0Rt9XEC0BJQ878Y jFajdcLV1l3HK3PRwF9aOciifwO4Xi308UeYMCiseRAh2UYSEmA1t9MKAxkjc+yvQ1ae 2KfmP0Ok0uGDK2NpLz0Iad2Or7kPKAGPjxDBBtFq8MK7lTFYShYSvK4lJkXC5FGa516i HRj52S857upyz9Q/d4wNYj2Daq8yl/Sibs1JhWmjP7BrWx+m3lybnqhh3DjhlVMWPVvZ etNw== X-Gm-Message-State: AOAM532TJK7GY08ZKhoBERuXzxyFgPkfEkaPoGy2UZN12J+vi+sWUtub wrR5TbP4b8Sf2xSU9Pc64XO+0N6pFDYxggrLu20lkqGwcY7bK3ExXiCXqe5rIHT1JyKDOeaH/y/ JDi7WzpABzrqkpv9aKjEEn9wuUF0aIKhMYrnStvOwv8Z0kTS5JO9Zu9sOaUQTUJjUCQcR X-Google-Smtp-Source: ABdhPJyINF5JntVdt+ioKhUjqjN/bBOPzrVTD2w1oUoEhnbTpmGTaS/hR+cGgUQSwljD58v2o8zcxVyfggfhcq0F X-Received: from zxwang42.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2936]) (user=zixuanwang job=sendgmr) by 2002:a62:7d84:0:b029:3b8:49bb:4c3f with SMTP id y126-20020a627d840000b02903b849bb4c3fmr6953419pfc.49.1630033957129; Thu, 26 Aug 2021 20:12:37 -0700 (PDT) Date: Fri, 27 Aug 2021 03:12:12 +0000 In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com> Message-Id: <20210827031222.2778522-8-zixuanwang@google.com> Mime-Version: 1.0 References: <20210827031222.2778522-1-zixuanwang@google.com> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog Subject: [kvm-unit-tests PATCH v2 07/17] x86 UEFI: Set up memory allocator From: Zixuan Wang To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com, erdemaktas@google.com, rientjes@google.com, seanjc@google.com, brijesh.singh@amd.com, Thomas.Lendacky@amd.com, varad.gautam@suse.com, jroedel@suse.de, bp@suse.de Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org KVM-Unit-Tests library implements a memory allocator which requires two arguments to set up (See `lib/alloc_phys.c:phys_alloc_init()` for more details): 1. A base (start) physical address 2. Size of available memory for allocation To get this memory info, we scan all the memory regions returned by `LibMemoryMap()`, find out the largest free memory region and use it for memory allocation. After retrieving this memory info, we call `ExitBootServices` so that KVM-Unit-Tests has full control of the machine, and UEFI will not touch the memory after this point. Starting from this commit, `x86/hypercall.c` test case can run in UEFI and generates the same output as in Seabios. Co-developed-by: Varad Gautam Signed-off-by: Varad Gautam Signed-off-by: Zixuan Wang --- lib/efi.c | 28 +++++++++++++--- lib/efi.h | 2 +- lib/x86/asm/setup.h | 16 +++++++++- lib/x86/setup.c | 78 ++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 116 insertions(+), 8 deletions(-) diff --git a/lib/efi.c b/lib/efi.c index 99307db..b7a69d3 100644 --- a/lib/efi.c +++ b/lib/efi.c @@ -31,9 +31,10 @@ efi_status_t efi_get_memory_map(struct efi_boot_memmap *map) efi_memory_desc_t *m = NULL; efi_status_t status; unsigned long key = 0, map_size = 0, desc_size = 0; + u32 desc_ver; status = efi_bs_call(get_memory_map, &map_size, - NULL, &key, &desc_size, NULL); + NULL, &key, &desc_size, &desc_ver); if (status != EFI_BUFFER_TOO_SMALL || map_size == 0) goto out; @@ -48,12 +49,13 @@ efi_status_t efi_get_memory_map(struct efi_boot_memmap *map) /* Get the map. */ status = efi_bs_call(get_memory_map, &map_size, - m, &key, &desc_size, NULL); + m, &key, &desc_size, &desc_ver); if (status != EFI_SUCCESS) { efi_free_pool(m); goto out; } + *map->desc_ver = desc_ver; *map->desc_size = desc_size; *map->map_size = map_size; *map->key_ptr = key; @@ -62,18 +64,34 @@ out: return status; } -efi_status_t efi_exit_boot_services(void *handle, struct efi_boot_memmap *map) +efi_status_t efi_exit_boot_services(void *handle, unsigned long mapkey) { - return efi_bs_call(exit_boot_services, handle, *map->key_ptr); + return efi_bs_call(exit_boot_services, handle, mapkey); } efi_status_t efi_main(efi_handle_t handle, efi_system_table_t *sys_tab) { int ret; + unsigned long mapkey = 0; + efi_status_t status; + efi_bootinfo_t efi_bootinfo; efi_system_table = sys_tab; - setup_efi(); + setup_efi_bootinfo(&efi_bootinfo); + status = setup_efi_pre_boot(&mapkey, &efi_bootinfo); + if (status != EFI_SUCCESS) { + printf("Failed to set up before ExitBootServices, exiting.\n"); + return status; + } + + status = efi_exit_boot_services(handle, mapkey); + if (status != EFI_SUCCESS) { + printf("Failed to exit boot services\n"); + return status; + } + + setup_efi(&efi_bootinfo); ret = main(__argc, __argv, __environ); /* Shutdown the guest VM */ diff --git a/lib/efi.h b/lib/efi.h index 60cdb6f..2d3772c 100644 --- a/lib/efi.h +++ b/lib/efi.h @@ -11,7 +11,7 @@ efi_status_t _relocate(long ldbase, Elf64_Dyn *dyn, efi_handle_t handle, efi_system_table_t *sys_tab); efi_status_t efi_get_memory_map(struct efi_boot_memmap *map); -efi_status_t efi_exit_boot_services(void *handle, struct efi_boot_memmap *map); +efi_status_t efi_exit_boot_services(void *handle, unsigned long mapkey); efi_status_t efi_main(efi_handle_t handle, efi_system_table_t *sys_tab); #endif /* _EFI_H_ */ diff --git a/lib/x86/asm/setup.h b/lib/x86/asm/setup.h index eb1cf73..8ff31ef 100644 --- a/lib/x86/asm/setup.h +++ b/lib/x86/asm/setup.h @@ -4,8 +4,22 @@ #ifdef TARGET_EFI #include "x86/apic.h" #include "x86/smp.h" +#include "efi.h" -void setup_efi(void); +/* + * efi_bootinfo_t: stores EFI-related machine info retrieved by + * setup_efi_pre_boot(), and is then used by setup_efi(). setup_efi() cannot + * retrieve this info as it is called after ExitBootServices and thus some EFI + * resources are not available. + */ +typedef struct { + phys_addr_t free_mem_start; + phys_addr_t free_mem_size; +} efi_bootinfo_t; + +void setup_efi_bootinfo(efi_bootinfo_t *efi_bootinfo); +void setup_efi(efi_bootinfo_t *efi_bootinfo); +efi_status_t setup_efi_pre_boot(unsigned long *mapkey, efi_bootinfo_t *efi_bootinfo); #endif /* TARGET_EFI */ #endif /* _X86_ASM_SETUP_H_ */ diff --git a/lib/x86/setup.c b/lib/x86/setup.c index 0a065fe..a49e0d4 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -131,6 +131,81 @@ extern phys_addr_t ring0stacktop; extern gdt_entry_t gdt64[]; extern size_t ring0stacksize; +void setup_efi_bootinfo(efi_bootinfo_t *efi_bootinfo) +{ + efi_bootinfo->free_mem_size = 0; + efi_bootinfo->free_mem_start = 0; +} + +static efi_status_t setup_pre_boot_memory(unsigned long *mapkey, efi_bootinfo_t *efi_bootinfo) +{ + int i; + unsigned long free_mem_total_pages; + efi_status_t status; + struct efi_boot_memmap map; + efi_memory_desc_t *buffer, *d; + unsigned long map_size, desc_size, buff_size; + u32 desc_ver; + + map.map = &buffer; + map.map_size = &map_size; + map.desc_size = &desc_size; + map.desc_ver = &desc_ver; + map.buff_size = &buff_size; + map.key_ptr = mapkey; + + status = efi_get_memory_map(&map); + if (status != EFI_SUCCESS) { + return status; + } + + /* + * The 'buffer' contains multiple descriptors that describe memory + * regions maintained by UEFI. This code records the largest free + * EFI_CONVENTIONAL_MEMORY region which will be used to set up the + * memory allocator, so that the memory allocator can work in the + * largest free continuous memory region. + */ + free_mem_total_pages = 0; + for (i = 0; i < map_size; i += desc_size) { + d = (efi_memory_desc_t *)(&((u8 *)buffer)[i]); + if (d->type == EFI_CONVENTIONAL_MEMORY) { + if (free_mem_total_pages < d->num_pages) { + free_mem_total_pages = d->num_pages; + efi_bootinfo->free_mem_size = free_mem_total_pages << EFI_PAGE_SHIFT; + efi_bootinfo->free_mem_start = d->phys_addr; + } + } + } + + if (efi_bootinfo->free_mem_size == 0) { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + +efi_status_t setup_efi_pre_boot(unsigned long *mapkey, efi_bootinfo_t *efi_bootinfo) +{ + efi_status_t status; + + status = setup_pre_boot_memory(mapkey, efi_bootinfo); + if (status != EFI_SUCCESS) { + printf("setup_pre_boot_memory() failed: "); + switch (status) { + case EFI_OUT_OF_RESOURCES: + printf("No free memory region\n"); + break; + default: + printf("Unknown error\n"); + break; + } + return status; + } + + return EFI_SUCCESS; +} + static void setup_gdt_tss(void) { gdt_entry_t *tss_lo, *tss_hi; @@ -169,7 +244,7 @@ static void setup_gdt_tss(void) load_gdt_tss(tss_offset); } -void setup_efi(void) +void setup_efi(efi_bootinfo_t *efi_bootinfo) { reset_apic(); setup_gdt_tss(); @@ -179,6 +254,7 @@ void setup_efi(void) enable_apic(); enable_x2apic(); smp_init(); + phys_alloc_init(efi_bootinfo->free_mem_start, efi_bootinfo->free_mem_size); } #endif /* TARGET_EFI */ From patchwork Fri Aug 27 03:12:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12461135 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-23.5 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY,USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E484BC43214 for ; Fri, 27 Aug 2021 03:12:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CD2E260F5C for ; Fri, 27 Aug 2021 03:12:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244130AbhH0DN3 (ORCPT ); Thu, 26 Aug 2021 23:13:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36168 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244100AbhH0DN1 (ORCPT ); Thu, 26 Aug 2021 23:13:27 -0400 Received: from mail-pf1-x44a.google.com (mail-pf1-x44a.google.com [IPv6:2607:f8b0:4864:20::44a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BDEA8C061757 for ; Thu, 26 Aug 2021 20:12:39 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id h14-20020a62b40e0000b02903131bc4a1acso1016423pfn.4 for ; Thu, 26 Aug 2021 20:12:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=wafX0J1iAcDNb1VM5RGEmbl1J6prBNTEbq3Ps4I44sY=; b=SaQjJDSXhq8hvX6H3FNhakkb3egG/AqIipM5x2jQke8kQ+wlnP2WsD7e795fYKVOI1 QdSrBxWzQHR4A4uoEu/W5fs6f3iEvum8dmxoRsI59zU1DnvJvnu/QLsgCBi5PLQMTv6Z OCoTMLr5/W51PNs/WBQJVjz4LOvGN/0Tqrsyd8cJZeybhWt19eI06SSWgRgAQqYTToD+ jRbXjgGzlfRfLsBSmlSqh0VLEXov577KXfziNSLDXP9xz4K5o7yU4SKIcM5VYT+UyYwJ FNql+2Nk9NrKhgBxXpcsnTYJ8XOpKnLV69OSm2J3QRoqEkCHDEvbhDz/71yg8V3Kk+qt Rjxg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=wafX0J1iAcDNb1VM5RGEmbl1J6prBNTEbq3Ps4I44sY=; b=XMYugRZNC2vnO2xYF4VIo7EzgmUIUKt86CZWkhM5Y9HxzrTNq5O8riwVBzV4hXWi2F Qa547yKVx1z95BRO7JCUl+/wCInq2lzeWf12SfnzJxo3bT9lhAProtELYSkM23fozsY6 CfxL5QxnjnMbMm0J+jApzB32qaJVdbAzofF7OHpTe6SctqykbaxKo8M0FCwgYciHqkc8 dbg7RbztIA8B2w6YWK/TRw1ZSYQr2JS209AzzGLmlgqHuAflBXJP2PSkgSH+A5qHp7Vo PinUKdZcL3rkiRKJ7EbWYmMmvvtDGXVY4lnW/lUQbwSFCGgjrfgAzbuZrtwYRzC8JKV4 RfXg== X-Gm-Message-State: AOAM532rnS8j6XtZ1kv/Pq6SW62goB0QbLGB7hYUWyMf79KCYHMTPMfG ONKTmarlycH7JvXmL3IfotYlwQzLUHBg4M7G8WxUNiifXQJpcRXkebmKsTYAmulVYoRFIwieSiD S5CIALCW83+N9IPpH0Kk3UYp4LEyU6VCunVOzemSI4K7Jm94HJQYMpTi5LbQPEIXWNJ8x X-Google-Smtp-Source: ABdhPJwAveJ4bj0cPWLrYTnNHCsbW/hoo27bHQfyQmw+3XMveZgp1gedd5W8VlxFY/rqvPRzbRoUP9g3xFj4qTpt X-Received: from zxwang42.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2936]) (user=zixuanwang job=sendgmr) by 2002:a05:6a00:10cb:b029:3c6:8cc9:5098 with SMTP id d11-20020a056a0010cbb02903c68cc95098mr6983523pfu.41.1630033959005; Thu, 26 Aug 2021 20:12:39 -0700 (PDT) Date: Fri, 27 Aug 2021 03:12:13 +0000 In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com> Message-Id: <20210827031222.2778522-9-zixuanwang@google.com> Mime-Version: 1.0 References: <20210827031222.2778522-1-zixuanwang@google.com> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog Subject: [kvm-unit-tests PATCH v2 08/17] x86 UEFI: Set up RSDP after UEFI boot up From: Zixuan Wang To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com, erdemaktas@google.com, rientjes@google.com, seanjc@google.com, brijesh.singh@amd.com, Thomas.Lendacky@amd.com, varad.gautam@suse.com, jroedel@suse.de, bp@suse.de Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Root system description pointer (RSDP) is a data structure used in the ACPI programming interface. In BIOS, RSDP is located within a predefined memory area, so a program can scan the memory area and find RSDP. But in UEFI, RSDP may not appear in that memory area, instead, a program should find it in the EFI system table. This commit provides RSDP set up code in UEFI: 1. Read RSDP from EFI system table 2. Pass RSDP pointer to find_acpi_table_attr() function From this commit, the `x86/s3.c` test can run in UEFI and generates similar output as in Seabios, note that: 1. In its output, memory addresses are different than Seabios's, this is because EFI application starts from a dynamic runtime address, not a fixed predefined memory address 2. There is a short delay (~5 secs) after the test case prints "PM1a event registers" line. This test case sleeps for a few seconds and then wakes up, so give it a few seconds to run. Signed-off-by: Zixuan Wang --- lib/efi.c | 15 +++++++++++++++ lib/efi.h | 1 + lib/linux/uefi.h | 15 +++++++++++++++ lib/x86/acpi.c | 38 +++++++++++++++++++++++++++++++------- lib/x86/acpi.h | 11 +++++++++++ lib/x86/asm/setup.h | 2 ++ lib/x86/setup.c | 13 +++++++++++++ 7 files changed, 88 insertions(+), 7 deletions(-) diff --git a/lib/efi.c b/lib/efi.c index b7a69d3..a0d4476 100644 --- a/lib/efi.c +++ b/lib/efi.c @@ -69,6 +69,21 @@ efi_status_t efi_exit_boot_services(void *handle, unsigned long mapkey) return efi_bs_call(exit_boot_services, handle, mapkey); } +efi_status_t efi_get_system_config_table(efi_guid_t table_guid, void **table) +{ + size_t i; + efi_config_table_t *tables; + + tables = (efi_config_table_t *)efi_system_table->tables; + for (i = 0; i < efi_system_table->nr_tables; i++) { + if (!memcmp(&table_guid, &tables[i].guid, sizeof(efi_guid_t))) { + *table = tables[i].table; + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} + efi_status_t efi_main(efi_handle_t handle, efi_system_table_t *sys_tab) { int ret; diff --git a/lib/efi.h b/lib/efi.h index 2d3772c..dbb8159 100644 --- a/lib/efi.h +++ b/lib/efi.h @@ -12,6 +12,7 @@ efi_status_t _relocate(long ldbase, Elf64_Dyn *dyn, efi_handle_t handle, efi_system_table_t *sys_tab); efi_status_t efi_get_memory_map(struct efi_boot_memmap *map); efi_status_t efi_exit_boot_services(void *handle, unsigned long mapkey); +efi_status_t efi_get_system_config_table(efi_guid_t table_guid, void **table); efi_status_t efi_main(efi_handle_t handle, efi_system_table_t *sys_tab); #endif /* _EFI_H_ */ diff --git a/lib/linux/uefi.h b/lib/linux/uefi.h index 9adc7ab..d1d599f 100644 --- a/lib/linux/uefi.h +++ b/lib/linux/uefi.h @@ -58,6 +58,21 @@ typedef guid_t efi_guid_t; (b) & 0xff, ((b) >> 8) & 0xff, \ (c) & 0xff, ((c) >> 8) & 0xff, d } } +#define ACPI_TABLE_GUID EFI_GUID(0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + +typedef struct { + efi_guid_t guid; + u32 table; +} efi_config_table_32_t; + +typedef union { + struct { + efi_guid_t guid; + void *table; + }; + efi_config_table_32_t mixed_mode; +} efi_config_table_t; + /* * Generic EFI table header */ diff --git a/lib/x86/acpi.c b/lib/x86/acpi.c index 4373106..0f75d79 100644 --- a/lib/x86/acpi.c +++ b/lib/x86/acpi.c @@ -1,9 +1,37 @@ #include "libcflat.h" #include "acpi.h" +#ifdef TARGET_EFI +struct rsdp_descriptor *efi_rsdp = NULL; + +void setup_efi_rsdp(struct rsdp_descriptor *rsdp) { + efi_rsdp = rsdp; +} + +static struct rsdp_descriptor *get_rsdp(void) { + if (efi_rsdp == NULL) { + printf("Can't find RSDP from UEFI, maybe setup_efi_rsdp() was not called\n"); + } + return efi_rsdp; +} +#else +static struct rsdp_descriptor *get_rsdp(void) { + struct rsdp_descriptor *rsdp; + unsigned long addr; + for(addr = 0xf0000; addr < 0x100000; addr += 16) { + rsdp = (void*)addr; + if (rsdp->signature == RSDP_SIGNATURE_8BYTE) + break; + } + if (addr == 0x100000) { + return NULL; + } + return rsdp; +} +#endif /* TARGET_EFI */ + void* find_acpi_table_addr(u32 sig) { - unsigned long addr; struct rsdp_descriptor *rsdp; struct rsdt_descriptor_rev1 *rsdt; void *end; @@ -19,12 +47,8 @@ void* find_acpi_table_addr(u32 sig) return (void*)(ulong)fadt->firmware_ctrl; } - for(addr = 0xf0000; addr < 0x100000; addr += 16) { - rsdp = (void*)addr; - if (rsdp->signature == 0x2052545020445352LL) - break; - } - if (addr == 0x100000) { + rsdp = get_rsdp(); + if (rsdp == NULL) { printf("Can't find RSDP\n"); return 0; } diff --git a/lib/x86/acpi.h b/lib/x86/acpi.h index 1b80374..db8ee56 100644 --- a/lib/x86/acpi.h +++ b/lib/x86/acpi.h @@ -11,6 +11,13 @@ #define FACP_SIGNATURE ACPI_SIGNATURE('F','A','C','P') #define FACS_SIGNATURE ACPI_SIGNATURE('F','A','C','S') + +#define ACPI_SIGNATURE_8BYTE(c1, c2, c3, c4, c5, c6, c7, c8) \ + ((uint64_t)(ACPI_SIGNATURE(c1, c2, c3, c4))) | \ + ((uint64_t)(ACPI_SIGNATURE(c5, c6, c7, c8)) << 32) + +#define RSDP_SIGNATURE_8BYTE (ACPI_SIGNATURE_8BYTE('R', 'S', 'D', ' ', 'P', 'T', 'R', ' ')) + struct rsdp_descriptor { /* Root System Descriptor Pointer */ u64 signature; /* ACPI signature, contains "RSD PTR " */ u8 checksum; /* To make sum of struct == 0 */ @@ -101,4 +108,8 @@ struct facs_descriptor_rev1 void* find_acpi_table_addr(u32 sig); +#ifdef TARGET_EFI +void setup_efi_rsdp(struct rsdp_descriptor *rsdp); +#endif /* TARGET_EFI */ + #endif diff --git a/lib/x86/asm/setup.h b/lib/x86/asm/setup.h index 8ff31ef..40fd963 100644 --- a/lib/x86/asm/setup.h +++ b/lib/x86/asm/setup.h @@ -2,6 +2,7 @@ #define _X86_ASM_SETUP_H_ #ifdef TARGET_EFI +#include "x86/acpi.h" #include "x86/apic.h" #include "x86/smp.h" #include "efi.h" @@ -15,6 +16,7 @@ typedef struct { phys_addr_t free_mem_start; phys_addr_t free_mem_size; + struct rsdp_descriptor *rsdp; } efi_bootinfo_t; void setup_efi_bootinfo(efi_bootinfo_t *efi_bootinfo); diff --git a/lib/x86/setup.c b/lib/x86/setup.c index a49e0d4..1ddfb8c 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -135,6 +135,7 @@ void setup_efi_bootinfo(efi_bootinfo_t *efi_bootinfo) { efi_bootinfo->free_mem_size = 0; efi_bootinfo->free_mem_start = 0; + efi_bootinfo->rsdp = NULL; } static efi_status_t setup_pre_boot_memory(unsigned long *mapkey, efi_bootinfo_t *efi_bootinfo) @@ -185,6 +186,11 @@ static efi_status_t setup_pre_boot_memory(unsigned long *mapkey, efi_bootinfo_t return EFI_SUCCESS; } +static efi_status_t setup_pre_boot_rsdp(efi_bootinfo_t *efi_bootinfo) +{ + return efi_get_system_config_table(ACPI_TABLE_GUID, (void **)&efi_bootinfo->rsdp); +} + efi_status_t setup_efi_pre_boot(unsigned long *mapkey, efi_bootinfo_t *efi_bootinfo) { efi_status_t status; @@ -203,6 +209,12 @@ efi_status_t setup_efi_pre_boot(unsigned long *mapkey, efi_bootinfo_t *efi_booti return status; } + status = setup_pre_boot_rsdp(efi_bootinfo); + if (status != EFI_SUCCESS) { + printf("Cannot find RSDP in EFI system table\n"); + return status; + } + return EFI_SUCCESS; } @@ -255,6 +267,7 @@ void setup_efi(efi_bootinfo_t *efi_bootinfo) enable_x2apic(); smp_init(); phys_alloc_init(efi_bootinfo->free_mem_start, efi_bootinfo->free_mem_size); + setup_efi_rsdp(efi_bootinfo->rsdp); } #endif /* TARGET_EFI */ From patchwork Fri Aug 27 03:12:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12461139 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 003E2C432BE for ; Fri, 27 Aug 2021 03:12:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DFB7460F6F for ; Fri, 27 Aug 2021 03:12:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244135AbhH0DNa (ORCPT ); Thu, 26 Aug 2021 23:13:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36176 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244100AbhH0DN3 (ORCPT ); Thu, 26 Aug 2021 23:13:29 -0400 Received: from mail-pf1-x449.google.com (mail-pf1-x449.google.com [IPv6:2607:f8b0:4864:20::449]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 96A4EC061757 for ; Thu, 26 Aug 2021 20:12:41 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id d13-20020a056a0010cd00b003eb385150d1so7290pfu.10 for ; Thu, 26 Aug 2021 20:12:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=cEVYnZ9WXh+TM89zUGRqPhzSuIPcHo66mvZNyy63GPM=; b=v+30AWh9oYz8b6Jxri2eayuGHfVSk0NuoHCa1xhpZgm9UAx5uc/z66J1q5a34ZoDut ikmGApsoiMMwHDT67ZSZyurqUokd5830en/xY392j8VFxlWXsu3tLlqnfvrpqu4Qi1/w AV129cBq1gjB5+FFFzcE95nE1sth+/WmaVIomHyr1UFGaphwYHm93y5U6aG2dibtpw8z cDiBeLPcZGi/uJs944zwANwU354cAcTgP6IdGX/tB0ggFHg0icH0zaP3ciPET7IXuUpC cDNdzmbJpcaJdFB6zHoOImQGNoArsVk2CsmT0fTiWNyTkbczY+agoQY5LUZQ5uZ5yTOq hohA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=cEVYnZ9WXh+TM89zUGRqPhzSuIPcHo66mvZNyy63GPM=; b=YRVVJsG1CwuWubhOeuZMXrKimO75bjAKFQ5rmFeDXFS/7BYLI6yqZDi46q9BdILCez S3XKoBFpDGo9a3orkZHj33F67GTlTHpQ4zkOo0mllXZTYKaqYZtW2FjXU05IrcyKOsDf 2um6OUZKW1+XNHYudcEOKOKPq4Y4s5e7rC8tyKQKy0uVll3MaHbRKTl7wlA0K8oQ5oyb oTzvJjMgHBbNer8tsogoRbXXNeMiQRXnrXZzS+StKSCUtX7+a/ulNvD5cZy/ucKXk1Yb +3Yn9txSclMCfitDx/9q2TRlu7qFu7o2e5PVyihlgqV/j+NMZyir3t7JLx27f4rcxwdc xkLg== X-Gm-Message-State: AOAM532eIjxwhRag3I84d4P7liTghBbotz+pWAGm3YQhn6VuOfCkYeoH LrzVTkZWFmrytjbBPko+FkCq8/nCxJeEPn3ZK/n9UCRKEgdwRqgrs/OF0X9ZK4/stfATAz2aWDT yePdbEp4zBiOnmRUY8LOo+gGZfpz9nqTPGSAYrx3XWPxz46xaYEQoJp0h8btH81xM9Qfs X-Google-Smtp-Source: ABdhPJxGmTH0Aw6rGbKSPai8bbX+mcmOR83a50sO0seLfL7BZG9yC6Zuj0MqzSUMD1dmIV7UPclrzY/JYaKQXfa2 X-Received: from zxwang42.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2936]) (user=zixuanwang job=sendgmr) by 2002:a17:902:ab98:b029:12b:acc0:e18c with SMTP id f24-20020a170902ab98b029012bacc0e18cmr6616698plr.10.1630033960925; Thu, 26 Aug 2021 20:12:40 -0700 (PDT) Date: Fri, 27 Aug 2021 03:12:14 +0000 In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com> Message-Id: <20210827031222.2778522-10-zixuanwang@google.com> Mime-Version: 1.0 References: <20210827031222.2778522-1-zixuanwang@google.com> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog Subject: [kvm-unit-tests PATCH v2 09/17] x86 UEFI: Set up page tables From: Zixuan Wang To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com, erdemaktas@google.com, rientjes@google.com, seanjc@google.com, brijesh.singh@amd.com, Thomas.Lendacky@amd.com, varad.gautam@suse.com, jroedel@suse.de, bp@suse.de Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org UEFI sets up page tables before executing EFI application binaries. These page tables do not allow user space code to access kernel space memory. But `x86/syscall.c` test case places a user space function `syscall_tf_user32` inside kernel space memory. When using UEFI page tables, fetching this kernel memory from user space triggers a #PF fault, which is not expected by this test case. KVM-Unit-Tests defines page tables that allow such behavior. So the solution to this problem is to load KVM-Unit-Tests' page tables: 1. Copy the page table definition from `x86/cstart64.S` 2. Update page table entries with runtime memory addresses 3. Update CR3 register with the new page table root address Since this commit, `x86/syscall.c` can run in UEFI and generate same output as in Seabios, using the following command: ./x86/efi/run ./x86/syscall.efi --cpu Opteron_G1,vendor=AuthenticAMD Signed-off-by: Zixuan Wang --- lib/x86/asm/page.h | 1 + lib/x86/asm/setup.h | 3 +++ lib/x86/setup.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ x86/efi/efistart64.S | 21 ++++++++++++++++ 4 files changed, 82 insertions(+) diff --git a/lib/x86/asm/page.h b/lib/x86/asm/page.h index fc14160..f6f740b 100644 --- a/lib/x86/asm/page.h +++ b/lib/x86/asm/page.h @@ -31,6 +31,7 @@ typedef unsigned long pgd_t; #define PT_ACCESSED_MASK (1ull << 5) #define PT_DIRTY_MASK (1ull << 6) #define PT_PAGE_SIZE_MASK (1ull << 7) +#define PT_GLOBAL_MASK (1ull << 8) #define PT64_NX_MASK (1ull << 63) #define PT_ADDR_MASK GENMASK_ULL(51, 12) diff --git a/lib/x86/asm/setup.h b/lib/x86/asm/setup.h index 40fd963..16bad0f 100644 --- a/lib/x86/asm/setup.h +++ b/lib/x86/asm/setup.h @@ -4,7 +4,9 @@ #ifdef TARGET_EFI #include "x86/acpi.h" #include "x86/apic.h" +#include "x86/processor.h" #include "x86/smp.h" +#include "asm/page.h" #include "efi.h" /* @@ -22,6 +24,7 @@ typedef struct { void setup_efi_bootinfo(efi_bootinfo_t *efi_bootinfo); void setup_efi(efi_bootinfo_t *efi_bootinfo); efi_status_t setup_efi_pre_boot(unsigned long *mapkey, efi_bootinfo_t *efi_bootinfo); +void setup_5level_page_table(void); #endif /* TARGET_EFI */ #endif /* _X86_ASM_SETUP_H_ */ diff --git a/lib/x86/setup.c b/lib/x86/setup.c index 1ddfb8c..03598fe 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -218,6 +218,62 @@ efi_status_t setup_efi_pre_boot(unsigned long *mapkey, efi_bootinfo_t *efi_booti return EFI_SUCCESS; } +/* Defined in cstart64.S or efistart64.S */ +extern phys_addr_t ptl5; +extern phys_addr_t ptl4; +extern phys_addr_t ptl3; +extern phys_addr_t ptl2; + +static void setup_page_table(void) +{ + pgd_t *curr_pt; + phys_addr_t flags; + int i; + + /* Set default flags */ + flags = PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK; + + /* Level 5 */ + curr_pt = (pgd_t *)&ptl5; + curr_pt[0] = ((phys_addr_t)&ptl4) | flags; + /* Level 4 */ + curr_pt = (pgd_t *)&ptl4; + curr_pt[0] = ((phys_addr_t)&ptl3) | flags; + /* Level 3 */ + curr_pt = (pgd_t *)&ptl3; + for (i = 0; i < 4; i++) { + curr_pt[i] = (((phys_addr_t)&ptl2) + i * PAGE_SIZE) | flags; + } + /* Level 2 */ + curr_pt = (pgd_t *)&ptl2; + flags |= PT_ACCESSED_MASK | PT_DIRTY_MASK | PT_PAGE_SIZE_MASK | PT_GLOBAL_MASK; + for (i = 0; i < 4 * 512; i++) { + curr_pt[i] = ((phys_addr_t)(i << 21)) | flags; + } + + /* Load 4-level page table */ + write_cr3((ulong)&ptl4); +} + +void setup_5level_page_table(void) +{ + /* Check if 5-level page table is already enabled */ + if (read_cr4() & X86_CR4_LA57) { + return; + } + + /* Disable CR4.PCIDE */ + write_cr4(read_cr4() & ~(X86_CR4_PCIDE)); + /* Disable CR0.PG */ + write_cr0(read_cr0() & ~(X86_CR0_PG)); + + /* Load new page table */ + write_cr3((ulong)&ptl5); + + /* Enable CR4.LA57 */ + write_cr4(read_cr4() | X86_CR4_LA57); +} + static void setup_gdt_tss(void) { gdt_entry_t *tss_lo, *tss_hi; @@ -268,6 +324,7 @@ void setup_efi(efi_bootinfo_t *efi_bootinfo) smp_init(); phys_alloc_init(efi_bootinfo->free_mem_start, efi_bootinfo->free_mem_size); setup_efi_rsdp(efi_bootinfo->rsdp); + setup_page_table(); } #endif /* TARGET_EFI */ diff --git a/x86/efi/efistart64.S b/x86/efi/efistart64.S index a14bd46..86c3760 100644 --- a/x86/efi/efistart64.S +++ b/x86/efi/efistart64.S @@ -22,6 +22,27 @@ ring0stacktop: .data +.align PAGE_SIZE +.globl ptl2 +ptl2: + . = . + 4 * PAGE_SIZE +.align PAGE_SIZE + +.globl ptl3 +ptl3: + . = . + PAGE_SIZE +.align PAGE_SIZE + +.globl ptl4 +ptl4: + . = . + PAGE_SIZE +.align PAGE_SIZE + +.globl ptl5 +ptl5: + . = . + PAGE_SIZE +.align PAGE_SIZE + boot_idt: .rept 256 .quad 0 From patchwork Fri Aug 27 03:12:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12461141 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AE626C4320E for ; Fri, 27 Aug 2021 03:12:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9345960F6C for ; Fri, 27 Aug 2021 03:12:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244138AbhH0DNc (ORCPT ); Thu, 26 Aug 2021 23:13:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36184 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244100AbhH0DNb (ORCPT ); Thu, 26 Aug 2021 23:13:31 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 26B63C061757 for ; Thu, 26 Aug 2021 20:12:43 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id k23-20020a17090a591700b001796382f0d7so1466999pji.5 for ; Thu, 26 Aug 2021 20:12:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=atNNYXtbk9TC6UpTQBAC/hR8Ctg/gaBiFSHbwgD+93k=; b=rTnmRp6p/qwQZeBK96cIG/Y1oNLRCL/QQge1y7BqDXWEJ/hYwG9hY1YEl4nh+AkIQf fdCUnFiNNNvn1SyXlMUfSjki1QNjpAQsmCkaNoJZGDjRrQWlRd6HEfwy+vQ8MBdNYgCd pBs6Tz0iEKTC4QMmi7ubsCEaJHbQfMn2zjQQQDaay5yAAuELjIgszQX/S2SbOEF2w1Dd umSRD3zXV3or2ubcahDztYbdTln2HJqsQZ9Ud3He9jwOS5cxcG3JLVimcqEF8z9qQ5Hu H0p+4/bKf00hoMe0wDzKM8f1HHD1Dy8jO3EXMLTtMao8Mpt6YutIO8QOwrx0RVU4kYAW um6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=atNNYXtbk9TC6UpTQBAC/hR8Ctg/gaBiFSHbwgD+93k=; b=hrbJrTvJYKkOPt2pOES3aKO08va0DHwhHHvKLl+xAFn+pOMKfWl3FeShC+h5hwzpX8 x4wyQaU8wAlOSNe1JO6pGFT4L5pQ2fes1tEO95cqIR09+3KFCWeXP2jclI64XhhTmWYJ MwzzIM0JvDDBMMAbtzg3C6IYzHEar0CWxRt8npeuK1zCcbH0+CnY2BgtDsF1lm7W6/aC r1M5zp2CQT8cv9hO1RKqnNA1FWCv4I6y0Uojx75K9kfEb9s6ZypHFIS6OwgpoDEa3C/h VxEyVFEYsZBbb57AwO74qlsiOyrifgznHnwIYNP2SJ/K5erzSoSg3dosZ7LbFnVFvqIS EDaQ== X-Gm-Message-State: AOAM532nU7NHIldCefFAdSmCX004oVXDMIEz5TEQBGL2Vud1g0bS7fM5 ahIKuuoXy/tKTR2wv0U6+3/oRmiCjPP++SHoILXRzA0CnA1Tg6b0/fCfAYCIo1T7gb95b+lc2ji 5bukeZCF9e5BryF6IFuDimJhFDX2neCYnTIopUIuX7u3lNkIfgsJu0xxb+nP/KEQPdNn3 X-Google-Smtp-Source: ABdhPJxWygwZWXPwW8RKxqxkk/a/0h9spx31Rkd9ZJdE+APuYTlEQSSwYEhj4+ICPrzIv68g7Ksjrj1I5G9yn+8C X-Received: from zxwang42.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2936]) (user=zixuanwang job=sendgmr) by 2002:a62:7e41:0:b029:3e0:9c3f:ab50 with SMTP id z62-20020a627e410000b02903e09c3fab50mr6812881pfc.57.1630033962506; Thu, 26 Aug 2021 20:12:42 -0700 (PDT) Date: Fri, 27 Aug 2021 03:12:15 +0000 In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com> Message-Id: <20210827031222.2778522-11-zixuanwang@google.com> Mime-Version: 1.0 References: <20210827031222.2778522-1-zixuanwang@google.com> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog Subject: [kvm-unit-tests PATCH v2 10/17] x86 UEFI: Convert x86 test cases to PIC From: Zixuan Wang To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com, erdemaktas@google.com, rientjes@google.com, seanjc@google.com, brijesh.singh@amd.com, Thomas.Lendacky@amd.com, varad.gautam@suse.com, jroedel@suse.de, bp@suse.de Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org UEFI loads EFI applications to dynamic runtime addresses, so it requires all applications to be compiled as PIC (position independent code). PIC does not allow the usage of compile time absolute address. This commit converts multiple x86 test cases to PIC so they can compile and run in UEFI: - x86/cet.efi - x86/emulator.c: x86/emulator.c depends on lib/x86/usermode.c. But usermode.c contains non-PIC inline assembly code. This commit converts lib/x86/usermode.c and x86/emulator.c to PIC, so x86/emulator.c can compile and run in UEFI. - x86/vmware_backdoors.c: it depends on lib/x86/usermode.c and now works without modifications - x86/eventinj.c - x86/smap.c - x86/access.c - x86/umip.c Signed-off-by: Zixuan Wang --- lib/x86/usermode.c | 3 ++- x86/Makefile.common | 10 +++++----- x86/Makefile.x86_64 | 7 ++++--- x86/access.c | 9 +++++---- x86/cet.c | 8 +++++--- x86/emulator.c | 5 +++-- x86/eventinj.c | 6 ++++-- x86/smap.c | 8 ++++---- x86/umip.c | 10 +++++++--- 9 files changed, 39 insertions(+), 27 deletions(-) diff --git a/lib/x86/usermode.c b/lib/x86/usermode.c index f032523..c550545 100644 --- a/lib/x86/usermode.c +++ b/lib/x86/usermode.c @@ -58,7 +58,8 @@ uint64_t run_in_user(usermode_func func, unsigned int fault_vector, "pushq %[user_stack_top]\n\t" "pushfq\n\t" "pushq %[user_cs]\n\t" - "pushq $user_mode\n\t" + "lea user_mode(%%rip), %%rdx\n\t" + "pushq %%rdx\n\t" "iretq\n" "user_mode:\n\t" diff --git a/x86/Makefile.common b/x86/Makefile.common index 4859bf3..959379c 100644 --- a/x86/Makefile.common +++ b/x86/Makefile.common @@ -81,16 +81,16 @@ tests-common = $(TEST_DIR)/vmexit.$(exe) $(TEST_DIR)/tsc.$(exe) \ $(TEST_DIR)/init.$(exe) \ $(TEST_DIR)/hyperv_synic.$(exe) $(TEST_DIR)/hyperv_stimer.$(exe) \ $(TEST_DIR)/hyperv_connections.$(exe) \ - $(TEST_DIR)/tsx-ctrl.$(exe) + $(TEST_DIR)/tsx-ctrl.$(exe) \ + $(TEST_DIR)/eventinj.$(exe) \ + $(TEST_DIR)/umip.$(exe) # The following test cases are disabled when building EFI tests because they # use absolute addresses in their inline assembly code, which cannot compile # with the '-fPIC' flag ifneq ($(TARGET_EFI),y) -tests-common += $(TEST_DIR)/eventinj.$(exe) \ - $(TEST_DIR)/smap.$(exe) \ - $(TEST_DIR)/realmode.$(exe) \ - $(TEST_DIR)/umip.$(exe) +tests-common += $(TEST_DIR)/smap.$(exe) \ + $(TEST_DIR)/realmode.$(exe) endif test_cases: $(tests-common) $(tests) diff --git a/x86/Makefile.x86_64 b/x86/Makefile.x86_64 index aa23b22..7e8a57a 100644 --- a/x86/Makefile.x86_64 +++ b/x86/Makefile.x86_64 @@ -30,20 +30,21 @@ tests += $(TEST_DIR)/intel-iommu.$(exe) tests += $(TEST_DIR)/rdpru.$(exe) tests += $(TEST_DIR)/pks.$(exe) tests += $(TEST_DIR)/pmu_lbr.$(exe) +tests += $(TEST_DIR)/emulator.$(exe) +tests += $(TEST_DIR)/vmware_backdoors.$(exe) # The following test cases are disabled when building EFI tests because they # use absolute addresses in their inline assembly code, which cannot compile # with the '-fPIC' flag ifneq ($(TARGET_EFI),y) tests += $(TEST_DIR)/access.$(exe) -tests += $(TEST_DIR)/emulator.$(exe) tests += $(TEST_DIR)/svm.$(exe) tests += $(TEST_DIR)/vmx.$(exe) -tests += $(TEST_DIR)/vmware_backdoors.$(exe) +endif + ifneq ($(fcf_protection_full),) tests += $(TEST_DIR)/cet.$(exe) endif -endif include $(SRCDIR)/$(TEST_DIR)/Makefile.common diff --git a/x86/access.c b/x86/access.c index 4725bbd..8d620a7 100644 --- a/x86/access.c +++ b/x86/access.c @@ -700,7 +700,7 @@ static int ac_test_do_access(ac_test_t *at) if (F(AC_ACCESS_TWICE)) { asm volatile ( - "mov $fixed2, %%rsi \n\t" + "lea fixed2(%%rip), %%rsi \n\t" "mov (%[addr]), %[reg] \n\t" "fixed2:" : [reg]"=r"(r), [fault]"=a"(fault), "=b"(e) @@ -710,7 +710,7 @@ static int ac_test_do_access(ac_test_t *at) fault = 0; } - asm volatile ("mov $fixed1, %%rsi \n\t" + asm volatile ("lea fixed1(%%rip), %%rsi \n\t" "mov %%rsp, %%rdx \n\t" "cmp $0, %[user] \n\t" "jz do_access \n\t" @@ -719,7 +719,8 @@ static int ac_test_do_access(ac_test_t *at) "pushq %[user_stack_top] \n\t" "pushfq \n\t" "pushq %[user_cs] \n\t" - "pushq $do_access \n\t" + "lea do_access(%%rip), %%r8\n\t" + "pushq %%r8\n\t" "iretq \n" "do_access: \n\t" "cmp $0, %[fetch] \n\t" @@ -744,7 +745,7 @@ static int ac_test_do_access(ac_test_t *at) [user_cs]"i"(USER_CS), [user_stack_top]"r"(user_stack + sizeof user_stack), [kernel_entry_vector]"i"(0x20) - : "rsi"); + : "rsi", "r8"); asm volatile (".section .text.pf \n\t" "page_fault: \n\t" diff --git a/x86/cet.c b/x86/cet.c index a21577a..a4b79cb 100644 --- a/x86/cet.c +++ b/x86/cet.c @@ -52,7 +52,7 @@ static u64 cet_ibt_func(void) printf("No endbr64 instruction at jmp target, this triggers #CP...\n"); asm volatile ("movq $2, %rcx\n" "dec %rcx\n" - "leaq 2f, %rax\n" + "leaq 2f(%rip), %rax\n" "jmp *%rax \n" "2:\n" "dec %rcx\n"); @@ -67,7 +67,8 @@ void test_func(void) { "pushq %[user_stack_top]\n\t" "pushfq\n\t" "pushq %[user_cs]\n\t" - "pushq $user_mode\n\t" + "lea user_mode(%%rip), %%rax\n\t" + "pushq %%rax\n\t" "iretq\n" "user_mode:\n\t" @@ -77,7 +78,8 @@ void test_func(void) { [user_ds]"i"(USER_DS), [user_cs]"i"(USER_CS), [user_stack_top]"r"(user_stack + - sizeof(user_stack))); + sizeof(user_stack)) + : "rax"); } #define SAVE_REGS() \ diff --git a/x86/emulator.c b/x86/emulator.c index 9fda1a0..4d2de24 100644 --- a/x86/emulator.c +++ b/x86/emulator.c @@ -262,12 +262,13 @@ static void test_pop(void *mem) asm volatile("mov %%rsp, %[tmp] \n\t" "mov %[stack_top], %%rsp \n\t" - "push $1f \n\t" + "lea 1f(%%rip), %%rax \n\t" + "push %%rax \n\t" "ret \n\t" "2: jmp 2b \n\t" "1: mov %[tmp], %%rsp" : [tmp]"=&r"(tmp) : [stack_top]"r"(stack_top) - : "memory"); + : "memory", "rax"); report(1, "ret"); stack_top[-1] = 0x778899; diff --git a/x86/eventinj.c b/x86/eventinj.c index 46593c9..0cd68e8 100644 --- a/x86/eventinj.c +++ b/x86/eventinj.c @@ -155,9 +155,11 @@ asm("do_iret:" "pushf"W" \n\t" "mov %cs, %ecx \n\t" "push"W" %"R "cx \n\t" - "push"W" $2f \n\t" + "lea"W" 2f(%"R "ip), %"R "bx \n\t" + "push"W" %"R "bx \n\t" - "cmpb $0, no_test_device\n\t" // see if need to flush + "mov no_test_device(%"R "ip), %bl \n\t" + "cmpb $0, %bl\n\t" // see if need to flush "jnz 1f\n\t" "outl %eax, $0xe4 \n\t" // flush page "1: \n\t" diff --git a/x86/smap.c b/x86/smap.c index ac2c8d5..b3ee16f 100644 --- a/x86/smap.c +++ b/x86/smap.c @@ -161,10 +161,10 @@ int main(int ac, char **av) test = -1; asm("or $(" xstr(USER_BASE) "), %"R "sp \n" "push $44 \n " - "decl test\n" + "decl test(%"R "ip)\n" "and $~(" xstr(USER_BASE) "), %"R "sp \n" "pop %"R "ax\n" - "movl %eax, test"); + "movl %eax, test(%"R "ip)"); report(pf_count == 0 && test == 44, "write to user stack with AC=1"); @@ -173,10 +173,10 @@ int main(int ac, char **av) test = -1; asm("or $(" xstr(USER_BASE) "), %"R "sp \n" "push $45 \n " - "decl test\n" + "decl test(%"R "ip)\n" "and $~(" xstr(USER_BASE) "), %"R "sp \n" "pop %"R "ax\n" - "movl %eax, test"); + "movl %eax, test(%"R "ip)"); report(pf_count == 1 && test == 45 && save == -1, "write to user stack with AC=0"); diff --git a/x86/umip.c b/x86/umip.c index c5700b3..8b4e798 100644 --- a/x86/umip.c +++ b/x86/umip.c @@ -23,7 +23,10 @@ static void gp_handler(struct ex_regs *regs) #define GP_ASM(stmt, in, clobber) \ asm volatile ( \ - "mov" W " $1f, %[expected_rip]\n\t" \ + "push" W " %%" R "ax\n\t" \ + "lea 1f(%%" R "ip), %%" R "ax\n\t" \ + "mov %%" R "ax, %[expected_rip]\n\t" \ + "pop" W " %%" R "ax\n\t" \ "movl $2f-1f, %[skip_count]\n\t" \ "1: " stmt "\n\t" \ "2: " \ @@ -130,7 +133,8 @@ static int do_ring3(void (*fn)(const char *), const char *arg) "push" W " %%" R "dx \n\t" "pushf" W "\n\t" "push" W " %[user_cs] \n\t" - "push" W " $1f \n\t" + "lea 1f(%%" R "ip), %%" R "dx \n\t" + "push" W " %%" R "dx \n\t" "iret" W "\n" "1: \n\t" "push %%" R "cx\n\t" /* save kernel SP */ @@ -144,7 +148,7 @@ static int do_ring3(void (*fn)(const char *), const char *arg) #endif "pop %%" R "cx\n\t" - "mov $1f, %%" R "dx\n\t" + "lea 1f(%%" R "ip), %%" R "dx\n\t" "int %[kernel_entry_vector]\n\t" ".section .text.entry \n\t" "kernel_entry: \n\t" From patchwork Fri Aug 27 03:12:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12461143 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DF55DC432BE for ; Fri, 27 Aug 2021 03:12:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C5A4960F6C for ; Fri, 27 Aug 2021 03:12:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244143AbhH0DNd (ORCPT ); Thu, 26 Aug 2021 23:13:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36192 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244100AbhH0DNc (ORCPT ); Thu, 26 Aug 2021 23:13:32 -0400 Received: from mail-pl1-x64a.google.com (mail-pl1-x64a.google.com [IPv6:2607:f8b0:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 805E8C061757 for ; Thu, 26 Aug 2021 20:12:44 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id z10-20020a170903018a00b00134def0a883so370685plg.0 for ; Thu, 26 Aug 2021 20:12:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=lvY+8GWji/ARTEhKIY5rBNP81l9FgFJzeMAybYzicOI=; b=sx/fDyVK+kVJAZiNNBRgwWLKTJZUtcY7LNauRS1BPDHfsrUWdmEChMkz3yy+K7GLZA 4e9prciwNURGaxaZOND14RQ2Et8EiCc/YPPlmzBofonvZQw89Cl/GroasAgm9kkK5u+4 8ds1Da0pbPEVgefnP572VieQSLHMPWVnAgXZ6kWGISP4HOWgzw3qWsUGFmT7nWgHxzkU KDD2E2WgWTvbG4kjWxuv8rEsBFqAmR6eMk4yb0Ek3y204h1/GLhv9npHxcvAyuDMBmSP WZo99Mnm7Yc1qCrIt71jcLTu935mNgLPE/cV8f6QoLHp8aSk3dCQXbYbUxUKQnBqjIdx 3aXg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=lvY+8GWji/ARTEhKIY5rBNP81l9FgFJzeMAybYzicOI=; b=IG6iJZ7av8SUUjiXvQwvE9VYEWIMzJzHxNAvUmTt1ihskmeE7OqanW03nfkwYgY1pB 8mkuqaKpxYeIzKxQ5w6UxCPmpVR5xrAjPNHjwd3sxQkgErP21Xvdr7JT+SGyjaCLbZ07 91eWYFlrzJhqimlkXi5W+LWYLhzvcs5ydQUio8e4txwpf1ELK2eFjb2Fp+4zovbkjRTx zCJvcCxLVIbdaWiSAfvUDBrI/R/Os4r0Riig6gLUv99DmM8RaRuxFGRHnuEuuEv9XBJF AoSyU4OLvaG5Y3XuSu6WWe1MRK4idUjhNoLnQi14FBrk5ZGAkxMzmpe/mTSKIPqubZKU n1Sg== X-Gm-Message-State: AOAM530i2qQ1nyCvPkq1oGg/ogHS+LedLbzboG/phI4z/2irQNRMoqGi dDhuD0kwue13drz4du4fGRYtKX/IQhqPlKpfDBBtWciZvLSf+DrcYvkoDiRJ8day87oeokrw4sp J3Ibw+D0IYdbaxKcXQ1sD+YTFtki9magfLXY9W0lAf6cQFfHc+ymLVtQjnLQHIPypN1t3 X-Google-Smtp-Source: ABdhPJxWe5g2ygm8GXyFdJBIbX2JQ0WzOsGIZrR+oLfCDHCIQ8fLAdInL4MyS0i8e0sJ4ARgcZUTTgAGDAqVXO5b X-Received: from zxwang42.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2936]) (user=zixuanwang job=sendgmr) by 2002:a62:dd83:0:b029:30f:d69:895f with SMTP id w125-20020a62dd830000b029030f0d69895fmr6922410pff.17.1630033963875; Thu, 26 Aug 2021 20:12:43 -0700 (PDT) Date: Fri, 27 Aug 2021 03:12:16 +0000 In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com> Message-Id: <20210827031222.2778522-12-zixuanwang@google.com> Mime-Version: 1.0 References: <20210827031222.2778522-1-zixuanwang@google.com> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog Subject: [kvm-unit-tests PATCH v2 11/17] x86 AMD SEV: Initial support From: Zixuan Wang To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com, erdemaktas@google.com, rientjes@google.com, seanjc@google.com, brijesh.singh@amd.com, Thomas.Lendacky@amd.com, varad.gautam@suse.com, jroedel@suse.de, bp@suse.de Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org AMD Secure Encrypted Virtualization (SEV) is a hardware accelerated memory encryption feature that protects guest VMs from host attacks. This commit provides set up code and a test case for AMD SEV. The set up code checks if SEV is supported and enabled, and then sets SEV c-bit for each page table entry. Co-developed-by: Hyunwook (Wooky) Baek Signed-off-by: Hyunwook (Wooky) Baek Signed-off-by: Zixuan Wang --- lib/x86/amd_sev.c | 77 +++++++++++++++++++++++++++++++++++++++++++++ lib/x86/amd_sev.h | 45 ++++++++++++++++++++++++++ lib/x86/asm/setup.h | 1 + lib/x86/setup.c | 15 +++++++++ x86/Makefile.common | 1 + x86/Makefile.x86_64 | 3 ++ x86/amd_sev.c | 64 +++++++++++++++++++++++++++++++++++++ 7 files changed, 206 insertions(+) create mode 100644 lib/x86/amd_sev.c create mode 100644 lib/x86/amd_sev.h create mode 100644 x86/amd_sev.c diff --git a/lib/x86/amd_sev.c b/lib/x86/amd_sev.c new file mode 100644 index 0000000..5498ed6 --- /dev/null +++ b/lib/x86/amd_sev.c @@ -0,0 +1,77 @@ +/* + * AMD SEV support in KVM-Unit-Tests + * + * Copyright (c) 2021, Google Inc + * + * Authors: + * Zixuan Wang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include "amd_sev.h" +#include "x86/processor.h" + +static unsigned long long amd_sev_c_bit_pos; + +bool amd_sev_enabled(void) +{ + struct cpuid cpuid_out; + static bool sev_enabled; + static bool initialized = false; + + /* Check CPUID and MSR for SEV status and store it for future function calls. */ + if (!initialized) { + sev_enabled = false; + initialized = true; + + /* Test if we can query SEV features */ + cpuid_out = cpuid(CPUID_FN_LARGEST_EXT_FUNC_NUM); + if (cpuid_out.a < CPUID_FN_ENCRYPT_MEM_CAPAB) { + return sev_enabled; + } + + /* Test if SEV is supported */ + cpuid_out = cpuid(CPUID_FN_ENCRYPT_MEM_CAPAB); + if (!(cpuid_out.a & SEV_SUPPORT_MASK)) { + return sev_enabled; + } + + /* Test if SEV is enabled */ + if (!(rdmsr(MSR_SEV_STATUS) & SEV_ENABLED_MASK)) { + return sev_enabled; + } + + sev_enabled = true; + } + + return sev_enabled; +} + +efi_status_t setup_amd_sev(void) +{ + struct cpuid cpuid_out; + + if (!amd_sev_enabled()) { + return EFI_UNSUPPORTED; + } + + /* + * Extract C-Bit position from ebx[5:0] + * AMD64 Architecture Programmer's Manual Volume 3 + * - Section " Function 8000_001Fh - Encrypted Memory Capabilities" + */ + cpuid_out = cpuid(CPUID_FN_ENCRYPT_MEM_CAPAB); + amd_sev_c_bit_pos = (unsigned long long)(cpuid_out.b & 0x3f); + + return EFI_SUCCESS; +} + +unsigned long long get_amd_sev_c_bit_mask(void) +{ + if (amd_sev_enabled()) { + return 1ull << amd_sev_c_bit_pos; + } else { + return 0; + } +} diff --git a/lib/x86/amd_sev.h b/lib/x86/amd_sev.h new file mode 100644 index 0000000..516d500 --- /dev/null +++ b/lib/x86/amd_sev.h @@ -0,0 +1,45 @@ +/* + * AMD SEV support in KVM-Unit-Tests + * + * Copyright (c) 2021, Google Inc + * + * Authors: + * Zixuan Wang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#ifndef _X86_AMD_SEV_H_ +#define _X86_AMD_SEV_H_ + +#ifdef TARGET_EFI + +#include "libcflat.h" +#include "desc.h" +#include "asm/page.h" +#include "efi.h" + +/* + * AMD Programmer's Manual Volume 3 + * - Section "Function 8000_0000h - Maximum Extended Function Number and Vendor String" + * - Section "Function 8000_001Fh - Encrypted Memory Capabilities" + */ +#define CPUID_FN_LARGEST_EXT_FUNC_NUM 0x80000000 +#define CPUID_FN_ENCRYPT_MEM_CAPAB 0x8000001f +#define SEV_SUPPORT_MASK 0b10 + +/* + * AMD Programmer's Manual Volume 2 + * - Section "SEV_STATUS MSR" + */ +#define MSR_SEV_STATUS 0xc0010131 +#define SEV_ENABLED_MASK 0b1 + +bool amd_sev_enabled(void); +efi_status_t setup_amd_sev(void); + +unsigned long long get_amd_sev_c_bit_mask(void); + +#endif /* TARGET_EFI */ + +#endif /* _X86_AMD_SEV_H_ */ diff --git a/lib/x86/asm/setup.h b/lib/x86/asm/setup.h index 16bad0f..d494528 100644 --- a/lib/x86/asm/setup.h +++ b/lib/x86/asm/setup.h @@ -8,6 +8,7 @@ #include "x86/smp.h" #include "asm/page.h" #include "efi.h" +#include "x86/amd_sev.h" /* * efi_bootinfo_t: stores EFI-related machine info retrieved by diff --git a/lib/x86/setup.c b/lib/x86/setup.c index 03598fe..bdda337 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -215,6 +215,18 @@ efi_status_t setup_efi_pre_boot(unsigned long *mapkey, efi_bootinfo_t *efi_booti return status; } + status = setup_amd_sev(); + if (status != EFI_SUCCESS) { + switch (status) { + case EFI_UNSUPPORTED: + /* Continue if AMD SEV is not supported */ + break; + default: + printf("Set up AMD SEV failed\n"); + return status; + } + } + return EFI_SUCCESS; } @@ -233,6 +245,9 @@ static void setup_page_table(void) /* Set default flags */ flags = PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK; + /* Set AMD SEV C-Bit for page table entries */ + flags |= get_amd_sev_c_bit_mask(); + /* Level 5 */ curr_pt = (pgd_t *)&ptl5; curr_pt[0] = ((phys_addr_t)&ptl4) | flags; diff --git a/x86/Makefile.common b/x86/Makefile.common index 959379c..0913083 100644 --- a/x86/Makefile.common +++ b/x86/Makefile.common @@ -23,6 +23,7 @@ cflatobjs += lib/x86/stack.o cflatobjs += lib/x86/fault_test.o cflatobjs += lib/x86/delay.o ifeq ($(TARGET_EFI),y) +cflatobjs += lib/x86/amd_sev.o cflatobjs += lib/x86/setup.o cflatobjs += lib/efi.o cflatobjs += x86/efi/reloc_x86_64.o diff --git a/x86/Makefile.x86_64 b/x86/Makefile.x86_64 index 7e8a57a..8304939 100644 --- a/x86/Makefile.x86_64 +++ b/x86/Makefile.x86_64 @@ -32,6 +32,9 @@ tests += $(TEST_DIR)/pks.$(exe) tests += $(TEST_DIR)/pmu_lbr.$(exe) tests += $(TEST_DIR)/emulator.$(exe) tests += $(TEST_DIR)/vmware_backdoors.$(exe) +ifeq ($(TARGET_EFI),y) +tests += $(TEST_DIR)/amd_sev.$(exe) +endif # The following test cases are disabled when building EFI tests because they # use absolute addresses in their inline assembly code, which cannot compile diff --git a/x86/amd_sev.c b/x86/amd_sev.c new file mode 100644 index 0000000..a07a48f --- /dev/null +++ b/x86/amd_sev.c @@ -0,0 +1,64 @@ +/* + * AMD SEV test cases + * + * Copyright (c) 2021, Google Inc + * + * Authors: + * Hyunwook (Wooky) Baek + * Zixuan Wang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#include "libcflat.h" +#include "x86/processor.h" +#include "x86/amd_sev.h" + +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 + +static int test_sev_activation(void) +{ + struct cpuid cpuid_out; + u64 msr_out; + + printf("SEV activation test is loaded.\n"); + + /* Tests if CPUID function to check SEV is implemented */ + cpuid_out = cpuid(CPUID_FN_LARGEST_EXT_FUNC_NUM); + printf("CPUID Fn8000_0000[EAX]: 0x%08x\n", cpuid_out.a); + if (cpuid_out.a < CPUID_FN_ENCRYPT_MEM_CAPAB) { + printf("CPUID does not support FN%08x\n", + CPUID_FN_ENCRYPT_MEM_CAPAB); + return EXIT_FAILURE; + } + + /* Tests if SEV is supported */ + cpuid_out = cpuid(CPUID_FN_ENCRYPT_MEM_CAPAB); + printf("CPUID Fn8000_001F[EAX]: 0x%08x\n", cpuid_out.a); + printf("CPUID Fn8000_001F[EBX]: 0x%08x\n", cpuid_out.b); + if (!(cpuid_out.a & SEV_SUPPORT_MASK)) { + printf("SEV is not supported.\n"); + return EXIT_FAILURE; + } + printf("SEV is supported\n"); + + /* Tests if SEV is enabled */ + msr_out = rdmsr(MSR_SEV_STATUS); + printf("MSR C001_0131[EAX]: 0x%08lx\n", msr_out & 0xffffffff); + if (!(msr_out & SEV_ENABLED_MASK)) { + printf("SEV is not enabled.\n"); + return EXIT_FAILURE; + } + printf("SEV is enabled\n"); + + return EXIT_SUCCESS; +} + +int main(void) +{ + int rtn; + rtn = test_sev_activation(); + report(rtn == EXIT_SUCCESS, "SEV activation test."); + return report_summary(); +} From patchwork Fri Aug 27 03:12:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12461145 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CDC91C4320A for ; Fri, 27 Aug 2021 03:12:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B517C60F6C for ; Fri, 27 Aug 2021 03:12:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244149AbhH0DNf (ORCPT ); Thu, 26 Aug 2021 23:13:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36196 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244100AbhH0DNe (ORCPT ); Thu, 26 Aug 2021 23:13:34 -0400 Received: from mail-pl1-x64a.google.com (mail-pl1-x64a.google.com [IPv6:2607:f8b0:4864:20::64a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4CCE0C061757 for ; Thu, 26 Aug 2021 20:12:46 -0700 (PDT) Received: by mail-pl1-x64a.google.com with SMTP id h5-20020a170902704500b00137e251c362so606905plt.10 for ; Thu, 26 Aug 2021 20:12:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=cuN0ollxjDV2DaaXoouEXtDeSL4O0HORunjVAJir1EM=; b=fPij6UYNMIqXWvZFmfEq5DLfP9i7hwzdhyrY1gE3x9U7gAlV7ObTDdSPres2nM/pUh cMtEwrZVK7zG4Lhk/Dr6aCjEXCLbSy4y5u5QV2ZfH8UZv65T9awCCOKZqgQodznszu07 hEaspyGMb6sTa7QDK7trVC81oGiDvewgQJZR71Ux2eFVKwSAEmzzBLlmCsrrmWUGa1Yx w1nmENx0UEjyzWVyhfXpUodztKNUtl9kab1Bu7y4HaLWiibK/WKQxi2u5JG01oJ44rgr +CzqKv5MMLDKakgUtB6h0yZIhbi4Zblm0CPBBxyTrib6LllfJQpvHV+vp4fcp6ccL+BH sFrg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=cuN0ollxjDV2DaaXoouEXtDeSL4O0HORunjVAJir1EM=; b=ITBQM955h9K6ZlPdI9o6Saw18mLeaDs2Lf0bZUwWbVW9CH1CyWaXaTqSyS52Ladyzb wCZncU4+Q5LClK3GSUbcRWPqeV8zEhczs1lqtLN1lpI0xyT3WgEc4Tv2+uDb1aw5Q1N8 Uzdi9liHnYfmnHiQywoMCFiq9f9AXs8Eq6050XizJ02tVAG2o3nzrjT86Dy/wZ102sFh aulAxydNXMFESD1/cRh3OOeJuBgbjYLEw/S0H7G50wLIo1GjBtd6n36181/fngE4bMw5 hiHpGGtbUyjzvFVzgsEv9yzjaUED4ihpH7MEMoCjr51aVyGlPg33R23zI/WPxYoEvwSv FTzg== X-Gm-Message-State: AOAM530ZHsgI7CYx7R5N6t+AuVSlO1NELLEq1CyPmpOgnzf4I5AEi0Sl 8MqkH34EjMN+3YYdbmScHZCRk63MZl3jNKm1YlB7hOpwQ3WTFxPaDiaj8Hnnx7tdsnGiaLAx/FN tm8jnQaCkPCn/wDJlbDBukXrFrUzJbht1xwX96urjAcuaGyYOK4St7YicjGQ2FHpQMJmp X-Google-Smtp-Source: ABdhPJxc224gwn0ff3V2VKSMQCy0L3Z40ttBYtS4iOxip53RYOh6O/Jm/89BmIAZtZE+E4Kcc2p3HIlKT4vZ5D1L X-Received: from zxwang42.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2936]) (user=zixuanwang job=sendgmr) by 2002:a62:38c9:0:b0:3f2:6ab2:1828 with SMTP id f192-20020a6238c9000000b003f26ab21828mr4784538pfa.37.1630033965667; Thu, 26 Aug 2021 20:12:45 -0700 (PDT) Date: Fri, 27 Aug 2021 03:12:17 +0000 In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com> Message-Id: <20210827031222.2778522-13-zixuanwang@google.com> Mime-Version: 1.0 References: <20210827031222.2778522-1-zixuanwang@google.com> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog Subject: [kvm-unit-tests PATCH v2 12/17] x86 AMD SEV: Page table with c-bit From: Zixuan Wang To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com, erdemaktas@google.com, rientjes@google.com, seanjc@google.com, brijesh.singh@amd.com, Thomas.Lendacky@amd.com, varad.gautam@suse.com, jroedel@suse.de, bp@suse.de Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org AMD SEV introduces c-bit to page table entries. To work with AMD SEV: 1. c-bit should be set for new page table entries 2. address calculation should not use c-bit as part of address Signed-off-by: Zixuan Wang --- lib/x86/amd_sev.c | 10 ++++++++++ lib/x86/amd_sev.h | 1 + lib/x86/asm/page.h | 27 ++++++++++++++++++++++++--- lib/x86/vm.c | 18 ++++++++++++++---- 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/lib/x86/amd_sev.c b/lib/x86/amd_sev.c index 5498ed6..f5e3585 100644 --- a/lib/x86/amd_sev.c +++ b/lib/x86/amd_sev.c @@ -75,3 +75,13 @@ unsigned long long get_amd_sev_c_bit_mask(void) return 0; } } + +unsigned long long get_amd_sev_addr_upperbound(void) +{ + if (amd_sev_enabled()) { + return amd_sev_c_bit_pos - 1; + } else { + /* Default memory upper bound */ + return PT_ADDR_UPPER_BOUND_DEFAULT; + } +} diff --git a/lib/x86/amd_sev.h b/lib/x86/amd_sev.h index 516d500..2780560 100644 --- a/lib/x86/amd_sev.h +++ b/lib/x86/amd_sev.h @@ -39,6 +39,7 @@ bool amd_sev_enabled(void); efi_status_t setup_amd_sev(void); unsigned long long get_amd_sev_c_bit_mask(void); +unsigned long long get_amd_sev_addr_upperbound(void); #endif /* TARGET_EFI */ diff --git a/lib/x86/asm/page.h b/lib/x86/asm/page.h index f6f740b..c25bc66 100644 --- a/lib/x86/asm/page.h +++ b/lib/x86/asm/page.h @@ -25,6 +25,12 @@ typedef unsigned long pgd_t; #define LARGE_PAGE_SIZE (1024 * PAGE_SIZE) #endif +#ifdef TARGET_EFI +/* lib/x86/amd_sev.c */ +extern unsigned long long get_amd_sev_c_bit_mask(void); +extern unsigned long long get_amd_sev_addr_upperbound(void); +#endif /* TARGET_EFI */ + #define PT_PRESENT_MASK (1ull << 0) #define PT_WRITABLE_MASK (1ull << 1) #define PT_USER_MASK (1ull << 2) @@ -33,10 +39,25 @@ typedef unsigned long pgd_t; #define PT_PAGE_SIZE_MASK (1ull << 7) #define PT_GLOBAL_MASK (1ull << 8) #define PT64_NX_MASK (1ull << 63) -#define PT_ADDR_MASK GENMASK_ULL(51, 12) -#define PDPTE64_PAGE_SIZE_MASK (1ull << 7) -#define PDPTE64_RSVD_MASK GENMASK_ULL(51, cpuid_maxphyaddr()) +/* + * Without AMD SEV, the default address upper bound is 51 (i.e., pte bit 51 and + * lower bits are addresses). But with AMD SEV enabled, the upper bound is one + * bit lower than the c-bit position. + */ +#define PT_ADDR_UPPER_BOUND_DEFAULT (51) + +#ifdef TARGET_EFI +#define PT_ADDR_UPPER_BOUND (get_amd_sev_addr_upperbound()) +#else +#define PT_ADDR_UPPER_BOUND (PT_ADDR_UPPER_BOUND_DEFAULT) +#endif /* TARGET_EFI */ + +#define PT_ADDR_LOWER_BOUND (PAGE_SHIFT) +#define PT_ADDR_MASK GENMASK_ULL(PT_ADDR_UPPER_BOUND, PT_ADDR_LOWER_BOUND) + +#define PDPTE64_PAGE_SIZE_MASK (1ull << 7) +#define PDPTE64_RSVD_MASK GENMASK_ULL(PT_ADDR_UPPER_BOUND, cpuid_maxphyaddr()) #define PT_AD_MASK (PT_ACCESSED_MASK | PT_DIRTY_MASK) diff --git a/lib/x86/vm.c b/lib/x86/vm.c index 5cd2ee4..0ebc860 100644 --- a/lib/x86/vm.c +++ b/lib/x86/vm.c @@ -26,6 +26,9 @@ pteval_t *install_pte(pgd_t *cr3, pt_page = 0; memset(new_pt, 0, PAGE_SIZE); pt[offset] = virt_to_phys(new_pt) | PT_PRESENT_MASK | PT_WRITABLE_MASK | pte_opt_mask; +#ifdef TARGET_EFI + pt[offset] |= get_amd_sev_c_bit_mask(); +#endif /* TARGET_EFI */ } pt = phys_to_virt(pt[offset] & PT_ADDR_MASK); } @@ -63,7 +66,7 @@ struct pte_search find_pte_level(pgd_t *cr3, void *virt, if (r.level == lowest_level) return r; - pt = phys_to_virt(pte & 0xffffffffff000ull); + pt = phys_to_virt(pte & PT_ADDR_MASK); } } @@ -94,13 +97,20 @@ pteval_t *get_pte_level(pgd_t *cr3, void *virt, int pte_level) pteval_t *install_large_page(pgd_t *cr3, phys_addr_t phys, void *virt) { - return install_pte(cr3, 2, virt, - phys | PT_PRESENT_MASK | PT_WRITABLE_MASK | pte_opt_mask | PT_PAGE_SIZE_MASK, 0); + phys_addr_t flags = PT_PRESENT_MASK | PT_WRITABLE_MASK | pte_opt_mask | PT_PAGE_SIZE_MASK; +#ifdef TARGET_EFI + flags |= get_amd_sev_c_bit_mask(); +#endif /* TARGET_EFI */ + return install_pte(cr3, 2, virt, phys | flags, 0); } pteval_t *install_page(pgd_t *cr3, phys_addr_t phys, void *virt) { - return install_pte(cr3, 1, virt, phys | PT_PRESENT_MASK | PT_WRITABLE_MASK | pte_opt_mask, 0); + phys_addr_t flags = PT_PRESENT_MASK | PT_WRITABLE_MASK | pte_opt_mask; +#ifdef TARGET_EFI + flags |= get_amd_sev_c_bit_mask(); +#endif /* TARGET_EFI */ + return install_pte(cr3, 1, virt, phys | flags, 0); } void install_pages(pgd_t *cr3, phys_addr_t phys, size_t len, void *virt) From patchwork Fri Aug 27 03:12:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12461147 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BC224C432BE for ; Fri, 27 Aug 2021 03:12:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A684860F5C for ; Fri, 27 Aug 2021 03:12:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244153AbhH0DNg (ORCPT ); Thu, 26 Aug 2021 23:13:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36206 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244100AbhH0DNg (ORCPT ); Thu, 26 Aug 2021 23:13:36 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F003EC061757 for ; Thu, 26 Aug 2021 20:12:47 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id 41-20020a17090a0fac00b00195a5a61ab8so1107731pjz.3 for ; Thu, 26 Aug 2021 20:12:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=4TornJd3esEN0slc3+Yshw+33yLpq3lBCewRutYBCuQ=; b=uZhZtJzLMpePq5SIQP/2eHXp+t3a65SEkGSHmr1yUgyXxvrCA7b6ZANN6mRXCp2SzF 1QvUC3xkWckXvNP1DxiBEheTLlcP4zKTY7070bRvwb/D7tNycE7GZzUgvAdWSHl5xK2/ QMZSqnF10d6NpNyQiHBBsjG/htXBz7cmGWwT5OYCzgb4o9vHlATMocDiHZVpfvW3/Yjs 6Q3iqRtat3s3VZpzcb3cFw8eihTdF5OrlPFdFo7chG+hO5S5AiY0HOUws78/cHamAO8t KPLbhKOr7/dSfmXreGtOt9P0eejh64UjZDLgP0xwA+bc89JeDuiXKxVBqHjdhCeOVXr9 IYBQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=4TornJd3esEN0slc3+Yshw+33yLpq3lBCewRutYBCuQ=; b=BkcZRL37ytuODecaIxEpYRxz882RgKE1uBnod5AL4dp6MG9c2j93qLeTGbpr6Ztb2s Re3CNvMdWkctCf8x4jFQRo1kbWCWiRuxIZhywIQKD6QnbMXO7VGzMLmwrStAYCSemxqW TYTEKHIxljcU4AzhsQDdpY+tAeUfVrhNE/lQq21phLRgArB3O7savckAGV4hNgu3k+5Z sSRFfhEhzpczpvphBvnWOCUS+eK6HPA0FzGgJa/hhxXqtZxbwdJjl6xStrk7Ig3C9E88 tPYFAc2OEIZykJJzX+th1nTKYS8rwY4KCcQIk2M8MfpcBKyzrBDnvNNetcRaNFTLiTbK qX3A== X-Gm-Message-State: AOAM533C4mDbkiGuNkGtAFQCJt+vJfxppYe+2a4C3osAZeh/mePcL1oq AfnHKgV37vcH9qysJPfZo26vjTvRjeKYMtRfsLUVVTz4qdvhboGM+J8mDv6dE2bNXlz4EGONuAz FnuelXtWb7wzLhXNGM6m1PpTfb7Xq4F/f9cDBGtmS9e5ZPZ2E7RzbZtRHgFUIQ6C3KCu0 X-Google-Smtp-Source: ABdhPJyKeM7nnyPzzvC8oQB4xeB24hy00w/dR7CfNUK5uiPWUgjz5QrbtGVd4pRu1s0rPDH6ACDF2UOXsrKnZdlc X-Received: from zxwang42.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2936]) (user=zixuanwang job=sendgmr) by 2002:a65:6a09:: with SMTP id m9mr5992565pgu.269.1630033967383; Thu, 26 Aug 2021 20:12:47 -0700 (PDT) Date: Fri, 27 Aug 2021 03:12:18 +0000 In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com> Message-Id: <20210827031222.2778522-14-zixuanwang@google.com> Mime-Version: 1.0 References: <20210827031222.2778522-1-zixuanwang@google.com> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog Subject: [kvm-unit-tests PATCH v2 13/17] x86 AMD SEV-ES: Check SEV-ES status From: Zixuan Wang To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com, erdemaktas@google.com, rientjes@google.com, seanjc@google.com, brijesh.singh@amd.com, Thomas.Lendacky@amd.com, varad.gautam@suse.com, jroedel@suse.de, bp@suse.de Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This commit provides initial start up code for KVM-Unit-Tests to run in an SEV-ES guest VM. This start up code checks if SEV-ES feature is supported and enabled for the guest. In this commit, KVM-Unit-Tests can pass the SEV-ES check and enter setup_efi() function, but crashes in setup_gdt_tss(), which will be fixed by follow-up commits. Signed-off-by: Zixuan Wang --- lib/x86/amd_sev.c | 24 ++++++++++++++++++++++++ lib/x86/amd_sev.h | 7 +++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/x86/amd_sev.c b/lib/x86/amd_sev.c index f5e3585..8d4df8c 100644 --- a/lib/x86/amd_sev.c +++ b/lib/x86/amd_sev.c @@ -67,6 +67,30 @@ efi_status_t setup_amd_sev(void) return EFI_SUCCESS; } +bool amd_sev_es_enabled(void) +{ + static bool sev_es_enabled; + static bool initialized = false; + + if (!initialized) { + sev_es_enabled = false; + initialized = true; + + if (!amd_sev_enabled()) { + return sev_es_enabled; + } + + /* Test if SEV-ES is enabled */ + if (!(rdmsr(MSR_SEV_STATUS) & SEV_ES_ENABLED_MASK)) { + return sev_es_enabled; + } + + sev_es_enabled = true; + } + + return sev_es_enabled; +} + 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 2780560..b73a872 100644 --- a/lib/x86/amd_sev.h +++ b/lib/x86/amd_sev.h @@ -32,12 +32,15 @@ * AMD Programmer's Manual Volume 2 * - Section "SEV_STATUS MSR" */ -#define MSR_SEV_STATUS 0xc0010131 -#define SEV_ENABLED_MASK 0b1 +#define MSR_SEV_STATUS 0xc0010131 +#define SEV_ENABLED_MASK 0b1 +#define SEV_ES_ENABLED_MASK 0b10 bool amd_sev_enabled(void); efi_status_t setup_amd_sev(void); +bool amd_sev_es_enabled(void); + unsigned long long get_amd_sev_c_bit_mask(void); unsigned long long get_amd_sev_addr_upperbound(void); From patchwork Fri Aug 27 03:12:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12461149 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6D193C4320A for ; Fri, 27 Aug 2021 03:12:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 555AA60F6F for ; Fri, 27 Aug 2021 03:12:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244156AbhH0DNi (ORCPT ); Thu, 26 Aug 2021 23:13:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36214 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244100AbhH0DNh (ORCPT ); Thu, 26 Aug 2021 23:13:37 -0400 Received: from mail-pf1-x44a.google.com (mail-pf1-x44a.google.com [IPv6:2607:f8b0:4864:20::44a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BDBCCC061757 for ; Thu, 26 Aug 2021 20:12:49 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id u8-20020a056a00098800b003eb2fbd34dcso135895pfg.12 for ; Thu, 26 Aug 2021 20:12:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=uZrve0kQ15HP3z2KuePyyhfbkhhcrwnoA/T8g2iERmI=; b=HAijQV9n2kvFCVpu4WKrSYqhGuXDgMZMqgz2QZwXiCHc9dE+QviJx8BH8gH6NI4abc Nv36FpRnJiw+gIEol8cRuO1iHglpFBba2m4qd27lHl1SkYdtfclRUpdYoVGp0y7ErhcB TTHn4HAbqYrv5DiGymKuC1OhLUTJHTPF7ERfzShVvlMoST2XXQNl5uKy95gBdZxcKqZf ypE4pLGWg6zlfL4UI4pzDepeCfmtq83R7NvR+Ak99c4VsmjFPUBzbNcNZN1DsxjtZU2/ WVj0/WVvrXMmKJd4ShKAuchWXAzjDOLUgz6O2trC16wpLuB0tLZ2kaVaWPTRX6j0Yf3s lXUg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=uZrve0kQ15HP3z2KuePyyhfbkhhcrwnoA/T8g2iERmI=; b=WF87Ibl0MSj/eeSsCL7V7iTK7GAOavO02vVlGNHVE7OOs6/xBFC2eF7GtT/lyTIndZ YLaM966Ma0EYIV/LNNszdJh8EjzMQ2B/m89P2cV7jjE4MChJbAr+GFTHJNlUljbhC5xB eZlDpDt+WnJx1OWrboD3y2ZZmysyeP0NDeqY/MNOa6G84P2yXK/LeX2pZjQOh0kfUK06 P9aJJRG2JZpq2PQk0oagIF1jWNbm2mp8Dv4jds/WfuhpGKCR1ySlhMfslflALX2cJ5B2 0ljVt+o1wH4fRyDU653AUu7iJvFgdAe/u5g46GY2vcudmyM06Ge3rTq5upVMYLs6+RJY 3FjA== X-Gm-Message-State: AOAM5311c/j4J7Lr4NwiaAG3v+kfkV3BUZCXneVVs2sXDy6v9xfBLOke nACfJgNWvGu3E+Ecmg3l2Kx7Reigolqipb6EoT+N4wTca0QQES+5I82VsOUPws+v4bshEW0l/Ou fKcJHsXl9BKnmkCce+h8SFgB30g5yZN44kvV8hCJvSqEWnXi/GRjmPrm1CrafHccgR5bH X-Google-Smtp-Source: ABdhPJxA3M1kNuojXNgdNrDa0zdBYaF8mldalWWDCuupojzLvR5mBpw7aNY0Hq9DkB9AocAdzIeYXv8d8JzkESGp X-Received: from zxwang42.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2936]) (user=zixuanwang job=sendgmr) by 2002:aa7:8e4f:0:b0:3ee:27d5:28bc with SMTP id d15-20020aa78e4f000000b003ee27d528bcmr6869363pfr.24.1630033969198; Thu, 26 Aug 2021 20:12:49 -0700 (PDT) Date: Fri, 27 Aug 2021 03:12:19 +0000 In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com> Message-Id: <20210827031222.2778522-15-zixuanwang@google.com> Mime-Version: 1.0 References: <20210827031222.2778522-1-zixuanwang@google.com> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog Subject: [kvm-unit-tests PATCH v2 14/17] x86 AMD SEV-ES: Load GDT with UEFI segments From: Zixuan Wang To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com, erdemaktas@google.com, rientjes@google.com, seanjc@google.com, brijesh.singh@amd.com, Thomas.Lendacky@amd.com, varad.gautam@suse.com, jroedel@suse.de, bp@suse.de Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Before this commit, KVM-Unit-Tests set up process crashes when executing 'lgdt' instruction under SEV-ES. This is because lgdt triggers UEFI procedures (e.g. UEFI #VC handler) that require UEFI's code and data segments. But these segments are are not compatible with KVM-Unit-Tests GDT: UEFI uses 0x30 as code segment and 0x38 as data segment, but in KVM-Unit-Tests' GDT, 0x30 is a data segment, and 0x38 is a code segment. This discrepancy crashes the UEFI procedures and thus crashes the 'lgdt' execution. This commit fixes this issue by copying UEFI GDT's code and data segments into KVM-Unit-Tests GDT, so that UEFI procedures (e.g. UEFI #VC handler) can work. In this commit, the guest VM passes setup_gdt_tss() but crashes in load_idt(), which will be fixed by follow-up commits. Signed-off-by: Zixuan Wang --- lib/x86/amd_sev.c | 41 +++++++++++++++++++++++++++++++++++++++++ lib/x86/amd_sev.h | 1 + lib/x86/setup.c | 4 ++++ 3 files changed, 46 insertions(+) diff --git a/lib/x86/amd_sev.c b/lib/x86/amd_sev.c index 8d4df8c..c9fabc4 100644 --- a/lib/x86/amd_sev.c +++ b/lib/x86/amd_sev.c @@ -91,6 +91,47 @@ bool amd_sev_es_enabled(void) return sev_es_enabled; } +static void copy_gdt_entry(gdt_entry_t *dst, gdt_entry_t *src, unsigned segment) +{ + unsigned index; + + index = segment / sizeof(gdt_entry_t); + dst[index] = src[index]; +} + +/* Defined in x86/efi/efistart64.S */ +extern gdt_entry_t gdt64[]; + +/* + * Copy UEFI's code and data segments to KVM-Unit-Tests GDT. + * + * This is because KVM-Unit-Tests reuses UEFI #VC handler that requires UEFI + * code and data segments to run. The UEFI #VC handler crashes the guest VM if + * these segments are not available. So we need to copy these two UEFI segments + * into KVM-Unit-Tests GDT. + * + * UEFI uses 0x30 as code segment and 0x38 as data segment. Fortunately, these + * segments can be safely overridden in KVM-Unit-Tests as they are used as + * protected mode and real mode segments (see x86/efi/efistart64.S for more + * details), which are not used in EFI set up process. + */ +void copy_uefi_segments(void) +{ + if (!amd_sev_es_enabled()) { + return; + } + + /* GDT and GDTR in current UEFI */ + gdt_entry_t *gdt_curr; + struct descriptor_table_ptr gdtr_curr; + + /* Copy code and data segments from UEFI */ + sgdt(&gdtr_curr); + gdt_curr = (gdt_entry_t *)gdtr_curr.base; + copy_gdt_entry(gdt64, gdt_curr, read_cs()); + copy_gdt_entry(gdt64, gdt_curr, read_ds()); +} + 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 b73a872..0b4ff8c 100644 --- a/lib/x86/amd_sev.h +++ b/lib/x86/amd_sev.h @@ -40,6 +40,7 @@ bool amd_sev_enabled(void); efi_status_t setup_amd_sev(void); bool amd_sev_es_enabled(void); +void copy_uefi_segments(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 bdda337..c6eb3e9 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -324,6 +324,10 @@ static void setup_gdt_tss(void) tss_hi->limit_low = (u16)((curr_tss_addr >> 32) & 0xffff); tss_hi->base_low = (u16)((curr_tss_addr >> 48) & 0xffff); + if (amd_sev_es_enabled()) { + copy_uefi_segments(); + } + load_gdt_tss(tss_offset); } From patchwork Fri Aug 27 03:12:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12461151 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 880F2C432BE for ; Fri, 27 Aug 2021 03:12:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 72ADE60F6C for ; Fri, 27 Aug 2021 03:12:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244160AbhH0DNj (ORCPT ); Thu, 26 Aug 2021 23:13:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36222 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244100AbhH0DNj (ORCPT ); Thu, 26 Aug 2021 23:13:39 -0400 Received: from mail-pg1-x549.google.com (mail-pg1-x549.google.com [IPv6:2607:f8b0:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 50B91C061757 for ; Thu, 26 Aug 2021 20:12:51 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id 32-20020a6315600000b029023caa2bfec4so502184pgv.20 for ; Thu, 26 Aug 2021 20:12:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=6Or8JGri7gHTTsWTaZhjhFlqCYKlq3JhtE5Agq3KsCM=; b=X0G7T0UCY0YXpFZSMAtPi9Y7lq/g0O23xteuI5QCtrYneqmXlViLiI3Ri1mEaiOT9P g9hotFquJHMX/1BIGaO6L+V9znINaD/Ie6f+yY34ngICdzz1xNcpU/MXZy1tgEmABIRt MAIQSdoqImOnOcLQvwO0V8Q4o5+VKRtYXz1Lsm86mO8ZHDh6XcuQ8ITuz3ZiNsJRt3U7 6A5eUMWN37I+MrzsRz4vNetpZxRl9715IlkjLqQQiYaunRE6CIrECy5Nu2d/QAQmGNte KEY8nZc8Zy+DZ4Awkt//I/LLV3jXuNpE+o2BZSCq/KHf+LcGUII1AfqF6ArNbYf0U1qK 8mxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=6Or8JGri7gHTTsWTaZhjhFlqCYKlq3JhtE5Agq3KsCM=; b=snUVCrRH46SR+sOnytBK7QF1iO4wV9I+1kwxHOnUn54eVVYLUe1/sbetqbVtXUv7ig KWytUoovAfHWRLixlR313em6QSvZ8qhdjX+Fn8+ikxgKggq2rsZCydpzeks9EyKp8I+C Dy/Lv2aTCKKHsNrC678yGdW8YzP5MnjlCFTocQXKkgLXLB/tCRwe5E8nbmlrLyVIUZeY ZEHKTC/bDJEdAy9EvLmT5uByWd5RE+bisZmyvLpJH7OVPLe89iXV/h+PD11BTo8S3cmq +UTnMNzApjCBkQmOYiHEVauPUArFPXg4Q9okCDiy9RhBh2RNQjui80+IUYmQBQOPn6rN Xesg== X-Gm-Message-State: AOAM530roLe2g1Wqej1NuJZuoGsvFSKP1QJqKdxoWpDqe+gP6BKqQ0JF NdOktrIqoDfe+XW6AFu8Yjc59dycvCYqQnpyt7MOlDH8ZVFlGThD9sIiEFzK0JxyY/Hf0JSBfLR nkBOaesGNOFXIpDb2vhtjsCMfRrt2FL8R2LstXRwuGF/K5Kc86KcE4cEVa4C+sWH0kWdC X-Google-Smtp-Source: ABdhPJyoNq+oMHVqi8CU15SvoSW9msaiv9bTqJaPwie9CkHUzRQISPUBPLpbhylU1fMfcByQkIK/bpI0EwEB0lMN X-Received: from zxwang42.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2936]) (user=zixuanwang job=sendgmr) by 2002:a05:6a00:23ca:b0:3e1:2d8:33f3 with SMTP id g10-20020a056a0023ca00b003e102d833f3mr6966844pfc.42.1630033970648; Thu, 26 Aug 2021 20:12:50 -0700 (PDT) Date: Fri, 27 Aug 2021 03:12:20 +0000 In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com> Message-Id: <20210827031222.2778522-16-zixuanwang@google.com> Mime-Version: 1.0 References: <20210827031222.2778522-1-zixuanwang@google.com> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog Subject: [kvm-unit-tests PATCH v2 15/17] x86 AMD SEV-ES: Copy UEFI #VC IDT entry From: Zixuan Wang To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com, erdemaktas@google.com, rientjes@google.com, seanjc@google.com, brijesh.singh@amd.com, Thomas.Lendacky@amd.com, varad.gautam@suse.com, jroedel@suse.de, bp@suse.de Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org 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 --- 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; } From patchwork Fri Aug 27 03:12:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12461153 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A7A9AC432BE for ; Fri, 27 Aug 2021 03:12:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9035060F6C for ; Fri, 27 Aug 2021 03:12:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244163AbhH0DNm (ORCPT ); Thu, 26 Aug 2021 23:13:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36230 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244100AbhH0DNl (ORCPT ); Thu, 26 Aug 2021 23:13:41 -0400 Received: from mail-pf1-x449.google.com (mail-pf1-x449.google.com [IPv6:2607:f8b0:4864:20::449]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1DEE8C061757 for ; Thu, 26 Aug 2021 20:12:53 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id u8-20020a056a00098800b003eb2fbd34dcso135953pfg.12 for ; Thu, 26 Aug 2021 20:12:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=XPH3ZQXX9I+I0587YaKD8R4psbwwAlYn98ccCyKakYk=; b=SwieuOaAQS5W5lkr66cL1H4NoSfyavklD4k+6HKtsPmQFxwPlsUr5YhsAq3KuD06ut 54LIsODQxJJ/Y3Ucv8Qfv8/67jRGGkh49mtNU1c1Q1SfXZjdESzMQA51SiFt2zNSTBGw +amGXCwAycrVkRRHKLNo3XNDjmHzuRCWr+FthJ1pIOMHZi9WpSIPkd1e5AgCStbyErP9 o0lg2seiQG42zZPL7CjGAODEjCySuTeKlRgUO5IOs4e/3bcYpKvPIz0cmWT2Oa7BVCMR gB5FUJmvTvMqRDqIXijiqsgX2nLrkWkU6BZo3G2epBLSejX9ZBFVtK5iKlnj1OcJMo4f SUFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=XPH3ZQXX9I+I0587YaKD8R4psbwwAlYn98ccCyKakYk=; b=FT6NsgaHI9mJ9uzZuoYOHeVk1RE1YfKSjgETUMniVd5Mm2H8/yD9VMAIHZKV0M7ZQk 7hCp2B1ItBioe/tfY2h8whSHyl7A6Y/EfZJkm6J6XqJwq5UhpwTSQYaT6bWsYFxfQ5Ay 6H2BkRgrZVCvkKFRBfPW4gYlmXcA8POl2Dx6lG014n1c4jOrjafVLXkPpw40zP2WwdDb qTbL66X1QhxnsDXRZIHLw2piEMPbpTvVcuu3Np7RnEshzAtjMbT1Fzx1NKAsw4pQ3euu nPyWuEx3/Eb+QNTG8PhnpVDLJevOM0uOnc1Xq5LQk0FXBQoR5suRiDGd7Yz0aKt9Ards bQqQ== X-Gm-Message-State: AOAM53111y3GiMMt1FJt4PKdpRBWh4srpuE9l/eBRzOsAsK7lab+NpTp W2rtRaV1jTsp47UPBTcFaJwGrIIC2yyRKSSxgGdZAJH3eHyLqOylcvq3krwxYq9IRTw+Wp0Xd7w Hu02NmbeRegDLeAMb0yfTWfbLTGNZGnv+9W9y9yCA1W6pbU6lqV1eNU7H84m2xPJLkJ3o X-Google-Smtp-Source: ABdhPJxPF7ce+g60jM6xNgBJNlfTQXqnu/Xa48pJ2blinykBlQVXHQwck9GOKD/Ci7mB9KlkJRvKLV/tMYM7AN1o X-Received: from zxwang42.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2936]) (user=zixuanwang job=sendgmr) by 2002:a62:80d8:0:b0:3f2:72f5:bb31 with SMTP id j207-20020a6280d8000000b003f272f5bb31mr3803357pfd.0.1630033972517; Thu, 26 Aug 2021 20:12:52 -0700 (PDT) Date: Fri, 27 Aug 2021 03:12:21 +0000 In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com> Message-Id: <20210827031222.2778522-17-zixuanwang@google.com> Mime-Version: 1.0 References: <20210827031222.2778522-1-zixuanwang@google.com> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog Subject: [kvm-unit-tests PATCH v2 16/17] x86 AMD SEV-ES: Set up GHCB page From: Zixuan Wang To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com, erdemaktas@google.com, rientjes@google.com, seanjc@google.com, brijesh.singh@amd.com, Thomas.Lendacky@amd.com, varad.gautam@suse.com, jroedel@suse.de, bp@suse.de Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org AMD SEV-ES introduces a GHCB page for guest/host communication. This page should be unencrypted, i.e. its c-bit should be unset, otherwise the guest VM may crash when #VC exception happens. By default, KVM-Unit-Tests only sets up 2MiB pages, i.e. only Level 2 page table entries are provided. Unsetting GHCB Level 2 pte's c-bit still crashes the guest VM. The solution is to unset only its Level 1 pte's c-bit. This commit provides GHCB page set up code that: 1. finds GHCB Level 1 pte 2. if not found, installs corresponding Level 1 pages 3. unsets GHCB Level 1 pte's c-bit In this commit, KVM-Unit-Tests can run in an SEV-ES VM and boot into test cases' main(). Signed-off-by: Zixuan Wang --- lib/x86/amd_sev.c | 37 +++++++++++++++++++++++++++++++++++++ lib/x86/amd_sev.h | 7 +++++++ lib/x86/setup.c | 4 ++++ 3 files changed, 48 insertions(+) diff --git a/lib/x86/amd_sev.c b/lib/x86/amd_sev.c index d1e43ae..e004a7e 100644 --- a/lib/x86/amd_sev.c +++ b/lib/x86/amd_sev.c @@ -11,6 +11,7 @@ #include "amd_sev.h" #include "x86/processor.h" +#include "x86/vm.h" static unsigned long long amd_sev_c_bit_pos; @@ -116,6 +117,42 @@ efi_status_t setup_amd_sev_es(void) return EFI_SUCCESS; } +void setup_ghcb_pte(pgd_t *page_table) +{ + /* + * SEV-ES guest uses GHCB page to communicate with the host. This page + * must be unencrypted, i.e. its c-bit should be unset. To do so, this + * function searches GHCB's L1 pte, creates corresponding L1 ptes if not + * found, and unsets the c-bit of GHCB's L1 pte. + */ + phys_addr_t ghcb_addr, ghcb_base_addr; + pteval_t *pte; + + /* Read the current GHCB page addr */ + ghcb_addr = rdmsr(SEV_ES_GHCB_MSR_INDEX); + + /* Search Level 1 page table entry for GHCB page */ + pte = get_pte_level(page_table, (void *)ghcb_addr, 1); + + /* Create Level 1 pte for GHCB page if not found */ + if (pte == NULL) { + /* Find Level 2 page base address */ + ghcb_base_addr = ghcb_addr & ~(LARGE_PAGE_SIZE - 1); + /* Install Level 1 ptes */ + install_pages(page_table, ghcb_base_addr, LARGE_PAGE_SIZE, (void *)ghcb_base_addr); + /* Find Level 2 pte, set as 4KB pages */ + pte = get_pte_level(page_table, (void *)ghcb_addr, 2); + assert(pte); + *pte &= ~(PT_PAGE_SIZE_MASK); + /* Find Level 1 GHCB pte */ + pte = get_pte_level(page_table, (void *)ghcb_addr, 1); + assert(pte); + } + + /* Unset c-bit in Level 1 GHCB pte */ + *pte &= ~(get_amd_sev_c_bit_mask()); +} + 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 aaa4806..81f5605 100644 --- a/lib/x86/amd_sev.h +++ b/lib/x86/amd_sev.h @@ -45,8 +45,15 @@ efi_status_t setup_amd_sev(void); */ #define SEV_ES_VC_HANDLER_VECTOR 29 +/* + * AMD Programmer's Manual Volume 2 + * - Section "GHCB" + */ +#define SEV_ES_GHCB_MSR_INDEX 0xc0010130 + bool amd_sev_es_enabled(void); efi_status_t setup_amd_sev_es(void); +void setup_ghcb_pte(pgd_t *page_table); 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 9075a22..0de3ec2 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -278,6 +278,10 @@ static void setup_page_table(void) curr_pt[i] = ((phys_addr_t)(i << 21)) | flags; } + if (amd_sev_es_enabled()) { + setup_ghcb_pte((pgd_t *)&ptl4); + } + /* Load 4-level page table */ write_cr3((ulong)&ptl4); } From patchwork Fri Aug 27 03:12:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12461155 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-26.3 required=3.0 tests=BAYES_00,DKIMWL_WL_MED, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 72323C432BE for ; Fri, 27 Aug 2021 03:12:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5A36D60F6F for ; Fri, 27 Aug 2021 03:12:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244164AbhH0DNo (ORCPT ); Thu, 26 Aug 2021 23:13:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36240 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244100AbhH0DNm (ORCPT ); Thu, 26 Aug 2021 23:13:42 -0400 Received: from mail-pf1-x449.google.com (mail-pf1-x449.google.com [IPv6:2607:f8b0:4864:20::449]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D55B3C061757 for ; Thu, 26 Aug 2021 20:12:54 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id h10-20020a056a00170a00b003e31c4d9992so2213405pfc.23 for ; Thu, 26 Aug 2021 20:12:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=Qz364tHRAJ7dP0GQYPGE0P0hbUEMQJvVz6b5KTAgE7E=; b=rQtnQCIRf/agAPpzYjcXG7j1LQuaBaIyqiBfub4K8iun6kji5eA+XV6xse6BsRJUDa IQF912b9rKlW/0M82oK3FXHTio3Q43KQD7Y+LQCMjtFzjWrUHL1Og/eMoR1WI4DjkXye PTnpSTAOcpIdUauj+UkAu3V5uQSqN1a/6Z1McR9SgvcCSIEfrmIS3y10pP3tak2703TJ lal1uCCvE6LW/4pDoaEvmundqM2pB1uF8eHaWNlzytipabFTCJ3nqgZh3c+ux05oy9vD RAhB19ALY/gMaItOZTWPhl2bweh+H95emTRZoHIk/JxmQ5gtHYh4gOP6wAy4zofSOWg/ 5itQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=Qz364tHRAJ7dP0GQYPGE0P0hbUEMQJvVz6b5KTAgE7E=; b=FDPp0Tfx4HMMcIvLMXSsrYnbmxFTuxtrRqm1j56DF0mta70ndxlbBwhuTAkvWbS1fg hAnvctf/qgnw4Ld5x6Jd3PZyMhAqatAV79lxxExzEulsk1VP5dliOPqlgiK7Z1qpVTIt wZmZYxS1BQ51bSN22MK3mDAf2OVB1j/mN/V51jLEVJSYHSF50GnCVonUWpLNxT6PRHPs RNhF4iSQrOEkEugGO3Aeo9IY+zwzy0P6aNeQjbqeXPvTFq5NKXX2OXLcbwsJ+Yy81Ovp XNyQMZik/nK3l5eB/y2xzBtI369ksriJlg2XvYGnF4lSanJZUKgbVGXlpPwZPuM/vGKA +/XA== X-Gm-Message-State: AOAM531Pr3Y+Ud7UmN4GRtjBRUK59A1fbF/QRx9cswFzP2QCd+Y0Yqra 1ORkUDYBvtBz733JbfapEQyBjIS2AnzJiq4WKTuNKWdHpT+RA2DfDt1We+K6L1xK9Qa6WslBMOa e7ylZpgwcqxrtObprqbZbUHYCa2n7OzKy0VNNzKsgDn8t7vkuOv+XXbrNr0hvjAaIJaR+ X-Google-Smtp-Source: ABdhPJwImo/T88iRiHHkN6lNf2ehUGO8/S3BpeEHG7ohI3SSZjVH0sSHih+5JQrrEya8bG6a8FyMNUJ9/xxRP6JV X-Received: from zxwang42.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:2936]) (user=zixuanwang job=sendgmr) by 2002:a62:3887:0:b0:3f2:6c5a:8a92 with SMTP id f129-20020a623887000000b003f26c5a8a92mr4677725pfa.8.1630033974271; Thu, 26 Aug 2021 20:12:54 -0700 (PDT) Date: Fri, 27 Aug 2021 03:12:22 +0000 In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com> Message-Id: <20210827031222.2778522-18-zixuanwang@google.com> Mime-Version: 1.0 References: <20210827031222.2778522-1-zixuanwang@google.com> X-Mailer: git-send-email 2.33.0.259.gc128427fd7-goog Subject: [kvm-unit-tests PATCH v2 17/17] x86 AMD SEV-ES: Add test cases From: Zixuan Wang To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com, erdemaktas@google.com, rientjes@google.com, seanjc@google.com, brijesh.singh@amd.com, Thomas.Lendacky@amd.com, varad.gautam@suse.com, jroedel@suse.de, bp@suse.de Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org SEV-ES introduces #VC handler for guest/host communications, e.g., accessing MSR, executing CPUID. This commit provides test cases to check if SEV-ES is enabled and if rdmsr/wrmsr are handled correctly in SEV-ES. Signed-off-by: Zixuan Wang --- x86/amd_sev.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/x86/amd_sev.c b/x86/amd_sev.c index a07a48f..21a491c 100644 --- a/x86/amd_sev.c +++ b/x86/amd_sev.c @@ -13,6 +13,7 @@ #include "libcflat.h" #include "x86/processor.h" #include "x86/amd_sev.h" +#include "msr.h" #define EXIT_SUCCESS 0 #define EXIT_FAILURE 1 @@ -55,10 +56,39 @@ static int test_sev_activation(void) return EXIT_SUCCESS; } +static int test_sev_es_activation(void) +{ + if (!(rdmsr(MSR_SEV_STATUS) & SEV_ES_ENABLED_MASK)) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +static int test_sev_es_msr(void) +{ + /* + * With SEV-ES, rdmsr/wrmsr trigger #VC exception. If #VC is handled + * correctly, rdmsr/wrmsr should work like without SEV-ES and not crash + * the guest VM. + */ + u64 val = 0x1234; + wrmsr(MSR_TSC_AUX, val); + if(val != rdmsr(MSR_TSC_AUX)) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + int main(void) { int rtn; rtn = test_sev_activation(); report(rtn == EXIT_SUCCESS, "SEV activation test."); + rtn = test_sev_es_activation(); + report(rtn == EXIT_SUCCESS, "SEV-ES activation test."); + rtn = test_sev_es_msr(); + report(rtn == EXIT_SUCCESS, "SEV-ES MSR test."); return report_summary(); }