hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
kernel/arch/x86/kernel/process_64.c
....@@ -272,9 +272,9 @@
272272 unsigned long flags;
273273
274274 /* Interrupts need to be off for FSGSBASE */
275
- local_irq_save(flags);
275
+ local_irq_save_full(flags);
276276 save_fsgs(current);
277
- local_irq_restore(flags);
277
+ local_irq_restore_full(flags);
278278 }
279279 #if IS_ENABLED(CONFIG_KVM)
280280 EXPORT_SYMBOL_GPL(current_save_fsgs);
....@@ -410,9 +410,9 @@
410410 if (boot_cpu_has(X86_FEATURE_FSGSBASE)) {
411411 unsigned long flags;
412412
413
- local_irq_save(flags);
413
+ local_irq_save_full(flags);
414414 gsbase = __rdgsbase_inactive();
415
- local_irq_restore(flags);
415
+ local_irq_restore_full(flags);
416416 } else {
417417 rdmsrl(MSR_KERNEL_GS_BASE, gsbase);
418418 }
....@@ -425,9 +425,9 @@
425425 if (boot_cpu_has(X86_FEATURE_FSGSBASE)) {
426426 unsigned long flags;
427427
428
- local_irq_save(flags);
428
+ local_irq_save_full(flags);
429429 __wrgsbase_inactive(gsbase);
430
- local_irq_restore(flags);
430
+ local_irq_restore_full(flags);
431431 } else {
432432 wrmsrl(MSR_KERNEL_GS_BASE, gsbase);
433433 }
....@@ -537,8 +537,17 @@
537537 struct thread_struct *next = &next_p->thread;
538538 int cpu = smp_processor_id();
539539
540
+ /*
541
+ * Dovetail: Switching context on the out-of-band stage is
542
+ * legit, and we may have preempted an in-band (soft)irq
543
+ * handler earlier. Since oob handlers never switch stack,
544
+ * make sure to restrict the following test to in-band
545
+ * callers.
546
+ */
540547 WARN_ON_ONCE(IS_ENABLED(CONFIG_DEBUG_ENTRY) &&
541
- this_cpu_read(irq_count) != -1);
548
+ running_inband() && this_cpu_read(irq_count) != -1);
549
+
550
+ WARN_ON_ONCE(dovetail_debug() && !hard_irqs_disabled());
542551
543552 if (!test_thread_flag(TIF_NEED_FPU_LOAD))
544553 switch_fpu_prepare(prev_p, cpu);
....@@ -719,6 +728,7 @@
719728
720729 long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2)
721730 {
731
+ unsigned long flags;
722732 int ret = 0;
723733
724734 switch (option) {
....@@ -726,7 +736,7 @@
726736 if (unlikely(arg2 >= TASK_SIZE_MAX))
727737 return -EPERM;
728738
729
- preempt_disable();
739
+ flags = hard_preempt_disable();
730740 /*
731741 * ARCH_SET_GS has always overwritten the index
732742 * and the base. Zero is the most sensible value
....@@ -747,7 +757,7 @@
747757 task->thread.gsindex = 0;
748758 x86_gsbase_write_task(task, arg2);
749759 }
750
- preempt_enable();
760
+ hard_preempt_enable(flags);
751761 break;
752762 }
753763 case ARCH_SET_FS: {
....@@ -758,7 +768,7 @@
758768 if (unlikely(arg2 >= TASK_SIZE_MAX))
759769 return -EPERM;
760770
761
- preempt_disable();
771
+ flags = hard_preempt_disable();
762772 /*
763773 * Set the selector to 0 for the same reason
764774 * as %gs above.
....@@ -776,7 +786,7 @@
776786 task->thread.fsindex = 0;
777787 x86_fsbase_write_task(task, arg2);
778788 }
779
- preempt_enable();
789
+ hard_preempt_enable(flags);
780790 break;
781791 }
782792 case ARCH_GET_FS: {