{
        savesegment(fs, task->thread.fsindex);
        savesegment(gs, task->thread.gsindex);
-       save_base_legacy(task, task->thread.fsindex, FS);
-       save_base_legacy(task, task->thread.gsindex, GS);
+       if (static_cpu_has(X86_FEATURE_FSGSBASE)) {
+               /*
+                * If FSGSBASE is enabled, we can't make any useful guesses
+                * about the base, and user code expects us to save the current
+                * value.  Fortunately, reading the base directly is efficient.
+                */
+               task->thread.fsbase = rdfsbase();
+               task->thread.gsbase = __rdgsbase_inactive();
+       } else {
+               save_base_legacy(task, task->thread.fsindex, FS);
+               save_base_legacy(task, task->thread.gsindex, GS);
+       }
 }
 
 #if IS_ENABLED(CONFIG_KVM)
 static __always_inline void x86_fsgsbase_load(struct thread_struct *prev,
                                              struct thread_struct *next)
 {
-       load_seg_legacy(prev->fsindex, prev->fsbase,
-                       next->fsindex, next->fsbase, FS);
-       load_seg_legacy(prev->gsindex, prev->gsbase,
-                       next->gsindex, next->gsbase, GS);
+       if (static_cpu_has(X86_FEATURE_FSGSBASE)) {
+               /* Update the FS and GS selectors if they could have changed. */
+               if (unlikely(prev->fsindex || next->fsindex))
+                       loadseg(FS, next->fsindex);
+               if (unlikely(prev->gsindex || next->gsindex))
+                       loadseg(GS, next->gsindex);
+
+               /* Update the bases. */
+               wrfsbase(next->fsbase);
+               __wrgsbase_inactive(next->gsbase);
+       } else {
+               load_seg_legacy(prev->fsindex, prev->fsbase,
+                               next->fsindex, next->fsbase, FS);
+               load_seg_legacy(prev->gsindex, prev->gsbase,
+                               next->gsindex, next->gsbase, GS);
+       }
 }
 
 static unsigned long x86_fsgsbase_read_task(struct task_struct *task,