Received: by 2002:a05:6a10:144:0:0:0:0 with SMTP id 4csp270503pxw; Fri, 8 Apr 2022 07:12:18 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxm+9EYEToZvjkozDNC6IlA7Pn1U99w311VF+fiNv8dMjVYbG+X5KpdTVFxLrf0wW0WRK+T X-Received: by 2002:a17:906:19c6:b0:6ce:98a4:5ee6 with SMTP id h6-20020a17090619c600b006ce98a45ee6mr18179697ejd.567.1649427138237; Fri, 08 Apr 2022 07:12:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1649427138; cv=none; d=google.com; s=arc-20160816; b=y4y+c26w3qtVomViI4a7z8q1UxNemFQX1EUIVY9qVowHxSNSJiLmRr7r1IcYZiNgnT ezf7l2PlAKYGVD/3QQGroff9Zj3+VWzdVw5MHo440IV4R+r9vNJJCvBq41MuczdAG/zV th6V8RM37Ppp7MzE9IbRAVu/LP3zoOFkkD3K0raCRKvZDThRICjtvhaCGWhYwqeWewb2 4CRFHF7Zn/EPIl/CIcztPJ9KAGFZJFSD3KKZHIgX4691tAb6ZYF6FgNSwdAcIKnrPF20 MvM8tr7siOnuO06gsn5XV7aZPdTXiCu5+Zj4DcnPpcImgHA0LN5HIqOM5STGXCmjG1re ox2Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:robot-unsubscribe :robot-id:message-id:mime-version:references:in-reply-to:cc:subject :to:reply-to:sender:from:dkim-signature:dkim-signature:date; bh=7zVJxZmTkeFBH8xY0eIsdhqZxrT9IdulUaaEJaYUEDg=; b=VgfHUPrk37Oub7YuZRzTsya2Ea7EluV2J9BLPr4mlBkeCm6JJb6Rq9V326tWv3IBp0 b0ImImc7BJQ8X3caiIxweo0MMEs7rvL6xEhaBhjAKGD/RY7R+zGCBIchWjP+7DGYkpNU nRRjUDplr9qqZcSL/jAY8ysOLOjJqwNhEsqOEpXl3gTnRextQcWCzSJIsnXHyiBaH6Ci bmlM1Sa4cQ90GIWUuj+lbCJh4NBvduCVOEjAqwgPDfCVp6Sw74qg2HGyu0jVO75L6Nsg WnOs5rqhJE+Q1r/IjURuSwv8P7sjp/hgNnF93/C2En5qNyKmUaB93hkrX70L3WWLacLK Rklg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=2bvgesqa; dkim=neutral (no key) header.i=@linutronix.de; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id j21-20020a170906475500b006df76385e08si244653ejs.680.2022.04.08.07.11.20; Fri, 08 Apr 2022 07:12:18 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=2bvgesqa; dkim=neutral (no key) header.i=@linutronix.de; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233616AbiDHJPp (ORCPT + 99 others); Fri, 8 Apr 2022 05:15:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42454 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232892AbiDHJMD (ORCPT ); Fri, 8 Apr 2022 05:12:03 -0400 Received: from galois.linutronix.de (Galois.linutronix.de [IPv6:2a0a:51c0:0:12e:550::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6DF361E86BE; Fri, 8 Apr 2022 02:09:09 -0700 (PDT) Date: Fri, 08 Apr 2022 09:09:07 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1649408948; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7zVJxZmTkeFBH8xY0eIsdhqZxrT9IdulUaaEJaYUEDg=; b=2bvgesqa0+GDb31z3s0KT4zVKyPobnJwMOXZGPAOq/m9XahnazPkk/ObHpLZ0/NWnA/ZOW 0uVpmcwZlUXn1bjr0R4DU5svK/Ub9y/0OaA6OpbJ4iYlkXtbft1E+58xJso7Wio7zl6Ym1 Cyam9yqJDyAjclF12om2bPepYAlbVEW9eC6JEL/wBeGK2YuEKIW3Unkc8PHOmWrl3Ywfdn RdIF1iU97XoxQlkwrK51Nc4TAImZpezZGHHFOOUhok9zT87nD7A0XEaA6JCIefctd4M/bl jHmbDWVLr93WiqEfChZY8wfat9JPR5oH5vdty9jOCCIiZv2d64DUWzNG3XJY2Q== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1649408948; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7zVJxZmTkeFBH8xY0eIsdhqZxrT9IdulUaaEJaYUEDg=; b=SJ8mrd+eptObALeWz1ajDTVfURlCvge22L66KlT+d4N2uc8a1NTWB19/jkK2gwBSa16Bud tFgfRMmpuK4s+IBA== From: "tip-bot2 for Brijesh Singh" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: x86/sev] x86/sev: Check the VMPL level Cc: Brijesh Singh , Borislav Petkov , x86@kernel.org, linux-kernel@vger.kernel.org In-Reply-To: <20220307213356.2797205-15-brijesh.singh@amd.com> References: <20220307213356.2797205-15-brijesh.singh@amd.com> MIME-Version: 1.0 Message-ID: <164940894730.389.11280397008447131834.tip-bot2@tip-bot2> Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The following commit has been merged into the x86/sev branch of tip: Commit-ID: 81cc3df9a90e7817494421ecc48ede6bd5e8132b Gitweb: https://git.kernel.org/tip/81cc3df9a90e7817494421ecc48ede6bd5e8132b Author: Brijesh Singh AuthorDate: Wed, 09 Feb 2022 12:10:08 -06:00 Committer: Borislav Petkov CommitterDate: Wed, 06 Apr 2022 13:10:34 +02:00 x86/sev: Check the VMPL level The Virtual Machine Privilege Level (VMPL) feature in the SEV-SNP architecture allows a guest VM to divide its address space into four levels. The level can be used to provide hardware isolated abstraction layers within a VM. VMPL0 is the highest privilege level, and VMPL3 is the least privilege level. Certain operations must be done by the VMPL0 software, such as: * Validate or invalidate memory range (PVALIDATE instruction) * Allocate VMSA page (RMPADJUST instruction when VMSA=1) The initial SNP support requires that the guest kernel is running at VMPL0. Add such a check to verify the guest is running at level 0 before continuing the boot. There is no easy method to query the current VMPL level, so use the RMPADJUST instruction to determine whether the guest is running at the VMPL0. [ bp: Massage commit message. ] Signed-off-by: Brijesh Singh Signed-off-by: Borislav Petkov Link: https://lore.kernel.org/r/20220307213356.2797205-15-brijesh.singh@amd.com --- arch/x86/boot/compressed/sev.c | 28 ++++++++++++++++++++++++++-- arch/x86/include/asm/sev-common.h | 1 + arch/x86/include/asm/sev.h | 16 ++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c index 5b38931..eb42178 100644 --- a/arch/x86/boot/compressed/sev.c +++ b/arch/x86/boot/compressed/sev.c @@ -199,6 +199,26 @@ finish: sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ); } +static void enforce_vmpl0(void) +{ + u64 attrs; + int err; + + /* + * RMPADJUST modifies RMP permissions of a lesser-privileged (numerically + * higher) privilege level. Here, clear the VMPL1 permission mask of the + * GHCB page. If the guest is not running at VMPL0, this will fail. + * + * If the guest is running at VMPL0, it will succeed. Even if that operation + * modifies permission bits, it is still ok to do so currently because Linux + * SNP guests are supported only on VMPL0 so VMPL1 or higher permission masks + * changing is a don't-care. + */ + attrs = 1; + if (rmpadjust((unsigned long)&boot_ghcb_page, RMP_PG_SIZE_4K, attrs)) + sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_NOT_VMPL0); +} + void sev_enable(struct boot_params *bp) { unsigned int eax, ebx, ecx, edx; @@ -242,8 +262,12 @@ void sev_enable(struct boot_params *bp) * SNP is supported in v2 of the GHCB spec which mandates support for HV * features. */ - if (sev_status & MSR_AMD64_SEV_SNP_ENABLED && !(get_hv_features() & GHCB_HV_FT_SNP)) - sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED); + if (sev_status & MSR_AMD64_SEV_SNP_ENABLED) { + if (!(get_hv_features() & GHCB_HV_FT_SNP)) + sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED); + + enforce_vmpl0(); + } sme_me_mask = BIT_ULL(ebx & 0x3f); } diff --git a/arch/x86/include/asm/sev-common.h b/arch/x86/include/asm/sev-common.h index 6f037c2..7ac5842 100644 --- a/arch/x86/include/asm/sev-common.h +++ b/arch/x86/include/asm/sev-common.h @@ -89,6 +89,7 @@ #define GHCB_TERM_REGISTER 0 /* GHCB GPA registration failure */ #define GHCB_TERM_PSC 1 /* Page State Change failure */ #define GHCB_TERM_PVALIDATE 2 /* Pvalidate failure */ +#define GHCB_TERM_NOT_VMPL0 3 /* SNP guest is not running at VMPL-0 */ #define GHCB_RESP_CODE(v) ((v) & GHCB_MSR_INFO_MASK) diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h index 4ee9897..e374518 100644 --- a/arch/x86/include/asm/sev.h +++ b/arch/x86/include/asm/sev.h @@ -63,6 +63,9 @@ extern bool handle_vc_boot_ghcb(struct pt_regs *regs); /* Software defined (when rFlags.CF = 1) */ #define PVALIDATE_FAIL_NOUPDATE 255 +/* RMP page size */ +#define RMP_PG_SIZE_4K 0 + #ifdef CONFIG_AMD_MEM_ENCRYPT extern struct static_key_false sev_es_enable_key; extern void __sev_es_ist_enter(struct pt_regs *regs); @@ -90,6 +93,18 @@ extern enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb, struct es_em_ctxt *ctxt, u64 exit_code, u64 exit_info_1, u64 exit_info_2); +static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs) +{ + int rc; + + /* "rmpadjust" mnemonic support in binutils 2.36 and newer */ + asm volatile(".byte 0xF3,0x0F,0x01,0xFE\n\t" + : "=a"(rc) + : "a"(vaddr), "c"(rmp_psize), "d"(attrs) + : "memory", "cc"); + + return rc; +} static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate) { bool no_rmpupdate; @@ -114,6 +129,7 @@ static inline int sev_es_setup_ap_jump_table(struct real_mode_header *rmh) { ret static inline void sev_es_nmi_complete(void) { } static inline int sev_es_efi_map_ghcbs(pgd_t *pgd) { return 0; } static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate) { return 0; } +static inline int rmpadjust(unsigned long vaddr, bool rmp_psize, unsigned long attrs) { return 0; } #endif #endif