[PATCH v11 35/37] x86/syscall: Split IDT syscall setup code into idt_syscall_init()

Xin Li posted 37 patches 2 years, 4 months ago
There is a newer version of this series
[PATCH v11 35/37] x86/syscall: Split IDT syscall setup code into idt_syscall_init()
Posted by Xin Li 2 years, 4 months ago
Because FRED uses the ring 3 FRED entrypoint for SYSCALL and SYSENTER and
ERETU is the only legit instruction to return to ring 3, there is NO need
to setup SYSCALL and SYSENTER MSRs for FRED, except the IA32_STAR MSR.

Split IDT syscall setup code into idt_syscall_init() to make it easy to
skip syscall setup code when FRED is enabled.

Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Shan Kang <shan.kang@intel.com>
Signed-off-by: Xin Li <xin3.li@intel.com>
---
 arch/x86/kernel/cpu/common.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 20bbedbf6dcb..2ee4e7b597a3 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -2071,10 +2071,8 @@ static void wrmsrl_cstar(unsigned long val)
 		wrmsrl(MSR_CSTAR, val);
 }
 
-/* May not be marked __init: used by software suspend */
-void syscall_init(void)
+static inline void idt_syscall_init(void)
 {
-	wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
 	wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);
 
 	if (ia32_enabled()) {
@@ -2108,6 +2106,15 @@ void syscall_init(void)
 	       X86_EFLAGS_AC|X86_EFLAGS_ID);
 }
 
+/* May not be marked __init: used by software suspend */
+void syscall_init(void)
+{
+	/* The default user and kernel segments */
+	wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
+
+	idt_syscall_init();
+}
+
 #else	/* CONFIG_X86_64 */
 
 #ifdef CONFIG_STACKPROTECTOR
-- 
2.34.1
Re: [PATCH v11 35/37] x86/syscall: Split IDT syscall setup code into idt_syscall_init()
Posted by H. Peter Anvin 2 years, 4 months ago
On September 23, 2023 2:42:10 AM PDT, Xin Li <xin3.li@intel.com> wrote:
>Because FRED uses the ring 3 FRED entrypoint for SYSCALL and SYSENTER and
>ERETU is the only legit instruction to return to ring 3, there is NO need
>to setup SYSCALL and SYSENTER MSRs for FRED, except the IA32_STAR MSR.
>
>Split IDT syscall setup code into idt_syscall_init() to make it easy to
>skip syscall setup code when FRED is enabled.
>
>Suggested-by: Thomas Gleixner <tglx@linutronix.de>
>Tested-by: Shan Kang <shan.kang@intel.com>
>Signed-off-by: Xin Li <xin3.li@intel.com>
>---
> arch/x86/kernel/cpu/common.c | 13 ++++++++++---
> 1 file changed, 10 insertions(+), 3 deletions(-)
>
>diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
>index 20bbedbf6dcb..2ee4e7b597a3 100644
>--- a/arch/x86/kernel/cpu/common.c
>+++ b/arch/x86/kernel/cpu/common.c
>@@ -2071,10 +2071,8 @@ static void wrmsrl_cstar(unsigned long val)
> 		wrmsrl(MSR_CSTAR, val);
> }
> 
>-/* May not be marked __init: used by software suspend */
>-void syscall_init(void)
>+static inline void idt_syscall_init(void)
> {
>-	wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
> 	wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);
> 
> 	if (ia32_enabled()) {
>@@ -2108,6 +2106,15 @@ void syscall_init(void)
> 	       X86_EFLAGS_AC|X86_EFLAGS_ID);
> }
> 
>+/* May not be marked __init: used by software suspend */
>+void syscall_init(void)
>+{
>+	/* The default user and kernel segments */
>+	wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
>+
>+	idt_syscall_init();
>+}
>+
> #else	/* CONFIG_X86_64 */
> 
> #ifdef CONFIG_STACKPROTECTOR

Am I missing something, or is this patch a noop?
Re: [PATCH v11 35/37] x86/syscall: Split IDT syscall setup code into idt_syscall_init()
Posted by Thomas Gleixner 2 years, 4 months ago
On Mon, Sep 25 2023 at 09:07, H. Peter Anvin wrote:
> On September 23, 2023 2:42:10 AM PDT, Xin Li <xin3.li@intel.com> wrote:
>>+/* May not be marked __init: used by software suspend */
>>+void syscall_init(void)
>>+{
>>+	/* The default user and kernel segments */
>>+	wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
>>+
>>+	idt_syscall_init();
>>+}
>>+
>> #else	/* CONFIG_X86_64 */
>> 
>> #ifdef CONFIG_STACKPROTECTOR
>
> Am I missing something, or is this patch a noop?

