Subject: [PATCH v1 1/1] x86/tdx: Don't write CSTAR MSR on Intel

From: Andi Kleen <[email protected]>

Intel CPUs do not support SYSCALL in 32-bit mode, but the kernel
initializes MSR_CSTAR unconditionally. That MSR write is normally
ignored by the CPU, but in a TDX guest it raises a #VE trap.

Exclude Intel CPUs from the MSR_CSTAR initialization.

Signed-off-by: Andi Kleen <[email protected]>
Reviewed-by: Tony Luck <[email protected]>
Signed-off-by: Kuppuswamy Sathyanarayanan <[email protected]>
---
arch/x86/kernel/cpu/common.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 0083464de5e3..8917eb412c4a 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1787,6 +1787,18 @@ EXPORT_PER_CPU_SYMBOL(__preempt_count);

DEFINE_PER_CPU(unsigned long, cpu_current_top_of_stack) = TOP_OF_INIT_STACK;

+/* Don't write CSTAR MSR on Intel platforms */
+void wrmsrl_cstar(unsigned long val)
+{
+ /*
+ * Intel CPUs do not support 32-bit SYSCALL. Writing to MSR_CSTAR
+ * is normally ignored by the CPU, but raises a #VE trap in a TDX
+ * guest.
+ */
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+ wrmsrl(MSR_CSTAR, val);
+}
+
/* May not be marked __init: used by software suspend */
void syscall_init(void)
{
@@ -1794,7 +1806,7 @@ void syscall_init(void)
wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);

#ifdef CONFIG_IA32_EMULATION
- wrmsrl(MSR_CSTAR, (unsigned long)entry_SYSCALL_compat);
+ wrmsrl_cstar((unsigned long)entry_SYSCALL_compat);
/*
* This only works on Intel CPUs.
* On AMD CPUs these MSRs are 32-bit, CPU truncates MSR_IA32_SYSENTER_EIP.
@@ -1806,7 +1818,7 @@ void syscall_init(void)
(unsigned long)(cpu_entry_stack(smp_processor_id()) + 1));
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)entry_SYSENTER_compat);
#else
- wrmsrl(MSR_CSTAR, (unsigned long)ignore_sysret);
+ wrmsrl_cstar((unsigned long)ignore_sysret);
wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)GDT_ENTRY_INVALID_SEG);
wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, 0ULL);
--
2.25.1



2021-11-18 21:02:37

by Thomas Gleixner

[permalink] [raw]
Subject: Re: [PATCH v1 1/1] x86/tdx: Don't write CSTAR MSR on Intel

On Mon, Nov 15 2021 at 16:51, Kuppuswamy Sathyanarayanan wrote:
>
> DEFINE_PER_CPU(unsigned long, cpu_current_top_of_stack) = TOP_OF_INIT_STACK;
>
> +/* Don't write CSTAR MSR on Intel platforms */
> +void wrmsrl_cstar(unsigned long val)

static, no?

Thanks,

tglx

Subject: Re: [PATCH v1 1/1] x86/tdx: Don't write CSTAR MSR on Intel



On 11/18/21 1:02 PM, Thomas Gleixner wrote:
>> DEFINE_PER_CPU(unsigned long, cpu_current_top_of_stack) = TOP_OF_INIT_STACK;
>>
>> +/* Don't write CSTAR MSR on Intel platforms */
>> +void wrmsrl_cstar(unsigned long val)
> static, no?

Yes. It should be static. I will fix it.

--
Sathyanarayanan Kuppuswamy
Linux Kernel Developer

Subject: [PATCH v2] x86/tdx: Don't write CSTAR MSR on Intel

From: Andi Kleen <[email protected]>

Intel CPUs do not support SYSCALL in 32-bit mode, but the kernel
initializes MSR_CSTAR unconditionally. That MSR write is normally
ignored by the CPU, but in a TDX guest it raises a #VE trap.

Exclude Intel CPUs from the MSR_CSTAR initialization.

Signed-off-by: Andi Kleen <[email protected]>
Reviewed-by: Tony Luck <[email protected]>
Signed-off-by: Kuppuswamy Sathyanarayanan <[email protected]>
---

Changes since v1:
* Made wrmsrl_cstar() static.

arch/x86/kernel/cpu/common.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 0083464de5e3..c3bb03201f2a 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1787,6 +1787,18 @@ EXPORT_PER_CPU_SYMBOL(__preempt_count);

DEFINE_PER_CPU(unsigned long, cpu_current_top_of_stack) = TOP_OF_INIT_STACK;

+/* Don't write CSTAR MSR on Intel platforms */
+static void wrmsrl_cstar(unsigned long val)
+{
+ /*
+ * Intel CPUs do not support 32-bit SYSCALL. Writing to MSR_CSTAR
+ * is normally ignored by the CPU, but raises a #VE trap in a TDX
+ * guest.
+ */
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+ wrmsrl(MSR_CSTAR, val);
+}
+
/* May not be marked __init: used by software suspend */
void syscall_init(void)
{
@@ -1794,7 +1806,7 @@ void syscall_init(void)
wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);

