From patchwork Mon Feb 26 08:25:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Isaku Yamahata X-Patchwork-Id: 206390 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:a81b:b0:108:e6aa:91d0 with SMTP id bq27csp1943788dyb; Mon, 26 Feb 2024 00:47:44 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCXcjyKp9LaKyixa7GoNI+bDaoSewx2M+1y7vgBonC6vRIuA/Ge/GKYRY7CTAGxCwYofRymDOgAgC+l+4l7dFU9RX/yTkg== X-Google-Smtp-Source: AGHT+IEP3OHg769yz95oDoU57aZATVn/QNkvB77tUGja6NHdQ1lkwS7VzCeWk1P+pKO75/70R/Os X-Received: by 2002:a17:903:2281:b0:1db:35b5:7e37 with SMTP id b1-20020a170903228100b001db35b57e37mr8543624plh.50.1708937264676; Mon, 26 Feb 2024 00:47:44 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708937264; cv=pass; d=google.com; s=arc-20160816; b=kJVSVbAtLEwRMpfNMxJbclhlwQivlqqriPdZcTT4v71t7Pd7asPZ3aaFQKepnwhYm+ UJNEAKfnU3C/6jkRoi0JS8SUbhONK5qROWt349yY9qrldDOz3e4UQb8t20RhxWDKtRv9 2bqilDhRNAK7WWH+fxnqbC6SugLLdzxCnuT+6GtACpVSjdp+PtM4PevqNdn2EDlDjeNB 1YE7XjmrRMKwQr/N8CklrC8dQ6M4PqxWaf1n1XFJvLP7a8nsbjwdZrapdDE4qgZfNbdk m4LNdAbkc+gnXxYIOQ5N5i7ANaIcyQxu57m054pAaJ5LcVhUd4LBQudxbKCrn6DryWKe dfog== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=GmT5roFAE/zKiUU7JgefEFYi37fHo8chiE8Nk+qyrmQ=; fh=j9S4ruAawPBgAnXSFLA5CQa14NHzDWYpxXu4ldeEAVs=; b=KvtF70Zlm04SD6hi+n7dqhAIuGr2q8nJB5ApvwQfydMUKoY/dKHA05v5oHXpBQfasI 8dVNxms459IDlZMDOLnB7iTmsdHVRNECMkdm+hGAl5c0F74RprDj65z3MKVh/tLTPwfM 2humZeXZGxDmTPRyoRuqDK8xkkv4RqoLIqFm3VEFMIK2G4aFGL2aKxzp3uANoZCfS0L5 l2NP7YmoZXlQ9IEQXDLhmOvM9FtoHJu7U9+4c4WXvk3W73h9Hc7HGoMdTtTqd73tOu/J Rwmnh3pnVa1vE8uNQqyUU05XEA9NUCGxOvrvkql+w9j0TQolJIzAa3nqRNcOse1ocPQJ 7YhQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=bIopRedQ; arc=pass (i=1 spf=pass spfdomain=intel.com dkim=pass dkdomain=intel.com dmarc=pass fromdomain=intel.com); spf=pass (google.com: domain of linux-kernel+bounces-80791-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-80791-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [147.75.48.161]) by mx.google.com with ESMTPS id w3-20020a170902904300b001dc69aeefafsi3315459plz.517.2024.02.26.00.47.44 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 26 Feb 2024 00:47:44 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-80791-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) client-ip=147.75.48.161; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=bIopRedQ; arc=pass (i=1 spf=pass spfdomain=intel.com dkim=pass dkdomain=intel.com dmarc=pass fromdomain=intel.com); spf=pass (google.com: domain of linux-kernel+bounces-80791-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-80791-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id 8FF7DB20B47 for ; Mon, 26 Feb 2024 08:39:20 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9FF9A5BADB; Mon, 26 Feb 2024 08:28:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="bIopRedQ" Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A274856B7F; Mon, 26 Feb 2024 08:27:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=192.198.163.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708936080; cv=none; b=h54WaVaSFQEsDoRiFRTh5RbAuF5jttLOBDq/P/P2tTOCVOFcYiAjsNXc5JCqBoebIZsQdbUOgY94Gv4Ea12KjtfOMnigbt6mbHkoTiNtvgZyuGsMrWlJ/qGXPRduKTPAUt3HBkg2eQcoCQQfz8X+GSALky0H65UrJ22TXHUiLHE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708936080; c=relaxed/simple; bh=alim40x+Y9lFNx4C2cK1mohNsqNIRwdAHp3QxJCHc1Q=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=P97zzO1r8b6VRmr9a5ydyVjPVG/9V/Jdc8wtaY9r6JzaxLeHhjq/jCCSUvNz0tr3sIZezUaU3UPtmuNKAWB4E4ALegrYd1HY7GRLH3SpkdjZqzW92lTsH9DPd4op0WGndUKoSSN58iUYQz6xgP4uAdmmgH+02xcfQJxfi0GqtR0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=bIopRedQ; arc=none smtp.client-ip=192.198.163.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1708936077; x=1740472077; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=alim40x+Y9lFNx4C2cK1mohNsqNIRwdAHp3QxJCHc1Q=; b=bIopRedQQjI8oo6Lx73J9h4Mw/3e/38Y3kGQgoDKLTurCnaBHJr/o1he UvexwcQVpK2auibcTPxM3dc/ypNpIgL6lHdwVEj3abmAYkKqecUKjw8Y0 zWtF+vCHcLLlexoFwfYSB3QMI39rZN6kpduqyKgMh8ycJg1q4Wma8cHJ7 KZTQzaFO3BBO0ps3O8ZUkOy93ooz5J0bLWr8bMuLO4TK5f6Zvc+zU4uji nYQJuB5zaGbb9+uuvuszZQitrqYt/iPmeSXYiIf2cmzjbs/6g9AGircp/ Njsin/n3ks1f+EdfYIC9CLGnPhK05xuJnmzT8w3048IHspfD4sx1ZQ08W Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10995"; a="6155266" X-IronPort-AV: E=Sophos;i="6.06,185,1705392000"; d="scan'208";a="6155266" Received: from orviesa009.jf.intel.com ([10.64.159.149]) by fmvoesa107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Feb 2024 00:27:55 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.06,185,1705392000"; d="scan'208";a="6615507" Received: from ls.sc.intel.com (HELO localhost) ([172.25.112.31]) by orviesa009-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Feb 2024 00:27:55 -0800 From: isaku.yamahata@intel.com To: kvm@vger.kernel.org, linux-kernel@vger.kernel.org Cc: isaku.yamahata@intel.com, isaku.yamahata@gmail.com, Paolo Bonzini , erdemaktas@google.com, Sean Christopherson , Sagi Shahar , Kai Huang , chen.bo@intel.com, hang.yuan@intel.com, tina.zhang@intel.com, Sean Christopherson , Binbin Wu , Yuan Yao Subject: [PATCH v19 029/130] KVM: TDX: Add C wrapper functions for SEAMCALLs to the TDX module Date: Mon, 26 Feb 2024 00:25:31 -0800 Message-Id: <7cfd33d896fce7b49bcf4b7179d0ded22c06b8c2.1708933498.git.isaku.yamahata@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791950601228304544 X-GMAIL-MSGID: 1791950601228304544 From: Isaku Yamahata A VMM interacts with the TDX module using a new instruction (SEAMCALL). For instance, a TDX VMM does not have full access to the VM control structure corresponding to VMX VMCS. Instead, a VMM induces the TDX module to act on behalf via SEAMCALLs. Define C wrapper functions for SEAMCALLs for readability. Some SEAMCALL APIs donate host pages to TDX module or guest TD, and the donated pages are encrypted. Those require the VMM to flush the cache lines to avoid cache line alias. Signed-off-by: Sean Christopherson Signed-off-by: Isaku Yamahata Reviewed-by: Binbin Wu Reviewed-by: Yuan Yao --- Changes v19: - Update the commit message to match the patch by Yuan - Use seamcall() and seamcall_ret() by paolo v18: - removed stub functions for __seamcall{,_ret}() - Added Reviewed-by Binbin - Make tdx_seamcall() use struct tdx_module_args instead of taking each inputs. v15 -> v16: - use struct tdx_module_args instead of struct tdx_module_output - Add tdh_mem_sept_rd() for SEPT_VE_DISABLE=1. Signed-off-by: Isaku Yamahata --- arch/x86/kvm/vmx/tdx_ops.h | 360 +++++++++++++++++++++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 arch/x86/kvm/vmx/tdx_ops.h diff --git a/arch/x86/kvm/vmx/tdx_ops.h b/arch/x86/kvm/vmx/tdx_ops.h new file mode 100644 index 000000000000..c5bb165b260e --- /dev/null +++ b/arch/x86/kvm/vmx/tdx_ops.h @@ -0,0 +1,360 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* constants/data definitions for TDX SEAMCALLs */ + +#ifndef __KVM_X86_TDX_OPS_H +#define __KVM_X86_TDX_OPS_H + +#include + +#include +#include +#include + +#include "tdx_errno.h" +#include "tdx_arch.h" +#include "x86.h" + +static inline u64 tdx_seamcall(u64 op, struct tdx_module_args *in, + struct tdx_module_args *out) +{ + u64 ret; + + if (out) { + *out = *in; + ret = seamcall_ret(op, out); + } else + ret = seamcall(op, in); + + if (unlikely(ret == TDX_SEAMCALL_UD)) { + /* + * SEAMCALLs fail with TDX_SEAMCALL_UD returned when VMX is off. + * This can happen when the host gets rebooted or live + * updated. In this case, the instruction execution is ignored + * as KVM is shut down, so the error code is suppressed. Other + * than this, the error is unexpected and the execution can't + * continue as the TDX features reply on VMX to be on. + */ + kvm_spurious_fault(); + return 0; + } + return ret; +} + +static inline u64 tdh_mng_addcx(hpa_t tdr, hpa_t addr) +{ + struct tdx_module_args in = { + .rcx = addr, + .rdx = tdr, + }; + + clflush_cache_range(__va(addr), PAGE_SIZE); + return tdx_seamcall(TDH_MNG_ADDCX, &in, NULL); +} + +static inline u64 tdh_mem_page_add(hpa_t tdr, gpa_t gpa, hpa_t hpa, hpa_t source, + struct tdx_module_args *out) +{ + struct tdx_module_args in = { + .rcx = gpa, + .rdx = tdr, + .r8 = hpa, + .r9 = source, + }; + + clflush_cache_range(__va(hpa), PAGE_SIZE); + return tdx_seamcall(TDH_MEM_PAGE_ADD, &in, out); +} + +static inline u64 tdh_mem_sept_add(hpa_t tdr, gpa_t gpa, int level, hpa_t page, + struct tdx_module_args *out) +{ + struct tdx_module_args in = { + .rcx = gpa | level, + .rdx = tdr, + .r8 = page, + }; + + clflush_cache_range(__va(page), PAGE_SIZE); + return tdx_seamcall(TDH_MEM_SEPT_ADD, &in, out); +} + +static inline u64 tdh_mem_sept_rd(hpa_t tdr, gpa_t gpa, int level, + struct tdx_module_args *out) +{ + struct tdx_module_args in = { + .rcx = gpa | level, + .rdx = tdr, + }; + + return tdx_seamcall(TDH_MEM_SEPT_RD, &in, out); +} + +static inline u64 tdh_mem_sept_remove(hpa_t tdr, gpa_t gpa, int level, + struct tdx_module_args *out) +{ + struct tdx_module_args in = { + .rcx = gpa | level, + .rdx = tdr, + }; + + return tdx_seamcall(TDH_MEM_SEPT_REMOVE, &in, out); +} + +static inline u64 tdh_vp_addcx(hpa_t tdvpr, hpa_t addr) +{ + struct tdx_module_args in = { + .rcx = addr, + .rdx = tdvpr, + }; + + clflush_cache_range(__va(addr), PAGE_SIZE); + return tdx_seamcall(TDH_VP_ADDCX, &in, NULL); +} + +static inline u64 tdh_mem_page_relocate(hpa_t tdr, gpa_t gpa, hpa_t hpa, + struct tdx_module_args *out) +{ + struct tdx_module_args in = { + .rcx = gpa, + .rdx = tdr, + .r8 = hpa, + }; + + clflush_cache_range(__va(hpa), PAGE_SIZE); + return tdx_seamcall(TDH_MEM_PAGE_RELOCATE, &in, out); +} + +static inline u64 tdh_mem_page_aug(hpa_t tdr, gpa_t gpa, hpa_t hpa, + struct tdx_module_args *out) +{ + struct tdx_module_args in = { + .rcx = gpa, + .rdx = tdr, + .r8 = hpa, + }; + + clflush_cache_range(__va(hpa), PAGE_SIZE); + return tdx_seamcall(TDH_MEM_PAGE_AUG, &in, out); +} + +static inline u64 tdh_mem_range_block(hpa_t tdr, gpa_t gpa, int level, + struct tdx_module_args *out) +{ + struct tdx_module_args in = { + .rcx = gpa | level, + .rdx = tdr, + }; + + return tdx_seamcall(TDH_MEM_RANGE_BLOCK, &in, out); +} + +static inline u64 tdh_mng_key_config(hpa_t tdr) +{ + struct tdx_module_args in = { + .rcx = tdr, + }; + + return tdx_seamcall(TDH_MNG_KEY_CONFIG, &in, NULL); +} + +static inline u64 tdh_mng_create(hpa_t tdr, int hkid) +{ + struct tdx_module_args in = { + .rcx = tdr, + .rdx = hkid, + }; + + clflush_cache_range(__va(tdr), PAGE_SIZE); + return tdx_seamcall(TDH_MNG_CREATE, &in, NULL); +} + +static inline u64 tdh_vp_create(hpa_t tdr, hpa_t tdvpr) +{ + struct tdx_module_args in = { + .rcx = tdvpr, + .rdx = tdr, + }; + + clflush_cache_range(__va(tdvpr), PAGE_SIZE); + return tdx_seamcall(TDH_VP_CREATE, &in, NULL); +} + +static inline u64 tdh_mng_rd(hpa_t tdr, u64 field, struct tdx_module_args *out) +{ + struct tdx_module_args in = { + .rcx = tdr, + .rdx = field, + }; + + return tdx_seamcall(TDH_MNG_RD, &in, out); +} + +static inline u64 tdh_mr_extend(hpa_t tdr, gpa_t gpa, + struct tdx_module_args *out) +{ + struct tdx_module_args in = { + .rcx = gpa, + .rdx = tdr, + }; + + return tdx_seamcall(TDH_MR_EXTEND, &in, out); +} + +static inline u64 tdh_mr_finalize(hpa_t tdr) +{ + struct tdx_module_args in = { + .rcx = tdr, + }; + + return tdx_seamcall(TDH_MR_FINALIZE, &in, NULL); +} + +static inline u64 tdh_vp_flush(hpa_t tdvpr) +{ + struct tdx_module_args in = { + .rcx = tdvpr, + }; + + return tdx_seamcall(TDH_VP_FLUSH, &in, NULL); +} + +static inline u64 tdh_mng_vpflushdone(hpa_t tdr) +{ + struct tdx_module_args in = { + .rcx = tdr, + }; + + return tdx_seamcall(TDH_MNG_VPFLUSHDONE, &in, NULL); +} + +static inline u64 tdh_mng_key_freeid(hpa_t tdr) +{ + struct tdx_module_args in = { + .rcx = tdr, + }; + + return tdx_seamcall(TDH_MNG_KEY_FREEID, &in, NULL); +} + +static inline u64 tdh_mng_init(hpa_t tdr, hpa_t td_params, + struct tdx_module_args *out) +{ + struct tdx_module_args in = { + .rcx = tdr, + .rdx = td_params, + }; + + return tdx_seamcall(TDH_MNG_INIT, &in, out); +} + +static inline u64 tdh_vp_init(hpa_t tdvpr, u64 rcx) +{ + struct tdx_module_args in = { + .rcx = tdvpr, + .rdx = rcx, + }; + + return tdx_seamcall(TDH_VP_INIT, &in, NULL); +} + +static inline u64 tdh_vp_rd(hpa_t tdvpr, u64 field, + struct tdx_module_args *out) +{ + struct tdx_module_args in = { + .rcx = tdvpr, + .rdx = field, + }; + + return tdx_seamcall(TDH_VP_RD, &in, out); +} + +static inline u64 tdh_mng_key_reclaimid(hpa_t tdr) +{ + struct tdx_module_args in = { + .rcx = tdr, + }; + + return tdx_seamcall(TDH_MNG_KEY_RECLAIMID, &in, NULL); +} + +static inline u64 tdh_phymem_page_reclaim(hpa_t page, + struct tdx_module_args *out) +{ + struct tdx_module_args in = { + .rcx = page, + }; + + return tdx_seamcall(TDH_PHYMEM_PAGE_RECLAIM, &in, out); +} + +static inline u64 tdh_mem_page_remove(hpa_t tdr, gpa_t gpa, int level, + struct tdx_module_args *out) +{ + struct tdx_module_args in = { + .rcx = gpa | level, + .rdx = tdr, + }; + + return tdx_seamcall(TDH_MEM_PAGE_REMOVE, &in, out); +} + +static inline u64 tdh_sys_lp_shutdown(void) +{ + struct tdx_module_args in = { + }; + + return tdx_seamcall(TDH_SYS_LP_SHUTDOWN, &in, NULL); +} + +static inline u64 tdh_mem_track(hpa_t tdr) +{ + struct tdx_module_args in = { + .rcx = tdr, + }; + + return tdx_seamcall(TDH_MEM_TRACK, &in, NULL); +} + +static inline u64 tdh_mem_range_unblock(hpa_t tdr, gpa_t gpa, int level, + struct tdx_module_args *out) +{ + struct tdx_module_args in = { + .rcx = gpa | level, + .rdx = tdr, + }; + + return tdx_seamcall(TDH_MEM_RANGE_UNBLOCK, &in, out); +} + +static inline u64 tdh_phymem_cache_wb(bool resume) +{ + struct tdx_module_args in = { + .rcx = resume ? 1 : 0, + }; + + return tdx_seamcall(TDH_PHYMEM_CACHE_WB, &in, NULL); +} + +static inline u64 tdh_phymem_page_wbinvd(hpa_t page) +{ + struct tdx_module_args in = { + .rcx = page, + }; + + return tdx_seamcall(TDH_PHYMEM_PAGE_WBINVD, &in, NULL); +} + +static inline u64 tdh_vp_wr(hpa_t tdvpr, u64 field, u64 val, u64 mask, + struct tdx_module_args *out) +{ + struct tdx_module_args in = { + .rcx = tdvpr, + .rdx = field, + .r8 = val, + .r9 = mask, + }; + + return tdx_seamcall(TDH_VP_WR, &in, out); +} + +#endif /* __KVM_X86_TDX_OPS_H */