Received: by 2002:a05:6a10:413:0:0:0:0 with SMTP id 19csp948588pxp; Wed, 16 Mar 2022 22:19:00 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzPog8WKSlbiW7qpMwI0TMn+KiUycHs88oqAbsKmn0V17r16D/8domnlvdwf1fA5cELjSQY X-Received: by 2002:a17:902:d2c4:b0:151:d1ee:a627 with SMTP id n4-20020a170902d2c400b00151d1eea627mr2940192plc.59.1647494340435; Wed, 16 Mar 2022 22:19:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1647494340; cv=none; d=google.com; s=arc-20160816; b=qc2mQPlEHtV2Tr3KErn/L9oicGBNmPYAqDBG6l1g6UcxPC0gKBHHiFPr47DyzaLW1I T1locZ4amgj+SQZKZA6JbHp3FBCzb1k9yVkh0OW/bIFFgNJ8Mn+J7hEZCxxFHEW6Ju0/ 3Kpyg/QRBJ/9qnGBkYcnBLcu/xT0kem+AbF0AfYd8j5WHUUpTgfoZjrUXd5xq9IF1Aki 0RMfAYAAS+VR8x/FlyLEQHmTQ8bMsFZ9LDGaSkNtf1D+rQD0LboL/EyVncNXxBIPvHeN 0gKPfsml9VIkWyONz6ddgZLo+ksaiFDORl9EEiCcDUi+VL3gsoh51zMLZt/viMNDs4ax 5r/Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=MIKezNrG5zcPQyYWBBKK3jboIvNiP2cpEXLx0jxr8LU=; b=NjZj+ikcaT5tKuL7BQ+Vpk3hMvubJVaWLsDIvnf4W/uGw6p2OltCnsr2P+yjooJhTA p4t4Ut+7o50Lx+ZyFbuRn923mULHF5KR3zyV/sy6PZCtDi23d9+kulJq5jagGLZxeGHo J6ypfndAa+PH0ove3mgRr6wB+LuSpVGajnwVEo1khRKzcy80WQDHyOkK2mHAI9mMZieu 7+sqB0lnuwCWT9k8DSNmNjXb9WLK7qA8iMrDc+U5JZztXXRX+rGazzcMdqyVENUa0rW+ jby9hMU9UKtFa4IfOdN8eAu3Otxw2f1LIGL5JQj3+ftuQuPhQf3kIFABqR9lEnbl6lVY uD9w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=WfUNr6uu; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [2620:137:e000::1:18]) by mx.google.com with ESMTPS id x5-20020a627c05000000b004f6fe1f305bsi3586176pfc.230.2022.03.16.22.19.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 16 Mar 2022 22:19:00 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) client-ip=2620:137:e000::1:18; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=WfUNr6uu; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id E9FA3202894; Wed, 16 Mar 2022 21:26:12 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352674AbiCPCLe (ORCPT + 99 others); Tue, 15 Mar 2022 22:11:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46914 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352530AbiCPCLR (ORCPT ); Tue, 15 Mar 2022 22:11:17 -0400 Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 91BFD5DA57 for ; Tue, 15 Mar 2022 19:10:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647396604; x=1678932604; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=gSuQ8q4nToFptHNU3QmagEk21QtphWEGEe+0SgSEyVc=; b=WfUNr6uu3Iz0mYJKWcDzKxU1tlsMfoMPAH6P76btLHPBxFiM2maZxxMT WoC6q/Jj+iR3/A4jLb6amFMZGgxgBjlVIWKqZV9eidvh1QhF/Lk929E2B hz3j1RS8/sVcLXptvTrkk98iInYfdGLkSR5ACjceQ26woFgjOBr86YXjr LG/umqQLUQ6nc0dT6RKKG7V7HEiNgnljGWLCIwyqZCMfVItPuBe3bOsV1 kJ4q3c3SWD6EPoMKX46Q2J8zCwCYNdk9EyxYQeU/iTLZXDVMY9iLX67pr Owi/sKI9TzsSgRS9RLEJlUagCnatLjN1m+kuepuACFykgcJ+f7Oide3g5 Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10286"; a="236415656" X-IronPort-AV: E=Sophos;i="5.90,185,1643702400"; d="scan'208";a="236415656" Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Mar 2022 19:10:04 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.90,185,1643702400"; d="scan'208";a="613475486" Received: from black.fi.intel.com ([10.237.72.28]) by fmsmga004.fm.intel.com with ESMTP; 15 Mar 2022 19:09:57 -0700 Received: by black.fi.intel.com (Postfix, from userid 1000) id 048B47B7; Wed, 16 Mar 2022 04:10:09 +0200 (EET) From: "Kirill A. Shutemov" To: tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@intel.com, luto@kernel.org, peterz@infradead.org Cc: sathyanarayanan.kuppuswamy@linux.intel.com, aarcange@redhat.com, ak@linux.intel.com, dan.j.williams@intel.com, david@redhat.com, hpa@zytor.com, jgross@suse.com, jmattson@google.com, joro@8bytes.org, jpoimboe@redhat.com, knsathya@kernel.org, pbonzini@redhat.com, sdeep@vmware.com, seanjc@google.com, tony.luck@intel.com, vkuznets@redhat.com, wanpengli@tencent.com, thomas.lendacky@amd.com, brijesh.singh@amd.com, x86@kernel.org, linux-kernel@vger.kernel.org, "Kirill A. Shutemov" , Dave Hansen Subject: [PATCHv6 10/30] x86/tdx: Handle CPUID via #VE Date: Wed, 16 Mar 2022 05:08:36 +0300 Message-Id: <20220316020856.24435-11-kirill.shutemov@linux.intel.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220316020856.24435-1-kirill.shutemov@linux.intel.com> References: <20220316020856.24435-1-kirill.shutemov@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-3.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=unavailable 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 In TDX guests, most CPUID leaf/sub-leaf combinations are virtualized by the TDX module while some trigger #VE. Implement the #VE handling for EXIT_REASON_CPUID by handing it through the hypercall, which in turn lets the TDX module handle it by invoking the host VMM. More details on CPUID Virtualization can be found in the TDX module specification, the section titled "CPUID Virtualization". Note that VMM that handles the hypercall is not trusted. It can return data that may steer the guest kernel in wrong direct. Only allow VMM to control range reserved for hypervisor communication. Return all-zeros for any CPUID outside the hypervisor range. It matches CPU behaviour for non-supported leaf. Co-developed-by: Kuppuswamy Sathyanarayanan Signed-off-by: Kuppuswamy Sathyanarayanan Reviewed-by: Andi Kleen Reviewed-by: Tony Luck Signed-off-by: Kirill A. Shutemov Reviewed-by: Dave Hansen --- arch/x86/coco/tdx/tdx.c | 58 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c index 8addc242aa0e..7c89860552d7 100644 --- a/arch/x86/coco/tdx/tdx.c +++ b/arch/x86/coco/tdx/tdx.c @@ -173,6 +173,48 @@ static bool write_msr(struct pt_regs *regs) return !__tdx_hypercall(&args, 0); } +static bool handle_cpuid(struct pt_regs *regs) +{ + struct tdx_hypercall_args args = { + .r10 = TDX_HYPERCALL_STANDARD, + .r11 = hcall_func(EXIT_REASON_CPUID), + .r12 = regs->ax, + .r13 = regs->cx, + }; + + /* + * Only allow VMM to control range reserved for hypervisor + * communication. + * + * Return all-zeros for any CPUID outside the range. It matches CPU + * behaviour for non-supported leaf. + */ + if (regs->ax < 0x40000000 || regs->ax > 0x4FFFFFFF) { + regs->ax = regs->bx = regs->cx = regs->dx = 0; + return true; + } + + /* + * Emulate the CPUID instruction via a hypercall. More info about + * ABI can be found in TDX Guest-Host-Communication Interface + * (GHCI), section titled "VP.VMCALL". + */ + if (__tdx_hypercall(&args, TDX_HCALL_HAS_OUTPUT)) + return false; + + /* + * As per TDX GHCI CPUID ABI, r12-r15 registers contain contents of + * EAX, EBX, ECX, EDX registers after the CPUID instruction execution. + * So copy the register contents back to pt_regs. + */ + regs->ax = args.r12; + regs->bx = args.r13; + regs->cx = args.r14; + regs->dx = args.r15; + + return true; +} + void tdx_get_ve_info(struct ve_info *ve) { struct tdx_module_output out; @@ -196,6 +238,18 @@ void tdx_get_ve_info(struct ve_info *ve) ve->instr_info = upper_32_bits(out.r10); } +/* Handle the user initiated #VE */ +static bool virt_exception_user(struct pt_regs *regs, struct ve_info *ve) +{ + switch (ve->exit_reason) { + case EXIT_REASON_CPUID: + return handle_cpuid(regs); + default: + pr_warn("Unexpected #VE: %lld\n", ve->exit_reason); + return false; + } +} + /* Handle the kernel #VE */ static bool virt_exception_kernel(struct pt_regs *regs, struct ve_info *ve) { @@ -206,6 +260,8 @@ static bool virt_exception_kernel(struct pt_regs *regs, struct ve_info *ve) return read_msr(regs); case EXIT_REASON_MSR_WRITE: return write_msr(regs); + case EXIT_REASON_CPUID: + return handle_cpuid(regs); default: pr_warn("Unexpected #VE: %lld\n", ve->exit_reason); return false; @@ -217,7 +273,7 @@ bool tdx_handle_virt_exception(struct pt_regs *regs, struct ve_info *ve) bool ret; if (user_mode(regs)) - ret = false; + ret = virt_exception_user(regs, ve); else ret = virt_exception_kernel(regs, ve); -- 2.34.1