#ifdef CONFIG_IA32_EMULATION
- wrmsrl(MSR_CSTAR, (unsigned long)entry_SYSCALL_compat);
+ wrmsrl_cstar((unsigned long)entry_SYSCALL_compat);
/*
* This only works on Intel CPUs.
* On AMD CPUs these MSRs are 32-bit, CPU truncates MSR_IA32_SYSENTER_EIP.
@@ -1806,7 +1818,7 @@ void syscall_init(void)
(unsigned long)(cpu_entry_stack(smp_processor_id()) + 1));
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)entry_SYSENTER_compat);
#else
- wrmsrl(MSR_CSTAR, (unsigned long)ignore_sysret);
+ wrmsrl_cstar((unsigned long)ignore_sysret);
wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)GDT_ENTRY_INVALID_SEG);
wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, 0ULL);
--
2.25.1


2021-11-24 23:40:56

by Thomas Gleixner

[permalink] [raw]
Subject: Re: [PATCH v2] x86/tdx: Don't write CSTAR MSR on Intel

Kuppuswamy,

On Thu, Nov 18 2021 at 19:58, Kuppuswamy Sathyanarayanan wrote:

almost. The subject line is bogus:

x86/tdx: Don't write CSTAR MSR on Intel

This has nothing to do with TDX in the first place as the actual check
is for CPU vendor == Intel. It's absolutely no requirement to remove
this for TDX. TDX could just handle the #VE and ignore the write.

It's an obvious optimization without TDX because the write is pointless
independent of TDX. There is no value to slap TDX on everything just
because.

Also 'write on Intel' should be 'write on Intel CPUs' to make sense.

> +/* Don't write CSTAR MSR on Intel platforms */

How is this comment useful? The proper explanation is below.

> +static void wrmsrl_cstar(unsigned long val)
> +{
> + /*
> + * Intel CPUs do not support 32-bit SYSCALL. Writing to MSR_CSTAR
> + * is normally ignored by the CPU, but raises a #VE trap in a TDX
> + * guest.
> + */
> + if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
> + wrmsrl(MSR_CSTAR, val);
> +}

I fixed it up for you because of Thanksgiving.

Thanks,

tglx

Subject: [tip: x86/cpu] x86/cpu: Don't write CSTAR MSR on Intel CPUs

The following commit has been merged into the x86/cpu branch of tip:

Commit-ID: 9c7e2634f647630db4e0719391dd80cd81132a66
Gitweb: https://git.kernel.org/tip/9c7e2634f647630db4e0719391dd80cd81132a66
Author: Andi Kleen <[email protected]>
AuthorDate: Thu, 18 Nov 2021 19:58:03 -08:00
Committer: Thomas Gleixner <[email protected]>
CommitterDate: Thu, 25 Nov 2021 00:40:34 +01:00

x86/cpu: Don't write CSTAR MSR on Intel CPUs

Intel CPUs do not support SYSCALL in 32-bit mode, but the kernel
initializes MSR_CSTAR unconditionally. That MSR write is normally
ignored by the CPU, but in a TDX guest it raises a #VE trap.

Exclude Intel CPUs from the MSR_CSTAR initialization.

[ tglx: Fixed the subject line and removed the redundant comment. ]

Signed-off-by: Andi Kleen <[email protected]>
Signed-off-by: Kuppuswamy Sathyanarayanan <[email protected]>
Signed-off-by: Thomas Gleixner <[email protected]>
Reviewed-by: Tony Luck <[email protected]>
Link: https://lore.kernel.org/r/20211119035803.4012145-1-sathyanarayanan.kuppuswamy@linux.intel.com

---
arch/x86/kernel/cpu/common.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 0083464..0663642 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1787,6 +1787,17 @@ EXPORT_PER_CPU_SYMBOL(__preempt_count);

DEFINE_PER_CPU(unsigned long, cpu_current_top_of_stack) = TOP_OF_INIT_STACK;

+static void wrmsrl_cstar(unsigned long val)
+{
+ /*
+ * Intel CPUs do not support 32-bit SYSCALL. Writing to MSR_CSTAR
+ * is so far ignored by the CPU, but raises a #VE trap in a TDX
+ * guest. Avoid the pointless write on all Intel CPUs.
+ */
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+ wrmsrl(MSR_CSTAR, val);
+}
+
/* May not be marked __init: used by software suspend */
void syscall_init(void)
{
@@ -1794,7 +1805,7 @@ void syscall_init(void)
wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);

#ifdef CONFIG_IA32_EMULATION
- wrmsrl(MSR_CSTAR, (unsigned long)entry_SYSCALL_compat);
+ wrmsrl_cstar((unsigned long)entry_SYSCALL_compat);
/*
* This only works on Intel CPUs.
* On AMD CPUs these MSRs are 32-bit, CPU truncates MSR_IA32_SYSENTER_EIP.
@@ -1806,7 +1817,7 @@ void syscall_init(void)
(unsigned long)(cpu_entry_stack(smp_processor_id()) + 1));
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)entry_SYSENTER_compat);
#else
- wrmsrl(MSR_CSTAR, (unsigned long)ignore_sysret);
+ wrmsrl_cstar((unsigned long)ignore_sysret);
wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)GDT_ENTRY_INVALID_SEG);
wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, 0ULL);

Subject: Re: [PATCH v2] x86/tdx: Don't write CSTAR MSR on Intel



On 11/24/21 3:40 PM, Thomas Gleixner wrote:
> I fixed it up for you because of Thanksgiving.

Thanks.

--
Sathyanarayanan Kuppuswamy
Linux Kernel Developer