From nobody Sun Sep 7 12:19:02 2025 Received: from mail-wr1-f73.google.com (mail-wr1-f73.google.com [209.85.221.73]) (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 AD5031D88AC for ; Wed, 16 Jul 2025 03:22:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752636151; cv=none; b=hFlqK5/OQE6MXc53oMWu2M2WHnwlBhizZwQufVRE2V2kbn1qSeHBYR11E7JeDPp6TcUVUFW/UCdMemMgMq0XfRHuhhjt8qXnAMWhiwpFgSmDR4H9BFgzn131cr/MvygmjJ4Ov2PumzDUBpuP0jxSpJWwtinaxBxbHhHYeWjF33A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752636151; c=relaxed/simple; bh=y7ZqIPfzZjjineUnECWqLBqlDGZnJoXywp+4TUmHp9o=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Iab3+/j2jVcFBjJzb9bYbcaDGgyso0H7K7KH6s6POgOilZg9fR3O9s2iA+9dBC4cYPdxodE0dYaAGU5vJe+KwcgU/yU2Rvz5HN4T9YGU6SZJmfLFgR7200OZmQN0xhp+nJ4gy8rM+vbWpT7CjLQYc/CZGI1wE/7kR1GwlRfE3+c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--ardb.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=SJ7n264n; arc=none smtp.client-ip=209.85.221.73 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--ardb.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="SJ7n264n" Received: by mail-wr1-f73.google.com with SMTP id ffacd0b85a97d-3a5780e8137so187770f8f.1 for ; Tue, 15 Jul 2025 20:22:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1752636148; x=1753240948; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=/0fjCI0G736hAl1WDZx4JeO72oXnyOHjec7DN5JofkU=; b=SJ7n264nk4rI0pqCt/PDJhWTK55zo5agUaLdhWaL+h40PRzGaVG0BaH5iYsrd2+JQ9 6Mn8NDrZNGGHKs2gnzWrnZMxxfWJtg4CmwJMZaWxcsn+iLWWSzkld3W4Y7ijRauJBdRQ GrC5NcuGrzw0/V7/I80LEVbnAehA9Khk8fzc+hZfchAODLd8/IcSF2YFT+lp3umzWl5e p+TSokEhuvVHbelvmvh/kuLYG4Oy/169Ybg6RY3H3Ux/f1YIzISjtk6EDWgFatdDSvMM 5p8CzKXstdgFtViwACNp6oqV3NVntJ+VL4We7cBXlCHZ6wof7tEVmUCCzgtDjt6GkDpK 9oSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752636148; x=1753240948; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=/0fjCI0G736hAl1WDZx4JeO72oXnyOHjec7DN5JofkU=; b=aYSpm5VlzrEKxw4Jm1vNJ9+VxBswmXmkJZ+57N2bvegRBEg0mYoiJcrYUcmxiiuxuN yZEK5QzknxiY97e46xaHzxs+nXOUJg/Vl1QbSYoG/dy/F80SgtBpubcreDqJ+Ss6dC3D awdajViZHCW+EB6/MJIRUM6TvNlCBoH0roD26PyuCRgwOK3cdy0vNgD2MAAXxNPZRPil xvaKuqSX++TsshelrVlqWc6Sm+yTZcPS/fd/2zEu5CaoeVej8HR4oKn1KqcJCdHFymx7 T+r0LWDKjganz7P1MdUbdqgLd3T1xmQRsRxVn0SSaWX+1K6nHdmtOFwRdq/iKOph0WQ5 EIEA== X-Gm-Message-State: AOJu0YzIj9LamS7Y4pgpjhStbMBJl13TnSavsUBN/jUgRjQzeJeuvRJk HqVb8lYmJG7tDYDS0udCzNak67hDu4xxWJybD9zFlsGcGkZH2mLMRNtfC3JYuA1TR9GiQR4Bg8o 7EKNo4KPUtPqzY1+XacsXr55NyW5kj9AxKIfoDnzr9+m33M/CN7RHAM+okGsbDutJVE6GFtUUX+ V4R+RT9tGtR9ujOAbCk+RiNunUCE3QzEl7Jw== X-Google-Smtp-Source: AGHT+IHZsh8QXDncu61aFGu0BfFlm2IHVc/aAaVB89BaHUimD0u4dpZbcZwRvH2egJwuE4R/GKNncjW4 X-Received: from wmtf7.prod.google.com ([2002:a05:600c:8b47:b0:454:d702:f3c2]) (user=ardb job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6000:3104:b0:3b5:f6f9:e803 with SMTP id ffacd0b85a97d-3b60953aa6bmr4933891f8f.14.1752636148059; Tue, 15 Jul 2025 20:22:28 -0700 (PDT) Date: Wed, 16 Jul 2025 05:18:16 +0200 In-Reply-To: <20250716031814.2096113-24-ardb+git@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250716031814.2096113-24-ardb+git@google.com> X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 X-Developer-Signature: v=1; a=openpgp-sha256; l=7370; i=ardb@kernel.org; h=from:subject; bh=yhK4qsChfODRjxrHDoe+/mi4JoskP7s/+110xhLEhCc=; b=owGbwMvMwCVmkMcZplerG8N4Wi2JIaNcivlAs3ipz8LFTkeXzNZ+fc+j58OH/W8+Z0+2lT3g4 9ly4t2JjlIWBjEuBlkxRRaB2X/f7Tw9UarWeZYszBxWJpAhDFycAjCR0+8ZGZrPrSxi9TmreeK0 27SDDzQaL/2JFvdfY+nmry0Tcvm7tTYjw6eK+4KXjLb9dQhf5PFL8oupV96+pQ6bnCP2d3t8Xn0 snhMA X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog Message-ID: <20250716031814.2096113-25-ardb+git@google.com> Subject: [PATCH v5 01/22] x86/sev: Separate MSR and GHCB based snp_cpuid() via a callback From: Ard Biesheuvel To: linux-kernel@vger.kernel.org Cc: linux-efi@vger.kernel.org, x86@kernel.org, Ard Biesheuvel , Borislav Petkov , Ingo Molnar , Kevin Loughlin , Tom Lendacky , Josh Poimboeuf , Peter Zijlstra , Nikunj A Dadhania Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Ard Biesheuvel There are two distinct callers of snp_cpuid(): one where the MSR protocol is always used, and one where the GHCB page based interface is always used. The snp_cpuid() logic does not care about the distinction, which only matters at a lower level. But the fact that it supports both interfaces means that the GHCB page based logic is pulled into the early startup code where PA to VA conversions are problematic, given that it runs from the 1:1 mapping of memory. So keep snp_cpuid() itself in the startup code, but factor out the hypervisor calls via a callback, so that the GHCB page handling can be moved out. Code refactoring only - no functional change intended. Signed-off-by: Ard Biesheuvel Reviewed-by: Tom Lendacky --- arch/x86/boot/startup/sev-shared.c | 60 ++++---------------- arch/x86/coco/sev/vc-shared.c | 49 +++++++++++++++- arch/x86/include/asm/sev.h | 3 +- 3 files changed, 61 insertions(+), 51 deletions(-) diff --git a/arch/x86/boot/startup/sev-shared.c b/arch/x86/boot/startup/sev= -shared.c index 7a706db87b93..c401d0391537 100644 --- a/arch/x86/boot/startup/sev-shared.c +++ b/arch/x86/boot/startup/sev-shared.c @@ -342,44 +342,7 @@ static int __sev_cpuid_hv_msr(struct cpuid_leaf *leaf) return ret; } =20 -static int __sev_cpuid_hv_ghcb(struct ghcb *ghcb, struct es_em_ctxt *ctxt,= struct cpuid_leaf *leaf) -{ - u32 cr4 =3D native_read_cr4(); - int ret; - - ghcb_set_rax(ghcb, leaf->fn); - ghcb_set_rcx(ghcb, leaf->subfn); - - if (cr4 & X86_CR4_OSXSAVE) - /* Safe to read xcr0 */ - ghcb_set_xcr0(ghcb, xgetbv(XCR_XFEATURE_ENABLED_MASK)); - else - /* xgetbv will cause #UD - use reset value for xcr0 */ - ghcb_set_xcr0(ghcb, 1); - - ret =3D sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_CPUID, 0, 0); - if (ret !=3D ES_OK) - return ret; - - if (!(ghcb_rax_is_valid(ghcb) && - ghcb_rbx_is_valid(ghcb) && - ghcb_rcx_is_valid(ghcb) && - ghcb_rdx_is_valid(ghcb))) - return ES_VMM_ERROR; =20 - leaf->eax =3D ghcb->save.rax; - leaf->ebx =3D ghcb->save.rbx; - leaf->ecx =3D ghcb->save.rcx; - leaf->edx =3D ghcb->save.rdx; - - return ES_OK; -} - -static int sev_cpuid_hv(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct= cpuid_leaf *leaf) -{ - return ghcb ? __sev_cpuid_hv_ghcb(ghcb, ctxt, leaf) - : __sev_cpuid_hv_msr(leaf); -} =20 /* * This may be called early while still running on the initial identity @@ -484,21 +447,20 @@ snp_cpuid_get_validated_func(struct cpuid_leaf *leaf) return false; } =20 -static void snp_cpuid_hv(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struc= t cpuid_leaf *leaf) +static void snp_cpuid_hv_msr(void *ctx, struct cpuid_leaf *leaf) { - if (sev_cpuid_hv(ghcb, ctxt, leaf)) + if (__sev_cpuid_hv_msr(leaf)) sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_CPUID_HV); } =20 -static int __head -snp_cpuid_postprocess(struct ghcb *ghcb, struct es_em_ctxt *ctxt, - struct cpuid_leaf *leaf) +static int __head snp_cpuid_postprocess(void (*cpuid_fn)(void *ctx, struct= cpuid_leaf *), + void *ctx, struct cpuid_leaf *leaf) { struct cpuid_leaf leaf_hv =3D *leaf; =20 switch (leaf->fn) { case 0x1: - snp_cpuid_hv(ghcb, ctxt, &leaf_hv); + cpuid_fn(ctx, &leaf_hv); =20 /* initial APIC ID */ leaf->ebx =3D (leaf_hv.ebx & GENMASK(31, 24)) | (leaf->ebx & GENMASK(23,= 0)); @@ -517,7 +479,7 @@ snp_cpuid_postprocess(struct ghcb *ghcb, struct es_em_c= txt *ctxt, break; case 0xB: leaf_hv.subfn =3D 0; - snp_cpuid_hv(ghcb, ctxt, &leaf_hv); + cpuid_fn(ctx, &leaf_hv); =20 /* extended APIC ID */ leaf->edx =3D leaf_hv.edx; @@ -565,7 +527,7 @@ snp_cpuid_postprocess(struct ghcb *ghcb, struct es_em_c= txt *ctxt, } break; case 0x8000001E: - snp_cpuid_hv(ghcb, ctxt, &leaf_hv); + cpuid_fn(ctx, &leaf_hv); =20 /* extended APIC ID */ leaf->eax =3D leaf_hv.eax; @@ -586,8 +548,8 @@ snp_cpuid_postprocess(struct ghcb *ghcb, struct es_em_c= txt *ctxt, * Returns -EOPNOTSUPP if feature not enabled. Any other non-zero return v= alue * should be treated as fatal by caller. */ -int __head -snp_cpuid(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *l= eaf) +int __head snp_cpuid(void (*cpuid_fn)(void *ctx, struct cpuid_leaf *), voi= d *ctx, + struct cpuid_leaf *leaf) { const struct snp_cpuid_table *cpuid_table =3D snp_cpuid_get_table(); =20 @@ -621,7 +583,7 @@ snp_cpuid(struct ghcb *ghcb, struct es_em_ctxt *ctxt, s= truct cpuid_leaf *leaf) return 0; } =20 - return snp_cpuid_postprocess(ghcb, ctxt, leaf); + return snp_cpuid_postprocess(cpuid_fn, ctx, leaf); } =20 /* @@ -648,7 +610,7 @@ void __head do_vc_no_ghcb(struct pt_regs *regs, unsigne= d long exit_code) leaf.fn =3D fn; leaf.subfn =3D subfn; =20 - ret =3D snp_cpuid(NULL, NULL, &leaf); + ret =3D snp_cpuid(snp_cpuid_hv_msr, NULL, &leaf); if (!ret) goto cpuid_done; =20 diff --git a/arch/x86/coco/sev/vc-shared.c b/arch/x86/coco/sev/vc-shared.c index 2c0ab0fdc060..b4688f69102e 100644 --- a/arch/x86/coco/sev/vc-shared.c +++ b/arch/x86/coco/sev/vc-shared.c @@ -409,15 +409,62 @@ static enum es_result vc_handle_ioio(struct ghcb *ghc= b, struct es_em_ctxt *ctxt) return ret; } =20 +static int __sev_cpuid_hv_ghcb(struct ghcb *ghcb, struct es_em_ctxt *ctxt,= struct cpuid_leaf *leaf) +{ + u32 cr4 =3D native_read_cr4(); + int ret; + + ghcb_set_rax(ghcb, leaf->fn); + ghcb_set_rcx(ghcb, leaf->subfn); + + if (cr4 & X86_CR4_OSXSAVE) + /* Safe to read xcr0 */ + ghcb_set_xcr0(ghcb, xgetbv(XCR_XFEATURE_ENABLED_MASK)); + else + /* xgetbv will cause #UD - use reset value for xcr0 */ + ghcb_set_xcr0(ghcb, 1); + + ret =3D sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_CPUID, 0, 0); + if (ret !=3D ES_OK) + return ret; + + if (!(ghcb_rax_is_valid(ghcb) && + ghcb_rbx_is_valid(ghcb) && + ghcb_rcx_is_valid(ghcb) && + ghcb_rdx_is_valid(ghcb))) + return ES_VMM_ERROR; + + leaf->eax =3D ghcb->save.rax; + leaf->ebx =3D ghcb->save.rbx; + leaf->ecx =3D ghcb->save.rcx; + leaf->edx =3D ghcb->save.rdx; + + return ES_OK; +} + +struct cpuid_ctx { + struct ghcb *ghcb; + struct es_em_ctxt *ctxt; +}; + +static void snp_cpuid_hv_ghcb(void *p, struct cpuid_leaf *leaf) +{ + struct cpuid_ctx *ctx =3D p; + + if (__sev_cpuid_hv_ghcb(ctx->ghcb, ctx->ctxt, leaf)) + sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_CPUID_HV); +} + static int vc_handle_cpuid_snp(struct ghcb *ghcb, struct es_em_ctxt *ctxt) { + struct cpuid_ctx ctx =3D { ghcb, ctxt }; struct pt_regs *regs =3D ctxt->regs; struct cpuid_leaf leaf; int ret; =20 leaf.fn =3D regs->ax; leaf.subfn =3D regs->cx; - ret =3D snp_cpuid(ghcb, ctxt, &leaf); + ret =3D snp_cpuid(snp_cpuid_hv_ghcb, &ctx, &leaf); if (!ret) { regs->ax =3D leaf.eax; regs->bx =3D leaf.ebx; diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h index 89075ff19afa..2cabf617de3c 100644 --- a/arch/x86/include/asm/sev.h +++ b/arch/x86/include/asm/sev.h @@ -552,7 +552,8 @@ struct cpuid_leaf { u32 edx; }; =20 -int snp_cpuid(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_lea= f *leaf); +int snp_cpuid(void (*cpuid_hv)(void *ctx, struct cpuid_leaf *), + void *ctx, struct cpuid_leaf *leaf); =20 void __noreturn sev_es_terminate(unsigned int set, unsigned int reason); enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb, --=20 2.50.0.727.gbf7dc18ff4-goog