--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+