From patchwork Mon Oct 4 20:49: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: 12534795 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 151F6C433F5 for ; Mon, 4 Oct 2021 20:49:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E8C1261357 for ; Mon, 4 Oct 2021 20:49:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232836AbhJDUv2 (ORCPT ); Mon, 4 Oct 2021 16:51:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55494 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232452AbhJDUvZ (ORCPT ); Mon, 4 Oct 2021 16:51:25 -0400 Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1714EC061745 for ; Mon, 4 Oct 2021 13:49:36 -0700 (PDT) Received: by mail-pl1-x635.google.com with SMTP id t11so744004plq.11 for ; Mon, 04 Oct 2021 13:49:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=fnoNH14Q0HbTfzGd4rffMzlYIvIU57Kx4gAb9gX9Tbc=; b=GeF7aqzjC1ZR1xtqOPnvNazHqxAD58qzI+M+dpiv5qVxAoF6RbtsJD6HNEHZuTx9/Z mucPKHz52+dzQC+Y6xCydzsPdYj7uE9zzQ0m2jKmkam4S307l9RC97/l7P6cuAdWfCJD ELNiBf1+VmlIDsB+O2IBKAOWHFt14WHWXHtTZSTgNCutVMUPbsUVT/fq2/sBbP6aysHG yrvtQW0ujY9ruP+Oyu9wL9g0xrwlSLSxaxrLgCrcOTiRCQf1lowIQ4ShuychgcUU6ZWp iXjXRGt1WvOy/EIsgrSv7KCBQ601M5M2RPzw6E7C0RXiOWSmXjkDC+H6r5omEyZ/kT1g TJLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=fnoNH14Q0HbTfzGd4rffMzlYIvIU57Kx4gAb9gX9Tbc=; b=yLsuAEooWTyJLaojCXFsE9M7zRNE1auHUshiCfuWnpr7umKA/wHqv13PCVZfIQUpOD 7nBH4MAeNzYZ/2JNGSCwYf/YrzdEUa/ZbKxpbyLmW1Nd5JgXpRP+fBxh3KqCybq/cOJA weVucQkbljAd/jyF+6/Tg9VghMiVABhicCl7wLWZ9Z3nOK/xiUKQqKPSogrtjwvOeU1T h0+QXalgr12NOzn/pJCt9pIs9QuIDmdOmYCCnRCAYxoiEhl68Z/aeV9Zs/HSQ1S4gKOp tiVWFPR0NzLwkK4TUNtor5IW2xAlkeW8M63VPcZd6jJjgKrWJOZhI6mXnF1A+o9U36c4 bRQQ== X-Gm-Message-State: AOAM532s/kpnplfEm06hBfaaYYAa5cCtgYznzJ+QMyACj43XIBd+FdBT NGGN88acbTTlyHl9AkUQsCng8wg8WNyMNg== X-Google-Smtp-Source: ABdhPJw/ABF6wn4QhiA0SBcr5YJ+Zs0jNJi2w5j8UoUbCSJlacucuLIsMG9xl0nENUX9EbKlAMJfpQ== X-Received: by 2002:a17:90a:345:: with SMTP id 5mr38682686pjf.189.1633380575172; Mon, 04 Oct 2021 13:49:35 -0700 (PDT) Received: from localhost.localdomain (netadmin.ucsd.edu. [137.110.160.224]) by smtp.gmail.com with ESMTPSA id o12sm13635063pjm.57.2021.10.04.13.49.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Oct 2021 13:49:34 -0700 (PDT) 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 Subject: [kvm-unit-tests PATCH v3 01/17] x86: Move IDT, GDT and TSS to desc.c Date: Mon, 4 Oct 2021 13:49:15 -0700 Message-Id: <20211004204931.1537823-2-zxwang42@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211004204931.1537823-1-zxwang42@gmail.com> References: <20211004204931.1537823-1-zxwang42@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Zixuan Wang Move the IDT, GDT and TSS data structures from x86/cstart64.S to lib/x86/desc.c, so that the follow-up UEFI support commits can reuse these definitions, without re-defining them in UEFI's boot up assembly code. In this commit, tss_descr is defined as a pointer, instead of an assembly label. This type change leads to several updates in the x86/vmx.c. Fortunately x86/vmx.c is only used in x86_64, so it is not necessary to be compatible with i386's tss_descr type which is an assembly label. Signed-off-by: Zixuan Wang --- lib/x86/asm/setup.h | 8 +++++ lib/x86/desc.c | 46 ++++++++++++++++++++++++++- lib/x86/desc.h | 6 +++- lib/x86/setup.c | 43 +++++++++++++++++++++++++ x86/cstart64.S | 77 ++------------------------------------------- x86/vmx.c | 8 ++--- 6 files changed, 107 insertions(+), 81 deletions(-) create mode 100644 lib/x86/asm/setup.h diff --git a/lib/x86/asm/setup.h b/lib/x86/asm/setup.h new file mode 100644 index 0000000..19ded12 --- /dev/null +++ b/lib/x86/asm/setup.h @@ -0,0 +1,8 @@ +#ifndef _X86_ASM_SETUP_H_ +#define _X86_ASM_SETUP_H_ + +#ifdef __x86_64__ +unsigned long setup_tss(void); +#endif /* __x86_64__ */ + +#endif /* _X86_ASM_SETUP_H_ */ diff --git a/lib/x86/desc.c b/lib/x86/desc.c index e7378c1..d1eb97b 100644 --- a/lib/x86/desc.c +++ b/lib/x86/desc.c @@ -3,6 +3,50 @@ #include "processor.h" #include +#ifdef __x86_64__ +#include "apic-defs.h" + +/* Boot-related data structures */ + +/* IDT and IDT descriptor */ +idt_entry_t boot_idt[256] = {0}; + +struct descriptor_table_ptr idt_descr = { + .limit = sizeof(boot_idt) - 1, + .base = (phys_addr_t)boot_idt, +}; + +/* GDT, TSS and descriptors */ +gdt_entry_t gdt64[GDT64_PRE_TSS_ENTRIES + MAX_TEST_CPUS * 2] = { + { 0, 0, 0, 0x00, 0x00, 0}, /* 0x00 null */ + {0xffff, 0, 0, 0x9b, 0xaf, 0}, /* 0x08 64-bit code segment */ + {0xffff, 0, 0, 0x93, 0xcf, 0}, /* 0x10 32/64-bit data segment */ + {0xffff, 0, 0, 0x1b, 0xaf, 0}, /* 0x18 64-bit code segment, not present */ + {0xffff, 0, 0, 0x9b, 0xcf, 0}, /* 0x20 32-bit code segment */ + {0xffff, 0, 0, 0x9b, 0x8f, 0}, /* 0x28 16-bit code segment */ + {0xffff, 0, 0, 0x93, 0x8f, 0}, /* 0x30 16-bit data segment */ + {0xffff, 0, 0, 0xfb, 0xcf, 0}, /* 0x38 32-bit code segment (user) */ + {0xffff, 0, 0, 0xf3, 0xcf, 0}, /* 0x40 32/64-bit data segment (user) */ + {0xffff, 0, 0, 0xfb, 0xaf, 0}, /* 0x48 64-bit code segment (user) */ + { 0, 0, 0, 0x00, 0x00, 0}, /* 0x50 null */ + { 0, 0, 0, 0x00, 0x00, 0}, /* 0x58 null */ + { 0, 0, 0, 0x00, 0x00, 0}, /* 0x60 null */ + { 0, 0, 0, 0x00, 0x00, 0}, /* 0x68 null */ + { 0, 0, 0, 0x00, 0x00, 0}, /* 0x70 null */ + { 0, 0, 0, 0x00, 0x00, 0}, /* 0x78 null */ +}; + +struct descriptor_table_ptr gdt64_desc = { + .limit = sizeof(gdt64) - 1, + .base = (phys_addr_t)gdt64, +}; + +struct descriptor_table_ptr *tss_descr = + (struct descriptor_table_ptr *)&gdt64[GDT64_PRE_TSS_ENTRIES]; + +tss64_t tss[MAX_TEST_CPUS] = {0}; +#endif + #ifndef __x86_64__ __attribute__((regparm(1))) #endif @@ -374,7 +418,7 @@ void set_intr_alt_stack(int e, void *addr) void setup_alt_stack(void) { - tss.ist1 = (u64)intr_alt_stack + 4096; + tss[0].ist1 = (u64)intr_alt_stack + 4096; } #endif diff --git a/lib/x86/desc.h b/lib/x86/desc.h index a6ffb38..c7ee881 100644 --- a/lib/x86/desc.h +++ b/lib/x86/desc.h @@ -208,7 +208,11 @@ void set_idt_task_gate(int vec, u16 sel); void set_intr_task_gate(int vec, void *fn); void setup_tss32(void); #else -extern tss64_t tss; +extern tss64_t tss[]; +/* In gdt64, there are 16 entries before TSS entries */ +#define GDT64_PRE_TSS_ENTRIES (16) +#define GDT64_TSS_OFFSET (GDT64_PRE_TSS_ENTRIES) +extern gdt_entry_t gdt64[]; #endif unsigned exception_vector(void); diff --git a/lib/x86/setup.c b/lib/x86/setup.c index 7befe09..8c73156 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,10 @@ #include "fwcfg.h" #include "alloc_phys.h" #include "argv.h" +#include "desc.h" +#include "apic.h" +#include "apic-defs.h" +#include "asm/setup.h" extern char edata; @@ -97,6 +102,44 @@ void find_highmem(void) phys_alloc_init(best_start, best_end - best_start); } } + +extern phys_addr_t ring0stacktop; + +/* Setup TSS for the current processor, and return TSS offset within gdt64 */ +unsigned long setup_tss(void) +{ + u32 id; + gdt_entry_t *gdt_entry_lo, *gdt_entry_hi; + tss64_t *tss_entry; + phys_addr_t tss_entry_addr; + + id = apic_id(); + + /* Runtime address of current TSS */ + tss_entry = &tss[id]; + tss_entry_addr = (phys_addr_t)tss_entry; + + /* Update TSS */ + memset((void *)tss_entry, 0, sizeof(tss64_t)); + tss_entry->rsp0 = (u64)((u8*)&ring0stacktop - id * 4096); + + /* Each TSS descriptor takes up 2 GDT entries */ + gdt_entry_lo = &gdt64[GDT64_PRE_TSS_ENTRIES + id * 2 + 0]; + gdt_entry_hi = &gdt64[GDT64_PRE_TSS_ENTRIES + id * 2 + 1]; + + /* Update TSS descriptors */ + memset((void *)gdt_entry_lo, 0, sizeof(gdt_entry_t)); + memset((void *)gdt_entry_hi, 0, sizeof(gdt_entry_t)); + gdt_entry_lo->access = 0x89; + gdt_entry_lo->limit_low = 0xffff; + gdt_entry_lo->base_low = (u16)(tss_entry_addr & 0xffff); + gdt_entry_lo->base_middle = (u8)((tss_entry_addr >> 16) & 0xff); + gdt_entry_lo->base_high = (u8)((tss_entry_addr >> 24) & 0xff); + gdt_entry_hi->limit_low = (u16)((tss_entry_addr >> 32) & 0xffff); + gdt_entry_hi->base_low = (u16)((tss_entry_addr >> 48) & 0xffff); + + return (GDT64_PRE_TSS_ENTRIES + id * 2) * sizeof(gdt_entry_t); +} #endif void setup_multiboot(struct mbi_bootinfo *bi) diff --git a/x86/cstart64.S b/x86/cstart64.S index 5c6ad38..57383c1 100644 --- a/x86/cstart64.S +++ b/x86/cstart64.S @@ -1,11 +1,7 @@ #include "apic-defs.h" -.globl boot_idt - -.globl idt_descr -.globl tss_descr -.globl gdt64_desc +.globl ring0stacktop .globl online_cpus .globl cpu_online_count @@ -51,56 +47,6 @@ ptl5: .align 4096 -boot_idt: - .rept 256 - .quad 0 - .quad 0 - .endr -end_boot_idt: - -gdt64_desc: - .word gdt64_end - gdt64 - 1 - .quad 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: - -i = 0 -.globl tss -tss: - .rept max_cpus - .long 0 - .quad ring0stacktop - i * 4096 - .quad 0, 0 - .quad 0, 0, 0, 0, 0, 0, 0, 0 - .long 0, 0, 0 -i = i + 1 - .endr -tss_end: - mb_boot_info: .quad 0 pt_root: .quad ptl4 @@ -291,31 +237,12 @@ setup_5level_page_table: lvl5: retq -idt_descr: - .word end_boot_idt - boot_idt - 1 - .quad boot_idt - online_cpus: .fill (max_cpus + 7) / 8, 1, 0 load_tss: lidtq idt_descr - mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax - mov (%rax), %eax - shr $24, %eax - mov %eax, %ebx - shl $4, %ebx - mov $((tss_end - tss) / max_cpus), %edx - imul %edx - add $tss, %rax - mov %ax, tss_descr+2(%rbx) - shr $16, %rax - mov %al, tss_descr+4(%rbx) - shr $8, %rax - mov %al, tss_descr+7(%rbx) - shr $8, %rax - mov %eax, tss_descr+8(%rbx) - lea tss_descr-gdt64(%rbx), %rax + call setup_tss ltr %ax ret diff --git a/x86/vmx.c b/x86/vmx.c index f0b853a..37aff12 100644 --- a/x86/vmx.c +++ b/x86/vmx.c @@ -75,7 +75,7 @@ union vmx_ept_vpid ept_vpid; extern struct descriptor_table_ptr gdt64_desc; extern struct descriptor_table_ptr idt_descr; -extern struct descriptor_table_ptr tss_descr; +extern struct descriptor_table_ptr *tss_descr; extern void *vmx_return; extern void *entry_sysenter; extern void *guest_entry; @@ -1276,7 +1276,7 @@ static void init_vmcs_host(void) vmcs_write(HOST_SEL_FS, KERNEL_DS); vmcs_write(HOST_SEL_GS, KERNEL_DS); vmcs_write(HOST_SEL_TR, TSS_MAIN); - vmcs_write(HOST_BASE_TR, tss_descr.base); + vmcs_write(HOST_BASE_TR, tss_descr->base); vmcs_write(HOST_BASE_GDTR, gdt64_desc.base); vmcs_write(HOST_BASE_IDTR, idt_descr.base); vmcs_write(HOST_BASE_FS, 0); @@ -1332,7 +1332,7 @@ static void init_vmcs_guest(void) vmcs_write(GUEST_BASE_DS, 0); vmcs_write(GUEST_BASE_FS, 0); vmcs_write(GUEST_BASE_GS, 0); - vmcs_write(GUEST_BASE_TR, tss_descr.base); + vmcs_write(GUEST_BASE_TR, tss_descr->base); vmcs_write(GUEST_BASE_LDTR, 0); vmcs_write(GUEST_LIMIT_CS, 0xFFFFFFFF); @@ -1342,7 +1342,7 @@ static void init_vmcs_guest(void) vmcs_write(GUEST_LIMIT_FS, 0xFFFFFFFF); vmcs_write(GUEST_LIMIT_GS, 0xFFFFFFFF); vmcs_write(GUEST_LIMIT_LDTR, 0xffff); - vmcs_write(GUEST_LIMIT_TR, tss_descr.limit); + vmcs_write(GUEST_LIMIT_TR, tss_descr->limit); vmcs_write(GUEST_AR_CS, 0xa09b); vmcs_write(GUEST_AR_DS, 0xc093); From patchwork Mon Oct 4 20:49: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: 12534797 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 439BBC433F5 for ; Mon, 4 Oct 2021 20:49:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2767A611C8 for ; Mon, 4 Oct 2021 20:49:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236279AbhJDUvb (ORCPT ); Mon, 4 Oct 2021 16:51:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55502 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232647AbhJDUv0 (ORCPT ); Mon, 4 Oct 2021 16:51:26 -0400 Received: from mail-pj1-x102d.google.com (mail-pj1-x102d.google.com [IPv6:2607:f8b0:4864:20::102d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9D0E7C061745 for ; Mon, 4 Oct 2021 13:49:37 -0700 (PDT) Received: by mail-pj1-x102d.google.com with SMTP id kk10so3168419pjb.1 for ; Mon, 04 Oct 2021 13:49:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=4pm9339gKSLSUALkz1hC2l0S1H4xA4h9VVwwQcqHFOg=; b=YBpxpRRcdKvN8Ve4dNSOYikMjMlajTkOFwEnV5IaGzE5qPcR+knCHqcZrmQzt0at51 HQyxoobaE4rF6jryx7JtKcey2DQFq51wNvbWXvqUaioMNekohmdP56KzO/+EjELyvXnN O8PF2Sss8dIqsu4beuTVScZZ8jYiF6g/XG8Zxuck9dtSuj/2RKU901yxFDrjzcoeB8gZ n3ysoF2R+Qkmwr5KMukjlz2S8S57JcKMgxU5oipWq03ciMWd77AbchN7aB4hbQjiC7d8 KFQQ45BvEI8VLV708VMoLWgTwzrb9MspH527A9VuMolmBElE7mCZfL3DaD8NiWHuAd0x NwMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=4pm9339gKSLSUALkz1hC2l0S1H4xA4h9VVwwQcqHFOg=; b=xaJdZKqkI4+GXFBK+PxGLj1o39kPicLi19wZsKhWKkkH+YLLmRMfYfqSAcE3bCdvxQ AkxOpCRz5OmKhQvU3/XtK+UY85IzBU+MXl4UQ+aCn/N2AllKKSOA4tT2ifKIw1oMNARk HPZaRw3b3tQjcQaKf7ckyaGJKuzm6xJm6++wA4l4SXL5POoUOanI9Ei/2bAhL9momXMS +qy2CKeQ4cEIpfMxO1RNtSastSgbrlyPQPiWuwKlyMKDEsmOmRoiO3xWUUQZwm7Q3JJu lN77IzVd+n67hOvaDuUURoI7kGnuGKid6QyONfAA9z+2HV9OMAMEVX6dkFDjCJQeqj30 0KJg== X-Gm-Message-State: AOAM531KI1eK3szKQ1STpRXTt70pVdzakrN9tkMC/NpJ/Q8RVTUa+FWo BFRuw03zhAUaVpjrYRuBMN3v/pJBrmaWmA== X-Google-Smtp-Source: ABdhPJya8uMThlgp6inS+ozkfA/mbkbaJ6Yav/WJSrWjB+0B6aFr6eFcq+zL17PraQpABwupaao/Tw== X-Received: by 2002:a17:902:c401:b0:13e:9f66:54f6 with SMTP id k1-20020a170902c40100b0013e9f6654f6mr1612013plk.2.1633380576670; Mon, 04 Oct 2021 13:49:36 -0700 (PDT) Received: from localhost.localdomain (netadmin.ucsd.edu. [137.110.160.224]) by smtp.gmail.com with ESMTPSA id o12sm13635063pjm.57.2021.10.04.13.49.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Oct 2021 13:49:36 -0700 (PDT) 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 Subject: [kvm-unit-tests PATCH v3 02/17] x86 UEFI: Copy code from Linux Date: Mon, 4 Oct 2021 13:49:16 -0700 Message-Id: <20211004204931.1537823-3-zxwang42@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211004204931.1537823-1-zxwang42@gmail.com> References: <20211004204931.1537823-1-zxwang42@gmail.com> MIME-Version: 1.0 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/efi.h | 518 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 518 insertions(+) create mode 100644 lib/linux/efi.h diff --git a/lib/linux/efi.h b/lib/linux/efi.h new file mode 100644 index 0000000..bb4601b --- /dev/null +++ b/lib/linux/efi.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 __attribute__((aligned(__alignof__(u32)))); +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 Mon Oct 4 20:49: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: 12534799 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4B993C433EF for ; Mon, 4 Oct 2021 20:49:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3465561507 for ; Mon, 4 Oct 2021 20:49:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233029AbhJDUvd (ORCPT ); Mon, 4 Oct 2021 16:51:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55510 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232884AbhJDUv2 (ORCPT ); Mon, 4 Oct 2021 16:51:28 -0400 Received: from mail-pl1-x62f.google.com (mail-pl1-x62f.google.com [IPv6:2607:f8b0:4864:20::62f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 09BE9C061749 for ; Mon, 4 Oct 2021 13:49:39 -0700 (PDT) Received: by mail-pl1-x62f.google.com with SMTP id t4so800337plo.0 for ; Mon, 04 Oct 2021 13:49:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=LN79VK4oUfP1jBlueSCHop8deFKXmtHsFgLKU4/bmMo=; b=eFpm2ImeVnGDnoapuApMzdujExeOkT+mXVcpu8tp4xeq49brEqpA5X7QlYsci2/ltd K3N/+S9R6O0YRoliWCucSalb6R2SrmAq1NV3HCY+T30rc5cJLIBQfSdnuMoUan5H+PZ0 8nquKXOTIv4t3UGfanT/27ecRMmYLMiayxkPej5kW8SwUxuOJCX3ctvkfCNISiFoViNv dN4907FzE54iq/yLJtgwsQM0d+7uH2jHmSkDPUD6KEy9v5AOMo9HzyZPGQ1qcylPXSm/ WDujdIri+cdtzkGzo+8obMsV9s6GrX4ITzgXhYoQFnLXGWG5XzcMgzbZJaJ0qy0Ooiro 6oww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=LN79VK4oUfP1jBlueSCHop8deFKXmtHsFgLKU4/bmMo=; b=43ah6jfwv97++0Q9eQFSJAfltOKCC1iMKiI6SY0OxmcIPY97GLBQrVpOFwLM7QIGwA wW81vowfoBEr3ZmPFgvlRCLYpIUy1zvCGFEbMGCJxzraSKtUIodth1chmu4MafaJ7b/8 EOlmfsqfxXbNV4mVfK9dGFnO7ZMuVPVKpSxzq5irYuzZsJqg4s/RON6O3EsTO9386AOI gyvtml6bFX/wP5SLoW8NI3C+wwbwaZX+2dtaWYKO6ZQ57d7AgZ8IuXTCQkO+tLy6c61j mg7fok3X63lSdaD+iZcCFxJy3dJUXhddd31n7ieXeVcvdQrSNqJwyXQNZ2Vfz/1wTvl9 uHnQ== X-Gm-Message-State: AOAM533NVB1XWVP7vkr6LWv2l0tqwBtq3KaOftwngFsVjejZRxzpZFYH VdHpjj0PHik3nBZ4NhMWNh69E+07H/TSVA== X-Google-Smtp-Source: ABdhPJyL7QwG9T1ZO/uPk64YSsqICTIjqcO8W6FokdLXXyeaTD4rCPs034Fr9deaPS1UqbiZB3JwrA== X-Received: by 2002:a17:90a:a609:: with SMTP id c9mr14979847pjq.134.1633380578148; Mon, 04 Oct 2021 13:49:38 -0700 (PDT) Received: from localhost.localdomain (netadmin.ucsd.edu. [137.110.160.224]) by smtp.gmail.com with ESMTPSA id o12sm13635063pjm.57.2021.10.04.13.49.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Oct 2021 13:49:37 -0700 (PDT) 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 Subject: [kvm-unit-tests PATCH v3 03/17] x86 UEFI: Implement UEFI function calls Date: Mon, 4 Oct 2021 13:49:17 -0700 Message-Id: <20211004204931.1537823-4-zxwang42@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211004204931.1537823-1-zxwang42@gmail.com> References: <20211004204931.1537823-1-zxwang42@gmail.com> MIME-Version: 1.0 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 | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 lib/efi.c diff --git a/lib/efi.c b/lib/efi.c new file mode 100644 index 0000000..7f08f0e --- /dev/null +++ b/lib/efi.c @@ -0,0 +1,67 @@ +/* + * EFI-related functions to set up and run test cases in EFI + * + * Copyright (c) 2021, SUSE, Varad Gautam + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ +#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 Mon Oct 4 20:49: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: 12534801 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 21370C4332F for ; Mon, 4 Oct 2021 20:49:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 02738611C8 for ; Mon, 4 Oct 2021 20:49:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231229AbhJDUve (ORCPT ); Mon, 4 Oct 2021 16:51:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55522 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233615AbhJDUva (ORCPT ); Mon, 4 Oct 2021 16:51:30 -0400 Received: from mail-pg1-x52e.google.com (mail-pg1-x52e.google.com [IPv6:2607:f8b0:4864:20::52e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AC3F4C06174E for ; Mon, 4 Oct 2021 13:49:40 -0700 (PDT) Received: by mail-pg1-x52e.google.com with SMTP id 75so17745051pga.3 for ; Mon, 04 Oct 2021 13:49:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=vTbKvlhs0bVw+nGLMovJsoALx/6y2sNucVpS/ZwEi/A=; b=cLkltRkTcqnPEHh8dV0q11TeaiAa4NQfBabpl6U4IyHtowaVDYbIsFqb1bq3MdWwju 4Mlz3sZ3IYpLZW7xk9kyPHyNt68POyjId26b8Tet/gLeoEsbZf8IJ2KvnL8Z74uJTg2R i3r9iGI1CxWtpeh/uEBhhhKySnuambZJjy0r2GWrebqgWhHRL7v4xsds1t7kWhKZ634V Ep1/VvCjZQ+W8xhAv8KxBx3qXUX+vPz3Fpz7zou7ibo7f/z+uF0HYlhtqQUrCUiRbXn6 bJxJm+znSu02WPP6W4AuuzGLUXI3pWwn5Ux8yStDWAWLg4w6TBa+lIGS+kO5SCn82oVK jsMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=vTbKvlhs0bVw+nGLMovJsoALx/6y2sNucVpS/ZwEi/A=; b=vhmdX9h/bGXublSVtqwQBwkYTWWAptttim9zC+RBtZK0wEEbFqPBjW5UHz0uJDrGMU Y595zz08U4gL401A2NXP3cqzrHsnR0nIL/bg9PD4iiGqROBDAk7O5QHoZF6rgTWCVVQi +XokP+bIsym/ubzYJhUAPjaqkV9Ij5TGSFYinekXvhWHU9Hv6GRL4nJFx8zVF1pA3WGv TdH4JX2vxtpPMuc49RQ0yrJGuOpG24D2NrlzsErKQ2lZdV+VE01DfiOHsGRy100FPdME vRk2Od2vuEdBB0kACivMUTWnJAzVviuA0eLlWsFDn9HZynvwlR4rVGgCRtxy16YvbSfp NKnw== X-Gm-Message-State: AOAM531XVUUlN4Vu0H82uxLEdMbHvF04CV7J42bOCSAFSWajWNtOAHmj c64B74AW4czquax6znximE3TrQ9EcbhvvQ== X-Google-Smtp-Source: ABdhPJxomvxfW8+fIihpzvXjyZbjnyC4m0fhqGSJxe9IW8vuuefNzsiX3E1/kRmrraE4N28pe91BOQ== X-Received: by 2002:a63:85c6:: with SMTP id u189mr12417515pgd.381.1633380579724; Mon, 04 Oct 2021 13:49:39 -0700 (PDT) Received: from localhost.localdomain (netadmin.ucsd.edu. [137.110.160.224]) by smtp.gmail.com with ESMTPSA id o12sm13635063pjm.57.2021.10.04.13.49.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Oct 2021 13:49:39 -0700 (PDT) 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 Subject: [kvm-unit-tests PATCH v3 04/17] x86 UEFI: Copy code from GNU-EFI Date: Mon, 4 Oct 2021 13:49:18 -0700 Message-Id: <20211004204931.1537823-5-zxwang42@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211004204931.1537823-1-zxwang42@gmail.com> References: <20211004204931.1537823-1-zxwang42@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Zixuan Wang 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..bc1f733 --- /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 Mon Oct 4 20:49: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: 12534805 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1CF41C433F5 for ; Mon, 4 Oct 2021 20:49:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F2290611C8 for ; Mon, 4 Oct 2021 20:49:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234829AbhJDUvf (ORCPT ); Mon, 4 Oct 2021 16:51:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55526 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236407AbhJDUvc (ORCPT ); Mon, 4 Oct 2021 16:51:32 -0400 Received: from mail-pj1-x102d.google.com (mail-pj1-x102d.google.com [IPv6:2607:f8b0:4864:20::102d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9DAB8C061749 for ; Mon, 4 Oct 2021 13:49:42 -0700 (PDT) Received: by mail-pj1-x102d.google.com with SMTP id g13-20020a17090a3c8d00b00196286963b9so341114pjc.3 for ; Mon, 04 Oct 2021 13:49:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Suu6DW6bEf7DMT6ZVAPNX64kQClYku/ByWPTgcLW1eA=; b=gRB1mV4JHDV/uK8xA5MchW4dVXnpIdIJNSoq9PE4IEUPSiCjK7ASM9txsxIV4+hAjJ GDTRWp7pOIn7qJMqC/hOcCqkpDgURSZ3uQCNiMQc89/bDBEFoQ8/l6ojYQ2BnjSCS+/2 BeC+bSmrjnl29tMBxn1SPNyFNNPnknUqdEcQVRblwAGWAntvh/obP8tSFeTolyW5UNt2 aD5vc9FxexpH9Xa7Ee58LlLVqo2aC6GUYNbocUrNwcfGOIutz653pIgw8UQ01Bby0E8m kkMsM8Cj1PBl5VpwkgDxuOSByvb6QvxGEUvy9CS+OMKOMKzV1mnngcWG4Qb5hAPmu6RD dGfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Suu6DW6bEf7DMT6ZVAPNX64kQClYku/ByWPTgcLW1eA=; b=Kw0EkGwoIMBs3V+Q1pyNpQtEgkee67mJzBtQc3suGzdE/dURTzRuwpxYpyeCJ/VcKb 8lZ+nBPzVi1ziTJhbRGCb/yztMKEqgIx0NpS/H5jMVUxMxUTZ/uS6bUR2bK5UeUA/gOA KvLcVYzLLxp1qYOxrMIbG79taLVR7GOWkY3s89Isyhf/5ScKQVd+5uiE2rWd9Xr59hva Qn37I60w5LsaOG5xMPTGHepMdMRhm0fvjVOPgHD0lYHK2sVoRAD9QxTfD7etiDtvNrNT BNxVpcGe4eoAAL6h9hH4bQopK1wRcczVRdTxuoaF81pnZLSRbxW/G0T2+ixI4x0evZMn NLow== X-Gm-Message-State: AOAM533xxGnSkAkqtOB87cXO63zXpLQYQPO4IMixK9lKAV2CW2UP52sG 9Usdo0F6V1+3oGc3LkmZuVe1OfDGxps34A== X-Google-Smtp-Source: ABdhPJzobJ5LB3me41NK1Ut7D1X0GRkTlLXX9Q7l1YwWZC6u0McJtrRfHE70pCp4OnYdUXh+x7WUMg== X-Received: by 2002:a17:90b:3852:: with SMTP id nl18mr235040pjb.9.1633380581347; Mon, 04 Oct 2021 13:49:41 -0700 (PDT) Received: from localhost.localdomain (netadmin.ucsd.edu. [137.110.160.224]) by smtp.gmail.com with ESMTPSA id o12sm13635063pjm.57.2021.10.04.13.49.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Oct 2021 13:49:40 -0700 (PDT) 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 Subject: [kvm-unit-tests PATCH v3 05/17] x86 UEFI: Boot from UEFI Date: Mon, 4 Oct 2021 13:49:19 -0700 Message-Id: <20211004204931.1537823-6-zxwang42@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211004204931.1537823-1-zxwang42@gmail.com> References: <20211004204931.1537823-1-zxwang42@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Zixuan Wang 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 | 32 +++++++++++++++----- lib/efi.h | 21 +++++++++++++ lib/linux/efi.h | 10 +++++-- lib/x86/asm/setup.h | 7 +++++ lib/x86/setup.c | 13 ++++++++ x86/Makefile.common | 67 +++++++++++++++++++++++++++++++----------- x86/Makefile.i386 | 5 ++-- x86/Makefile.x86_64 | 54 ++++++++++++++++++++++------------ x86/efi/README.md | 40 ++++++++++++++++++++++++- x86/efi/reloc_x86_64.c | 8 ++--- x86/efi/run | 63 +++++++++++++++++++++++++++++++++++++++ x86/run | 16 ++++++++-- 16 files changed, 323 insertions(+), 57 deletions(-) create mode 100644 lib/efi.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 6792b93..6465929 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 7f08f0e..f3214b8 100644 --- a/lib/efi.c +++ b/lib/efi.c @@ -2,12 +2,22 @@ * EFI-related functions 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 -unsigned long __efiapi efi_main(efi_handle_t handle, efi_system_table_t *sys_tab); +#include "efi.h" +#include +#include + +/* 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); + efi_system_table_t *efi_system_table = NULL; static void efi_free_pool(void *ptr) @@ -15,7 +25,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; @@ -53,15 +63,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..889de18 --- /dev/null +++ b/lib/efi.h @@ -0,0 +1,21 @@ +#ifndef _EFI_H_ +#define _EFI_H_ + +/* + * EFI-related functions in . This file's name "efi.h" is in + * conflict with GNU-EFI library's "efi.h", but does not include + * GNU-EFI headers or links against GNU-EFI. + * + * Copyright (c) 2021, Google Inc, Zixuan Wang + * + * SPDX-License-Identifier: LGPL-2.0-or-later + */ +#include "linux/efi.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/efi.h b/lib/linux/efi.h index bb4601b..3d68c28 100644 --- a/lib/linux/efi.h +++ b/lib/linux/efi.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 index 19ded12..a1f869c 100644 --- a/lib/x86/asm/setup.h +++ b/lib/x86/asm/setup.h @@ -5,4 +5,11 @@ unsigned long setup_tss(void); #endif /* __x86_64__ */ +#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 8c73156..2fbf04f 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -161,6 +161,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 bc1f733..d62758c 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..7b6068e 100644 --- a/x86/efi/reloc_x86_64.c +++ b/x86/efi/reloc_x86_64.c @@ -37,14 +37,10 @@ SUCH DAMAGE. */ -#include -#include - +#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 Mon Oct 4 20:49: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: 12534803 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C9ACCC433EF for ; Mon, 4 Oct 2021 20:49:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id ACDB1611C8 for ; Mon, 4 Oct 2021 20:49:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236821AbhJDUvf (ORCPT ); Mon, 4 Oct 2021 16:51:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55522 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232788AbhJDUvd (ORCPT ); Mon, 4 Oct 2021 16:51:33 -0400 Received: from mail-pj1-x102f.google.com (mail-pj1-x102f.google.com [IPv6:2607:f8b0:4864:20::102f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BD016C061745 for ; Mon, 4 Oct 2021 13:49:43 -0700 (PDT) Received: by mail-pj1-x102f.google.com with SMTP id on12-20020a17090b1d0c00b001997c60aa29so628986pjb.1 for ; Mon, 04 Oct 2021 13:49:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=VZmYVBTYU6HJTLci6i04nKEFCPp+tbbCbVxTFDfMLQs=; b=cZE+DDWKARtSxW1ndBEm/4lpqnxFLAomSZ3FQ0CJpnptLmDPp06fXKqsDtx4t5sxV1 aZOx91K+lD+4W311r1ae7RtEK8H0IfQTQ3du88TgdvXgJmzNpXCq7rXTBPgjKwEGgU4t dZKZ8Qy/1mV5GtEafL2QnxUDl8yhQ35TJWsqZEQ7pPIeUGHnBrZWbHx+J05j/HDtOn/k G2g7PfL/1R2YCFLi3asBrV3zNk+Fg1CnsGkcVq28B0o+SZ3dNqw1mbBhSPkCmOQoUEj3 fckKtZq+aQjAnOtUT1wIO8A28fRuEqnoW/IuYHtwCUtTC9StnZGbTx4hB+t/iP/i1e2k 3xUg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=VZmYVBTYU6HJTLci6i04nKEFCPp+tbbCbVxTFDfMLQs=; b=le1foSsGnlFwW9hsBcdH8ayBXox4Vsfp+X85LYzEfOArgpWgedWQGqw4q3Lao/jUq2 7jIZR64/uDqBxbJygNvY45v4F5a3g20VE1HLouhqWfBKF/qTAI2iUwiB6j/FEC6MrKFg gFtuLtFjAt/4euiDFqvc4bpwPrtIh128eFOlVZK/W6ng/59MWfNlzO1Z0wwZgOuJ6tEI 1T9R0FI5QEEgKGck0I4zLsNn/cyUwl/JkWOi17toDFqgC4fCsxvLdlyeog345DpgEQ6Q 5eKYOojF5nC1+JWpYk6l/x4Bx4BklGwBht1WxQQR1ap82lPXuYi/7rjmWwrbFwnOn4FA sfAw== X-Gm-Message-State: AOAM5307LXwyoxk7tZllsf5oeWEOp0g/NuqK5e/WF97aRvDt6TsyT9Nl yPoJAv2zzD9OGArJM7NrR/jFcR9Aif1Vdw== X-Google-Smtp-Source: ABdhPJzaB1WIe89VeW+nRBIA3mx3lKPylq6ZnQ7Vja2hILfp56ZY5LowxU/r3l1egmcIvJVKsP/WPQ== X-Received: by 2002:a17:90b:30c:: with SMTP id ay12mr11096456pjb.234.1633380582957; Mon, 04 Oct 2021 13:49:42 -0700 (PDT) Received: from localhost.localdomain (netadmin.ucsd.edu. [137.110.160.224]) by smtp.gmail.com with ESMTPSA id o12sm13635063pjm.57.2021.10.04.13.49.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Oct 2021 13:49:42 -0700 (PDT) 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 Subject: [kvm-unit-tests PATCH v3 06/17] x86 UEFI: Load IDT after UEFI boot up Date: Mon, 4 Oct 2021 13:49:20 -0700 Message-Id: <20211004204931.1537823-7-zxwang42@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211004204931.1537823-1-zxwang42@gmail.com> References: <20211004204931.1537823-1-zxwang42@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Zixuan Wang 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 by setting up and loding the IDT. 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 | 5 +++++ x86/Makefile.x86_64 | 2 +- x86/efi/README.md | 4 ++-- x86/efi/efistart64.S | 12 ++++++++++++ x86/efi/elf_x86_64_efi.lds | 6 +++++- 5 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 x86/efi/efistart64.S diff --git a/lib/x86/setup.c b/lib/x86/setup.c index 2fbf04f..8606fe8 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -163,9 +163,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 d62758c..a39f509 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..41e9185 --- /dev/null +++ b/x86/efi/efistart64.S @@ -0,0 +1,12 @@ +/* Startup code and pre-defined data structures */ + +#include "crt0-efi-x86_64.S" + +.section .init +.code64 +.text + +.globl load_idt +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 Mon Oct 4 20:49: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: 12534807 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E925DC4332F for ; Mon, 4 Oct 2021 20:49:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C8B9361357 for ; Mon, 4 Oct 2021 20:49:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236858AbhJDUvh (ORCPT ); Mon, 4 Oct 2021 16:51:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55542 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236804AbhJDUve (ORCPT ); Mon, 4 Oct 2021 16:51:34 -0400 Received: from mail-pf1-x42b.google.com (mail-pf1-x42b.google.com [IPv6:2607:f8b0:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2F4F3C061745 for ; Mon, 4 Oct 2021 13:49:45 -0700 (PDT) Received: by mail-pf1-x42b.google.com with SMTP id u7so15511016pfg.13 for ; Mon, 04 Oct 2021 13:49:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=LyBROeWt+x+Gb0k2+3naYdgZzhJi/mL+4noCZQs+mh0=; b=ZrxK42UXUj443Q+DL5rOArC+4H/EuCu8Iumk9HDsDVX+7uw9OJWCu2Yp6o5JGjXu85 1xKvSJ5eh1k6gV26nywxIOqjTh5bjxGT46+FO6v7HNVqBtA8CguXdfZxj8U6y+bOHwqy NbhhA2Sg/9K1HXuu/22D4nEmJVgpeRzNhjdWgtBzg+EW4tn6EwUBOf+H6pTcftbudc75 B4G8XIC3uHEL+nXJlLbM9Oc5f5D7HUIoz6Wp8uh6oqhLYVJbqWd5TknVWCSs1Ail0zLl gLtOXthoXU+yxDa3O2hXry7vJ3LbMelVPtCHB4rQp+/OgVVy8VTTcMgTGl+1ZCXhY0M1 ZsxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=LyBROeWt+x+Gb0k2+3naYdgZzhJi/mL+4noCZQs+mh0=; b=fIK+WfcSAWMrSoC/YhQDgRE7Jqlf71l7uYVtPQUpztpfYyRuGkuw6J6f4SHsqdM04A /Hq+xdZuPXUBhsODPCS+uk/uBuBbTqQRNLN8Eti3413XyswctfgSQy+WRNtYtF/0dJj/ fwrGvFRFynPPMsFs3R3eQ8rz8eB7FFngvVTgg+roRx76hOAVRUaXbuJT179tiy2ZoG6Z hNLgsjhT6on0+vrYwkYUBhD/9JAAui9fy/uToW7bnaZZGp7Lzs/GrFH+fQkN0Z489DMg S8uGMEk/NR3uZMYOpCTPDYzdkIEFknS66eTJf0GQwOaDc/9Y1T9KbLiuOG4Kl9BzeBT9 QonA== X-Gm-Message-State: AOAM530LMicW0Z3tVXglIZDQwREo7/aa4xqMREZlqbiSleYdWrNPL0qp 6ss2RFWdp77zXlZ7vIQZxSPkV6ooe0+xHw== X-Google-Smtp-Source: ABdhPJyKYy/qr1ghfGRzeW66V9Uj6dipSk23RgdWkP3yLGYh/woDhyqGtVSuMTsRQCAVrdHGu4lp/g== X-Received: by 2002:a63:1444:: with SMTP id 4mr5591667pgu.251.1633380584385; Mon, 04 Oct 2021 13:49:44 -0700 (PDT) Received: from localhost.localdomain (netadmin.ucsd.edu. [137.110.160.224]) by smtp.gmail.com with ESMTPSA id o12sm13635063pjm.57.2021.10.04.13.49.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Oct 2021 13:49:43 -0700 (PDT) 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 Subject: [kvm-unit-tests PATCH v3 07/17] x86 UEFI: Load GDT and TSS after UEFI boot up Date: Mon, 4 Oct 2021 13:49:21 -0700 Message-Id: <20211004204931.1537823-8-zxwang42@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211004204931.1537823-1-zxwang42@gmail.com> References: <20211004204931.1537823-1-zxwang42@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Zixuan Wang 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. 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 | 10 ++++++++++ x86/efi/efistart64.S | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/lib/x86/setup.c b/lib/x86/setup.c index 8606fe8..f4f9e1b 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -165,10 +165,20 @@ 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); + +static void setup_gdt_tss(void) +{ + size_t tss_offset; + + tss_offset = setup_tss(); + 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 41e9185..57299a5 100644 --- a/x86/efi/efistart64.S +++ b/x86/efi/efistart64.S @@ -1,7 +1,22 @@ /* Startup code and pre-defined data structures */ +#include "apic-defs.h" +#include "asm-generic/page.h" #include "crt0-efi-x86_64.S" +.globl ring0stacktop +.globl ring0stacksize + +max_cpus = MAX_TEST_CPUS +ring0stacksize = PAGE_SIZE + +.bss + +.globl ring0stacktop + . = . + ring0stacksize * max_cpus + .align 16 +ring0stacktop: + .section .init .code64 .text @@ -10,3 +25,30 @@ load_idt: lidtq idt_descr(%rip) retq + +.globl load_gdt_tss +load_gdt_tss: + /* 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 Mon Oct 4 20:49: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: 12534809 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 92359C433EF for ; Mon, 4 Oct 2021 20:49:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 77F31611C8 for ; Mon, 4 Oct 2021 20:49:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236833AbhJDUvi (ORCPT ); Mon, 4 Oct 2021 16:51:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55546 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236816AbhJDUvg (ORCPT ); Mon, 4 Oct 2021 16:51:36 -0400 Received: from mail-pf1-x435.google.com (mail-pf1-x435.google.com [IPv6:2607:f8b0:4864:20::435]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B140CC061745 for ; Mon, 4 Oct 2021 13:49:46 -0700 (PDT) Received: by mail-pf1-x435.google.com with SMTP id 145so15538117pfz.11 for ; Mon, 04 Oct 2021 13:49:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=hXwn823JQ7drM0H+obg9KOE1Pms6D1N1N6K9pRWG81k=; b=WoI4fBoxWE3mdyh98CyNLhDxgUAXTIh8qp7pvGV200fVCgKeYDHCxJ2FulryKtFwby +9pE0uNLGmu6AW5KWA+8p4Lf1ZxjPS4Ypjsfa4L7bkOTYH1gj8fjBOE1Kct9opZIBFMD H+FVEsEuYR2yM2mncBHwr7+CFJRiGr/dr29zeJxBwtnuu1Wqg2bxNlRcVoTq0Wef93Js 9uT5EBgCFepFTgjH2q+BIGNDHzlEJGjFK4bZ3+7mzK4Ty/7Rzsh7Xgvis72pzQ41zj5l 4OjMF1uhViBJE6cHmpOPYXDI+9a7WQzu2EVSMZ+ufP4lC08u3F0VivXbyLYPRoQ4LDik WlfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=hXwn823JQ7drM0H+obg9KOE1Pms6D1N1N6K9pRWG81k=; b=MfWsCLOSTpiZkSOG0S4e3/zZJXc1Giy0+yNj9jmtIDACB4Rkou3O2/9N02yFBCd5NA 96DwxTtWt2xjZp7KE4gpGhHL7b9jiOQhdf8537KHs6gE2oALI5XJsm3MHyx7AI+wi1HT HetTYiop2aGanPdGhj9gsEbZyYldeRj+hAHPw34CY+KIxGb6Jn7gf7kJZltEhJHmx/Ax li3YYOzc0G3lDPnB64/EeQ9bRGfqWopfRFUUgFSU9xEAwZK+R0U47xPYrsh2iygML5pm j7H7rCqIE7RwFVWzIvQXBfz6lGZsaVC/ps6azlXDRMX4rgnYCQNgkxtG+IemTlL2UyNo DWzg== X-Gm-Message-State: AOAM5303jbmBangRk9UnV7PJUTv6w1Menzax3rcmB6OqjztVIw+PCszO HIUDA0uVdEdR775GOoHaVosgsuuDEUJkrg== X-Google-Smtp-Source: ABdhPJwPlRUm3ZP49j3nLFJ+iXgfYKTcE7KP4LkuQvcCA9ZYRIuc6bA08adbFFh9WtorOz6Dx2oGLg== X-Received: by 2002:a63:dc03:: with SMTP id s3mr12514957pgg.88.1633380585819; Mon, 04 Oct 2021 13:49:45 -0700 (PDT) Received: from localhost.localdomain (netadmin.ucsd.edu. [137.110.160.224]) by smtp.gmail.com with ESMTPSA id o12sm13635063pjm.57.2021.10.04.13.49.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Oct 2021 13:49:45 -0700 (PDT) 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 Subject: [kvm-unit-tests PATCH v3 08/17] x86 UEFI: Set up memory allocator Date: Mon, 4 Oct 2021 13:49:22 -0700 Message-Id: <20211004204931.1537823-9-zxwang42@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211004204931.1537823-1-zxwang42@gmail.com> References: <20211004204931.1537823-1-zxwang42@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Zixuan Wang 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 f3214b8..c1c3806 100644 --- a/lib/efi.c +++ b/lib/efi.c @@ -30,9 +30,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; @@ -49,12 +50,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; @@ -63,18 +65,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 889de18..0f1dafd 100644 --- a/lib/efi.h +++ b/lib/efi.h @@ -15,7 +15,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 a1f869c..3f0a870 100644 --- a/lib/x86/asm/setup.h +++ b/lib/x86/asm/setup.h @@ -8,8 +8,22 @@ unsigned long setup_tss(void); #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 f4f9e1b..90f95a3 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -167,6 +167,81 @@ void setup_multiboot(struct mbi_bootinfo *bi) extern void load_idt(void); extern void load_gdt_tss(size_t tss_offset); +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) { size_t tss_offset; @@ -175,7 +250,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(); @@ -185,6 +260,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 Mon Oct 4 20:49:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12534811 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id ECCB0C433F5 for ; Mon, 4 Oct 2021 20:49:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D1FB9611C8 for ; Mon, 4 Oct 2021 20:49:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236822AbhJDUvk (ORCPT ); Mon, 4 Oct 2021 16:51:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55556 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236804AbhJDUvh (ORCPT ); Mon, 4 Oct 2021 16:51:37 -0400 Received: from mail-pf1-x42b.google.com (mail-pf1-x42b.google.com [IPv6:2607:f8b0:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 315DDC061745 for ; Mon, 4 Oct 2021 13:49:48 -0700 (PDT) Received: by mail-pf1-x42b.google.com with SMTP id h1so4850031pfv.12 for ; Mon, 04 Oct 2021 13:49:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=hbxdixGOhL1Yj10MTwZ7tyD6Xe68ywa+lhDixo0V7Ik=; b=eE/lUlC8Qk4ZntL1lZgNtpW7yBFVp5VNLkyce3RlsS0iouQhyWKHANSE7JODg6yCFz zE+NsaTeM9gECYM5NdgwMvUUnnb6WkPqF6M/ifo7v4vQoX5jft9hdd5OLPhpNAli6u2L ISzr/iGWYUlD5AXcSM6Lve/xkd85rQD0/otYvxhMzqnNAv8T7madjERVT/DugioG3s5G q8+pb9fHRi6OTtgGeeveQIT5jkbDPqwEvU1VucyfNvhHtKUJ3IkZHNpCQpA8yKDRct8e glAHUpVcmy7uAEL8CH1HK9tuSEUzsyL6/MJ3P8T+wsxA73d91b6Ozwg4VRVn6PgFMxzY 7nfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=hbxdixGOhL1Yj10MTwZ7tyD6Xe68ywa+lhDixo0V7Ik=; b=l5Roz+Wm+O/3EnpX4AagaAOxuPsMJUsjNiFzFF7NHDRTsz3ksOXpVBRBhcg2bdYiwC C6UGJbKS44yEg00GLu7tkH3y6Od1pI3b7LtMCUVI6nPm/It+502RmpAwwvR8o4n0s2hw GnCea0606gj/cWy21AMftEHf1B2uPvI56v/1QoayXAM21uRh/tNIoMw+4H8H6Ma6Jvho JdL84XqM4s1JkDLtukNvTn98vr36fvQIu9I2mzTpmxWhrM/AuQOTA7KyxCjMM9MhV6mn c/Ci2IJhglbS/2Lcp13GZAAyRKLtGr88C6ht3g1WgVyoswHt0wQ92izOZ8jIOGFWNpGQ AtoA== X-Gm-Message-State: AOAM533DXOPYtJEIdxbAt+AVRSTe6PLFx6yaZD4s4YB1SPKj/xDiW/qw 4yqUA0gsLciRzILYibDaX+jMZrs7RjLNAQ== X-Google-Smtp-Source: ABdhPJx7XjC/+bV0xB9zEBZN7+IvrxbwzTdFAo88x3F39WXjVh2G5bsepVNfiNZs+VCFAZxVyNB/Jw== X-Received: by 2002:a63:2361:: with SMTP id u33mr12588362pgm.369.1633380587301; Mon, 04 Oct 2021 13:49:47 -0700 (PDT) Received: from localhost.localdomain (netadmin.ucsd.edu. [137.110.160.224]) by smtp.gmail.com with ESMTPSA id o12sm13635063pjm.57.2021.10.04.13.49.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Oct 2021 13:49:46 -0700 (PDT) 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 Subject: [kvm-unit-tests PATCH v3 09/17] x86 UEFI: Set up RSDP after UEFI boot up Date: Mon, 4 Oct 2021 13:49:23 -0700 Message-Id: <20211004204931.1537823-10-zxwang42@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211004204931.1537823-1-zxwang42@gmail.com> References: <20211004204931.1537823-1-zxwang42@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Zixuan Wang 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/efi.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 c1c3806..9506830 100644 --- a/lib/efi.c +++ b/lib/efi.c @@ -70,6 +70,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 0f1dafd..1b3abd0 100644 --- a/lib/efi.h +++ b/lib/efi.h @@ -16,6 +16,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/efi.h b/lib/linux/efi.h index 3d68c28..7ac1082 100644 --- a/lib/linux/efi.h +++ b/lib/linux/efi.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 3f0a870..ecfcd5c 100644 --- a/lib/x86/asm/setup.h +++ b/lib/x86/asm/setup.h @@ -6,6 +6,7 @@ unsigned long setup_tss(void); #endif /* __x86_64__ */ #ifdef TARGET_EFI +#include "x86/acpi.h" #include "x86/apic.h" #include "x86/smp.h" #include "efi.h" @@ -19,6 +20,7 @@ unsigned long setup_tss(void); 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 90f95a3..6d81ab6 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -171,6 +171,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) @@ -221,6 +222,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; @@ -239,6 +245,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; } @@ -261,6 +273,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 Mon Oct 4 20:49:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12534813 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D6554C433FE for ; Mon, 4 Oct 2021 20:49:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BF80361357 for ; Mon, 4 Oct 2021 20:49:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236881AbhJDUvk (ORCPT ); Mon, 4 Oct 2021 16:51:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55566 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236849AbhJDUvi (ORCPT ); Mon, 4 Oct 2021 16:51:38 -0400 Received: from mail-pj1-x1029.google.com (mail-pj1-x1029.google.com [IPv6:2607:f8b0:4864:20::1029]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AB703C061749 for ; Mon, 4 Oct 2021 13:49:49 -0700 (PDT) Received: by mail-pj1-x1029.google.com with SMTP id k23so1565463pji.0 for ; Mon, 04 Oct 2021 13:49:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=8VvNjXnyjaiZ/2uDMcL9dog4rM3q7X5m0sWW0vporEg=; b=VaOwzDsm7+mXz+09yCl2e0OFqZ05j9/mrLUhE6iVMDOrpqfqCQPcEK8EI/OQ8uMMvx OzI4QtXYe6dRkAKQuhXF2//nMZl8d2vhC0jd39dTypVunQ7BuMD70XvYHgC+H1YJ5xIO YqvObVkKqD0gMfomM67Wx+Zyn8Sgl4yoS6klnXgH9FXEj/xB+WHEWZJZ4XqmgTwm3VX5 5+WZJdGdtXFDIhlAgC46osW7OD+pSDFMUFZFqD7sZ1XcMvLhzr3Ia0VRBS8Q9WoyeAuq 4HEvzgiCg2q7FoHq3907NzNtBZAbKo0x7Vy9G0yFO0SoRJob2dkRDrbZpqTeJSHAiofC /eug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=8VvNjXnyjaiZ/2uDMcL9dog4rM3q7X5m0sWW0vporEg=; b=kuCCp0jG+7sRzlTcfJNRIakjtlbEfrEgph4znLwWxSlNJECHHk3k6VT6SAeQjb2D9B dD4R4+0RS0EGVq9UTUXCNvZ9/acWwsE8X40is2RJ+LhWRdy+c+YjuuxfFT6RjtjwM1/u svIx5mHusmThBEdERbOoDNhkFViMOyihEjtnm4ADm1fVcWwesvpSWM7yIhzgurYPCpbj 4F2YMyd0OXFBzURZ+HmiGYmzxAafWKsaTN/lpjVtnMk61K7qvw3ifDCQf5YTs49Sg/mN ntlvYRkUv7U+aUiwZfBoDWUooDvxjO38YQXC3x1FoG8TMtobKZlMkRdwPCbDj3W4ceEd kjug== X-Gm-Message-State: AOAM533WxA4p1HJfhqQl8df7HX9CijIsJBZSw4knb8Ea8Y4oxAoNSeJb kZ10R40mssMyJmbczNZRpxXe6aqLvZuyCA== X-Google-Smtp-Source: ABdhPJxleKEyHjIO6/izRgjPdC9l0ZeVnDRBxEx/+LaiB/K/DF+jR0M1azwDtjRgivMr8Ehtd4ILbQ== X-Received: by 2002:a17:90a:312:: with SMTP id 18mr39253932pje.178.1633380588712; Mon, 04 Oct 2021 13:49:48 -0700 (PDT) Received: from localhost.localdomain (netadmin.ucsd.edu. [137.110.160.224]) by smtp.gmail.com with ESMTPSA id o12sm13635063pjm.57.2021.10.04.13.49.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Oct 2021 13:49:48 -0700 (PDT) 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 Subject: [kvm-unit-tests PATCH v3 10/17] x86 UEFI: Set up page tables Date: Mon, 4 Oct 2021 13:49:24 -0700 Message-Id: <20211004204931.1537823-11-zxwang42@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211004204931.1537823-1-zxwang42@gmail.com> References: <20211004204931.1537823-1-zxwang42@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Zixuan Wang 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 | 55 ++++++++++++++++++++++++++++++++++++++++++++ x86/efi/efistart64.S | 23 ++++++++++++++++++ 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 ecfcd5c..9cc135a 100644 --- a/lib/x86/asm/setup.h +++ b/lib/x86/asm/setup.h @@ -8,7 +8,9 @@ unsigned long setup_tss(void); #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" /* @@ -26,6 +28,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 6d81ab6..c1aa82a 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -254,6 +254,60 @@ 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) +{ + /* + * TODO: This function is a place holder for now. It is defined because + * some test cases (e.g. x86/access.c) expect it to exist. If this + * function is not defined, gcc may generate wrong position-independent + * code, which leads to incorrect memory access: if compiling + * x86/access.efi without this function defined, several data structures + * (e.g. apic_ops) get compile time offset memory addresses, but they + * should get runtime %rip based addresses. + * + * The reason this function does not contain any code: Setting up 5 + * level page table requires x86 to enter the real mode. But real mode + * is currently not supported in kvm-unit-tests under UEFI. + */ +} + static void setup_gdt_tss(void) { size_t tss_offset; @@ -274,6 +328,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 57299a5..adfff3a 100644 --- a/x86/efi/efistart64.S +++ b/x86/efi/efistart64.S @@ -17,6 +17,29 @@ ring0stacksize = PAGE_SIZE .align 16 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 + .section .init .code64 .text From patchwork Mon Oct 4 20:49:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12534815 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B5E24C433EF for ; Mon, 4 Oct 2021 20:49:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A081261357 for ; Mon, 4 Oct 2021 20:49:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236912AbhJDUvm (ORCPT ); Mon, 4 Oct 2021 16:51:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55578 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236830AbhJDUvk (ORCPT ); Mon, 4 Oct 2021 16:51:40 -0400 Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 07AC5C061753 for ; Mon, 4 Oct 2021 13:49:51 -0700 (PDT) Received: by mail-pj1-x102c.google.com with SMTP id on6so1590269pjb.5 for ; Mon, 04 Oct 2021 13:49:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=q/9RWqqT6mvxnBHido+m9H97/Yh27gw6y1a2mB+sxQ4=; b=QEOaElUWguXWk03z5E2sYH8GZtAdeYj2kdTUvkSWZdLAP+KELrOVT1EX96pSeRcHOa Z7VvJF/2bcq/K0Md+haBjsg16jo5b+NEJgwJ0KFsB9fFLnML5AhGG2n1uMblvEtBQq5f S50x2xl6Z7+u9ksU+jydvEuejPhR72YncTxL8cFdCBMAzS7n8gSA7iyUI/aEhtacuSRS sr4StvI20IB31pJ2ukZBZsCu5MNQnrT26yxNySSC6lrwa9Gdk/xq1T8qZEepoMBbr9Yk TmIC2r+ku/icRQzD7Nob/L/nyHm9Cyc47Sj42iut28qaW1auYmEMkbX5XqThzW/5frKS ZEgQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=q/9RWqqT6mvxnBHido+m9H97/Yh27gw6y1a2mB+sxQ4=; b=HDJgXVegfLg5zbPFHjaMNa345cdLYNjBII0RcdARALfwJlAD6y+mjMjuJ+s20aY8nO 1PdDwNLeY7rrWbYNfl3OIpoc1HR2G/lN/Uax9XZotk/IaG5uDEoRd8wIPUhwAjEJ0MCg yD9YCDg+5vrXziB8XfRATjSa1NVcynT4g3pcJdCKrNZPNkZtS7HrZcFD9H6TdQwdMv3F LWHdRA5Ig5trUBK/MDJ6Wy0bYF9cAd9gPcuJ+j7XNXxsJ9HJwgs/yogdYfKV9qKSyskS zHh5NI2Uc2kTSNt34rw9o9AxQ6YEIgEorkMGmRV6buP0AuqTlfKYJpG9RYjGWd4zpTRp oO4w== X-Gm-Message-State: AOAM531Npiv82mOzb230HOhXGr4MML0WgX8G8Llp9ycpR/kE/c3EJRk3 0t9UoiUCacccpnsdOmwSSKQnIyN3pnTLLw== X-Google-Smtp-Source: ABdhPJydoi2W5det4uQPuy7wOncFSAWlcE6xBllEMS/nHNyceSO13OwWozBqU5imjGF314qfXmQKwg== X-Received: by 2002:a17:90a:d58b:: with SMTP id v11mr32358188pju.207.1633380590146; Mon, 04 Oct 2021 13:49:50 -0700 (PDT) Received: from localhost.localdomain (netadmin.ucsd.edu. [137.110.160.224]) by smtp.gmail.com with ESMTPSA id o12sm13635063pjm.57.2021.10.04.13.49.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Oct 2021 13:49:49 -0700 (PDT) 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 Subject: [kvm-unit-tests PATCH v3 11/17] x86 UEFI: Convert x86 test cases to PIC Date: Mon, 4 Oct 2021 13:49:25 -0700 Message-Id: <20211004204931.1537823-12-zxwang42@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211004204931.1537823-1-zxwang42@gmail.com> References: <20211004204931.1537823-1-zxwang42@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Zixuan Wang 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 Mon Oct 4 20:49:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12534817 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8762BC4332F for ; Mon, 4 Oct 2021 20:49:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 73D5B61357 for ; Mon, 4 Oct 2021 20:49:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236836AbhJDUvm (ORCPT ); Mon, 4 Oct 2021 16:51:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55586 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236899AbhJDUvl (ORCPT ); Mon, 4 Oct 2021 16:51:41 -0400 Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 709ACC061745 for ; Mon, 4 Oct 2021 13:49:52 -0700 (PDT) Received: by mail-pl1-x62d.google.com with SMTP id j4so767612plx.4 for ; Mon, 04 Oct 2021 13:49:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=4pf7MMvUkYurjBtFBnw34EfDkowFQ0hcjHBvydN5AXU=; b=UFhCgMEeZDin9CVZAIC/IvQdzxPZWSIdT1bWvqkYRQcX/XV/ouQj+buUNpdaJDEw7/ zkFcjA0W7BSi55n9WBLtp8cJHkG2YCQaHaw+bLLCm+llJPHjcYPErJCHWdPbhn/DC4Mw wW+ablFRBJ1FkG1rdVKME05vUfEzhY5u1BLjGHwCRQCwU25Z9gGoKLPATxB30yUkhZG6 jsDqukxyr27TshI3AO4QQCyJkVLCqpn8GIjDgaT8Ytqwr7nTcObLPWzRfGTxMAzrwzkW m+YAZ81rVoEufec1Z6wERnvpTH/EUE6nM8FV69J8VQdFbccMBtSpme+Aim0uBWejGYyN tfJg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=4pf7MMvUkYurjBtFBnw34EfDkowFQ0hcjHBvydN5AXU=; b=D1fw0mEpTYemKShhQL7RTrr+o93NURnjsNZDtz3+EdRRit0E4o3JjJJd+E85fbDTdw GlWtYHR3/eYOb31Ci4Wk1jtkEO/DzDsK5L6hVMDrWaPGhJTtxB4rAHb+jOMx6WmMDAQA oedZxdbb74yVh8tBlLKRGsAN/EAA2TK7lMnvThfxXSRJ6da55O3o6GGzlqrsS6xVmOir B08CE2D9qPW5k+r2ZUgPincLPV3izXEC6MNjw/rvBjORgwckVfITPdoczJFXdmoW7S5T hUeN4/ed/1NuIL3vpcQf2fee+XobVL8z2UaHfv94kFkCSVLSdu65PYhulQrSPda2Pooq OC1g== X-Gm-Message-State: AOAM532/Jn+vaH3vV0V7gSBT5wumys3u5iJkkNVJQ9Ut+17B+pex7pws HnNDoUf2UUIg4oXVitMYks/xt2Q2GY3eZA== X-Google-Smtp-Source: ABdhPJybDboTcIoPrDromzX2NozKBWIAaGBiLcu1WvQuhqrFOAsjY55m14CEqiufm6Va+PtKDa0vBA== X-Received: by 2002:a17:90b:2382:: with SMTP id mr2mr28309837pjb.148.1633380591556; Mon, 04 Oct 2021 13:49:51 -0700 (PDT) Received: from localhost.localdomain (netadmin.ucsd.edu. [137.110.160.224]) by smtp.gmail.com with ESMTPSA id o12sm13635063pjm.57.2021.10.04.13.49.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Oct 2021 13:49:51 -0700 (PDT) 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 Subject: [kvm-unit-tests PATCH v3 12/17] x86 AMD SEV: Initial support Date: Mon, 4 Oct 2021 13:49:26 -0700 Message-Id: <20211004204931.1537823-13-zxwang42@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211004204931.1537823-1-zxwang42@gmail.com> References: <20211004204931.1537823-1-zxwang42@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Zixuan Wang 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 | 75 +++++++++++++++++++++++++++++++++++++++++++++ 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, 204 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..13e6455 --- /dev/null +++ b/lib/x86/amd_sev.c @@ -0,0 +1,75 @@ +/* + * 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 short 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) { + 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 short)(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..68483c9 --- /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 9cc135a..30ca341 100644 --- a/lib/x86/asm/setup.h +++ b/lib/x86/asm/setup.h @@ -12,6 +12,7 @@ unsigned long setup_tss(void); #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 c1aa82a..ad7f725 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -251,6 +251,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; } @@ -269,6 +281,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 Mon Oct 4 20:49:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12534819 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1C8D2C433F5 for ; Mon, 4 Oct 2021 20:49:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0053C61357 for ; Mon, 4 Oct 2021 20:49:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236905AbhJDUvo (ORCPT ); Mon, 4 Oct 2021 16:51:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55596 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236849AbhJDUvn (ORCPT ); Mon, 4 Oct 2021 16:51:43 -0400 Received: from mail-pf1-x42a.google.com (mail-pf1-x42a.google.com [IPv6:2607:f8b0:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DD715C061745 for ; Mon, 4 Oct 2021 13:49:53 -0700 (PDT) Received: by mail-pf1-x42a.google.com with SMTP id u7so15511326pfg.13 for ; Mon, 04 Oct 2021 13:49:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=GbzETZ+Y0mictTqX5N0ZcqEh/OP0EgELTPz8FGTRb6g=; b=RIpQbAHA6M3Zl81BJghI3YQ/CnKFthWkbF0cA7nRtDY9ta321OeVoRS6T1w8Xo+lTG r6bq+dmwE0WTrgZiEC93KqWyPIcfYClIKc/OmV2DwFCZJlk4rKxcLyrJMZFKRneMKMRH ljJX2RkkVBBd/hLBf3lDyv2uUKm5+6XGSet7/eavBXuug0q41Je0V/4Z7uhOpQxPw4UH 3BSjJM4wX/OL0lbz4BsLADb+7Anpw1R14AYj9k+HjV4O+2aVfVInVhlFPOmNvQb0XI0l p/XNk7Cbg54D6xPSd28StkMh8Sjbf4vs1uR621NWC7AnAmZ8EBcYu3eurdQETf8u5IiK GibQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=GbzETZ+Y0mictTqX5N0ZcqEh/OP0EgELTPz8FGTRb6g=; b=pRVXYUdKTOtX8x01VjH8559PI/faa69qiPqkIKHROs7yZrSlKdQEnGRLIUYO897KY8 sn/Rn4cX4K4VLxBVEQAR2ac9wuqU8+Aua438Aqj2oACgNNOxlP6N8ExoWyI6VguhI6a/ gMQB6TQClNz1TVMwATnJmtYduiFhOWnFoRJRx3/don3xe9MSnhU9nCSt/XZV/PUrGMrp ey6/ck3obb7lLMHiKHo3xKOoKbe1hRI/7R6yiC2AMvc7w4O5BKUxcc4Eo2NfdqWDlRtl 2vv2a26PWMCR47tP5I3+nLgGRwZnAzSS6ZiqtQwpuG7u7ESccxqOhRqC318fHBqTIRoa NuXg== X-Gm-Message-State: AOAM530kAZkTWGlwNm8IyYQ/eiNJRieCk6hnhZFWijcLKzSYXmwjqqqM r+BHUrf8hl6Orveheq9loJAU6lcslMZ1Cw== X-Google-Smtp-Source: ABdhPJx0zLu5PsqFt0DX2QTLmUeZTNY3+ZTHohI9ziuTyWZ5+eQWZOAIiR8/cdL4Ooe02rmSXElFfQ== X-Received: by 2002:a63:79c7:: with SMTP id u190mr12622090pgc.378.1633380593012; Mon, 04 Oct 2021 13:49:53 -0700 (PDT) Received: from localhost.localdomain (netadmin.ucsd.edu. [137.110.160.224]) by smtp.gmail.com with ESMTPSA id o12sm13635063pjm.57.2021.10.04.13.49.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Oct 2021 13:49:52 -0700 (PDT) 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 Subject: [kvm-unit-tests PATCH v3 13/17] x86 AMD SEV: Page table with c-bit Date: Mon, 4 Oct 2021 13:49:27 -0700 Message-Id: <20211004204931.1537823-14-zxwang42@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211004204931.1537823-1-zxwang42@gmail.com> References: <20211004204931.1537823-1-zxwang42@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Zixuan Wang 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 13e6455..b555355 100644 --- a/lib/x86/amd_sev.c +++ b/lib/x86/amd_sev.c @@ -73,3 +73,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 68483c9..7de12f0 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 Mon Oct 4 20:49:28 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12534821 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 87C22C433EF for ; Mon, 4 Oct 2021 20:49:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7349F611C8 for ; Mon, 4 Oct 2021 20:49:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236899AbhJDUvp (ORCPT ); Mon, 4 Oct 2021 16:51:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55602 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236849AbhJDUvo (ORCPT ); Mon, 4 Oct 2021 16:51:44 -0400 Received: from mail-pl1-x630.google.com (mail-pl1-x630.google.com [IPv6:2607:f8b0:4864:20::630]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4642DC061745 for ; Mon, 4 Oct 2021 13:49:55 -0700 (PDT) Received: by mail-pl1-x630.google.com with SMTP id l6so752028plh.9 for ; Mon, 04 Oct 2021 13:49:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=J/yzxjhCplnRwuqqJdNmkaUNrYxsCF/32ZyLlXk4eKc=; b=GlaBqdlaF+f0d/AbTyPKQ21i99aH+dKzhzNhx2Le2t1Os5eIj/q2clsqbsT8NoF1UK v+GyXLFVBkZ7ppDMOUE2j65Bl/fn/2mkR62+fzN+9fmeUq8akQVlIUQoNarR6MDXyJZg mNqkpA1g+eMCWc6smOXBgOf8qMQEAc2VzyYyWBQuBuHWIz3Cj41u6IGYjMm1c5dH46XL aHmcf9BGctZ+cwGyKtwHin2r7cXFSggmDoP1IlloFFOSmaySj6QKzDQ+V3HA77fSpS2T XQc6aMVFNQecHhwRYTwkA2QE8YfrilKN5sG0/d+urx8fYiNVsaWy9yR32uvDl8QGI0IX jzSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=J/yzxjhCplnRwuqqJdNmkaUNrYxsCF/32ZyLlXk4eKc=; b=z9OP/hL7oTlI6P/PFKsJxetcdY2fLg47DtBQre65WyVfAJCcqMAr3q65ZEvvaNUHOc TdFCPtA5ND1t+z0BgF/GirkcvUjnU+klDIS5zpklzfRG2QIXclVNvTxKEzS7+k9WVZ95 Qe8hJviOhswpz0NUT7lRdQ2KBEhhWbIPX7hL02bZoNEIsLNkb7i+VCz4EVjIroQLOtvF tttwkdvIsNGA4fvhqfX7JICmhzH88JmxAaNMQP94YL9dmXDaxsCDvZrZ6IQk8EoasXdu t7DOBK9Nfzicf2snu69aMOtD1Jmb6he4ixh+rFLdJ+lNGPvtiqLUegeB0tVMY9+Q6Ecu B8Bw== X-Gm-Message-State: AOAM533BuwEU26pNNCPVEM0/3xxzL+NdAhxtZQJt3yBxJm0nI5/G+8Vc aj/oh68vgzvYYnVTf74UK/Pc4h1ncht99A== X-Google-Smtp-Source: ABdhPJzwmcoB/ZSG3vvrlPknqvZOifvZH7d22D49km16rJ96LSmnyOUOUEov8L0M/UkWOUSFQuSQ5Q== X-Received: by 2002:a17:903:2283:b0:13e:acd8:86c2 with SMTP id b3-20020a170903228300b0013eacd886c2mr1608247plh.78.1633380594461; Mon, 04 Oct 2021 13:49:54 -0700 (PDT) Received: from localhost.localdomain (netadmin.ucsd.edu. [137.110.160.224]) by smtp.gmail.com with ESMTPSA id o12sm13635063pjm.57.2021.10.04.13.49.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Oct 2021 13:49:53 -0700 (PDT) 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 Subject: [kvm-unit-tests PATCH v3 14/17] x86 AMD SEV-ES: Check SEV-ES status Date: Mon, 4 Oct 2021 13:49:28 -0700 Message-Id: <20211004204931.1537823-15-zxwang42@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211004204931.1537823-1-zxwang42@gmail.com> References: <20211004204931.1537823-1-zxwang42@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Zixuan Wang 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 | 22 ++++++++++++++++++++++ lib/x86/amd_sev.h | 7 +++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/x86/amd_sev.c b/lib/x86/amd_sev.c index b555355..88cf283 100644 --- a/lib/x86/amd_sev.c +++ b/lib/x86/amd_sev.c @@ -65,6 +65,28 @@ 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) { + 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 7de12f0..fb51fc2 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 Mon Oct 4 20:49:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12534823 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2B866C433EF for ; Mon, 4 Oct 2021 20:49:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0E05261357 for ; Mon, 4 Oct 2021 20:49:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236974AbhJDUvr (ORCPT ); Mon, 4 Oct 2021 16:51:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55608 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236893AbhJDUvq (ORCPT ); Mon, 4 Oct 2021 16:51:46 -0400 Received: from mail-pf1-x42d.google.com (mail-pf1-x42d.google.com [IPv6:2607:f8b0:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C0D5AC061745 for ; Mon, 4 Oct 2021 13:49:56 -0700 (PDT) Received: by mail-pf1-x42d.google.com with SMTP id u7so15511390pfg.13 for ; Mon, 04 Oct 2021 13:49:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=1DVzjRL09JB2xUZP0AjJSrzo6xvcKNISRV/HPGityTU=; b=VJl9H2ujB+AXmd4RiltnVlDA7FD+nY4yIB45fASsFHCFaMADblO2EP/qS307+AhU+w JK2GS6+8nWLozx5YIz8BR51WNY05lk7dQt2ILxgki8bAgGXBL7DB3ihcvnBD13YpI4EB 5v/tx9jxqR6jpQ0QHXRjTGqJ1EwNJ164A/TYlwlsEO1uyL3JgtP4bKk1cyi9r8DOpBbm GCz5Mi+++vT/Xlq8FO3imiIuHgxrtP5fIyA8vbPODB+T7hEfZSK4E2unYlLxHB8GcKpO qms7vt83kn7becDwvdGjQ6oLh1FGM7N11XsL/XBEd+ePSDgH4/RSZLAZvlgb9ogJBYSR Yxeg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=1DVzjRL09JB2xUZP0AjJSrzo6xvcKNISRV/HPGityTU=; b=TjL2XApiNY3yartalQcClI8zk7gSCcY1u5GBBz58jcNQeOGkBkb8y7Z4zvCPyJAOj5 Ccqufg+fFb+qh6Tw4qYeVbSJV7N+mTUBeR2inVPhnDP0RtwHwUBz6ItiCmiFRj7GTZgM UUTg7NSKpaqqgqTgckreG6NY3+tDt3C9J/u7tAFBwo4jBcJxV6QdsueHMgyTAHyyEjcp dJzW8aGbEaqseI24ncuCSpkA5/bHvJPI1aczAbajPCDPC6dByX5QIvWYtvSHuO8tN+8H m5/sEFQtT8ws8wQKPBSOCKTA1pAz6OBwMSfiKAGJQR45Pi3xnLuv+XRi7JjT0K3wDiNy e9NA== X-Gm-Message-State: AOAM53117LvAcBsxXqPhbW1fbX+82bbEKgaTVQa4VKF3sZiUyOugpSUx tFreuGo9OzrFbIR1jD/EHkrMItX1x+qJ3w== X-Google-Smtp-Source: ABdhPJzVQRG/3EW7Bm2SPxqvaCQykzNz6SJkhY8xTkU/Fqz7rRXg+IgYakcR9nHAWgM0puE2HH+1cA== X-Received: by 2002:a63:4b5a:: with SMTP id k26mr12713226pgl.241.1633380595957; Mon, 04 Oct 2021 13:49:55 -0700 (PDT) Received: from localhost.localdomain (netadmin.ucsd.edu. [137.110.160.224]) by smtp.gmail.com with ESMTPSA id o12sm13635063pjm.57.2021.10.04.13.49.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Oct 2021 13:49:55 -0700 (PDT) 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 Subject: [kvm-unit-tests PATCH v3 15/17] x86 AMD SEV-ES: Copy UEFI #VC IDT entry Date: Mon, 4 Oct 2021 13:49:29 -0700 Message-Id: <20211004204931.1537823-16-zxwang42@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211004204931.1537823-1-zxwang42@gmail.com> References: <20211004204931.1537823-1-zxwang42@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Zixuan Wang 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 | 30 ++++++++++++++++++++++++++++++ lib/x86/amd_sev.h | 7 +++++++ lib/x86/setup.c | 12 ++++++++++++ 3 files changed, 49 insertions(+) diff --git a/lib/x86/amd_sev.c b/lib/x86/amd_sev.c index 88cf283..50352df 100644 --- a/lib/x86/amd_sev.c +++ b/lib/x86/amd_sev.c @@ -87,6 +87,36 @@ bool amd_sev_es_enabled(void) return sev_es_enabled; } +efi_status_t setup_amd_sev_es(void) +{ + struct descriptor_table_ptr idtr; + idt_entry_t *idt; + idt_entry_t vc_handler_idt; + + if (!amd_sev_es_enabled()) { + return EFI_UNSUPPORTED; + } + + /* + * Copy UEFI's #VC IDT entry, so KVM-Unit-Tests can reuse it and does + * not have to re-implement a #VC handler. Also update the #VC IDT code + * segment to use KVM-Unit-Tests segments, KERNEL_CS, so that we do not + * have to copy the UEFI GDT entries into KVM-Unit-Tests GDT. + * + * TODO: Reusing UEFI #VC handler is a temporary workaround to simplify + * the boot up process, the long-term solution is to implement a #VC + * handler in kvm-unit-tests and load it, so that kvm-unit-tests does + * not depend on specific UEFI #VC handler implementation. + */ + sidt(&idtr); + idt = (idt_entry_t *)idtr.base; + vc_handler_idt = idt[SEV_ES_VC_HANDLER_VECTOR]; + vc_handler_idt.selector = KERNEL_CS; + boot_idt[SEV_ES_VC_HANDLER_VECTOR] = vc_handler_idt; + + return EFI_SUCCESS; +} + unsigned long long get_amd_sev_c_bit_mask(void) { if (amd_sev_enabled()) { diff --git a/lib/x86/amd_sev.h b/lib/x86/amd_sev.h index fb51fc2..0ea1fda 100644 --- a/lib/x86/amd_sev.h +++ b/lib/x86/amd_sev.h @@ -39,7 +39,14 @@ bool amd_sev_enabled(void); efi_status_t setup_amd_sev(void); +/* + * AMD Programmer's Manual Volume 2 + * - Section "#VC Exception" + */ +#define SEV_ES_VC_HANDLER_VECTOR 29 + bool amd_sev_es_enabled(void); +efi_status_t setup_amd_sev_es(void); unsigned long long get_amd_sev_c_bit_mask(void); unsigned long long get_amd_sev_addr_upperbound(void); diff --git a/lib/x86/setup.c b/lib/x86/setup.c index ad7f725..529c3d0 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -263,6 +263,18 @@ efi_status_t setup_efi_pre_boot(unsigned long *mapkey, efi_bootinfo_t *efi_booti } } + status = setup_amd_sev_es(); + if (status != EFI_SUCCESS) { + switch (status) { + case EFI_UNSUPPORTED: + /* Continue if AMD SEV-ES is not supported */ + break; + default: + printf("Set up AMD SEV-ES failed\n"); + return status; + } + } + return EFI_SUCCESS; } From patchwork Mon Oct 4 20:49:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12534825 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 11ADAC433EF for ; Mon, 4 Oct 2021 20:50:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F2AE0611C8 for ; Mon, 4 Oct 2021 20:50:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236977AbhJDUvt (ORCPT ); Mon, 4 Oct 2021 16:51:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55634 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236988AbhJDUvr (ORCPT ); Mon, 4 Oct 2021 16:51:47 -0400 Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 48D16C061745 for ; Mon, 4 Oct 2021 13:49:58 -0700 (PDT) Received: by mail-pj1-x102c.google.com with SMTP id qe4-20020a17090b4f8400b0019f663cfcd1so357123pjb.1 for ; Mon, 04 Oct 2021 13:49:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=3nCpi/3q0Xk4Fi+QEeFqwLO52wqA3929fKW6++LrdJk=; b=VWrm0JHjvocUm1hPVj7ML0GlfqQr6nG9WBEKsWlzGV7Tkwp+zfDq/7g3lrGSuGLcYo go9QfK/ioM6EXas5jZ+4AZiIcERyqGQgB+832MDZUEwVqGiq5Rdi0s3Z60wMqPnpeeSp jDhEZi/45h2Ns09nPDoifLaZx8Lz8VKaSg7qSRsFiF6xpHxZTqWjWbJ/zPoc8EwmzRIg DYCiJSp0C7Pa7Z9k+8J7ZA838WUWfUlYleeoqQ0f+iPi1oNTfnbFqTvEJzbbMVK5LkJ+ TxEWYByGkQQFDGZ+QYHIxHy8TUhXV2sk3dxQoxSRMicmzlvyqWTi5LxdNXtAyIst1La6 QqOA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=3nCpi/3q0Xk4Fi+QEeFqwLO52wqA3929fKW6++LrdJk=; b=Np/SGGMcT7QNnDvZ33nmnTd+eytq6tSs82iGLlIn5IwYN8jKMGI4ujikB9PWYfnB9+ oqBxQykUWRv1gYSmLBs9pj50bmY0JKRmNWXHZVh5qzk+kb3GKIeb/evQ0ntMqGMNYdbF kIT5m/pnOEHA+ltu/HP1dXU/urHJa4VqiCrKu+DKe1Wh51tewK7H64EBucc6nWi8wPo+ J1eEyA2DbF0xydahusek9TZRESi6ZKyaaonKb69GDg8PWYYyHQaQCHHSZSDxhw0Tlu8P iOV3tiMMiVQ7u5xAa1gU71FRqP2iOcl4X8/kKs5SvHIYGXHdfd6V79dPmVgFXYPl2Q29 VALA== X-Gm-Message-State: AOAM530TFvd+eivdkPgbQnTMaEVtbxQpH8NkBn1wKeyIOToEoJtxI90e t4deqH6JAYDtDDnK7D7t4LSQk+flWcAiSA== X-Google-Smtp-Source: ABdhPJwkxY4yEtBX1e4921tUQN0KNZN8C54VYbGsklheOHEE4mz/LR1YV2u25v7FZuc9/kwgR1hRAA== X-Received: by 2002:a17:90b:1646:: with SMTP id il6mr6043130pjb.129.1633380597371; Mon, 04 Oct 2021 13:49:57 -0700 (PDT) Received: from localhost.localdomain (netadmin.ucsd.edu. [137.110.160.224]) by smtp.gmail.com with ESMTPSA id o12sm13635063pjm.57.2021.10.04.13.49.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Oct 2021 13:49:56 -0700 (PDT) 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 Subject: [kvm-unit-tests PATCH v3 16/17] x86 AMD SEV-ES: Set up GHCB page Date: Mon, 4 Oct 2021 13:49:30 -0700 Message-Id: <20211004204931.1537823-17-zxwang42@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211004204931.1537823-1-zxwang42@gmail.com> References: <20211004204931.1537823-1-zxwang42@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Zixuan Wang 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 50352df..6672214 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 short amd_sev_c_bit_pos; @@ -117,6 +118,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()); +} + 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 0ea1fda..6a10f84 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); 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 529c3d0..1f2cdde 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -314,6 +314,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 Mon Oct 4 20:49:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zixuan Wang X-Patchwork-Id: 12534827 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F09C7C433F5 for ; Mon, 4 Oct 2021 20:50:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DA6BC61360 for ; Mon, 4 Oct 2021 20:50:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236962AbhJDUvv (ORCPT ); Mon, 4 Oct 2021 16:51:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55642 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237003AbhJDUvt (ORCPT ); Mon, 4 Oct 2021 16:51:49 -0400 Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9DAEAC061745 for ; Mon, 4 Oct 2021 13:49:59 -0700 (PDT) Received: by mail-pj1-x102c.google.com with SMTP id g13-20020a17090a3c8d00b00196286963b9so341603pjc.3 for ; Mon, 04 Oct 2021 13:49:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=xApr0Rvj6bYN3H9puUCvmsT2cm3F0qNnJSkbus3tXXU=; b=YbVGOHA73pa7aKEa0ypA97MfSgE3LzFuY1N4hqmPvSbPmzOL51gdEndjau9IN8Tfka 2p1S0GFu3Gy2yKHWZ/S1eGXkKhMBhnNeojfGCtXMA2fDqug4cZY+1Z+0+DSh73uAgJKo 6jk61Ii9U0PQ9RcKUf3WiB40JsgsgrgmSYTd3zRDlDqEZpvKxLW4K+8UoIh9fkYqfo52 +pEChKPgJah2lnKrVhhl4cecUzUMQmqy8wCUgYXj6lpKvazn/DQhjgKkDOMPhKDxrLoy ymho0ImzLfni4H5ohBxNcZv5C0NV05LQJTmvDMLns1dq1srZT1+QoRakCDMn3jzmKIjG KKCQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=xApr0Rvj6bYN3H9puUCvmsT2cm3F0qNnJSkbus3tXXU=; b=BNsn/pi+uXsezUCk421KQGmS4rXlN1KEk60S3KTz8bJxrAYQIRp//y1vUPFh1J4IAD Mx68V5zaxPDZpieaEjXcxe5ewyS23FNmZNPRK+4EO/Q3NW8MyCkZq1ry7jtZN9AnOMO4 PlrSNet4mMmZHLJkGCVJ7n/q4HKM18+oP9p2tJ6iuSMuuXqRZcSOJR+RD6IRJg7xo2/g 1z5zb9rbmMa19S6Y5JKkmz4F1gmExK+cfn1MbcOD8EcJY4NSDCW+M0YpDXkcyNLJ8UDn Iz1RdUyeXx+umsZ5zgQ+Qtve/QY6n7rYqMUAYP76HLYzOENXh3OU236o8GZn4PBlQ3Nw OStg== X-Gm-Message-State: AOAM530Mgf0wZMeWgxFSzjFdTp/Xf5tqWG/Fml/Y/EwUPxYoOArJrbPV ko3dwKOI+4Sqgm3u6O/aSR/D2kONaiZysw== X-Google-Smtp-Source: ABdhPJya37cYmMFF1l8RwaioKKcsn3jTcm6Oe5tzMPIercQqyNEewql/SDwCSb2sUkKWiiEAkH46dg== X-Received: by 2002:a17:902:9a04:b0:13a:1ae3:add2 with SMTP id v4-20020a1709029a0400b0013a1ae3add2mr1614170plp.28.1633380598813; Mon, 04 Oct 2021 13:49:58 -0700 (PDT) Received: from localhost.localdomain (netadmin.ucsd.edu. [137.110.160.224]) by smtp.gmail.com with ESMTPSA id o12sm13635063pjm.57.2021.10.04.13.49.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Oct 2021 13:49:58 -0700 (PDT) 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 Subject: [kvm-unit-tests PATCH v3 17/17] x86 AMD SEV-ES: Add test cases Date: Mon, 4 Oct 2021 13:49:31 -0700 Message-Id: <20211004204931.1537823-18-zxwang42@gmail.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211004204931.1537823-1-zxwang42@gmail.com> References: <20211004204931.1537823-1-zxwang42@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Zixuan Wang 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(); }