|
@@ -182,54 +182,61 @@ int set_tsc_mode(unsigned int val)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static inline void switch_to_bitmap(struct tss_struct *tss,
|
|
|
+ struct thread_struct *prev,
|
|
|
+ struct thread_struct *next,
|
|
|
+ unsigned long tifp, unsigned long tifn)
|
|
|
+{
|
|
|
+ if (tifn & _TIF_IO_BITMAP) {
|
|
|
+ /*
|
|
|
+ * Copy the relevant range of the IO bitmap.
|
|
|
+ * Normally this is 128 bytes or less:
|
|
|
+ */
|
|
|
+ memcpy(tss->io_bitmap, next->io_bitmap_ptr,
|
|
|
+ max(prev->io_bitmap_max, next->io_bitmap_max));
|
|
|
+ /*
|
|
|
+ * Make sure that the TSS limit is correct for the CPU
|
|
|
+ * to notice the IO bitmap.
|
|
|
+ */
|
|
|
+ refresh_tss_limit();
|
|
|
+ } else if (tifp & _TIF_IO_BITMAP) {
|
|
|
+ /*
|
|
|
+ * Clear any possible leftover bits:
|
|
|
+ */
|
|
|
+ memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
|
|
|
struct tss_struct *tss)
|
|
|
{
|
|
|
struct thread_struct *prev, *next;
|
|
|
+ unsigned long tifp, tifn;
|
|
|
|
|
|
prev = &prev_p->thread;
|
|
|
next = &next_p->thread;
|
|
|
|
|
|
- if (test_tsk_thread_flag(prev_p, TIF_BLOCKSTEP) ^
|
|
|
- test_tsk_thread_flag(next_p, TIF_BLOCKSTEP)) {
|
|
|
+ tifn = READ_ONCE(task_thread_info(next_p)->flags);
|
|
|
+ tifp = READ_ONCE(task_thread_info(prev_p)->flags);
|
|
|
+ switch_to_bitmap(tss, prev, next, tifp, tifn);
|
|
|
+
|
|
|
+ propagate_user_return_notify(prev_p, next_p);
|
|
|
+
|
|
|
+ if ((tifp ^ tifn) & _TIF_BLOCKSTEP) {
|
|
|
unsigned long debugctl = get_debugctlmsr();
|
|
|
|
|
|
debugctl &= ~DEBUGCTLMSR_BTF;
|
|
|
- if (test_tsk_thread_flag(next_p, TIF_BLOCKSTEP))
|
|
|
+ if (tifn & _TIF_BLOCKSTEP)
|
|
|
debugctl |= DEBUGCTLMSR_BTF;
|
|
|
-
|
|
|
update_debugctlmsr(debugctl);
|
|
|
}
|
|
|
|
|
|
- if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
|
|
|
- test_tsk_thread_flag(next_p, TIF_NOTSC)) {
|
|
|
- /* prev and next are different */
|
|
|
- if (test_tsk_thread_flag(next_p, TIF_NOTSC))
|
|
|
+ if ((tifp ^ tifn) & _TIF_NOTSC) {
|
|
|
+ if (tifn & _TIF_NOTSC)
|
|
|
hard_disable_TSC();
|
|
|
else
|
|
|
hard_enable_TSC();
|
|
|
}
|
|
|
-
|
|
|
- if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
|
|
|
- /*
|
|
|
- * Copy the relevant range of the IO bitmap.
|
|
|
- * Normally this is 128 bytes or less:
|
|
|
- */
|
|
|
- memcpy(tss->io_bitmap, next->io_bitmap_ptr,
|
|
|
- max(prev->io_bitmap_max, next->io_bitmap_max));
|
|
|
-
|
|
|
- /*
|
|
|
- * Make sure that the TSS limit is correct for the CPU
|
|
|
- * to notice the IO bitmap.
|
|
|
- */
|
|
|
- refresh_tss_limit();
|
|
|
- } else if (test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) {
|
|
|
- /*
|
|
|
- * Clear any possible leftover bits:
|
|
|
- */
|
|
|
- memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
|
|
|
- }
|
|
|
- propagate_user_return_notify(prev_p, next_p);
|
|
|
}
|
|
|
|
|
|
/*
|