From: Sean Christopherson <seanjc@google.com>
To: Peter Zijlstra <peterz@infradead.org>
Cc: "H. Peter Anvin" <hpa@zytor.com>,
x86@kernel.org, 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,
pbonzini@redhat.com, ardb@kernel.org, kees@kernel.org,
Arnd Bergmann <arnd@arndb.de>,
gregkh@linuxfoundation.org, jpoimboe@kernel.org,
linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org,
kvm@vger.kernel.org, linux-efi@vger.kernel.org,
samitolvanen@google.com, ojeda@kernel.org, xin@zytor.com
Subject: Re: [PATCH v2 00/13] objtool: Detect and warn about indirect calls in __nocfi functions
Date: Fri, 2 May 2025 12:53:36 -0700 [thread overview]
Message-ID: <aBUiwLV4ZY2HdRbz@google.com> (raw)
In-Reply-To: <20250502084007.GS4198@noisy.programming.kicks-ass.net>
[-- Attachment #1: Type: text/plain, Size: 1711 bytes --]
On Fri, May 02, 2025, Peter Zijlstra wrote:
> On Thu, May 01, 2025 at 11:30:18AM -0700, Sean Christopherson wrote:
>
> > Uh, aren't you making this way more complex than it needs to be?
>
> Possibly :-)
>
> > IIUC, KVM never
> > uses the FRED hardware entry points, i.e. the FRED entry tables don't need to be
> > in place because they'll never be used. The only bits of code KVM needs is the
> > __fred_entry_from_kvm() glue.
>
> But __fred_entry_from_kvm() calls into fred_extint(), which then
> directly uses the fred sysvec_table[] for dispatch. How would we not
> have to set up that table?
I missed that the first time around. From my self-reply:
: Hrm, and now I see that fred_extint() relies on fred_install_sysvec(), which makes
: me quite curious as to why IRQs didn't go sideways. Oh, because sysvec_table[]
: is statically defined at compile time except for PV crud.
:
: So yeah, I think my the patches are correct, they just the need a small bit of
: prep work to support dynamic setup of sysvec_table.
> > Lightly tested, but this combo works for IRQs and NMIs on non-FRED hardware.
>
> So the FRED NMI code is significantly different from the IDT NMI code
> and I really didn't want to go mixing those.
>
> If we get a nested NMI I don't think it'll behave well.
Ah, because FRED hardwware doesn't have the crazy NMI unblocking behavior, and
the FRED NMI entry code relies on that.
But I don't see why we need to care about NMIs from KVM, while they do bounce
through assembly to create a stack frame, the actual CALL is direct to
asm_exc_nmi_kvm_vmx(). If it's just the unwind hint that's needed, that
The attached patches handle the IRQ case and are passing my testing.
[-- Attachment #2: 0001-x86-fred-Install-system-vector-handlers-even-if-FRED.patch --]
[-- Type: text/x-diff, Size: 2455 bytes --]
From e605366a5ff6dfcfb45084828585e5fcfc5d3bcc Mon Sep 17 00:00:00 2001
From: Sean Christopherson <seanjc@google.com>
Date: Fri, 2 May 2025 07:24:01 -0700
Subject: [PATCH 1/3] x86/fred: Install system vector handlers even if FRED
isn't fully enabled
Install the system vector IRQ handlers for FRED even if FRED isn't fully
enabled in hardware. This will allow KVM to use the FRED IRQ path even
on non-FRED hardware, which in turn will eliminate a non-CFI indirect CALL
(KVM currently invokes the IRQ handler via an IDT lookup on the vector).
Not-yet-Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
[sean: extract from diff, drop stub, write changelog]
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/include/asm/idtentry.h | 9 ++-------
arch/x86/kernel/irqinit.c | 6 ++++--
2 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/arch/x86/include/asm/idtentry.h b/arch/x86/include/asm/idtentry.h
index a4ec27c67988..abd637e54e94 100644
--- a/arch/x86/include/asm/idtentry.h
+++ b/arch/x86/include/asm/idtentry.h
@@ -460,17 +460,12 @@ __visible noinstr void func(struct pt_regs *regs, \
#endif
void idt_install_sysvec(unsigned int n, const void *function);
-
-#ifdef CONFIG_X86_FRED
void fred_install_sysvec(unsigned int vector, const idtentry_t function);
-#else
-static inline void fred_install_sysvec(unsigned int vector, const idtentry_t function) { }
-#endif
#define sysvec_install(vector, function) { \
- if (cpu_feature_enabled(X86_FEATURE_FRED)) \
+ if (IS_ENABLED(CONFIG_X86_FRED)) \
fred_install_sysvec(vector, function); \
- else \
+ if (!cpu_feature_enabled(X86_FEATURE_FRED)) \
idt_install_sysvec(vector, asm_##function); \
}
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index f79c5edc0b89..6ab9eac64670 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -97,9 +97,11 @@ void __init native_init_IRQ(void)
/* Execute any quirks before the call gates are initialised: */
x86_init.irqs.pre_vector_init();
- if (cpu_feature_enabled(X86_FEATURE_FRED))
+ /* FRED's IRQ path may be used even if FRED isn't fully enabled. */
+ if (IS_ENABLED(CONFIG_X86_FRED))
fred_complete_exception_setup();
- else
+
+ if (!cpu_feature_enabled(X86_FEATURE_FRED))
idt_setup_apic_and_irq_gates();
lapic_assign_system_vectors();
base-commit: 45eb29140e68ffe8e93a5471006858a018480a45
--
2.49.0.906.g1f30a19c02-goog
[-- Attachment #3: 0002-x86-fred-Play-nice-with-invoking-asm_fred_entry_from.patch --]
[-- Type: text/x-diff, Size: 1722 bytes --]
From 12dc39eeb3d5ed1950a9bbaf4ac68c46943d0e9d Mon Sep 17 00:00:00 2001
From: Sean Christopherson <seanjc@google.com>
Date: Thu, 1 May 2025 11:20:29 -0700
Subject: [PATCH 2/3] x86/fred: Play nice with invoking
asm_fred_entry_from_kvm() on non-FRED hardware
Modify asm_fred_entry_from_kvm() to allow it to be invoked by KVM even
when FRED isn't fully enabled, e.g. when running with CONFIG_X86_FRED=y
on non-FRED hardware. This will allow forcing KVM to always use the FRED
entry points for 64-bit kernels, which in turn will eliminate a rather
gross non-CFI indirect call that KVM uses to trampoline IRQs by doing IDT
lookups.
When FRED isn't enabled, simply skip ERETS and restore RBP and RSP from
the stack frame prior to doing a "regular" RET back to KVM (in quotes
because of all the RET mitigation horrors).
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/entry/entry_64_fred.S | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/x86/entry/entry_64_fred.S b/arch/x86/entry/entry_64_fred.S
index 29c5c32c16c3..7aff2f0a285f 100644
--- a/arch/x86/entry/entry_64_fred.S
+++ b/arch/x86/entry/entry_64_fred.S
@@ -116,7 +116,8 @@ SYM_FUNC_START(asm_fred_entry_from_kvm)
movq %rsp, %rdi /* %rdi -> pt_regs */
call __fred_entry_from_kvm /* Call the C entry point */
POP_REGS
- ERETS
+
+ ALTERNATIVE "", __stringify(ERETS), X86_FEATURE_FRED
1:
/*
* Objtool doesn't understand what ERETS does, this hint tells it that
@@ -124,7 +125,7 @@ SYM_FUNC_START(asm_fred_entry_from_kvm)
* isn't strictly needed, but it's the simplest form.
*/
UNWIND_HINT_RESTORE
- pop %rbp
+ leave
RET
SYM_FUNC_END(asm_fred_entry_from_kvm)
--
2.49.0.906.g1f30a19c02-goog
[-- Attachment #4: 0003-x86-fred-KVM-VMX-Always-use-FRED-for-IRQs-when-CONFI.patch --]
[-- Type: text/x-diff, Size: 2775 bytes --]
From 047137843838e48af8ec9cfd36e62e605b43cacd Mon Sep 17 00:00:00 2001
From: Sean Christopherson <seanjc@google.com>
Date: Thu, 1 May 2025 11:10:39 -0700
Subject: [PATCH 3/3] x86/fred: KVM: VMX: Always use FRED for IRQs when
CONFIG_X86_FRED=y
Now that FRED provides C-code entry points for handling IRQs, use the FRED
infrastructure for forwarding IRQs even if FRED fully enabled, e.g. isn't
supported in hardware. Avoiding the non-FRED assembly trampolines into
the IDT handlers for IRQs eliminates the associated non-CFI indirect call
(KVM performs a CALL by doing a lookup on the IDT using the IRQ vector).
Keep NMIs on the legacy IDT path, as the FRED NMI entry code relies on
FRED's architectural behavior with respect to NMI blocking, i.e. doesn't
jump through the myriad hoops needed to deal with IRET "unexpectedly"
unmasking NMIs. KVM's NMI path already makes a direct CALL to C-code,
i.e. isn't problematic for CFI. KVM does make a short detour through
assembly code to build the stack frame, but the "FRED entry from KVM"
path does the same.
Force FRED for 64-bit kernels if KVM_INTEL is enabled, as the benefits of
eliminating the IRQ trampoline usage far outwieghts the code overhead for
FRED.
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/Kconfig | 1 +
arch/x86/kvm/vmx/vmx.c | 8 +++++++-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index 2eeffcec5382..712a2ff28ce4 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -95,6 +95,7 @@ config KVM_SW_PROTECTED_VM
config KVM_INTEL
tristate "KVM for Intel (and compatible) processors support"
depends on KVM && IA32_FEAT_CTL
+ select X86_FRED if X86_64
select KVM_GENERIC_PRIVATE_MEM if INTEL_TDX_HOST
select KVM_GENERIC_MEMORY_ATTRIBUTES if INTEL_TDX_HOST
help
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index ef2d7208dd20..3139658de9ed 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -6994,8 +6994,14 @@ static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu,
"unexpected VM-Exit interrupt info: 0x%x", intr_info))
return;
+ /*
+ * Invoke the kernel's IRQ handler for the vector. Use the FRED path
+ * when it's available even if FRED isn't fully enabled, e.g. even if
+ * FRED isn't supported in hardware, in order to avoid the indirect
+ * CALL in the non-FRED path.
+ */
kvm_before_interrupt(vcpu, KVM_HANDLING_IRQ);
- if (cpu_feature_enabled(X86_FEATURE_FRED))
+ if (IS_ENABLED(CONFIG_X86_FRED))
fred_entry_from_kvm(EVENT_TYPE_EXTINT, vector);
else
vmx_do_interrupt_irqoff(gate_offset((gate_desc *)host_idt_base + vector));
--
2.49.0.906.g1f30a19c02-goog
next prev parent reply other threads:[~2025-05-02 19:53 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-30 11:07 [PATCH v2 00/13] objtool: Detect and warn about indirect calls in __nocfi functions Peter Zijlstra
2025-04-30 11:07 ` [PATCH v2 01/13] x86/kvm/emulate: Implement test_cc() in C Peter Zijlstra
2025-04-30 11:07 ` [PATCH v2 02/13] x86/kvm/emulate: Introduce COP1 Peter Zijlstra
2025-04-30 16:19 ` Josh Poimboeuf
2025-04-30 19:05 ` Peter Zijlstra
2025-04-30 11:07 ` [PATCH v2 03/13] x86/kvm/emulate: Introduce COP2 Peter Zijlstra
2025-04-30 11:07 ` [PATCH v2 04/13] x86/kvm/emulate: Introduce COP2R Peter Zijlstra
2025-04-30 11:07 ` [PATCH v2 05/13] x86/kvm/emulate: Introduce COP2W Peter Zijlstra
2025-04-30 11:07 ` [PATCH v2 06/13] x86/kvm/emulate: Introduce COP2CL Peter Zijlstra
2025-04-30 11:07 ` [PATCH v2 07/13] x86/kvm/emulate: Introduce COP1SRC2 Peter Zijlstra
2025-04-30 11:07 ` [PATCH v2 08/13] x86/kvm/emulate: Introduce COP3WCL Peter Zijlstra
2025-04-30 11:07 ` [PATCH v2 09/13] x86/kvm/emulate: Convert em_salc() to C Peter Zijlstra
2025-04-30 11:07 ` [PATCH v2 10/13] x86/kvm/emulate: Remove fastops Peter Zijlstra
2025-04-30 11:07 ` [PATCH v2 11/13] x86,hyperv: Clean up hv_do_hypercall() Peter Zijlstra
2025-05-01 2:36 ` Michael Kelley
2025-04-30 11:07 ` [PATCH v2 12/13] x86_64,hyperv: Use direct call to hypercall-page Peter Zijlstra
2025-05-01 2:36 ` Michael Kelley
2025-05-01 8:59 ` Peter Zijlstra
2025-04-30 11:07 ` [PATCH v2 13/13] objtool: Validate kCFI calls Peter Zijlstra
2025-04-30 15:59 ` Josh Poimboeuf
2025-04-30 19:03 ` Peter Zijlstra
2025-05-01 15:56 ` Peter Zijlstra
2025-04-30 14:24 ` [PATCH v2 00/13] objtool: Detect and warn about indirect calls in __nocfi functions H. Peter Anvin
2025-04-30 19:06 ` Peter Zijlstra
2025-05-01 10:30 ` Peter Zijlstra
2025-05-01 15:38 ` Peter Zijlstra
2025-05-01 18:30 ` Sean Christopherson
2025-05-01 18:42 ` H. Peter Anvin
2025-05-01 18:59 ` Sean Christopherson
2025-05-02 6:12 ` Xin Li
2025-05-02 5:46 ` Xin Li
2025-05-02 5:48 ` Xin Li
2025-05-02 19:43 ` H. Peter Anvin
2025-05-02 8:40 ` Peter Zijlstra
2025-05-02 19:53 ` Sean Christopherson [this message]
2025-05-03 9:50 ` Peter Zijlstra
2025-05-03 18:28 ` Josh Poimboeuf
2025-05-06 7:31 ` Peter Zijlstra
2025-05-06 13:32 ` Peter Zijlstra
2025-05-06 19:18 ` Josh Poimboeuf
2025-05-28 7:44 ` Peter Zijlstra
2025-05-28 16:30 ` Peter Zijlstra
2025-05-28 16:35 ` Peter Zijlstra
2025-05-29 9:30 ` Peter Zijlstra
2025-06-03 5:43 ` Josh Poimboeuf
2025-06-03 16:29 ` Josh Poimboeuf
2025-06-05 17:19 ` Josh Poimboeuf
2025-06-06 10:49 ` Peter Zijlstra
2025-06-06 13:15 ` Sean Christopherson
2025-06-06 13:20 ` Peter Zijlstra
2025-05-01 18:33 ` Paolo Bonzini
2025-05-02 11:08 ` Peter Zijlstra
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aBUiwLV4ZY2HdRbz@google.com \
--to=seanjc@google.com \
--cc=ardb@kernel.org \
--cc=arnd@arndb.de \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=decui@microsoft.com \
--cc=gregkh@linuxfoundation.org \
--cc=haiyangz@microsoft.com \
--cc=hpa@zytor.com \
--cc=jpoimboe@kernel.org \
--cc=kees@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=kys@microsoft.com \
--cc=linux-efi@vger.kernel.org \
--cc=linux-hyperv@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=ojeda@kernel.org \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=samitolvanen@google.com \
--cc=tglx@linutronix.de \
--cc=wei.liu@kernel.org \
--cc=x86@kernel.org \
--cc=xin@zytor.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).