[PATCH v2 07/23] x86/boot: Use RSTORSSP to establish SSP

Andrew Cooper posted 23 patches 2 months ago
There is a newer version of this series
[PATCH v2 07/23] x86/boot: Use RSTORSSP to establish SSP
Posted by Andrew Cooper 2 months ago
Under FRED, SETSSBSY is disallowed, and we want to be setting up FRED prior to
setting up shadow stacks.  As we still need Supervisor Tokens in IDT mode, we
need mode-specific logic to establish SSP.

In FRED mode, write a Restore Token, RSTORSSP it, and discard the resulting
Previous-SSP token.

No change outside of FRED mode.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>

v2:
 * Some logic moved into prior patch.
---
 xen/arch/x86/boot/x86_64.S | 23 +++++++++++++++++++++--
 xen/arch/x86/setup.c       | 25 ++++++++++++++++++++++++-
 2 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/xen/arch/x86/boot/x86_64.S b/xen/arch/x86/boot/x86_64.S
index 11a7e9d3bd23..9705d03f849c 100644
--- a/xen/arch/x86/boot/x86_64.S
+++ b/xen/arch/x86/boot/x86_64.S
@@ -53,17 +53,21 @@ ENTRY(__high_start)
         mov     %rcx, STACK_CPUINFO_FIELD(cr4)(%r15)
         mov     %rcx, %cr4
 
-        /* WARNING! call/ret now fatal (iff SHSTK) until SETSSBSY loads SSP */
+        /* WARNING! CALL/RET now fatal (iff SHSTK) until SETSSBSY/RSTORSSP loads SSP */
 
 #if defined(CONFIG_XEN_SHSTK)
         test    $CET_SHSTK_EN, %al
         jz      .L_ap_cet_done
 
-        /* Derive the supervisor token address from %rsp. */
+        /* Derive the token address from %rsp. */
         mov     %rsp, %rdx
         and     $~(STACK_SIZE - 1), %rdx
         or      $(PRIMARY_SHSTK_SLOT + 1) * PAGE_SIZE - 8, %rdx
 
+        /* Establishing SSP differs between IDT or FRED mode. */
+        bt      $32 /* ilog2(X86_CR4_FRED) */, %rcx
+        jc      .L_fred_shstk
+
         /*
          * Write a new Supervisor Token.  It doesn't matter the first time a
          * CPU boots, but for S3 resume or hotplug this clears the busy bit so
@@ -71,6 +75,21 @@ ENTRY(__high_start)
          */
         wrssq   %rdx, (%rdx)
         setssbsy
+        jmp     .L_ap_cet_done
+
+.L_fred_shstk:
+
+        /*
+         * Write a Restore Token, value: &token + 8 + 64BIT (bit 0) at the
+         * base of the shstk (which isn't in use yet).
+         */
+        lea     9(%rdx), %rdi
+        wrssq   %rdi, (%rdx)
+        rstorssp (%rdx)
+
+        /* Discard the Previous-SSP Token from the shstk. */
+        mov     $2, %edx
+        incsspd %edx
 
 #endif /* CONFIG_XEN_SHSTK */
 .L_ap_cet_done:
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index a810bdf6d352..73799fcc684c 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -49,6 +49,7 @@
 #include <asm/prot-key.h>
 #include <asm/pv/domain.h>
 #include <asm/setup.h>
+#include <asm/shstk.h>
 #include <asm/smp.h>
 #include <asm/spec_ctrl.h>
 #include <asm/stubs.h>
