asm volatile("wrgsbase %0" :: "r" (gsbase) : "memory");
 }
 
+#include <asm/cpufeature.h>
+
 /* Helper functions for reading/writing FS/GS base */
 
 static inline unsigned long x86_fsbase_read_cpu(void)
 {
        unsigned long fsbase;
 
-       rdmsrl(MSR_FS_BASE, fsbase);
+       if (static_cpu_has(X86_FEATURE_FSGSBASE))
+               fsbase = rdfsbase();
+       else
+               rdmsrl(MSR_FS_BASE, fsbase);
 
        return fsbase;
 }
 
-static inline unsigned long x86_gsbase_read_cpu_inactive(void)
-{
-       unsigned long gsbase;
-
-       rdmsrl(MSR_KERNEL_GS_BASE, gsbase);
-
-       return gsbase;
-}
-
 static inline void x86_fsbase_write_cpu(unsigned long fsbase)
 {
-       wrmsrl(MSR_FS_BASE, fsbase);
+       if (static_cpu_has(X86_FEATURE_FSGSBASE))
+               wrfsbase(fsbase);
+       else
+               wrmsrl(MSR_FS_BASE, fsbase);
 }
 
-static inline void x86_gsbase_write_cpu_inactive(unsigned long gsbase)
-{
-       wrmsrl(MSR_KERNEL_GS_BASE, gsbase);
-}
+extern unsigned long x86_gsbase_read_cpu_inactive(void);
+extern void x86_gsbase_write_cpu_inactive(unsigned long gsbase);
 
 #endif /* CONFIG_X86_64 */
 
 
        GS
 };
 
+/*
+ * Out of line to be protected from kprobes. It is not used on Xen
+ * paravirt. When paravirt support is needed, it needs to be renamed
+ * with native_ prefix.
+ */
+static noinline unsigned long __rdgsbase_inactive(void)
+{
+       unsigned long gsbase;
+
+       lockdep_assert_irqs_disabled();
+
+       native_swapgs();
+       gsbase = rdgsbase();
+       native_swapgs();
+
+       return gsbase;
+}
+NOKPROBE_SYMBOL(__rdgsbase_inactive);
+
+/*
+ * Out of line to be protected from kprobes. It is not used on Xen
+ * paravirt. When paravirt support is needed, it needs to be renamed
+ * with native_ prefix.
+ */
+static noinline void __wrgsbase_inactive(unsigned long gsbase)
+{
+       lockdep_assert_irqs_disabled();
+
+       native_swapgs();
+       wrgsbase(gsbase);
+       native_swapgs();
+}
+NOKPROBE_SYMBOL(__wrgsbase_inactive);
+
 /*
  * Saves the FS or GS base for an outgoing thread if FSGSBASE extensions are
  * not available.  The goal is to be reasonably fast on non-FSGSBASE systems.
        return base;
 }
 
+unsigned long x86_gsbase_read_cpu_inactive(void)
+{
+       unsigned long gsbase;
+
+       if (static_cpu_has(X86_FEATURE_FSGSBASE)) {
+               unsigned long flags;
+
+               /* Interrupts are disabled here. */
+               local_irq_save(flags);
+               gsbase = __rdgsbase_inactive();
+               local_irq_restore(flags);
+       } else {
+               rdmsrl(MSR_KERNEL_GS_BASE, gsbase);
+       }
+
+       return gsbase;
+}
+
+void x86_gsbase_write_cpu_inactive(unsigned long gsbase)
+{
+       if (static_cpu_has(X86_FEATURE_FSGSBASE)) {
+               unsigned long flags;
+
+               /* Interrupts are disabled here. */
+               local_irq_save(flags);
+               __wrgsbase_inactive(gsbase);
+               local_irq_restore(flags);
+       } else {
+               wrmsrl(MSR_KERNEL_GS_BASE, gsbase);
+       }
+}
+
 unsigned long x86_fsbase_read_task(struct task_struct *task)
 {
        unsigned long fsbase;