[5/9] x86/hyperv: Use vmmcall to implement Hyper-V hypercall in sev-snp enlightened guest
Message ID | 20230601151624.1757616-6-ltykernel@gmail.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp422690vqr; Thu, 1 Jun 2023 08:38:59 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ4VYXkqH9rPVxTpfrps6SPr+zgLL89IsISd1FCrI1LzpDbTCGrVTOcSVbOXJPch/yFWVN62 X-Received: by 2002:a05:6a00:99e:b0:64d:1585:fff2 with SMTP id u30-20020a056a00099e00b0064d1585fff2mr11428487pfg.29.1685633938975; Thu, 01 Jun 2023 08:38:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1685633938; cv=none; d=google.com; s=arc-20160816; b=MmGymvyx2PiQNiVNnXqUgNytzTVo3/b/M2WRmPJMwyq6sa55bGkaXU3pAjxYSBe56z /lWc3eXRCdSymf2HRhnAZUSNd9AXJzaChHSI4ezcBcsA33rFL6fFAlmAAloPifCz57Jd d4kIS19eHJrXMUsrFHRpdxrftiYxxdQ+R8xMNdD3c3f+jXpdNagRgdDvga7tWLRpJF7Z TQxTqHH3W8XjLGwtULlcqkBJIwwg2Zwb9d+0Lu9a6rszcQIZ3HDbMx5aAJt/URXaEHsM d73JDYwD9RVLZw5OpnXu0HkmcXfmawhaPQPRgMOcYDT/9Z4hpp1CaX1vAjCIocE+K281 DgEg== 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=20PfxUIBn5Kpww1WZYnKX4OwKeg7lWWjkFwlEuv9yX8=; b=DE/ZGCFZrFMH4BX74M7AOlFht29rCeXlyL8Qc/F+R96eTC9ryRRtDcQFvBMcikF2hn 3VpEwt3FmkXckgjuj9kV1qcladNGHq9irADJK3Nnwx5zeyIefgU6EC+52kfU9GDbRyw/ LxM/MuGpTjlIgh3tY5MRFM+YFlE+WUWWJiMATI4BPsNSYN3k9XbDN2tshzPRHV+GgxIe 8tLdQWUms+3FpHjYIJq1yTkIcyjv/zvSU6kOCU1B7uEXc79vn1ozCDxYRHydfF9jZ6G7 Y1MYPvsGDasQQueqU2Rmd03P/dr5IOWvZGE4vv+oSLJBEjLncZM/M2wvO8u6rM25ONSn zokw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20221208 header.b=mdMXADuP; 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=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id f127-20020a625185000000b0064d2c5f0995si3584879pfb.235.2023.06.01.08.38.44; Thu, 01 Jun 2023 08:38:58 -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=@gmail.com header.s=20221208 header.b=mdMXADuP; 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=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234764AbjFAPQz (ORCPT <rfc822;limurcpp@gmail.com> + 99 others); Thu, 1 Jun 2023 11:16:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56036 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234382AbjFAPQh (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Thu, 1 Jun 2023 11:16:37 -0400 Received: from mail-pf1-x42f.google.com (mail-pf1-x42f.google.com [IPv6:2607:f8b0:4864:20::42f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A5A4112C; Thu, 1 Jun 2023 08:16:34 -0700 (PDT) Received: by mail-pf1-x42f.google.com with SMTP id d2e1a72fcca58-64d3bc502ddso1205712b3a.0; Thu, 01 Jun 2023 08:16:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1685632594; x=1688224594; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=20PfxUIBn5Kpww1WZYnKX4OwKeg7lWWjkFwlEuv9yX8=; b=mdMXADuPKtg6pZHi4rHdubjEZsdNyUwRcdf+1/mn0YEWGux7/x1eoRpO7JZbRlCKKp njD9GKsWD31Q/nWLjFhxKkJp4kfc5QrPg3eqwWXP8KYpfrrUgsAMjjNKC1qYfZDLatty 7GKUU49SuYeZG8eopqGeb50WCft7zv0NyBWeEn5VdivKfn+rtQ3eSsdp4sHL1uWu0AaW Lp/r1pRl6DPWuzClQkpjIS0Pdj0t+sss5B622u1I+ySyuo01E6ULflRSLRrHg8AyV9cv OsA8mmm58sdp7V/eab3zC2UHQZxBGNMgui41nqLuASPHfLxpDXbggRfotv2EDtajmZPt 9dug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685632594; x=1688224594; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=20PfxUIBn5Kpww1WZYnKX4OwKeg7lWWjkFwlEuv9yX8=; b=ZyYhsPNFxcob3j/4uv+nJ8woCFuEV+6KVORjL/O2CsLAGv1MNAa2wB5iDGpnh50Fdx SqTDuErSELRbYzVB+djGtKprEPHzZXTdRFxcJJQjt9kHs9OdFQzcWaOm4NYel/D7AM5r MXv4HvdMrFG/VFlYMdyVRNhiCv0htc+xLI8C7hDTThWqrwpOOTb9qngn5NMBaXKFIYL2 3ZEPI09WwG/5PT5rEUy01AYJBndK+bL4S5TGaahbAV0kGJvVvXsp93bEz1v5f3ELFnVM wJ28lIuT3M4d5fJNvPico0abB+0xG/kKvJLXRnbNHpMmNJy2DmxDktPUOaZPqFqfhFcJ V4bw== X-Gm-Message-State: AC+VfDwASh+o1vhICiWJkhUBSsCZguGQLSKF7uVQej9x+rkFRwvzhPcI Ku/ix5Xz5eaXg8yELmmj18Q= X-Received: by 2002:a05:6a20:3d85:b0:100:60f3:2975 with SMTP id s5-20020a056a203d8500b0010060f32975mr11694279pzi.4.1685632594074; Thu, 01 Jun 2023 08:16:34 -0700 (PDT) Received: from ubuntu-Virtual-Machine.corp.microsoft.com ([2001:4898:80e8:9:e0c3:5ec1:4a35:2168]) by smtp.gmail.com with ESMTPSA id f3-20020a635543000000b0051b460fd90fsm3282639pgm.8.2023.06.01.08.16.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Jun 2023 08:16:33 -0700 (PDT) From: Tianyu Lan <ltykernel@gmail.com> To: kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org, decui@microsoft.com, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, daniel.lezcano@linaro.org, arnd@arndb.de, michael.h.kelley@microsoft.com Cc: Tianyu Lan <tiala@microsoft.com>, linux-arch@vger.kernel.org, linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org, vkuznets@redhat.com Subject: [PATCH 5/9] x86/hyperv: Use vmmcall to implement Hyper-V hypercall in sev-snp enlightened guest Date: Thu, 1 Jun 2023 11:16:18 -0400 Message-Id: <20230601151624.1757616-6-ltykernel@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230601151624.1757616-1-ltykernel@gmail.com> References: <20230601151624.1757616-1-ltykernel@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE 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: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1767515293544363911?= X-GMAIL-MSGID: =?utf-8?q?1767515293544363911?= |
Series |
x86/hyperv: Add AMD sev-snp enlightened guest support on hyperv
|
|
Commit Message
Tianyu Lan
June 1, 2023, 3:16 p.m. UTC
From: Tianyu Lan <tiala@microsoft.com> In sev-snp enlightened guest, Hyper-V hypercall needs to use vmmcall to trigger vmexit and notify hypervisor to handle hypercall request. There is no x86 SEV SNP feature flag support so far and hardware provides MSR_AMD64_SEV register to check SEV-SNP capability with MSR_AMD64_SEV_ENABLED bit. ALTERNATIVE can't work without SEV-SNP x86 feature flag. May add later when the associated flag is introduced. Signed-off-by: Tianyu Lan <tiala@microsoft.com> --- arch/x86/include/asm/mshyperv.h | 44 ++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 11 deletions(-)
Comments
Tianyu Lan <ltykernel@gmail.com> writes: > From: Tianyu Lan <tiala@microsoft.com> > > In sev-snp enlightened guest, Hyper-V hypercall needs > to use vmmcall to trigger vmexit and notify hypervisor > to handle hypercall request. > > There is no x86 SEV SNP feature flag support so far and > hardware provides MSR_AMD64_SEV register to check SEV-SNP > capability with MSR_AMD64_SEV_ENABLED bit. ALTERNATIVE can't > work without SEV-SNP x86 feature flag. May add later when > the associated flag is introduced. > > Signed-off-by: Tianyu Lan <tiala@microsoft.com> > --- > arch/x86/include/asm/mshyperv.h | 44 ++++++++++++++++++++++++--------- > 1 file changed, 33 insertions(+), 11 deletions(-) > > diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h > index 31c476f4e656..d859d7c5f5e8 100644 > --- a/arch/x86/include/asm/mshyperv.h > +++ b/arch/x86/include/asm/mshyperv.h > @@ -61,16 +61,25 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output) > u64 hv_status; > > #ifdef CONFIG_X86_64 > - if (!hv_hypercall_pg) > - return U64_MAX; > + if (hv_isolation_type_en_snp()) { Would it be possible to redo 'hv_isolation_type_en_snp()' into a static inline doing static_branch_unlikely() so we avoid function call penalty here? > + __asm__ __volatile__("mov %4, %%r8\n" > + "vmmcall" > + : "=a" (hv_status), ASM_CALL_CONSTRAINT, > + "+c" (control), "+d" (input_address) > + : "r" (output_address) > + : "cc", "memory", "r8", "r9", "r10", "r11"); > + } else { > + if (!hv_hypercall_pg) > + return U64_MAX; > > - __asm__ __volatile__("mov %4, %%r8\n" > - CALL_NOSPEC > - : "=a" (hv_status), ASM_CALL_CONSTRAINT, > - "+c" (control), "+d" (input_address) > - : "r" (output_address), > - THUNK_TARGET(hv_hypercall_pg) > - : "cc", "memory", "r8", "r9", "r10", "r11"); > + __asm__ __volatile__("mov %4, %%r8\n" > + CALL_NOSPEC > + : "=a" (hv_status), ASM_CALL_CONSTRAINT, > + "+c" (control), "+d" (input_address) > + : "r" (output_address), > + THUNK_TARGET(hv_hypercall_pg) > + : "cc", "memory", "r8", "r9", "r10", "r11"); > + } > #else > u32 input_address_hi = upper_32_bits(input_address); > u32 input_address_lo = lower_32_bits(input_address); > @@ -104,7 +113,13 @@ static inline u64 _hv_do_fast_hypercall8(u64 control, u64 input1) > u64 hv_status; > > #ifdef CONFIG_X86_64 > - { > + if (hv_isolation_type_en_snp()) { > + __asm__ __volatile__( > + "vmmcall" > + : "=a" (hv_status), ASM_CALL_CONSTRAINT, > + "+c" (control), "+d" (input1) > + :: "cc", "r8", "r9", "r10", "r11"); > + } else { > __asm__ __volatile__(CALL_NOSPEC > : "=a" (hv_status), ASM_CALL_CONSTRAINT, > "+c" (control), "+d" (input1) > @@ -149,7 +164,14 @@ static inline u64 _hv_do_fast_hypercall16(u64 control, u64 input1, u64 input2) > u64 hv_status; > > #ifdef CONFIG_X86_64 > - { > + if (hv_isolation_type_en_snp()) { > + __asm__ __volatile__("mov %4, %%r8\n" > + "vmmcall" > + : "=a" (hv_status), ASM_CALL_CONSTRAINT, > + "+c" (control), "+d" (input1) > + : "r" (input2) > + : "cc", "r8", "r9", "r10", "r11"); > + } else { > __asm__ __volatile__("mov %4, %%r8\n" > CALL_NOSPEC > : "=a" (hv_status), ASM_CALL_CONSTRAINT,
On Thu, Jun 01, 2023 at 11:16:18AM -0400, Tianyu Lan wrote: > From: Tianyu Lan <tiala@microsoft.com> > > In sev-snp enlightened guest, Hyper-V hypercall needs > to use vmmcall to trigger vmexit and notify hypervisor > to handle hypercall request. > > There is no x86 SEV SNP feature flag support so far and > hardware provides MSR_AMD64_SEV register to check SEV-SNP > capability with MSR_AMD64_SEV_ENABLED bit. ALTERNATIVE can't > work without SEV-SNP x86 feature flag. May add later when > the associated flag is introduced. > > Signed-off-by: Tianyu Lan <tiala@microsoft.com> > --- > arch/x86/include/asm/mshyperv.h | 44 ++++++++++++++++++++++++--------- > 1 file changed, 33 insertions(+), 11 deletions(-) > > diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h > index 31c476f4e656..d859d7c5f5e8 100644 > --- a/arch/x86/include/asm/mshyperv.h > +++ b/arch/x86/include/asm/mshyperv.h > @@ -61,16 +61,25 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output) > u64 hv_status; > > #ifdef CONFIG_X86_64 > - if (!hv_hypercall_pg) > - return U64_MAX; > + if (hv_isolation_type_en_snp()) { > + __asm__ __volatile__("mov %4, %%r8\n" > + "vmmcall" > + : "=a" (hv_status), ASM_CALL_CONSTRAINT, > + "+c" (control), "+d" (input_address) > + : "r" (output_address) > + : "cc", "memory", "r8", "r9", "r10", "r11"); > + } else { > + if (!hv_hypercall_pg) > + return U64_MAX; > > - __asm__ __volatile__("mov %4, %%r8\n" > - CALL_NOSPEC > - : "=a" (hv_status), ASM_CALL_CONSTRAINT, > - "+c" (control), "+d" (input_address) > - : "r" (output_address), > - THUNK_TARGET(hv_hypercall_pg) > - : "cc", "memory", "r8", "r9", "r10", "r11"); > + __asm__ __volatile__("mov %4, %%r8\n" > + CALL_NOSPEC > + : "=a" (hv_status), ASM_CALL_CONSTRAINT, > + "+c" (control), "+d" (input_address) > + : "r" (output_address), > + THUNK_TARGET(hv_hypercall_pg) > + : "cc", "memory", "r8", "r9", "r10", "r11"); > + } > #else Remains unanswered: https://lkml.kernel.org/r/20230516102912.GG2587705%40hirez.programming.kicks-ass.net Would this not generate better code with an alternative?
On 6/8/2023 9:21 PM, Peter Zijlstra wrote: > On Thu, Jun 01, 2023 at 11:16:18AM -0400, Tianyu Lan wrote: >> From: Tianyu Lan <tiala@microsoft.com> >> >> In sev-snp enlightened guest, Hyper-V hypercall needs >> to use vmmcall to trigger vmexit and notify hypervisor >> to handle hypercall request. >> >> There is no x86 SEV SNP feature flag support so far and >> hardware provides MSR_AMD64_SEV register to check SEV-SNP >> capability with MSR_AMD64_SEV_ENABLED bit. ALTERNATIVE can't >> work without SEV-SNP x86 feature flag. May add later when >> the associated flag is introduced. >> >> Signed-off-by: Tianyu Lan <tiala@microsoft.com> >> --- >> arch/x86/include/asm/mshyperv.h | 44 ++++++++++++++++++++++++--------- >> 1 file changed, 33 insertions(+), 11 deletions(-) >> >> diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h >> index 31c476f4e656..d859d7c5f5e8 100644 >> --- a/arch/x86/include/asm/mshyperv.h >> +++ b/arch/x86/include/asm/mshyperv.h >> @@ -61,16 +61,25 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output) >> u64 hv_status; >> >> #ifdef CONFIG_X86_64 >> - if (!hv_hypercall_pg) >> - return U64_MAX; >> + if (hv_isolation_type_en_snp()) { >> + __asm__ __volatile__("mov %4, %%r8\n" >> + "vmmcall" >> + : "=a" (hv_status), ASM_CALL_CONSTRAINT, >> + "+c" (control), "+d" (input_address) >> + : "r" (output_address) >> + : "cc", "memory", "r8", "r9", "r10", "r11"); >> + } else { >> + if (!hv_hypercall_pg) >> + return U64_MAX; >> >> - __asm__ __volatile__("mov %4, %%r8\n" >> - CALL_NOSPEC >> - : "=a" (hv_status), ASM_CALL_CONSTRAINT, >> - "+c" (control), "+d" (input_address) >> - : "r" (output_address), >> - THUNK_TARGET(hv_hypercall_pg) >> - : "cc", "memory", "r8", "r9", "r10", "r11"); >> + __asm__ __volatile__("mov %4, %%r8\n" >> + CALL_NOSPEC >> + : "=a" (hv_status), ASM_CALL_CONSTRAINT, >> + "+c" (control), "+d" (input_address) >> + : "r" (output_address), >> + THUNK_TARGET(hv_hypercall_pg) >> + : "cc", "memory", "r8", "r9", "r10", "r11"); >> + } >> #else > > Remains unanswered: > > https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.kernel.org%2Fr%2F20230516102912.GG2587705%2540hirez.programming.kicks-ass.net&data=05%7C01%7CTianyu.Lan%40microsoft.com%7C60a576eb67634ffa27b108db68234d5a%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C638218273105649705%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=MFj67DON0K%2BUoUJbeaIA5oVTxyrzO3fb5DbxYgDWwX0%3D&reserved=0 > > Would this not generate better code with an alternative? Hi Peter: Thanks to review. I put the explaination in the change log. "There is no x86 SEV SNP feature(X86_FEATURE_SEV_SNP) flag support so far and hardware provides MSR_AMD64_SEV register to check SEV-SNP capability with MSR_AMD64_SEV_ENABLED bit ALTERNATIVE can't work without SEV-SNP x86 feature flag." There is no cpuid leaf bit to check AMD SEV-SNP feature. After some Hyper-V doesn't provides SEV and SEV-ES guest before and so may reuse X86_FEATURE_SEV and X86_FEATURE_SEV_ES flag as alternative feature check for Hyper-V SEV-SNP guest. Will refresh patch.
On 6/8/2023 11:15 PM, Tianyu Lan wrote: > On 6/8/2023 9:21 PM, Peter Zijlstra wrote: >> On Thu, Jun 01, 2023 at 11:16:18AM -0400, Tianyu Lan wrote: >>> From: Tianyu Lan <tiala@microsoft.com> >>> >>> In sev-snp enlightened guest, Hyper-V hypercall needs >>> to use vmmcall to trigger vmexit and notify hypervisor >>> to handle hypercall request. >>> >>> There is no x86 SEV SNP feature flag support so far and >>> hardware provides MSR_AMD64_SEV register to check SEV-SNP >>> capability with MSR_AMD64_SEV_ENABLED bit. ALTERNATIVE can't >>> work without SEV-SNP x86 feature flag. May add later when >>> the associated flag is introduced. >>> >>> Signed-off-by: Tianyu Lan <tiala@microsoft.com> >>> --- >>> arch/x86/include/asm/mshyperv.h | 44 ++++++++++++++++++++++++--------- >>> 1 file changed, 33 insertions(+), 11 deletions(-) >>> >>> diff --git a/arch/x86/include/asm/mshyperv.h >>> b/arch/x86/include/asm/mshyperv.h >>> index 31c476f4e656..d859d7c5f5e8 100644 >>> --- a/arch/x86/include/asm/mshyperv.h >>> +++ b/arch/x86/include/asm/mshyperv.h >>> @@ -61,16 +61,25 @@ static inline u64 hv_do_hypercall(u64 control, >>> void *input, void *output) >>> u64 hv_status; >>> #ifdef CONFIG_X86_64 >>> - if (!hv_hypercall_pg) >>> - return U64_MAX; >>> + if (hv_isolation_type_en_snp()) { >>> + __asm__ __volatile__("mov %4, %%r8\n" >>> + "vmmcall" >>> + : "=a" (hv_status), ASM_CALL_CONSTRAINT, >>> + "+c" (control), "+d" (input_address) >>> + : "r" (output_address) >>> + : "cc", "memory", "r8", "r9", "r10", "r11"); >>> + } else { >>> + if (!hv_hypercall_pg) >>> + return U64_MAX; >>> - __asm__ __volatile__("mov %4, %%r8\n" >>> - CALL_NOSPEC >>> - : "=a" (hv_status), ASM_CALL_CONSTRAINT, >>> - "+c" (control), "+d" (input_address) >>> - : "r" (output_address), >>> - THUNK_TARGET(hv_hypercall_pg) >>> - : "cc", "memory", "r8", "r9", "r10", "r11"); >>> + __asm__ __volatile__("mov %4, %%r8\n" >>> + CALL_NOSPEC >>> + : "=a" (hv_status), ASM_CALL_CONSTRAINT, >>> + "+c" (control), "+d" (input_address) >>> + : "r" (output_address), >>> + THUNK_TARGET(hv_hypercall_pg) >>> + : "cc", "memory", "r8", "r9", "r10", "r11"); >>> + } >>> #else >> >> Remains unanswered: >> >> https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.kernel.org%2Fr%2F20230516102912.GG2587705%2540hirez.programming.kicks-ass.net&data=05%7C01%7CTianyu.Lan%40microsoft.com%7C60a576eb67634ffa27b108db68234d5a%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C638218273105649705%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=MFj67DON0K%2BUoUJbeaIA5oVTxyrzO3fb5DbxYgDWwX0%3D&reserved=0 >> >> Would this not generate better code with an alternative? > > > Hi Peter: > Thanks to review. I put the explaination in the change log. > > "There is no x86 SEV SNP feature(X86_FEATURE_SEV_SNP) flag > support so far and hardware provides MSR_AMD64_SEV register > to check SEV-SNP capability with MSR_AMD64_SEV_ENABLED bit > ALTERNATIVE can't work without SEV-SNP x86 feature flag." > There is no cpuid leaf bit to check AMD SEV-SNP feature. > > After some Hyper-V doesn't provides SEV and SEV-ES guest before and so > may reuse X86_FEATURE_SEV and X86_FEATURE_SEV_ES flag as alternative > feature check for Hyper-V SEV-SNP guest. Will refresh patch. > Hi Peter: I tried using alternative for "vmmcall" and CALL_NOSPEC in a single Inline assembly. The output is different in the SEV-SNP mode. When SEV- SNP is enabled, thunk_target is not required. While it's necessary in the non SEV-SNP mode. Do you have any idea how to differentiate outputs in the single Inline assembly which just like alternative works for assembler template.
On Tue, Jun 27, 2023 at 06:57:28PM +0800, Tianyu Lan wrote: > > "There is no x86 SEV SNP feature(X86_FEATURE_SEV_SNP) flag I'm sure we can arrange such a feature if we need it, this isn't rocket science. Boris? > > support so far and hardware provides MSR_AMD64_SEV register > > to check SEV-SNP capability with MSR_AMD64_SEV_ENABLED bit > > ALTERNATIVE can't work without SEV-SNP x86 feature flag." > > There is no cpuid leaf bit to check AMD SEV-SNP feature. > > > > After some Hyper-V doesn't provides SEV and SEV-ES guest before and so > > may reuse X86_FEATURE_SEV and X86_FEATURE_SEV_ES flag as alternative > > feature check for Hyper-V SEV-SNP guest. Will refresh patch. > > > > Hi Peter: > I tried using alternative for "vmmcall" and CALL_NOSPEC in a single > Inline assembly. The output is different in the SEV-SNP mode. When SEV- > SNP is enabled, thunk_target is not required. While it's necessary in > the non SEV-SNP mode. Do you have any idea how to differentiate outputs in > the single Inline assembly which just like alternative works for > assembler template. This seems to work; it's a bit magical for having a nested ALTERNATIVE but the output seems correct (the outer alternative comes last in .altinstructions and thus has precedence). Sure the [thunk_target] input goes unsed in one of the alteratives, but who cares. static inline u64 hv_do_hypercall(u64 control, void *input, void *output) { u64 input_address = input ? virt_to_phys(input) : 0; u64 output_address = output ? virt_to_phys(output) : 0; u64 hv_status; #ifdef CONFIG_X86_64 if (!hv_hypercall_pg) return U64_MAX; #if 0 if (hv_isolation_type_en_snp()) { __asm__ __volatile__("mov %4, %%r8\n" "vmmcall" : "=a" (hv_status), ASM_CALL_CONSTRAINT, "+c" (control), "+d" (input_address) : "r" (output_address) : "cc", "memory", "r8", "r9", "r10", "r11"); } else { __asm__ __volatile__("mov %4, %%r8\n" CALL_NOSPEC : "=a" (hv_status), ASM_CALL_CONSTRAINT, "+c" (control), "+d" (input_address) : "r" (output_address), THUNK_TARGET(hv_hypercall_pg) : "cc", "memory", "r8", "r9", "r10", "r11"); } #endif asm volatile("mov %[output], %%r8\n" ALTERNATIVE(CALL_NOSPEC, "vmmcall", X86_FEATURE_SEV_ES) : "=a" (hv_status), ASM_CALL_CONSTRAINT, "+c" (control), "+d" (input_address) : [output] "r" (output_address), THUNK_TARGET(hv_hypercall_pg) : "cc", "memory", "r8", "r9", "r10", "r11"); #else u32 input_address_hi = upper_32_bits(input_address); u32 input_address_lo = lower_32_bits(input_address); u32 output_address_hi = upper_32_bits(output_address); u32 output_address_lo = lower_32_bits(output_address); if (!hv_hypercall_pg) return U64_MAX; __asm__ __volatile__(CALL_NOSPEC : "=A" (hv_status), "+c" (input_address_lo), ASM_CALL_CONSTRAINT : "A" (control), "b" (input_address_hi), "D"(output_address_hi), "S"(output_address_lo), THUNK_TARGET(hv_hypercall_pg) : "cc", "memory"); #endif /* !x86_64 */ return hv_status; } (in actual fact x86_64-defconfig + kvm_guest.config + HYPERV) $ ./scripts/objdump-func defconfig-build/arch/x86/hyperv/mmu.o hv_do_hypercall 0000 0000000000000cd0 <hv_do_hypercall.constprop.0>: 0000 cd0: 48 89 f9 mov %rdi,%rcx 0003 cd3: 31 d2 xor %edx,%edx 0005 cd5: 48 85 f6 test %rsi,%rsi 0008 cd8: 74 1b je cf5 <hv_do_hypercall.constprop.0+0x25> 000a cda: b8 00 00 00 80 mov $0x80000000,%eax 000f cdf: 48 01 c6 add %rax,%rsi 0012 ce2: 72 38 jb d1c <hv_do_hypercall.constprop.0+0x4c> 0014 ce4: 48 c7 c2 00 00 00 80 mov $0xffffffff80000000,%rdx 001b ceb: 48 2b 15 00 00 00 00 sub 0x0(%rip),%rdx # cf2 <hv_do_hypercall.constprop.0+0x22> cee: R_X86_64_PC32 page_offset_base-0x4 0022 cf2: 48 01 f2 add %rsi,%rdx 0025 cf5: 48 8b 35 00 00 00 00 mov 0x0(%rip),%rsi # cfc <hv_do_hypercall.constprop.0+0x2c> cf8: R_X86_64_PC32 hv_hypercall_pg-0x4 002c cfc: 48 85 f6 test %rsi,%rsi 002f cff: 74 0f je d10 <hv_do_hypercall.constprop.0+0x40> 0031 d01: 31 c0 xor %eax,%eax 0033 d03: 49 89 c0 mov %rax,%r8 0036 d06: ff d6 call *%rsi 0038 d08: 90 nop 0039 d09: 90 nop 003a d0a: 90 nop 003b d0b: e9 00 00 00 00 jmp d10 <hv_do_hypercall.constprop.0+0x40> d0c: R_X86_64_PLT32 __x86_return_thunk-0x4 0040 d10: 48 c7 c0 ff ff ff ff mov $0xffffffffffffffff,%rax 0047 d17: e9 00 00 00 00 jmp d1c <hv_do_hypercall.constprop.0+0x4c> d18: R_X86_64_PLT32 __x86_return_thunk-0x4 004c d1c: 48 8b 15 00 00 00 00 mov 0x0(%rip),%rdx # d23 <hv_do_hypercall.constprop.0+0x53> d1f: R_X86_64_PC32 phys_base-0x4 0053 d23: eb cd jmp cf2 <hv_do_hypercall.constprop.0+0x22> $ objdump -wdr -j .altinstr_replacement defconfig-build/arch/x86/hyperv/mmu.o 0000000000000000 <.altinstr_replacement>: 0: f3 48 0f b8 c7 popcnt %rdi,%rax 5: e8 00 00 00 00 call a <.altinstr_replacement+0xa> 6: R_X86_64_PLT32 __x86_indirect_thunk_rsi-0x4 a: 0f ae e8 lfence d: ff d6 call *%rsi f: 0f 01 d9 vmmcall $ ./readelf-section.sh defconfig-build/arch/x86/hyperv/mmu.o altinstructions Relocation section '.rela.altinstructions' at offset 0x5420 contains 8 entries: Offset Info Type Symbol's Value Symbol's Name + Addend 0000000000000000 0000000200000002 R_X86_64_PC32 0000000000000000 .text + 1e3 0000000000000004 0000000700000002 R_X86_64_PC32 0000000000000000 .altinstr_replacement + 0 000000000000000e 0000000200000002 R_X86_64_PC32 0000000000000000 .text + d06 0000000000000012 0000000700000002 R_X86_64_PC32 0000000000000000 .altinstr_replacement + 5 000000000000001c 0000000200000002 R_X86_64_PC32 0000000000000000 .text + d06 0000000000000020 0000000700000002 R_X86_64_PC32 0000000000000000 .altinstr_replacement + a 000000000000002a 0000000200000002 R_X86_64_PC32 0000000000000000 .text + d06 000000000000002e 0000000700000002 R_X86_64_PC32 0000000000000000 .altinstr_replacement + f
On Tue, Jun 27, 2023 at 01:50:02PM +0200, Peter Zijlstra wrote: > On Tue, Jun 27, 2023 at 06:57:28PM +0800, Tianyu Lan wrote: > > > > "There is no x86 SEV SNP feature(X86_FEATURE_SEV_SNP) flag > > I'm sure we can arrange such a feature if we need it, this isn't rocket > science. Boris? https://lore.kernel.org/r/20230612042559.375660-7-michael.roth@amd.com > This seems to work; it's a bit magical for having a nested ALTERNATIVE > but the output seems correct (the outer alternative comes last in > .altinstructions and thus has precedence). Sure the [thunk_target] input > goes unsed in one of the alteratives, but who cares. I'd like to avoid the nested alternative if not really necessary. I.e., a static_call should work here too no?
On Tue, Jun 27, 2023 at 02:05:02PM +0200, Borislav Petkov wrote: > On Tue, Jun 27, 2023 at 01:50:02PM +0200, Peter Zijlstra wrote: > > On Tue, Jun 27, 2023 at 06:57:28PM +0800, Tianyu Lan wrote: > > > > > > "There is no x86 SEV SNP feature(X86_FEATURE_SEV_SNP) flag > > > > I'm sure we can arrange such a feature if we need it, this isn't rocket > > science. Boris? > > https://lore.kernel.org/r/20230612042559.375660-7-michael.roth@amd.com > > > This seems to work; it's a bit magical for having a nested ALTERNATIVE > > but the output seems correct (the outer alternative comes last in > > .altinstructions and thus has precedence). Sure the [thunk_target] input > > goes unsed in one of the alteratives, but who cares. > > I'd like to avoid the nested alternative if not really necessary. I.e., I really don't see the problem with them; they work as expected. We rely on .altinstruction order elsewhere as well. That said; there is a tiny difference between: ALTERNATIVE_2(oldinst, newinst1, flag1, newinst2, flag2) and ALTERNATIVE(ALTERNATIVE(oldinst, newinst1, flag1), newinst2, flag2) and that is alt_instr::instrlen, when the inner alternative is the smaller, then the outer alternative will add additional padding that the inner (obviously) doesn't know about. However that is easily fixed. See the patch below. Boots for x86_64-defconfig. Look at how much gunk we can delete. > a static_call should work here too no? static_call() looses the inline, but perhaps the function is too large to get inlined anyway. --- Subject: x86/alternative: Simply ALTERNATIVE_n() Instead of making increasingly complicated ALTERNATIVE_n() implementations, use a nested alternative expressions. The only difference between: ALTERNATIVE_2(oldinst, newinst1, flag1, newinst2, flag2) and ALTERNATIVE(ALTERNATIVE(oldinst, newinst1, flag1), newinst2, flag2) is that the outer alternative can add additional padding when the inner alternative is the shorter one, which results in alt_instr::instrlen being inconsistent. However, this is easily remedied since the alt_instr entries will be consecutive and it is trivial to compute the max(alt_instr::instrlen) at runtime while patching. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> --- arch/x86/include/asm/alternative.h | 60 +++++--------------------------------- arch/x86/kernel/alternative.c | 7 ++++- 2 files changed, 13 insertions(+), 54 deletions(-) diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index d7da28fada87..16a98dd42ce0 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -171,36 +171,6 @@ static inline int alternatives_text_reserved(void *start, void *end) "((" alt_rlen(num) ")-(" alt_slen ")),0x90\n" \ alt_end_marker ":\n" -/* - * gas compatible max based on the idea from: - * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax - * - * The additional "-" is needed because gas uses a "true" value of -1. - */ -#define alt_max_short(a, b) "((" a ") ^ (((" a ") ^ (" b ")) & -(-((" a ") < (" b ")))))" - -/* - * Pad the second replacement alternative with additional NOPs if it is - * additionally longer than the first replacement alternative. - */ -#define OLDINSTR_2(oldinstr, num1, num2) \ - "# ALT: oldinstr2\n" \ - "661:\n\t" oldinstr "\n662:\n" \ - "# ALT: padding2\n" \ - ".skip -((" alt_max_short(alt_rlen(num1), alt_rlen(num2)) " - (" alt_slen ")) > 0) * " \ - "(" alt_max_short(alt_rlen(num1), alt_rlen(num2)) " - (" alt_slen ")), 0x90\n" \ - alt_end_marker ":\n" - -#define OLDINSTR_3(oldinsn, n1, n2, n3) \ - "# ALT: oldinstr3\n" \ - "661:\n\t" oldinsn "\n662:\n" \ - "# ALT: padding3\n" \ - ".skip -((" alt_max_short(alt_max_short(alt_rlen(n1), alt_rlen(n2)), alt_rlen(n3)) \ - " - (" alt_slen ")) > 0) * " \ - "(" alt_max_short(alt_max_short(alt_rlen(n1), alt_rlen(n2)), alt_rlen(n3)) \ - " - (" alt_slen ")), 0x90\n" \ - alt_end_marker ":\n" - #define ALTINSTR_ENTRY(ft_flags, num) \ " .long 661b - .\n" /* label */ \ " .long " b_replacement(num)"f - .\n" /* new instruction */ \ @@ -222,35 +192,19 @@ static inline int alternatives_text_reserved(void *start, void *end) ALTINSTR_REPLACEMENT(newinstr, 1) \ ".popsection\n" -#define ALTERNATIVE_2(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2) \ - OLDINSTR_2(oldinstr, 1, 2) \ - ".pushsection .altinstructions,\"a\"\n" \ - ALTINSTR_ENTRY(ft_flags1, 1) \ - ALTINSTR_ENTRY(ft_flags2, 2) \ - ".popsection\n" \ - ".pushsection .altinstr_replacement, \"ax\"\n" \ - ALTINSTR_REPLACEMENT(newinstr1, 1) \ - ALTINSTR_REPLACEMENT(newinstr2, 2) \ - ".popsection\n" +#define ALTERNATIVE_2(oldinst, newinst1, flag1, newinst2, flag2) \ + ALTERNATIVE(ALTERNATIVE(oldinst, newinst1, flag1), \ + newinst2, flag2) /* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */ #define ALTERNATIVE_TERNARY(oldinstr, ft_flags, newinstr_yes, newinstr_no) \ ALTERNATIVE_2(oldinstr, newinstr_no, X86_FEATURE_ALWAYS, \ newinstr_yes, ft_flags) -#define ALTERNATIVE_3(oldinsn, newinsn1, ft_flags1, newinsn2, ft_flags2, \ - newinsn3, ft_flags3) \ - OLDINSTR_3(oldinsn, 1, 2, 3) \ - ".pushsection .altinstructions,\"a\"\n" \ - ALTINSTR_ENTRY(ft_flags1, 1) \ - ALTINSTR_ENTRY(ft_flags2, 2) \ - ALTINSTR_ENTRY(ft_flags3, 3) \ - ".popsection\n" \ - ".pushsection .altinstr_replacement, \"ax\"\n" \ - ALTINSTR_REPLACEMENT(newinsn1, 1) \ - ALTINSTR_REPLACEMENT(newinsn2, 2) \ - ALTINSTR_REPLACEMENT(newinsn3, 3) \ - ".popsection\n" +#define ALTERNATIVE_3(oldinst, newinst1, flag1, newinst2, flag2, \ + newinst3, flag3) \ + ALTERNATIVE(ALTERNATIVE_2(oldinst, newinst1, flag1, newinst2, flag2), \ + newinst3, flag3) /* * Alternative instructions for different CPU types or capabilities. diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index a7e1ec50ad29..f0e34e6f01d4 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -398,7 +398,7 @@ apply_relocation(u8 *buf, size_t len, u8 *dest, u8 *src, size_t src_len) void __init_or_module noinline apply_alternatives(struct alt_instr *start, struct alt_instr *end) { - struct alt_instr *a; + struct alt_instr *a, *b; u8 *instr, *replacement; u8 insn_buff[MAX_PATCH_LEN]; @@ -415,6 +415,11 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start, for (a = start; a < end; a++) { int insn_buff_sz = 0; + for (b = a+1; b < end && b->instr_offset == a->instr_offset; b++) { + u8 len = max(a->instrlen, b->instrlen); + a->instrlen = b->instrlen = len; + } + instr = (u8 *)&a->instr_offset + a->instr_offset; replacement = (u8 *)&a->repl_offset + a->repl_offset; BUG_ON(a->instrlen > sizeof(insn_buff));
On Tue, Jun 27, 2023 at 03:38:35PM +0200, Peter Zijlstra wrote: > That said; there is a tiny difference between: > > ALTERNATIVE_2(oldinst, newinst1, flag1, newinst2, flag2) > > and > > ALTERNATIVE(ALTERNATIVE(oldinst, newinst1, flag1), > newinst2, flag2) > > and that is alt_instr::instrlen, when the inner alternative is the > smaller, then the outer alternative will add additional padding that the > inner (obviously) doesn't know about. New version: https://lkml.kernel.org/r/20230628104952.GA2439977%40hirez.programming.kicks-ass.net
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 31c476f4e656..d859d7c5f5e8 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -61,16 +61,25 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output) u64 hv_status; #ifdef CONFIG_X86_64 - if (!hv_hypercall_pg) - return U64_MAX; + if (hv_isolation_type_en_snp()) { + __asm__ __volatile__("mov %4, %%r8\n" + "vmmcall" + : "=a" (hv_status), ASM_CALL_CONSTRAINT, + "+c" (control), "+d" (input_address) + : "r" (output_address) + : "cc", "memory", "r8", "r9", "r10", "r11"); + } else { + if (!hv_hypercall_pg) + return U64_MAX; - __asm__ __volatile__("mov %4, %%r8\n" - CALL_NOSPEC - : "=a" (hv_status), ASM_CALL_CONSTRAINT, - "+c" (control), "+d" (input_address) - : "r" (output_address), - THUNK_TARGET(hv_hypercall_pg) - : "cc", "memory", "r8", "r9", "r10", "r11"); + __asm__ __volatile__("mov %4, %%r8\n" + CALL_NOSPEC + : "=a" (hv_status), ASM_CALL_CONSTRAINT, + "+c" (control), "+d" (input_address) + : "r" (output_address), + THUNK_TARGET(hv_hypercall_pg) + : "cc", "memory", "r8", "r9", "r10", "r11"); + } #else u32 input_address_hi = upper_32_bits(input_address); u32 input_address_lo = lower_32_bits(input_address); @@ -104,7 +113,13 @@ static inline u64 _hv_do_fast_hypercall8(u64 control, u64 input1) u64 hv_status; #ifdef CONFIG_X86_64 - { + if (hv_isolation_type_en_snp()) { + __asm__ __volatile__( + "vmmcall" + : "=a" (hv_status), ASM_CALL_CONSTRAINT, + "+c" (control), "+d" (input1) + :: "cc", "r8", "r9", "r10", "r11"); + } else { __asm__ __volatile__(CALL_NOSPEC : "=a" (hv_status), ASM_CALL_CONSTRAINT, "+c" (control), "+d" (input1) @@ -149,7 +164,14 @@ static inline u64 _hv_do_fast_hypercall16(u64 control, u64 input1, u64 input2) u64 hv_status; #ifdef CONFIG_X86_64 - { + if (hv_isolation_type_en_snp()) { + __asm__ __volatile__("mov %4, %%r8\n" + "vmmcall" + : "=a" (hv_status), ASM_CALL_CONSTRAINT, + "+c" (control), "+d" (input1) + : "r" (input2) + : "cc", "r8", "r9", "r10", "r11"); + } else { __asm__ __volatile__("mov %4, %%r8\n" CALL_NOSPEC : "=a" (hv_status), ASM_CALL_CONSTRAINT,