@@ -908,7 +909,29 @@ static void __init noreturn reinit_bsp_stack(void)
     if ( cpu_has_xen_shstk )
     {
         wrmsrl(MSR_S_CET, xen_msr_s_cet_value());
-        asm volatile ("setssbsy" ::: "memory");
+
+        /*
+         * IDT and FRED differ by a Supervisor Token on the shadow stack, and
+         * therefore by the value in MSR_PL0_SSP.
+         *
+         * In IDT mode, we use SETSSBSY to mark the Supervisor Token as busy.
+         * In FRED mode, there is no token, so we need to create a temporary
+         * Restore Token to establish SSP.
+         */
+        if ( opt_fred )
+        {
+            unsigned long *token =
+                (void *)stack + (PRIMARY_SHSTK_SLOT + 1) * PAGE_SIZE - 8;
+
+            wrss((unsigned long)token + 9, token);
+            asm volatile ( "rstorssp %0" : "+m" (*token) );
+            /*
+             * We need to discard the resulting Previous-SSP Token, but
+             * reset_stack_and_jump() will do that for us.
+             */
+        }
+        else
+            asm volatile ( "setssbsy" ::: "memory" );
     }
 
     reset_stack_and_jump(init_done);
-- 
2.39.5


Re: [PATCH v2 07/23] x86/boot: Use RSTORSSP to establish SSP
Posted by Jan Beulich 1 month, 4 weeks ago
On 28.08.2025 17:03, Andrew Cooper wrote:
> @@ -908,7 +909,29 @@ static void __init noreturn reinit_bsp_stack(void)
>      if ( cpu_has_xen_shstk )
>      {
>          wrmsrl(MSR_S_CET, xen_msr_s_cet_value());
> -        asm volatile ("setssbsy" ::: "memory");
> +
> +        /*
> +         * IDT and FRED differ by a Supervisor Token on the shadow stack, and
> +         * therefore by the value in MSR_PL0_SSP.

Beside not being overly relevant here afaict, is this last part of the sentence
actually correct? Patch 06 doesn't write different values into the MSR.

Jan
Re: [PATCH v2 07/23] x86/boot: Use RSTORSSP to establish SSP
Posted by Andrew Cooper 1 month, 4 weeks ago
On 01/09/2025 10:28 am, Jan Beulich wrote:
> On 28.08.2025 17:03, Andrew Cooper wrote:
>> @@ -908,7 +909,29 @@ static void __init noreturn reinit_bsp_stack(void)
>>      if ( cpu_has_xen_shstk )
>>      {
>>          wrmsrl(MSR_S_CET, xen_msr_s_cet_value());
>> -        asm volatile ("setssbsy" ::: "memory");
>> +
>> +        /*
>> +         * IDT and FRED differ by a Supervisor Token on the shadow stack, and
>> +         * therefore by the value in MSR_PL0_SSP.
> Beside not being overly relevant here afaict, is this last part of the sentence
> actually correct? Patch 06 doesn't write different values into the MSR.

It is correct, but also well hidden.

#define MSR_FRED_SSP_SL0                    MSR_PL0_SSP

I suppose I should should write MSR_PL0_SSP/MSR_FRED_SSP_SL0 here to
highlight the logically different names for the two modes.

~Andrew

Re: [PATCH v2 07/23] x86/boot: Use RSTORSSP to establish SSP
Posted by Jan Beulich 1 month, 4 weeks ago
On 01.09.2025 17:33, Andrew Cooper wrote:
> On 01/09/2025 10:28 am, Jan Beulich wrote:
>> On 28.08.2025 17:03, Andrew Cooper wrote:
>>> @@ -908,7 +909,29 @@ static void __init noreturn reinit_bsp_stack(void)
>>>      if ( cpu_has_xen_shstk )
>>>      {
>>>          wrmsrl(MSR_S_CET, xen_msr_s_cet_value());
>>> -        asm volatile ("setssbsy" ::: "memory");
>>> +
>>> +        /*
>>> +         * IDT and FRED differ by a Supervisor Token on the shadow stack, and
>>> +         * therefore by the value in MSR_PL0_SSP.
>> Beside not being overly relevant here afaict, is this last part of the sentence
>> actually correct? Patch 06 doesn't write different values into the MSR.
> 
> It is correct, but also well hidden.
> 
> #define MSR_FRED_SSP_SL0                    MSR_PL0_SSP
> 
> I suppose I should should write MSR_PL0_SSP/MSR_FRED_SSP_SL0 here to
> highlight the logically different names for the two modes.

But the code following the comment doesn't access any MSR. That's what
first tripped me up. It was only then that I wasn't able to spot the two
different writes. Now that you point out the aliasing it becomes clear
that until patch 14 it is simply impossible to find that other write.

Jan

Re: [PATCH v2 07/23] x86/boot: Use RSTORSSP to establish SSP
Posted by Andrew Cooper 1 month, 4 weeks ago
On 01/09/2025 4:41 pm, Jan Beulich wrote:
> On 01.09.2025 17:33, Andrew Cooper wrote:
>> On 01/09/2025 10:28 am, Jan Beulich wrote:
>>> On 28.08.2025 17:03, Andrew Cooper wrote:
>>>> @@ -908,7 +909,29 @@ static void __init noreturn reinit_bsp_stack(void)
>>>>      if ( cpu_has_xen_shstk )
>>>>      {
>>>>          wrmsrl(MSR_S_CET, xen_msr_s_cet_value());
>>>> -        asm volatile ("setssbsy" ::: "memory");
>>>> +
>>>> +        /*
>>>> +         * IDT and FRED differ by a Supervisor Token on the shadow stack, and
>>>> +         * therefore by the value in MSR_PL0_SSP.
>>> Beside not being overly relevant here afaict, is this last part of the sentence
>>> actually correct? Patch 06 doesn't write different values into the MSR.
>> It is correct, but also well hidden.
>>
>> #define MSR_FRED_SSP_SL0                    MSR_PL0_SSP
>>
>> I suppose I should should write MSR_PL0_SSP/MSR_FRED_SSP_SL0 here to
>> highlight the logically different names for the two modes.
> But the code following the comment doesn't access any MSR. That's what
> first tripped me up. It was only then that I wasn't able to spot the two
> different writes. Now that you point out the aliasing it becomes clear
> that until patch 14 it is simply impossible to find that other write.

I suppose the MSR value isn't relevant now that neither paths write the
value.  The first iteration had both writes here.

I guess I can drop that paragraph, and just have the second?

~Andrew

Re: [PATCH v2 07/23] x86/boot: Use RSTORSSP to establish SSP
Posted by Jan Beulich 1 month, 4 weeks ago
On 01.09.2025 20:53, Andrew Cooper wrote:
> On 01/09/2025 4:41 pm, Jan Beulich wrote:
>> On 01.09.2025 17:33, Andrew Cooper wrote:
>>> On 01/09/2025 10:28 am, Jan Beulich wrote:
>>>> On 28.08.2025 17:03, Andrew Cooper wrote:
>>>>> @@ -908,7 +909,29 @@ static void __init noreturn reinit_bsp_stack(void)
>>>>>      if ( cpu_has_xen_shstk )
>>>>>      {
>>>>>          wrmsrl(MSR_S_CET, xen_msr_s_cet_value());
>>>>> -        asm volatile ("setssbsy" ::: "memory");
>>>>> +
>>>>> +        /*
>>>>> +         * IDT and FRED differ by a Supervisor Token on the shadow stack, and
>>>>> +         * therefore by the value in MSR_PL0_SSP.
>>>> Beside not being overly relevant here afaict, is this last part of the sentence
>>>> actually correct? Patch 06 doesn't write different values into the MSR.
>>> It is correct, but also well hidden.
>>>
>>> #define MSR_FRED_SSP_SL0                    MSR_PL0_SSP
>>>
>>> I suppose I should should write MSR_PL0_SSP/MSR_FRED_SSP_SL0 here to
>>> highlight the logically different names for the two modes.
>> But the code following the comment doesn't access any MSR. That's what
>> first tripped me up. It was only then that I wasn't able to spot the two
>> different writes. Now that you point out the aliasing it becomes clear
>> that until patch 14 it is simply impossible to find that other write.
> 
> I suppose the MSR value isn't relevant now that neither paths write the
> value.  The first iteration had both writes here.
> 
> I guess I can drop that paragraph, and just have the second?

I'd keep everything up to the comma (plus the other paragraph of course).

Jan