mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* Kernel Shadow Stacks Versus XFEATURE_MASK_GUEST_SUPERVISOR
@ 2026-10-23 19:03 Dave Hansen
  2026-10-23 21:00 ` Paolo Bonzini
  0 siblings, 1 reply; 3+ messages in thread
From: Dave Hansen @ 2026-10-23 19:03 UTC (permalink / raw)
  To: Yang Weijiang, Gao, Chao, Edgecombe, Rick P, Maxim Levitsky,
	John Allen, LKML, pbonzini, peterz, john.allen, kvm, binbin.wu,
	Andrew Cooper, Thomas Gleixner, Bae, Chang Seok, Mehta, Sohil

So, I'm working on kernel shadow stacks. I have some nice optimization
code like fred_update_rsp0() for SSP0. It avoids WRMSR's on exits to
userspace if FRED_SSP0 hasn't changed, just like FRED_RSP0.

Well, turns out that FRED_SSP0 isn't like FRED_RSP0 in one very
important way: it is an alias for PL0_SSP, which is managed via
XFEATURE_CET_KERNEL which is in:

	/* Supervisor features which are enabled only in guest FPUs */
	#define XFEATURE_MASK_GUEST_SUPERVISOR  XFEATURE_MASK_CET_KERNEL

So, I was running along just fine in my nice shadow stack kernel going
in and out of the kernel just fine. But the first time I did an XRSTOR,
the XFEATURE_CET_KERNEL feature got set to its init state. My SSP0 cache
didn't notice and I tried to run userspace with SSP0=0. Much hilarity
ensued on the next kernel entry.

The most adorable part of all this is that I have KVM compiled
completely out on my config. The "only in guest FPUs" code is biting me
on a kernel that can't even run guests.

I think this all started because of 8b05b3c98816 ("x86/fpu/xstate: Add
CET supervisor xfeature support as a guest-only feature"), which seems
like mostly my doing. So I have mostly myself to blame.

Any thoughts on what we should do?

Actually context switching XFEATURE_CET_KERNEL seems kinda silly in a
lot of ways. PL0_SSP can always be derived _and_ it isn't actually even
needed at context switch time, only when running userspace.

I could just aggressively blow away my SSP0 cache any time an XRSTOR
touches XFEATURE_CET_KERNEL. That would be easy. But it also seems silly
that XFEATURE_CET_KERNEL is being blown away at _all_ during normal
context switches. Heck, it goes further than that because:

fpregs_restore_userregs() does:

	restore_fpregs_from_fpstate(fpu->fpstate,
				    XFEATURE_MASK_FPSTATE);

Where XFEATURE_MASK_FPSTATE contains XFEATURE_MASK_SUPERVISOR_SUPPORTED.

So a "restore_userregs" function is blowing away supervisor state.

IOW, I think we're using XFEATURE_MASK_FPSTATE a bit too broadly.

I'd like to get to a place where only the KVM code even has
XFEATURE_CET_KERNEL in its RFBM.

Anybody have any bright ideas?

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Kernel Shadow Stacks Versus XFEATURE_MASK_GUEST_SUPERVISOR
  2026-10-23 19:03 Kernel Shadow Stacks Versus XFEATURE_MASK_GUEST_SUPERVISOR Dave Hansen
@ 2026-10-23 21:00 ` Paolo Bonzini
  2026-10-23 21:21   ` Dave Hansen
  0 siblings, 1 reply; 3+ messages in thread
From: Paolo Bonzini @ 2026-10-23 21:00 UTC (permalink / raw)
  To: Dave Hansen, Yang Weijiang, Gao, Chao, Edgecombe, Rick P,
	Maxim Levitsky, John Allen, LKML, peterz, kvm, binbin.wu,
	Andrew Cooper, Thomas Gleixner, Bae, Chang Seok, Mehta, Sohil

On 10/23/26 21:03, Dave Hansen wrote:
> So, I'm working on kernel shadow stacks. I have some nice optimization
> code like fred_update_rsp0() for SSP0. It avoids WRMSR's on exits to
> userspace if FRED_SSP0 hasn't changed, just like FRED_RSP0.
> 
> Well, turns out that FRED_SSP0 isn't like FRED_RSP0 in one very
> important way: it is an alias for PL0_SSP, which is managed via
> XFEATURE_CET_KERNEL which is in:
> 
> 	/* Supervisor features which are enabled only in guest FPUs */
> 	#define XFEATURE_MASK_GUEST_SUPERVISOR  XFEATURE_MASK_CET_KERNEL
> 
> So, I was running along just fine in my nice shadow stack kernel going
> in and out of the kernel just fine. But the first time I did an XRSTOR,
> the XFEATURE_CET_KERNEL feature got set to its init state. My SSP0 cache
> didn't notice and I tried to run userspace with SSP0=0. Much hilarity
> ensued on the next kernel entry.
> 
> The most adorable part of all this is that I have KVM compiled
> completely out on my config. The "only in guest FPUs" code is biting me
> on a kernel that can't even run guests.

If you want to quickly work around for your !CONFIG_KVM kernel, I would do

#ifdef CONFIG_KVM
/* Supervisor features which are enabled only in guest FPUs */
#define XFEATURE_MASK_GUEST_SUPERVISOR  XFEATURE_MASK_CET_KERNEL
#else
#define XFEATURE_MASK_GUEST_SUPERVISOR  0
#endif

and a small adjustment like

         BUILD_BUG_ON((XFEATURE_MASK_USER_SUPPORTED |
                       XFEATURE_MASK_SUPERVISOR_SUPPORTED) &
                      ~XFEATURES_INIT_FPSTATE_HANDLED);

That will get rid of the bit in XSS.

> Any thoughts on what we should do?
> 
> Actually context switching XFEATURE_CET_KERNEL seems kinda silly in a
> lot of ways. PL0_SSP can always be derived _and_ it isn't actually even
> needed at context switch time, only when running userspace.

True but, just to understand, what is the performance like if you 
actually use XSAVES/XRSTORS to update SSP0 on context switches instead 
of WRMSR+cache?  Hopefully the microcode does a bunch of optimizations 
as well.

> I could just aggressively blow away my SSP0 cache any time an XRSTOR
> touches XFEATURE_CET_KERNEL. That would be easy. But it also seems silly
> that XFEATURE_CET_KERNEL is being blown away at _all_ during normal
> context switches. Heck, it goes further than that because:
> 
> fpregs_restore_userregs() does:
> 
> 	restore_fpregs_from_fpstate(fpu->fpstate,
> 				    XFEATURE_MASK_FPSTATE);
> 
> Where XFEATURE_MASK_FPSTATE contains XFEATURE_MASK_SUPERVISOR_SUPPORTED.

The actual mask used by restore_fpregs_from_fpstate is tighter though, 
it's "fpu_kernel_cfg.max_features & XFEATURE_MASK_FPSTATE".

Can you replace fpu_kernel_cfg.max_features with some fpstate->xyz 
(sorry too late to think it through :)) that has CET_KERNEL for the 
guest FPU and not for the regular one?

> So a "restore_userregs" function is blowing away supervisor state.
> 
> IOW, I think we're using XFEATURE_MASK_FPSTATE a bit too broadly.
> 
> I'd like to get to a place where only the KVM code even has
> XFEATURE_CET_KERNEL in its RFBM.
That I agree, but I think it can be handled in 
{save,restore}_fpregs_to_fpstate().

Paolo


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Kernel Shadow Stacks Versus XFEATURE_MASK_GUEST_SUPERVISOR
  2026-10-23 21:00 ` Paolo Bonzini