Yes. It's a noop at this point. Later on it gains a

     if (!fred)
        idt_syscall_init();

Sure we could do

     if (!fred) {
     	write_msr(foo...);
        ...
     }

too, but I prefer the separation. No strong opinion though.

Thanks,

        tglx
RE: [PATCH v11 35/37] x86/syscall: Split IDT syscall setup code into idt_syscall_init()
Posted by Li, Xin3 2 years, 4 months ago
> >diff --git a/arch/x86/kernel/cpu/common.c
> >b/arch/x86/kernel/cpu/common.c index 20bbedbf6dcb..2ee4e7b597a3 100644
> >--- a/arch/x86/kernel/cpu/common.c
> >+++ b/arch/x86/kernel/cpu/common.c
> >@@ -2071,10 +2071,8 @@ static void wrmsrl_cstar(unsigned long val)
> > 		wrmsrl(MSR_CSTAR, val);
> > }
> >
> >-/* May not be marked __init: used by software suspend */ -void
> >syscall_init(void)
> >+static inline void idt_syscall_init(void)
> > {
> >-	wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
> > 	wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);
> >
> > 	if (ia32_enabled()) {
> >@@ -2108,6 +2106,15 @@ void syscall_init(void)
> > 	       X86_EFLAGS_AC|X86_EFLAGS_ID);
> > }
> >
> >+/* May not be marked __init: used by software suspend */ void
> >+syscall_init(void) {
> >+	/* The default user and kernel segments */
> >+	wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
> >+
> >+	idt_syscall_init();
> >+}
> >+
> > #else	/* CONFIG_X86_64 */
> >
> > #ifdef CONFIG_STACKPROTECTOR
> 
> Am I missing something, or is this patch a noop?

Yes, this is a noop, just a cleanup patch w/o functionality change.

RE: [PATCH v11 35/37] x86/syscall: Split IDT syscall setup code into idt_syscall_init()
Posted by H. Peter Anvin 2 years, 4 months ago
On September 25, 2023 10:56:44 AM PDT, "Li, Xin3" <xin3.li@intel.com> wrote:
>> >diff --git a/arch/x86/kernel/cpu/common.c
>> >b/arch/x86/kernel/cpu/common.c index 20bbedbf6dcb..2ee4e7b597a3 100644
>> >--- a/arch/x86/kernel/cpu/common.c
>> >+++ b/arch/x86/kernel/cpu/common.c
>> >@@ -2071,10 +2071,8 @@ static void wrmsrl_cstar(unsigned long val)
>> > 		wrmsrl(MSR_CSTAR, val);
>> > }
>> >
>> >-/* May not be marked __init: used by software suspend */ -void
>> >syscall_init(void)
>> >+static inline void idt_syscall_init(void)
>> > {
>> >-	wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
>> > 	wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);
>> >
>> > 	if (ia32_enabled()) {
>> >@@ -2108,6 +2106,15 @@ void syscall_init(void)
>> > 	       X86_EFLAGS_AC|X86_EFLAGS_ID);
>> > }
>> >
>> >+/* May not be marked __init: used by software suspend */ void
>> >+syscall_init(void) {
>> >+	/* The default user and kernel segments */
>> >+	wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
>> >+
>> >+	idt_syscall_init();
>> >+}
>> >+
>> > #else	/* CONFIG_X86_64 */
>> >
>> > #ifdef CONFIG_STACKPROTECTOR
>> 
>> Am I missing something, or is this patch a noop?
>
>Yes, this is a noop, just a cleanup patch w/o functionality change.
>
>

It just seems to be completely redundant. We can just drop it, no? If we aren't going to explicitly clobber the registers there is no harm in setting them up for IDT unconditionally.
RE: [PATCH v11 35/37] x86/syscall: Split IDT syscall setup code into idt_syscall_init()
Posted by Li, Xin3 2 years, 4 months ago
> >Yes, this is a noop, just a cleanup patch w/o functionality change.
> >
> It just seems to be completely redundant. We can just drop it, no? If we aren't going
> to explicitly clobber the registers there is no harm in setting them up for IDT
> unconditionally.

If no objection, I can make the change, i.e., unconditionally set these
MSRs up for IDT.