__restore_processor_state() fixes
Subsystems (2)
cover __restore_processor_state() fixes
__restore_processor_state() was spaghetti code, made no sense, and had bugs. And I broke resume on 32-bit systems. This series cleans it up and fixes it (hopefully!).
Andy Lutomirski (3):
x86/power/64: Use struct desc_ptr for the IDT in struct saved_context x86/power/32: Move SYSENTER MSR restoration to fix_processor_context() x86/power: Make restore_processor_context() sane
arch/x86/include/asm/suspend_32.h | 8 +++- arch/x86/include/asm/suspend_64.h | 19 ++++++-- arch/x86/power/cpu.c | 99 ++++++++++++++++++--------------------- 3 files changed, 67 insertions(+), 59 deletions(-)
Signature · 1 line
2.13.6
PATCH 1/3 x86/power/64: Use struct desc_ptr for the IDT in struct saved_context
x86_64's saved_context nonsensically used separate idt_limit and idt_base fields and then cast &idt_limit to struct desc_ptr *. This was correct (with -fno-strict-aliasing), but it's confusing, served no purpose, and required ifdeffery. Just use struct desc_ptr directly.
--- arch/x86/include/asm/suspend_64.h | 3 +-- arch/x86/power/cpu.c | 11 +---------- 2 files changed, 2 insertions(+), 12 deletions(-)
arch/x86/include/asm/suspend_64.h +1 -2
@@ -30,8 +30,7 @@ struct saved_context {u16 gdt_pad;/* Unused */ struct desc_ptr gdt_desc;u16 idt_pad; -u16 idt_limit; -unsigned long idt_base; +struct desc_ptr idt;u16 ldt;u16 tss;unsigned long tr;
arch/x86/power/cpu.c +1 -10
@@ -82,12 +82,8 @@ static void __save_processor_state(struct saved_context *ctxt)/* * descriptor tables */ -#ifdef CONFIG_X86_32 store_idt (&ctxt->idt); -#else -/* CONFIG_X86_64 */ -store_idt ((struct desc_ptr *)&ctxt->idt_limit); -#endif +/* * We save it here, but restore it only in the hibernate case. * For ACPI S3 resume, this is loaded via 'early_gdt_desc' in 64-bit
@@ -219,12 +215,7 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)* now restore the descriptor tables to their proper values * ltr is done i fix_processor_context(). */ -#ifdef CONFIG_X86_32 load_idt (&ctxt->idt); -#else -/* CONFIG_X86_64 */ -load_idt ((const struct desc_ptr *)&ctxt->idt_limit); -#endif #ifdef CONFIG_X86_64 /*
Signature · 1 line
2.13.6
PATCH 2/3 x86/power/32: Move SYSENTER MSR restoration to fix_processor_context()
In reply to Andy Lutomirskix86_64 restores system call MSRs in fix_processor_context(), and x86_32 restored them along with segment registers. The 64-bit variant makes more sense, so move the 32-bit code to match the 64-bit code.
--- arch/x86/power/cpu.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
arch/x86/power/cpu.c +3 -6
@@ -174,6 +174,9 @@ static void fix_processor_context(void)write_gdt_entry (desc,GDT_ENTRY_TSS , &tss,DESC_TSS );syscall_init ();/* This sets MSR_*STAR and related */ +#else +if (boot_cpu_has (X86_FEATURE_SEP )) +enable_sep_cpu ();#endif load_TR_desc ();/* This does ltr */ load_mm_ldt (current->active_mm);/* This does lldt */
@@ -237,12 +240,6 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)loadsegment (fs, ctxt->fs);loadsegment (gs, ctxt->gs);loadsegment (ss, ctxt->ss); - -/* -* sysenter MSRs -*/ -if (boot_cpu_has (X86_FEATURE_SEP )) -enable_sep_cpu ();#else /* CONFIG_X86_64 */ asmvolatile ("movw %0, %%ds" ::"r" (ctxt->ds));
Signature · 1 line
2.13.6
PATCH 3/3 x86/power: Make restore_processor_context() sane
In reply to Andy LutomirskiMy previous attempt to fix a couple of bugs in __restore_processor_context() introduced yet another bug. Rather than trying to come up with a minimal fix, let's try to clean it up for real. This patch fixes quite a few things:
- The old code saved a nonsensical subset of segment registers. The only registers that need to be saved are those that contain userspace state or those that can't be trivially restored without percpu access working. (On x86_32, we can restore percpu access by writing __KERNEL_PERCPU to %fs. On x86_64, it's easier to save and restore the kernel's GSBASE.) With this patch, we restore hardcoded values to the kernel state where applicable and explicitly restore the user state after fixing all the descriptor tables.
- We used to use an unholy mix of inline asm and C helpers for segment register access. Let's get rid of the inline asm.
--- arch/x86/include/asm/suspend_32.h | 8 +++- arch/x86/include/asm/suspend_64.h | 16 +++++++- arch/x86/power/cpu.c | 79 ++++++++++++++++++++------------------- 3 files changed, 62 insertions(+), 41 deletions(-)
arch/x86/include/asm/suspend_32.h +7 -1
@@ -12,7 +12,13 @@/* image of the saved processor state */ struct saved_context { -u16 es, fs, gs, ss; +/* +* On x86_32, all segment registers, with the possible exception of +* gs, are saved at kernel entry in pt_regs. +*/ +#ifdef CONFIG_X86_32_LAZY_GS +u16 gs; +#endif unsigned long cr0, cr2, cr3, cr4;u64 misc_enable;bool misc_enable_saved;
arch/x86/include/asm/suspend_64.h +14 -2
@@ -20,8 +20,20 @@*/ struct saved_context {struct pt_regs regs; -u16 ds, es, fs, gs, ss; -unsigned long gs_base, gs_kernel_base, fs_base; + +/* +* User CS and SS are saved in current_pt_regs(). The rest of the +* segment selectors need to be saved and restored here. +*/ +u16 ds, es, fs, gs; + +/* +* Usermode FSBASE and GSBASE may not match the fs and gs selectors, +* so we save them separately. We save the kernelmode GSBASE to +* restore percpu access after resume. +*/ +unsigned long kernelmode_gs_base, usermode_gs_base, fs_base; +unsigned long cr0, cr2, cr3, cr4, cr8;u64 misc_enable;bool misc_enable_saved;
arch/x86/power/cpu.c +41 -38
118 lines not on this page · raw message
Signature · 1 line
2.13.6
Re: [PATCH urgent 3/3] x86/power: Make restore_processor_context() sane
Hi!
Quoted 15 lines
My previous attempt to fix a couple of bugs in
__restore_processor_context()introduced yet another bug. Rather than trying to come up with a minimal fix, let's try to clean it up for real. This patch fixes quite a few things:- The old code saved a nonsensical subset of segment registers. The only registers that need to be saved are those that contain userspace state or those that can't be trivially restored without percpu access working. (On
x86_32, we can restore percpu access by writing__KERNEL_PERCPUto %fs. Onx86_64, it's easier to save and restore the kernel's GSBASE.) With this patch, we restore hardcoded values to the kernel state where applicable and explicitly restore the user state after fixing all the descriptor tables.
Quoted 6 lines
- We used to use an unholy mix of inline asm and C helpers for segment register access. Let's get rid of the inline asm.
Tested-by Jarkko Nikula <[email protected]>Fixes 5b06bbcfc2c6 ("x86/power: Fix some ordering bugs in __restore_processor_context()")Signed-off-by Andy Lutomirski <[email protected]>
Thanks!
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Quoted 8 lines · CET Andy Lutomirski
__restore_processor_state()was spaghetti code, made no sense, and had bugs. And I broke resume on 32-bit systems. This series cleans it up and fixes it (hopefully!).Andy Lutomirski (3):
x86/power/64: Use structdesc_ptrfor the IDT in structsaved_contextx86/power/32: Move SYSENTER MSR restoration tofix_processor_context()x86/power: Makerestore_processor_context()sane
For all three:
Thanks!
Quoted 6 lines · Rafael J. Wysocki
Quoted 3 lines · CET Andy Lutomirski
__restore_processor_state()was spaghetti code, made no sense, and had bugs. And I broke resume on 32-bit systems. This series cleans it up and fixes it (hopefully!).
And I'm assuming I'll get these from the x86 -tip tree.
If not, somebody please holler, and I'll pick them up directly.
Linus
Quoted 5 lines · Rafael J. Wysocki
Quoted 4 lines · CET Andy Lutomirski
__restore_processor_state()was spaghetti code, made no sense, and had bugs. And I broke resume on 32-bit systems. This series cleans it up and fixes it (hopefully!).
Quoted 9 lines
Quoted 4 lines
Andy Lutomirski (3):
x86/power/64: Use structdesc_ptrfor the IDT in structsaved_contextx86/power/32: Move SYSENTER MSR restoration tofix_processor_context()x86/power: Makerestore_processor_context()saneFor all three:
Works still after split up so my tested by remains. Please note Pavel gave his reported/tested-by in 3/3.
Signature · 1 line
Jarkko
Ingo Molnar
AppliedQuoted 11 lines · Linus Torvalds
Quoted 6 lines · Rafael J. Wysocki
Quoted 3 lines · CET Andy Lutomirski
__restore_processor_state()was spaghetti code, made no sense, and had bugs. And I broke resume on 32-bit systems. This series cleans it up and fixes it (hopefully!).And I'm assuming I'll get these from the x86 -tip tree.
If not, somebody please holler, and I'll pick them up directly.
I have applied them to tip:x86/urgent with small changes to the changelogs, and will send them to you in a couple of hours.
These fixes are really nice, thanks guys for all the effort!
Thanks,
Ingo
Quoted 11 lines · Jarkko Nikula
Quoted 10 lines · Rafael J. Wysocki
Quoted 8 lines · CET Andy Lutomirski
__restore_processor_state()was spaghetti code, made no sense, and had bugs. And I broke resume on 32-bit systems. This series cleans it up and fixes it (hopefully!).Andy Lutomirski (3):
x86/power/64: Use structdesc_ptrfor the IDT in structsaved_contextx86/power/32: Move SYSENTER MSR restoration tofix_processor_context()x86/power: Makerestore_processor_context()sane
Quoted 7 lines
Quoted 4 lines
For all three:
Works still after split up so my tested by remains. Please note Pavel gave his reported/tested-by in 3/3.
Thanks, I've updated all the changelogs - and I've also added your Reported-by tag to patch #3.
Thanks,
Ingo
tip-bot for Andy Lutomirski
merge bot[tip:x86/urgent] x86/power: Make restore_processor_context() sane
In reply to Andy Lutomirskix86/power: Make restore_processor_context() sane
Commit-ID: 7ee18d677989e99635027cee04c878950e0752b9 Gitweb: https://git.kernel.org/tip/7ee18d677989e99635027cee04c878950e0752b9 Author: Andy Lutomirski <[email protected]> AuthorDate: Thu, 14 Dec 2017 13:19:07 -0800 Committer: Ingo Molnar <[email protected]> CommitDate: Fri, 15 Dec 2017 12:21:38 +0100
x86/power: Make restore_processor_context() sane
My previous attempt to fix a couple of bugs in __restore_processor_context():
5b06bbcfc2c6 ("x86/power: Fix some ordering bugs in __restore_processor_context()")
... introduced yet another bug, breaking suspend-resume.
Rather than trying to come up with a minimal fix, let's try to clean it up for real. This patch fixes quite a few things:
- The old code saved a nonsensical subset of segment registers. The only registers that need to be saved are those that contain userspace state or those that can't be trivially restored without percpu access working. (On x86_32, we can restore percpu access by writing __KERNEL_PERCPU to %fs. On x86_64, it's easier to save and restore the kernel's GSBASE.) With this patch, we restore hardcoded values to the kernel state where applicable and explicitly restore the user state after fixing all the descriptor tables.
- We used to use an unholy mix of inline asm and C helpers for segment register access. Let's get rid of the inline asm.
This fixes the reported s2ram hangs and make the code all around more logical.
--- arch/x86/include/asm/suspend_32.h | 8 +++- arch/x86/include/asm/suspend_64.h | 16 +++++++- arch/x86/power/cpu.c | 79 ++++++++++++++++++++------------------- 3 files changed, 62 insertions(+), 41 deletions(-)
arch/x86/include/asm/suspend_32.h +7 -1
@@ -12,7 +12,13 @@/* image of the saved processor state */ struct saved_context { -u16 es, fs, gs, ss; +/* +* On x86_32, all segment registers, with the possible exception of +* gs, are saved at kernel entry in pt_regs. +*/ +#ifdef CONFIG_X86_32_LAZY_GS +u16 gs; +#endif unsigned long cr0, cr2, cr3, cr4;u64 misc_enable;bool misc_enable_saved;
arch/x86/include/asm/suspend_64.h +14 -2
@@ -20,8 +20,20 @@*/ struct saved_context {struct pt_regs regs; -u16 ds, es, fs, gs, ss; -unsigned long gs_base, gs_kernel_base, fs_base; + +/* +* User CS and SS are saved in current_pt_regs(). The rest of the +* segment selectors need to be saved and restored here. +*/ +u16 ds, es, fs, gs; + +/* +* Usermode FSBASE and GSBASE may not match the fs and gs selectors, +* so we save them separately. We save the kernelmode GSBASE to +* restore percpu access after resume. +*/ +unsigned long kernelmode_gs_base, usermode_gs_base, fs_base; +unsigned long cr0, cr2, cr3, cr4, cr8;u64 misc_enable;bool misc_enable_saved;
arch/x86/power/cpu.c +41 -38
118 lines not on this page · raw message
tip-bot for Andy Lutomirski
merge bot[tip:x86/urgent] x86/power/64: Use struct desc_ptr for the IDT in struct saved_context
In reply to Andy Lutomirskix86/power/64: Use struct desc_ptr for the IDT in struct saved_context
Commit-ID: 090edbe23ff57940fca7f57d9165ce57a826bd7a Gitweb: https://git.kernel.org/tip/090edbe23ff57940fca7f57d9165ce57a826bd7a Author: Andy Lutomirski <[email protected]> AuthorDate: Thu, 14 Dec 2017 13:19:05 -0800 Committer: Ingo Molnar <[email protected]> CommitDate: Fri, 15 Dec 2017 12:18:29 +0100
x86/power/64: Use struct desc_ptr for the IDT in struct saved_context
x86_64's saved_context nonsensically used separate idt_limit and idt_base fields and then cast &idt_limit to struct desc_ptr *.
This was correct (with -fno-strict-aliasing), but it's confusing, served no purpose, and required #ifdeffery. Simplify this by using struct desc_ptr directly.
No change in functionality.
--- arch/x86/include/asm/suspend_64.h | 3 +-- arch/x86/power/cpu.c | 11 +---------- 2 files changed, 2 insertions(+), 12 deletions(-)
arch/x86/include/asm/suspend_64.h +1 -2
@@ -30,8 +30,7 @@ struct saved_context {u16 gdt_pad;/* Unused */ struct desc_ptr gdt_desc;u16 idt_pad; -u16 idt_limit; -unsigned long idt_base; +struct desc_ptr idt;u16 ldt;u16 tss;unsigned long tr;
arch/x86/power/cpu.c +1 -10
@@ -82,12 +82,8 @@ static void __save_processor_state(struct saved_context *ctxt)/* * descriptor tables */ -#ifdef CONFIG_X86_32 store_idt (&ctxt->idt); -#else -/* CONFIG_X86_64 */ -store_idt ((struct desc_ptr *)&ctxt->idt_limit); -#endif +/* * We save it here, but restore it only in the hibernate case. * For ACPI S3 resume, this is loaded via 'early_gdt_desc' in 64-bit
@@ -219,12 +215,7 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)* now restore the descriptor tables to their proper values * ltr is done i fix_processor_context(). */ -#ifdef CONFIG_X86_32 load_idt (&ctxt->idt); -#else -/* CONFIG_X86_64 */ -load_idt ((const struct desc_ptr *)&ctxt->idt_limit); -#endif #ifdef CONFIG_X86_64 /*
tip-bot for Andy Lutomirski
merge bot[tip:x86/urgent] x86/power/32: Move SYSENTER MSR restoration to fix_processor_context()
In reply to Andy Lutomirskix86/power/32: Move SYSENTER MSR restoration to fix_processor_context()
Commit-ID: 896c80bef4d3b357814a476663158aaf669d0fb3 Gitweb: https://git.kernel.org/tip/896c80bef4d3b357814a476663158aaf669d0fb3 Author: Andy Lutomirski <[email protected]> AuthorDate: Thu, 14 Dec 2017 13:19:06 -0800 Committer: Ingo Molnar <[email protected]> CommitDate: Fri, 15 Dec 2017 12:18:29 +0100
x86/power/32: Move SYSENTER MSR restoration to fix_processor_context()
x86_64 restores system call MSRs in fix_processor_context(), and x86_32 restored them along with segment registers. The 64-bit variant makes more sense, so move the 32-bit code to match the 64-bit code.
No side effects are expected to runtime behavior.
--- arch/x86/power/cpu.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
arch/x86/power/cpu.c +3 -6
@@ -174,6 +174,9 @@ static void fix_processor_context(void)write_gdt_entry (desc,GDT_ENTRY_TSS , &tss,DESC_TSS );syscall_init ();/* This sets MSR_*STAR and related */ +#else +if (boot_cpu_has (X86_FEATURE_SEP )) +enable_sep_cpu ();#endif load_TR_desc ();/* This does ltr */ load_mm_ldt (current->active_mm);/* This does lldt */
@@ -237,12 +240,6 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)loadsegment (fs, ctxt->fs);loadsegment (gs, ctxt->gs);loadsegment (ss, ctxt->ss); - -/* -* sysenter MSRs -*/ -if (boot_cpu_has (X86_FEATURE_SEP )) -enable_sep_cpu ();#else /* CONFIG_X86_64 */ asmvolatile ("movw %0, %%ds" ::"r" (ctxt->ds));