@ 2026-10-23 21:21   ` Dave Hansen
  0 siblings, 0 replies; 3+ messages in thread
From: Dave Hansen @ 2026-10-23 21:21 UTC (permalink / raw)
  To: Paolo Bonzini, Yang Weijiang, Gao, Chao, Edgecombe, Rick P,
	Maxim Levitsky, John Allen, LKML, peterz, kvm, binbin.wu,
	Andrew Cooper, Thomas Gleixner, Bae, Chang Seok, Mehta, Sohil

On 10/23/26 14:00, Paolo Bonzini wrote:
> On 10/23/26 21:03, Dave Hansen wrote:
...
> If you want to quickly work around for your !CONFIG_KVM kernel, I would do
> 
> #ifdef CONFIG_KVM
> /* Supervisor features which are enabled only in guest FPUs */
> #define XFEATURE_MASK_GUEST_SUPERVISOR  XFEATURE_MASK_CET_KERNEL
> #else
> #define XFEATURE_MASK_GUEST_SUPERVISOR  0
> #endif

Yup, that'd work for sure. Thanks!

>> Any thoughts on what we should do?
>>
>> Actually context switching XFEATURE_CET_KERNEL seems kinda silly in a
>> lot of ways. PL0_SSP can always be derived _and_ it isn't actually even
>> needed at context switch time, only when running userspace.
> 
> True but, just to understand, what is the performance like if you
> actually use XSAVES/XRSTORS to update SSP0 on context switches instead
> of WRMSR+cache?  Hopefully the microcode does a bunch of optimizations
> as well.

First, we can use WRMSRNS for this MSR, so it's faster than usual.
Second, on kernel=>kernel context switches that don't go out to
userspace, it doesn't need to be written at all. It's kinda like the
user FPU state. Third, I'm actually reusing the fred_ssp0 cache, so
further reduces the incremental cost. Fourth, it's not _really_
context-switched. There's never a need to read the register. It can
always be conjured out of thin air. It's possible to only write the
register, never read it.

I can benchmark it, but I seriously doubt that an XSAVE/XRSTOR at
context switch of three fields is going to beat an WRMSRNS of one.

>> I could just aggressively blow away my SSP0 cache any time an XRSTOR
>> touches XFEATURE_CET_KERNEL. That would be easy. But it also seems silly
>> that XFEATURE_CET_KERNEL is being blown away at _all_ during normal
>> context switches. Heck, it goes further than that because:
>>
>> fpregs_restore_userregs() does:
>>
>>     restore_fpregs_from_fpstate(fpu->fpstate,
>>                     XFEATURE_MASK_FPSTATE);
>>
>> Where XFEATURE_MASK_FPSTATE contains XFEATURE_MASK_SUPERVISOR_SUPPORTED.
> 
> The actual mask used by restore_fpregs_from_fpstate is tighter though,
> it's "fpu_kernel_cfg.max_features & XFEATURE_MASK_FPSTATE".
> 
> Can you replace fpu_kernel_cfg.max_features with some fpstate->xyz
> (sorry too late to think it through :)) that has CET_KERNEL for the
> guest FPU and not for the regular one?

Sure I can give that a shot.

There's one minor issue in that we need to init dynamic features which
_aren't_ in fpstate->xfeatures when context switching. There's a little
note about this in restore_fpregs_from_fpstate().

I think what you're getting at is that we need _something_ to say that
KVM fpstates should muck with XFEATURE_CET_KERNEL and task fpstates
should not, even though the task ones have space for XFEATURE_CET_KERNEL.

That's certainly doable.

>> So a "restore_userregs" function is blowing away supervisor state.
>>
>> IOW, I think we're using XFEATURE_MASK_FPSTATE a bit too broadly.
>>
>> I'd like to get to a place where only the KVM code even has
>> XFEATURE_CET_KERNEL in its RFBM.
> That I agree, but I think it can be handled in {save,restore}
> _fpregs_to_fpstate().

I think I understand what you're going after at least. I'll poke at it a
bit more.

Thanks for the thoughts!

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-10-23 21:21 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-23 19:03 Kernel Shadow Stacks Versus XFEATURE_MASK_GUEST_SUPERVISOR Dave Hansen
2026-10-23 21:00 ` Paolo Bonzini
2026-10-23 21:21   ` Dave Hansen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®