]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
fixes for 4.14
authorSasha Levin <sashal@kernel.org>
Mon, 8 Apr 2019 23:16:07 +0000 (19:16 -0400)
committerSasha Levin <sashal@kernel.org>
Mon, 8 Apr 2019 23:16:07 +0000 (19:16 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.14/drm-i915-gvt-do-not-let-pin-count-of-shadow-mm-go-ne.patch [new file with mode: 0644]
queue-4.14/net-sfp-move-sfp_register_socket-call-from-sfp_remov.patch [new file with mode: 0644]
queue-4.14/powerpc-tm-limit-tm-code-inside-ppc_transactional_me.patch [new file with mode: 0644]
queue-4.14/series [new file with mode: 0644]
queue-4.14/x86-power-32-move-sysenter-msr-restoration-to-fix_pr.patch [new file with mode: 0644]
queue-4.14/x86-power-64-use-struct-desc_ptr-for-the-idt-in-stru.patch [new file with mode: 0644]
queue-4.14/x86-power-fix-some-ordering-bugs-in-__restore_proces.patch [new file with mode: 0644]
queue-4.14/x86-power-make-restore_processor_context-sane.patch [new file with mode: 0644]

diff --git a/queue-4.14/drm-i915-gvt-do-not-let-pin-count-of-shadow-mm-go-ne.patch b/queue-4.14/drm-i915-gvt-do-not-let-pin-count-of-shadow-mm-go-ne.patch
new file mode 100644 (file)
index 0000000..39b624d
--- /dev/null
@@ -0,0 +1,41 @@
+From 002558d2ebecfcd9d63b349b99e2c2bc8f75376a Mon Sep 17 00:00:00 2001
+From: Yan Zhao <yan.y.zhao@intel.com>
+Date: Mon, 8 Apr 2019 01:12:47 -0400
+Subject: drm/i915/gvt: do not let pin count of shadow mm go negative
+
+[ Upstream commit 663a50ceac75c2208d2ad95365bc8382fd42f44d ]
+
+shadow mm's pin count got increased in workload preparation phase, which
+is after workload scanning.
+it will get decreased in complete_current_workload() anyway after
+workload completion.
+Sometimes, if a workload meets a scanning error, its shadow mm pin count
+will not get increased but will get decreased in the end.
+This patch lets shadow mm's pin count not go below 0.
+
+Fixes: 2707e4446688 ("drm/i915/gvt: vGPU graphics memory virtualization")
+Cc: zhenyuw@linux.intel.com
+Cc: stable@vger.kernel.org #4.14+
+Signed-off-by: Yan Zhao <yan.y.zhao@intel.com>
+Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/gvt/gtt.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
+index dadacbe558ab..1a1f7eb46d1e 100644
+--- a/drivers/gpu/drm/i915/gvt/gtt.c
++++ b/drivers/gpu/drm/i915/gvt/gtt.c
+@@ -1629,7 +1629,7 @@ void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm)
+       if (WARN_ON(mm->type != INTEL_GVT_MM_PPGTT))
+               return;
+-      atomic_dec(&mm->pincount);
++      atomic_dec_if_positive(&mm->pincount);
+ }
+ /**
+-- 
+2.19.1
+
diff --git a/queue-4.14/net-sfp-move-sfp_register_socket-call-from-sfp_remov.patch b/queue-4.14/net-sfp-move-sfp_register_socket-call-from-sfp_remov.patch
new file mode 100644 (file)
index 0000000..a6a1363
--- /dev/null
@@ -0,0 +1,56 @@
+From 5193f75bdc2f151eb6e488c171f30719fec00e74 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <marek.behun@nic.cz>
+Date: Fri, 5 Apr 2019 11:07:58 +0200
+Subject: net: sfp: move sfp_register_socket call from sfp_remove to sfp_probe
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit c4ba68b8691e4 backported from upstream to 4.14 stable was
+probably applied wrongly, and instead of calling sfp_register_socket in
+sfp_probe, the socket registering code was put into sfp_remove. This is
+obviously wrong.
+
+The commit first appeared in 4.14.104. Fix it for the next 4.14 release.
+
+Fixes: c4ba68b8691e4 ("net: sfp: do not probe SFP module before we're attached")
+Cc: stable <stable@vger.kernel.org>
+Cc: Russell King <rmk+kernel@armlinux.org.uk>
+Cc: David S. Miller <davem@davemloft.net>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Marek BehĂșn <marek.behun@nic.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/phy/sfp.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
+index a1b68b19d912..5ab725a571a8 100644
+--- a/drivers/net/phy/sfp.c
++++ b/drivers/net/phy/sfp.c
+@@ -878,6 +878,10 @@ static int sfp_probe(struct platform_device *pdev)
+       if (poll)
+               mod_delayed_work(system_wq, &sfp->poll, poll_jiffies);
++      sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops);
++      if (!sfp->sfp_bus)
++              return -ENOMEM;
++
+       return 0;
+ }
+@@ -887,10 +891,6 @@ static int sfp_remove(struct platform_device *pdev)
+       sfp_unregister_socket(sfp->sfp_bus);
+-      sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops);
+-      if (!sfp->sfp_bus)
+-              return -ENOMEM;
+-
+       return 0;
+ }
+-- 
+2.19.1
+
diff --git a/queue-4.14/powerpc-tm-limit-tm-code-inside-ppc_transactional_me.patch b/queue-4.14/powerpc-tm-limit-tm-code-inside-ppc_transactional_me.patch
new file mode 100644 (file)
index 0000000..ed029a9
--- /dev/null
@@ -0,0 +1,73 @@
+From 4e9a1c280eee932a7a100607a471f56466311eb7 Mon Sep 17 00:00:00 2001
+From: Breno Leitao <leitao@debian.org>
+Date: Mon, 8 Apr 2019 16:32:38 +1000
+Subject: powerpc/tm: Limit TM code inside PPC_TRANSACTIONAL_MEM
+
+[ Upstream commit 897bc3df8c5aebb54c32d831f917592e873d0559 ]
+
+Commit e1c3743e1a20 ("powerpc/tm: Set MSR[TS] just prior to recheckpoint")
+moved a code block around and this block uses a 'msr' variable outside of
+the CONFIG_PPC_TRANSACTIONAL_MEM, however the 'msr' variable is declared
+inside a CONFIG_PPC_TRANSACTIONAL_MEM block, causing a possible error when
+CONFIG_PPC_TRANSACTION_MEM is not defined.
+
+       error: 'msr' undeclared (first use in this function)
+
+This is not causing a compilation error in the mainline kernel, because
+'msr' is being used as an argument of MSR_TM_ACTIVE(), which is defined as
+the following when CONFIG_PPC_TRANSACTIONAL_MEM is *not* set:
+
+       #define MSR_TM_ACTIVE(x) 0
+
+This patch just fixes this issue avoiding the 'msr' variable usage outside
+the CONFIG_PPC_TRANSACTIONAL_MEM block, avoiding trusting in the
+MSR_TM_ACTIVE() definition.
+
+Cc: stable@vger.kernel.org
+Reported-by: Christoph Biedl <linux-kernel.bfrz@manchmal.in-ulm.de>
+Fixes: e1c3743e1a20 ("powerpc/tm: Set MSR[TS] just prior to recheckpoint")
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/kernel/signal_64.c | 23 ++++++++++++++++++-----
+ 1 file changed, 18 insertions(+), 5 deletions(-)
+
+diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
+index 979b9463e17b..927384d85faf 100644
+--- a/arch/powerpc/kernel/signal_64.c
++++ b/arch/powerpc/kernel/signal_64.c
+@@ -746,12 +746,25 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
+               if (restore_tm_sigcontexts(current, &uc->uc_mcontext,
+                                          &uc_transact->uc_mcontext))
+                       goto badframe;
+-      }
+-      else
+-      /* Fall through, for non-TM restore */
++      } else
+ #endif
+-      if (restore_sigcontext(current, NULL, 1, &uc->uc_mcontext))
+-              goto badframe;
++      {
++              /*
++               * Fall through, for non-TM restore
++               *
++               * Unset MSR[TS] on the thread regs since MSR from user
++               * context does not have MSR active, and recheckpoint was
++               * not called since restore_tm_sigcontexts() was not called
++               * also.
++               *
++               * If not unsetting it, the code can RFID to userspace with
++               * MSR[TS] set, but without CPU in the proper state,
++               * causing a TM bad thing.
++               */
++              current->thread.regs->msr &= ~MSR_TS_MASK;
++              if (restore_sigcontext(current, NULL, 1, &uc->uc_mcontext))
++                      goto badframe;
++      }
+       if (restore_altstack(&uc->uc_stack))
+               goto badframe;
+-- 
+2.19.1
+
diff --git a/queue-4.14/series b/queue-4.14/series
new file mode 100644 (file)
index 0000000..3c9f1b1
--- /dev/null
@@ -0,0 +1,7 @@
+net-sfp-move-sfp_register_socket-call-from-sfp_remov.patch
+x86-power-fix-some-ordering-bugs-in-__restore_proces.patch
+x86-power-64-use-struct-desc_ptr-for-the-idt-in-stru.patch
+x86-power-32-move-sysenter-msr-restoration-to-fix_pr.patch
+x86-power-make-restore_processor_context-sane.patch
+drm-i915-gvt-do-not-let-pin-count-of-shadow-mm-go-ne.patch
+powerpc-tm-limit-tm-code-inside-ppc_transactional_me.patch
diff --git a/queue-4.14/x86-power-32-move-sysenter-msr-restoration-to-fix_pr.patch b/queue-4.14/x86-power-32-move-sysenter-msr-restoration-to-fix_pr.patch
new file mode 100644 (file)
index 0000000..6666598
--- /dev/null
@@ -0,0 +1,63 @@
+From d9a9ae47f7af9df371456fb77b29ad2c12bf4dbc Mon Sep 17 00:00:00 2001
+From: Andy Lutomirski <luto@kernel.org>
+Date: Thu, 14 Dec 2017 13:19:06 -0800
+Subject: x86/power/32: Move SYSENTER MSR restoration to
+ fix_processor_context()
+
+[ Upstream commit 896c80bef4d3b357814a476663158aaf669d0fb3 ]
+
+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.
+
+Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
+Signed-off-by: Andy Lutomirski <luto@kernel.org>
+Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Acked-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Borislav Petkov <bpetkov@suse.de>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Pavel Machek <pavel@ucw.cz>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
+Cc: Zhang Rui <rui.zhang@intel.com>
+Link: http://lkml.kernel.org/r/65158f8d7ee64dd6bbc6c1c83b3b34aaa854e3ae.1513286253.git.luto@kernel.org
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/power/cpu.c | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
+index cba2e2c3f89e..8e1668470b23 100644
+--- a/arch/x86/power/cpu.c
++++ b/arch/x86/power/cpu.c
+@@ -176,6 +176,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 */
+@@ -239,12 +242,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 */
+       asm volatile ("movw %0, %%ds" :: "r" (ctxt->ds));
+-- 
+2.19.1
+
diff --git a/queue-4.14/x86-power-64-use-struct-desc_ptr-for-the-idt-in-stru.patch b/queue-4.14/x86-power-64-use-struct-desc_ptr-for-the-idt-in-stru.patch
new file mode 100644 (file)
index 0000000..bfdc525
--- /dev/null
@@ -0,0 +1,83 @@
+From 896f9da0c46953beafe93453bd07c497688e78f3 Mon Sep 17 00:00:00 2001
+From: Andy Lutomirski <luto@kernel.org>
+Date: Thu, 14 Dec 2017 13:19:05 -0800
+Subject: x86/power/64: Use struct desc_ptr for the IDT in struct saved_context
+
+[ Upstream commit 090edbe23ff57940fca7f57d9165ce57a826bd7a ]
+
+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.
+
+Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
+Signed-off-by: Andy Lutomirski <luto@kernel.org>
+Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Acked-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Borislav Petkov <bpetkov@suse.de>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Pavel Machek <pavel@ucw.cz>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
+Cc: Zhang Rui <rui.zhang@intel.com>
+Link: http://lkml.kernel.org/r/967909ce38d341b01d45eff53e278e2728a3a93a.1513286253.git.luto@kernel.org
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/suspend_64.h |  3 +--
+ arch/x86/power/cpu.c              | 11 +----------
+ 2 files changed, 2 insertions(+), 12 deletions(-)
+
+diff --git a/arch/x86/include/asm/suspend_64.h b/arch/x86/include/asm/suspend_64.h
+index 7306e911faee..600e9e0aea51 100644
+--- a/arch/x86/include/asm/suspend_64.h
++++ b/arch/x86/include/asm/suspend_64.h
+@@ -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;
+diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
+index a51d2dfb57d1..cba2e2c3f89e 100644
+--- a/arch/x86/power/cpu.c
++++ b/arch/x86/power/cpu.c
+@@ -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
+@@ -221,12 +217,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
+       /*
+-- 
+2.19.1
+
diff --git a/queue-4.14/x86-power-fix-some-ordering-bugs-in-__restore_proces.patch b/queue-4.14/x86-power-fix-some-ordering-bugs-in-__restore_proces.patch
new file mode 100644 (file)
index 0000000..c753dc2
--- /dev/null
@@ -0,0 +1,128 @@
+From 15b5e7c4808e86d9ffd15b759af8686fd1dfaa5f Mon Sep 17 00:00:00 2001
+From: Andy Lutomirski <luto@kernel.org>
+Date: Thu, 30 Nov 2017 07:57:57 -0800
+Subject: x86/power: Fix some ordering bugs in __restore_processor_context()
+
+[ Upstream commit 5b06bbcfc2c621da3009da8decb7511500c293ed ]
+
+__restore_processor_context() had a couple of ordering bugs.  It
+restored GSBASE after calling load_gs_index(), and the latter can
+call into tracing code.  It also tried to restore segment registers
+before restoring the LDT, which is straight-up wrong.
+
+Reorder the code so that we restore GSBASE, then the descriptor
+tables, then the segments.
+
+This fixes two bugs.  First, it fixes a regression that broke resume
+under certain configurations due to irqflag tracing in
+native_load_gs_index().  Second, it fixes resume when the userspace
+process that initiated suspect had funny segments.  The latter can be
+reproduced by compiling this:
+
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ldt_echo.c - Echo argv[1] while using an LDT segment
+ */
+
+int main(int argc, char **argv)
+{
+       int ret;
+       size_t len;
+       char *buf;
+
+       const struct user_desc desc = {
+                .entry_number    = 0,
+                .base_addr       = 0,
+                .limit           = 0xfffff,
+                .seg_32bit       = 1,
+                .contents        = 0, /* Data, grow-up */
+                .read_exec_only  = 0,
+                .limit_in_pages  = 1,
+                .seg_not_present = 0,
+                .useable         = 0
+        };
+
+       if (argc != 2)
+               errx(1, "Usage: %s STRING", argv[0]);
+
+       len = asprintf(&buf, "%s\n", argv[1]);
+       if (len < 0)
+               errx(1, "Out of memory");
+
+       ret = syscall(SYS_modify_ldt, 1, &desc, sizeof(desc));
+       if (ret < -1)
+               errno = -ret;
+       if (ret)
+               err(1, "modify_ldt");
+
+       asm volatile ("movw %0, %%es" :: "rm" ((unsigned short)7));
+       write(1, buf, len);
+       return 0;
+}
+
+and running ldt_echo >/sys/power/mem
+
+Without the fix, the latter causes a triple fault on resume.
+
+Fixes: ca37e57bbe0c ("x86/entry/64: Add missing irqflags tracing to native_load_gs_index()")
+Reported-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
+Signed-off-by: Andy Lutomirski <luto@kernel.org>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
+Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Link: https://lkml.kernel.org/r/6b31721ea92f51ea839e79bd97ade4a75b1eeea2.1512057304.git.luto@kernel.org
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/power/cpu.c | 21 +++++++++++++++++----
+ 1 file changed, 17 insertions(+), 4 deletions(-)
+
+diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
+index 04d5157fe7f8..a51d2dfb57d1 100644
+--- a/arch/x86/power/cpu.c
++++ b/arch/x86/power/cpu.c
+@@ -228,8 +228,20 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
+       load_idt((const struct desc_ptr *)&ctxt->idt_limit);
+ #endif
++#ifdef CONFIG_X86_64
+       /*
+-       * segment registers
++       * We need GSBASE restored before percpu access can work.
++       * percpu access can happen in exception handlers or in complicated
++       * helpers like load_gs_index().
++       */
++      wrmsrl(MSR_GS_BASE, ctxt->gs_base);
++#endif
++
++      fix_processor_context();
++
++      /*
++       * Restore segment registers.  This happens after restoring the GDT
++       * and LDT, which happen in fix_processor_context().
+        */
+ #ifdef CONFIG_X86_32
+       loadsegment(es, ctxt->es);
+@@ -250,13 +262,14 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
+       load_gs_index(ctxt->gs);
+       asm volatile ("movw %0, %%ss" :: "r" (ctxt->ss));
++      /*
++       * Restore FSBASE and user GSBASE after reloading the respective
++       * segment selectors.
++       */
+       wrmsrl(MSR_FS_BASE, ctxt->fs_base);
+-      wrmsrl(MSR_GS_BASE, ctxt->gs_base);
+       wrmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base);
+ #endif
+-      fix_processor_context();
+-
+       do_fpu_end();
+       tsc_verify_tsc_adjust(true);
+       x86_platform.restore_sched_clock_state();
+-- 
+2.19.1
+
diff --git a/queue-4.14/x86-power-make-restore_processor_context-sane.patch b/queue-4.14/x86-power-make-restore_processor_context-sane.patch
new file mode 100644 (file)
index 0000000..db530c5
--- /dev/null
@@ -0,0 +1,229 @@
+From 5834343942fb3b5abe4e1a97def98504d96ae4ac Mon Sep 17 00:00:00 2001
+From: Andy Lutomirski <luto@kernel.org>
+Date: Thu, 14 Dec 2017 13:19:07 -0800
+Subject: x86/power: Make restore_processor_context() sane
+
+[ Upstream commit 7ee18d677989e99635027cee04c878950e0752b9 ]
+
+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.
+
+Analyzed-by: Linus Torvalds <torvalds@linux-foundation.org>
+Reported-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
+Reported-by: Pavel Machek <pavel@ucw.cz>
+Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
+Tested-by: Pavel Machek <pavel@ucw.cz>
+Signed-off-by: Andy Lutomirski <luto@kernel.org>
+Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Acked-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Borislav Petkov <bpetkov@suse.de>
+Cc: Josh Poimboeuf <jpoimboe@redhat.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
+Cc: Zhang Rui <rui.zhang@intel.com>
+Fixes: 5b06bbcfc2c6 ("x86/power: Fix some ordering bugs in __restore_processor_context()")
+Link: http://lkml.kernel.org/r/398ee68e5c0f766425a7b746becfc810840770ff.1513286253.git.luto@kernel.org
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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(-)
+
+diff --git a/arch/x86/include/asm/suspend_32.h b/arch/x86/include/asm/suspend_32.h
+index 982c325dad33..8be6afb58471 100644
+--- a/arch/x86/include/asm/suspend_32.h
++++ b/arch/x86/include/asm/suspend_32.h
+@@ -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;
+diff --git a/arch/x86/include/asm/suspend_64.h b/arch/x86/include/asm/suspend_64.h
+index 600e9e0aea51..a7af9f53c0cb 100644
+--- a/arch/x86/include/asm/suspend_64.h
++++ b/arch/x86/include/asm/suspend_64.h
+@@ -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;
+diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
+index 8e1668470b23..a7d966964c6f 100644
+--- a/arch/x86/power/cpu.c
++++ b/arch/x86/power/cpu.c
+@@ -99,22 +99,18 @@ static void __save_processor_state(struct saved_context *ctxt)
+       /*
+        * segment registers
+        */
+-#ifdef CONFIG_X86_32
+-      savesegment(es, ctxt->es);
+-      savesegment(fs, ctxt->fs);
++#ifdef CONFIG_X86_32_LAZY_GS
+       savesegment(gs, ctxt->gs);
+-      savesegment(ss, ctxt->ss);
+-#else
+-/* CONFIG_X86_64 */
+-      asm volatile ("movw %%ds, %0" : "=m" (ctxt->ds));
+-      asm volatile ("movw %%es, %0" : "=m" (ctxt->es));
+-      asm volatile ("movw %%fs, %0" : "=m" (ctxt->fs));
+-      asm volatile ("movw %%gs, %0" : "=m" (ctxt->gs));
+-      asm volatile ("movw %%ss, %0" : "=m" (ctxt->ss));
++#endif
++#ifdef CONFIG_X86_64
++      savesegment(gs, ctxt->gs);
++      savesegment(fs, ctxt->fs);
++      savesegment(ds, ctxt->ds);
++      savesegment(es, ctxt->es);
+       rdmsrl(MSR_FS_BASE, ctxt->fs_base);
+-      rdmsrl(MSR_GS_BASE, ctxt->gs_base);
+-      rdmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base);
++      rdmsrl(MSR_GS_BASE, ctxt->kernelmode_gs_base);
++      rdmsrl(MSR_KERNEL_GS_BASE, ctxt->usermode_gs_base);
+       mtrr_save_fixed_ranges(NULL);
+       rdmsrl(MSR_EFER, ctxt->efer);
+@@ -191,9 +187,12 @@ static void fix_processor_context(void)
+ }
+ /**
+- *    __restore_processor_state - restore the contents of CPU registers saved
+- *            by __save_processor_state()
+- *    @ctxt - structure to load the registers contents from
++ * __restore_processor_state - restore the contents of CPU registers saved
++ *                             by __save_processor_state()
++ * @ctxt - structure to load the registers contents from
++ *
++ * The asm code that gets us here will have restored a usable GDT, although
++ * it will be pointing to the wrong alias.
+  */
+ static void notrace __restore_processor_state(struct saved_context *ctxt)
+ {
+@@ -216,46 +215,50 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
+       write_cr2(ctxt->cr2);
+       write_cr0(ctxt->cr0);
++      /* Restore the IDT. */
++      load_idt(&ctxt->idt);
++
+       /*
+-       * now restore the descriptor tables to their proper values
+-       * ltr is done i fix_processor_context().
++       * Just in case the asm code got us here with the SS, DS, or ES
++       * out of sync with the GDT, update them.
+        */
+-      load_idt(&ctxt->idt);
++      loadsegment(ss, __KERNEL_DS);
++      loadsegment(ds, __USER_DS);
++      loadsegment(es, __USER_DS);
+-#ifdef CONFIG_X86_64
+       /*
+-       * We need GSBASE restored before percpu access can work.
+-       * percpu access can happen in exception handlers or in complicated
+-       * helpers like load_gs_index().
++       * Restore percpu access.  Percpu access can happen in exception
++       * handlers or in complicated helpers like load_gs_index().
+        */
+-      wrmsrl(MSR_GS_BASE, ctxt->gs_base);
++#ifdef CONFIG_X86_64
++      wrmsrl(MSR_GS_BASE, ctxt->kernelmode_gs_base);
++#else
++      loadsegment(fs, __KERNEL_PERCPU);
++      loadsegment(gs, __KERNEL_STACK_CANARY);
+ #endif
++      /* Restore the TSS, RO GDT, LDT, and usermode-relevant MSRs. */
+       fix_processor_context();
+       /*
+-       * Restore segment registers.  This happens after restoring the GDT
+-       * and LDT, which happen in fix_processor_context().
++       * Now that we have descriptor tables fully restored and working
++       * exception handling, restore the usermode segments.
+        */
+-#ifdef CONFIG_X86_32
++#ifdef CONFIG_X86_64
++      loadsegment(ds, ctxt->es);
+       loadsegment(es, ctxt->es);
+       loadsegment(fs, ctxt->fs);
+-      loadsegment(gs, ctxt->gs);
+-      loadsegment(ss, ctxt->ss);
+-#else
+-/* CONFIG_X86_64 */
+-      asm volatile ("movw %0, %%ds" :: "r" (ctxt->ds));
+-      asm volatile ("movw %0, %%es" :: "r" (ctxt->es));
+-      asm volatile ("movw %0, %%fs" :: "r" (ctxt->fs));
+       load_gs_index(ctxt->gs);
+-      asm volatile ("movw %0, %%ss" :: "r" (ctxt->ss));
+       /*
+-       * Restore FSBASE and user GSBASE after reloading the respective
+-       * segment selectors.
++       * Restore FSBASE and GSBASE after restoring the selectors, since
++       * restoring the selectors clobbers the bases.  Keep in mind
++       * that MSR_KERNEL_GS_BASE is horribly misnamed.
+        */
+       wrmsrl(MSR_FS_BASE, ctxt->fs_base);
+-      wrmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base);
++      wrmsrl(MSR_KERNEL_GS_BASE, ctxt->usermode_gs_base);
++#elif defined(CONFIG_X86_32_LAZY_GS)
++      loadsegment(gs, ctxt->gs);
+ #endif
+       do_fpu_end();
+-- 
+2.19.1
+