From nobody Sat Feb 7 13:05:35 2026 Received: from mail-pf1-f201.google.com (mail-pf1-f201.google.com [209.85.210.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C2258394496 for ; Tue, 20 Jan 2026 20:39:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768941583; cv=none; b=cIRZbGjZB5AY/t18XmQn+PCej3Qmwd5N04OHcOW6FPjMPOybRzEiSi6VXqlaJrvdDNzjCOgYZbes70u+4QhR/CCiI+kXzAZRYbjDWCxDGCZgKnTcEdLb+wFOyi6HCdrf6s7j0yVl5NcwiDr9Pycg5v8EFamE8WA9pOvECkN6Ekw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768941583; c=relaxed/simple; bh=BBNSLLdSFYFyUpLlez2P7xtkF8fzZ+LkUQxuzekxzqo=; h=Date:Mime-Version:Message-ID:Subject:From:To:Cc:Content-Type; b=TFr+QObrWgaDzJ8PrLbFdlg4mT3qn9+ooQVM1VIRAzagnIMnF55KXTqhBjuM332FyrCFFIoFwHB7uosGzNoyAIHxQ1G1Nr0aqdCWP9A7lShVCn5i7gp3571e8HYtp7K1Kk2Sr8F7UaDo8mV1ljDojf58syuDXfoLjpZR48GC1cI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=T/OQfhjH; arc=none smtp.client-ip=209.85.210.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="T/OQfhjH" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-81f8c209cfbso2699235b3a.2 for ; Tue, 20 Jan 2026 12:39:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1768941580; x=1769546380; darn=vger.kernel.org; h=cc:to:from:subject:message-id:mime-version:date:reply-to:from:to:cc :subject:date:message-id:reply-to; bh=fOlo8lJmeTgpVgWUOKyhN8UdU1E2up/RYKncWnWwFxk=; b=T/OQfhjH3VeujKZz7rrBsa/wsgRzHt5+vA/WJP4utnqoCPRuE7E0VhIYOJBP+tnZXa gHzY7y2nQYMsY1a857H9Lj0kCZ/9xMtyRIY1drJrSiq0RGQF+acPxHZZ0xt0GVXTUw/P T45NXzl+t9lUfAJaZmzBsRYFtHYGF5y25+wOwTtQeqnrFjujNMIRMSquiPC22hMT4hQF QMcx1N/VQ/8pIEQFDNUFUnwlcbstbO0JSl1bsdp0P6f6AYNQtiOyCzyAnqLsv5n+mRe9 gZW72hEwrLQmrcmn/arSfpJc2+PpuR1YJIHoO3kqjav5eP7ZQguEcx9j4L7uw4L8Cn2b mNMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768941580; x=1769546380; h=cc:to:from:subject:message-id:mime-version:date:reply-to :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=fOlo8lJmeTgpVgWUOKyhN8UdU1E2up/RYKncWnWwFxk=; b=g7OraqrANRFlC5qUHAOUlpeh2HBpnMw7IfNz1vSPmGPT/XTD+Ghdi/hZCX1zS7Qb+f 75x6imDc+R4xzv0XSCRLSgdZGW3cOOqdsJtbFooJ+ueCeh0WP1LGiWew4rqq1IawtKZM 5oTetCP6gYDhLkDX25ItYsRA7mDBIShQMuEwuBhFdwOMJ6SGtFl9O/EnlCiz4stk9kDk W0at2lLMR3NTT4le6DrH1Q/J0PskpaJpoVOogLv3JbCEsNlmw378FgburoKgz5pTjqZ6 9Hu0/mw/CXZvkbKBFvNJSlxFGTKWJauw340FOFux8hPQtyvFYAONY+Yi5SBfD2sRTdkx mX4w== X-Gm-Message-State: AOJu0YzWtujRqo41KAPJkO20sCILCbJ7WXO8TtgP2b/aLS8gSAxxNQEs dBBUtKpYVid6PKg6/UZmdp8VA56uOer7aeWWUG0YDGVQ819GBU0K8HBT33McReo2scpsaZZm2rq UBIs1Cg== X-Received: from pleg3.prod.google.com ([2002:a17:902:e383:b0:2a7:5f0f:c120]) (user=seanjc job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:4606:b0:366:14af:9bbf with SMTP id adf61e73a8af0-38dfe7c9f65mr14217718637.73.1768941579841; Tue, 20 Jan 2026 12:39:39 -0800 (PST) Reply-To: Sean Christopherson Date: Tue, 20 Jan 2026 12:39:37 -0800 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 X-Mailer: git-send-email 2.52.0.457.g6b5491de43-goog Message-ID: <20260120203937.1447592-1-seanjc@google.com> Subject: [PATCH] x86/tdx: Use pg_level in TDX APIs, not the TDX-Module's 0-based level From: Sean Christopherson To: Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, Kiryl Shutsemau , Sean Christopherson , Paolo Bonzini Cc: linux-kernel@vger.kernel.org, linux-coco@lists.linux.dev, kvm@vger.kernel.org, Kai Huang , Rick Edgecombe , Yan Zhao , Vishal Annapurve , Ackerley Tng Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Rework the TDX APIs to take the kernel's 1-based pg_level enum, not the TDX-Module's 0-based level. The APIs are _kernel_ APIs, not TDX-Module APIs, and the kernel (and KVM) uses "enum pg_level" literally everywhere. Using "enum pg_level" eliminates ambiguity when looking at the APIs (it's NOT clear that "int level" refers to the TDX-Module's level), and will allow for using existing helpers like page_level_size() when support for hugepages is added to the S-EPT APIs. No functional change intended. Cc: Kai Huang Cc: Dave Hansen Cc: Rick Edgecombe Cc: Yan Zhao Cc: Vishal Annapurve Cc: Ackerley Tng Signed-off-by: Sean Christopherson Acked-by: Kiryl Shutsemau Reviewed-by: Kai Huang Reviewed-by: Rick Edgecombe Reviewed-by: Yan Zhao Tested-by: Kai Huang Tested-by: Rick Edgecombe Tested-by: Yan Zhao --- Compile-tested only. Came across this when looking at the S-EPT hugepage series, specifically this code: =20 unsigned long npages =3D 1 << (level * PTE_SHIFT); which I was _sure_ was broken, until I realized @level wasn't what I thought it was. =20 arch/x86/include/asm/tdx.h | 14 ++++---------- arch/x86/kvm/vmx/tdx.c | 11 ++++------- arch/x86/virt/vmx/tdx/tdx.c | 26 ++++++++++++++++++-------- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 6b338d7f01b7..bc0d03e70fd6 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -189,19 +189,13 @@ static inline u64 mk_keyed_paddr(u16 hkid, struct pag= e *page) return ret; } =20 -static inline int pg_level_to_tdx_sept_level(enum pg_level level) -{ - WARN_ON_ONCE(level =3D=3D PG_LEVEL_NONE); - return level - 1; -} - u64 tdh_vp_enter(struct tdx_vp *vp, struct tdx_module_args *args); u64 tdh_mng_addcx(struct tdx_td *td, struct page *tdcs_page); u64 tdh_mem_page_add(struct tdx_td *td, u64 gpa, struct page *page, struct= page *source, u64 *ext_err1, u64 *ext_err2); -u64 tdh_mem_sept_add(struct tdx_td *td, u64 gpa, int level, struct page *p= age, u64 *ext_err1, u64 *ext_err2); +u64 tdh_mem_sept_add(struct tdx_td *td, u64 gpa, enum pg_level level, stru= ct page *page, u64 *ext_err1, u64 *ext_err2); u64 tdh_vp_addcx(struct tdx_vp *vp, struct page *tdcx_page); -u64 tdh_mem_page_aug(struct tdx_td *td, u64 gpa, int level, struct page *p= age, u64 *ext_err1, u64 *ext_err2); -u64 tdh_mem_range_block(struct tdx_td *td, u64 gpa, int level, u64 *ext_er= r1, u64 *ext_err2); +u64 tdh_mem_page_aug(struct tdx_td *td, u64 gpa, enum pg_level level, stru= ct page *page, u64 *ext_err1, u64 *ext_err2); +u64 tdh_mem_range_block(struct tdx_td *td, u64 gpa, enum pg_level level, u= 64 *ext_err1, u64 *ext_err2); u64 tdh_mng_key_config(struct tdx_td *td); u64 tdh_mng_create(struct tdx_td *td, u16 hkid); u64 tdh_vp_create(struct tdx_td *td, struct tdx_vp *vp); @@ -217,7 +211,7 @@ u64 tdh_vp_rd(struct tdx_vp *vp, u64 field, u64 *data); u64 tdh_vp_wr(struct tdx_vp *vp, u64 field, u64 data, u64 mask); u64 tdh_phymem_page_reclaim(struct page *page, u64 *tdx_pt, u64 *tdx_owner= , u64 *tdx_size); u64 tdh_mem_track(struct tdx_td *tdr); -u64 tdh_mem_page_remove(struct tdx_td *td, u64 gpa, u64 level, u64 *ext_er= r1, u64 *ext_err2); +u64 tdh_mem_page_remove(struct tdx_td *td, u64 gpa, enum pg_level level, u= 64 *ext_err1, u64 *ext_err2); u64 tdh_phymem_cache_wb(bool resume); u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td); u64 tdh_phymem_page_wbinvd_hkid(u64 hkid, struct page *page); diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c index 2d7a4d52ccfb..c47f4de2f19c 100644 --- a/arch/x86/kvm/vmx/tdx.c +++ b/arch/x86/kvm/vmx/tdx.c @@ -1648,14 +1648,13 @@ static int tdx_mem_page_add(struct kvm *kvm, gfn_t = gfn, enum pg_level level, static int tdx_mem_page_aug(struct kvm *kvm, gfn_t gfn, enum pg_level level, kvm_pfn_t pfn) { - int tdx_level =3D pg_level_to_tdx_sept_level(level); struct kvm_tdx *kvm_tdx =3D to_kvm_tdx(kvm); struct page *page =3D pfn_to_page(pfn); gpa_t gpa =3D gfn_to_gpa(gfn); u64 entry, level_state; u64 err; =20 - err =3D tdh_mem_page_aug(&kvm_tdx->td, gpa, tdx_level, page, &entry, &lev= el_state); + err =3D tdh_mem_page_aug(&kvm_tdx->td, gpa, level, page, &entry, &level_s= tate); if (unlikely(tdx_operand_busy(err))) return -EBUSY; =20 @@ -1699,12 +1698,11 @@ static int tdx_sept_set_private_spte(struct kvm *kv= m, gfn_t gfn, static int tdx_sept_link_private_spt(struct kvm *kvm, gfn_t gfn, enum pg_level level, void *private_spt) { - int tdx_level =3D pg_level_to_tdx_sept_level(level); gpa_t gpa =3D gfn_to_gpa(gfn); struct page *page =3D virt_to_page(private_spt); u64 err, entry, level_state; =20 - err =3D tdh_mem_sept_add(&to_kvm_tdx(kvm)->td, gpa, tdx_level, page, &ent= ry, + err =3D tdh_mem_sept_add(&to_kvm_tdx(kvm)->td, gpa, level, page, &entry, &level_state); if (unlikely(tdx_operand_busy(err))) return -EBUSY; @@ -1788,7 +1786,6 @@ static void tdx_sept_remove_private_spte(struct kvm *= kvm, gfn_t gfn, enum pg_level level, u64 mirror_spte) { struct page *page =3D pfn_to_page(spte_to_pfn(mirror_spte)); - int tdx_level =3D pg_level_to_tdx_sept_level(level); struct kvm_tdx *kvm_tdx =3D to_kvm_tdx(kvm); gpa_t gpa =3D gfn_to_gpa(gfn); u64 err, entry, level_state; @@ -1808,7 +1805,7 @@ static void tdx_sept_remove_private_spte(struct kvm *= kvm, gfn_t gfn, return; =20 err =3D tdh_do_no_vcpus(tdh_mem_range_block, kvm, &kvm_tdx->td, gpa, - tdx_level, &entry, &level_state); + level, &entry, &level_state); if (TDX_BUG_ON_2(err, TDH_MEM_RANGE_BLOCK, entry, level_state, kvm)) return; =20 @@ -1824,7 +1821,7 @@ static void tdx_sept_remove_private_spte(struct kvm *= kvm, gfn_t gfn, * Race with TDH.VP.ENTER due to (0-step mitigation) and Guest TDCALLs. */ err =3D tdh_do_no_vcpus(tdh_mem_page_remove, kvm, &kvm_tdx->td, gpa, - tdx_level, &entry, &level_state); + level, &entry, &level_state); if (TDX_BUG_ON_2(err, TDH_MEM_PAGE_REMOVE, entry, level_state, kvm)) return; =20 diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 5ce4ebe99774..22c0f832cb37 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1516,6 +1516,12 @@ static void tdx_clflush_page(struct page *page) clflush_cache_range(page_to_virt(page), PAGE_SIZE); } =20 +static int pg_level_to_tdx_sept_level(enum pg_level level) +{ + WARN_ON_ONCE(level =3D=3D PG_LEVEL_NONE); + return level - 1; +} + noinstr u64 tdh_vp_enter(struct tdx_vp *td, struct tdx_module_args *args) { args->rcx =3D td->tdvpr_pa; @@ -1556,10 +1562,11 @@ u64 tdh_mem_page_add(struct tdx_td *td, u64 gpa, st= ruct page *page, struct page } EXPORT_SYMBOL_FOR_KVM(tdh_mem_page_add); =20 -u64 tdh_mem_sept_add(struct tdx_td *td, u64 gpa, int level, struct page *p= age, u64 *ext_err1, u64 *ext_err2) +u64 tdh_mem_sept_add(struct tdx_td *td, u64 gpa, enum pg_level level, + struct page *page, u64 *ext_err1, u64 *ext_err2) { struct tdx_module_args args =3D { - .rcx =3D gpa | level, + .rcx =3D gpa | pg_level_to_tdx_sept_level(level), .rdx =3D tdx_tdr_pa(td), .r8 =3D page_to_phys(page), }; @@ -1587,10 +1594,11 @@ u64 tdh_vp_addcx(struct tdx_vp *vp, struct page *td= cx_page) } EXPORT_SYMBOL_FOR_KVM(tdh_vp_addcx); =20 -u64 tdh_mem_page_aug(struct tdx_td *td, u64 gpa, int level, struct page *p= age, u64 *ext_err1, u64 *ext_err2) +u64 tdh_mem_page_aug(struct tdx_td *td, u64 gpa, enum pg_level level, + struct page *page, u64 *ext_err1, u64 *ext_err2) { struct tdx_module_args args =3D { - .rcx =3D gpa | level, + .rcx =3D gpa | pg_level_to_tdx_sept_level(level), .rdx =3D tdx_tdr_pa(td), .r8 =3D page_to_phys(page), }; @@ -1606,10 +1614,11 @@ u64 tdh_mem_page_aug(struct tdx_td *td, u64 gpa, in= t level, struct page *page, u } EXPORT_SYMBOL_FOR_KVM(tdh_mem_page_aug); =20 -u64 tdh_mem_range_block(struct tdx_td *td, u64 gpa, int level, u64 *ext_er= r1, u64 *ext_err2) +u64 tdh_mem_range_block(struct tdx_td *td, u64 gpa, enum pg_level level, + u64 *ext_err1, u64 *ext_err2) { struct tdx_module_args args =3D { - .rcx =3D gpa | level, + .rcx =3D gpa | pg_level_to_tdx_sept_level(level), .rdx =3D tdx_tdr_pa(td), }; u64 ret; @@ -1822,10 +1831,11 @@ u64 tdh_mem_track(struct tdx_td *td) } EXPORT_SYMBOL_FOR_KVM(tdh_mem_track); =20 -u64 tdh_mem_page_remove(struct tdx_td *td, u64 gpa, u64 level, u64 *ext_er= r1, u64 *ext_err2) +u64 tdh_mem_page_remove(struct tdx_td *td, u64 gpa, enum pg_level level, + u64 *ext_err1, u64 *ext_err2) { struct tdx_module_args args =3D { - .rcx =3D gpa | level, + .rcx =3D gpa | pg_level_to_tdx_sept_level(level), .rdx =3D tdx_tdr_pa(td), }; u64 ret; base-commit: 24d479d26b25bce5faea3ddd9fa8f3a6c3129ea7 --=20 2.52.0.457.g6b5491de43-goog