|
@@ -359,16 +359,16 @@ EXPORT_SYMBOL(kernel_thread);
|
|
|
*/
|
|
|
void exit_thread(void)
|
|
|
{
|
|
|
- struct task_struct *tsk = current;
|
|
|
- struct thread_struct *t = &tsk->thread;
|
|
|
-
|
|
|
/* The process may have allocated an io port bitmap... nuke it. */
|
|
|
- if (unlikely(NULL != t->io_bitmap_ptr)) {
|
|
|
+ if (unlikely(test_thread_flag(TIF_IO_BITMAP))) {
|
|
|
+ struct task_struct *tsk = current;
|
|
|
+ struct thread_struct *t = &tsk->thread;
|
|
|
int cpu = get_cpu();
|
|
|
struct tss_struct *tss = &per_cpu(init_tss, cpu);
|
|
|
|
|
|
kfree(t->io_bitmap_ptr);
|
|
|
t->io_bitmap_ptr = NULL;
|
|
|
+ clear_thread_flag(TIF_IO_BITMAP);
|
|
|
/*
|
|
|
* Careful, clear this in the TSS too:
|
|
|
*/
|
|
@@ -387,6 +387,7 @@ void flush_thread(void)
|
|
|
|
|
|
memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
|
|
|
memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
|
|
|
+ clear_tsk_thread_flag(tsk, TIF_DEBUG);
|
|
|
/*
|
|
|
* Forget coprocessor state..
|
|
|
*/
|
|
@@ -431,7 +432,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
|
|
|
savesegment(gs,p->thread.gs);
|
|
|
|
|
|
tsk = current;
|
|
|
- if (unlikely(NULL != tsk->thread.io_bitmap_ptr)) {
|
|
|
+ if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
|
|
|
p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
|
|
|
if (!p->thread.io_bitmap_ptr) {
|
|
|
p->thread.io_bitmap_max = 0;
|
|
@@ -439,6 +440,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
|
|
|
}
|
|
|
memcpy(p->thread.io_bitmap_ptr, tsk->thread.io_bitmap_ptr,
|
|
|
IO_BITMAP_BYTES);
|
|
|
+ set_tsk_thread_flag(p, TIF_IO_BITMAP);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -533,10 +535,24 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
-static inline void
|
|
|
-handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss)
|
|
|
+static noinline void __switch_to_xtra(struct task_struct *next_p,
|
|
|
+ struct tss_struct *tss)
|
|
|
{
|
|
|
- if (!next->io_bitmap_ptr) {
|
|
|
+ struct thread_struct *next;
|
|
|
+
|
|
|
+ next = &next_p->thread;
|
|
|
+
|
|
|
+ if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
|
|
|
+ set_debugreg(next->debugreg[0], 0);
|
|
|
+ set_debugreg(next->debugreg[1], 1);
|
|
|
+ set_debugreg(next->debugreg[2], 2);
|
|
|
+ set_debugreg(next->debugreg[3], 3);
|
|
|
+ /* no 4 and 5 */
|
|
|
+ set_debugreg(next->debugreg[6], 6);
|
|
|
+ set_debugreg(next->debugreg[7], 7);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
|
|
|
/*
|
|
|
* Disable the bitmap via an invalid offset. We still cache
|
|
|
* the previous bitmap owner and the IO bitmap contents:
|
|
@@ -544,6 +560,7 @@ handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss)
|
|
|
tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
|
|
|
return;
|
|
|
}
|
|
|
+
|
|
|
if (likely(next == tss->io_bitmap_owner)) {
|
|
|
/*
|
|
|
* Previous owner of the bitmap (hence the bitmap content)
|
|
@@ -671,20 +688,11 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
|
|
|
set_iopl_mask(next->iopl);
|
|
|
|
|
|
/*
|
|
|
- * Now maybe reload the debug registers
|
|
|
+ * Now maybe handle debug registers and/or IO bitmaps
|
|
|
*/
|
|
|
- if (unlikely(next->debugreg[7])) {
|
|
|
- set_debugreg(next->debugreg[0], 0);
|
|
|
- set_debugreg(next->debugreg[1], 1);
|
|
|
- set_debugreg(next->debugreg[2], 2);
|
|
|
- set_debugreg(next->debugreg[3], 3);
|
|
|
- /* no 4 and 5 */
|
|
|
- set_debugreg(next->debugreg[6], 6);
|
|
|
- set_debugreg(next->debugreg[7], 7);
|
|
|
- }
|
|
|
-
|
|
|
- if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr))
|
|
|
- handle_io_bitmap(next, tss);
|
|
|
+ if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW))
|
|
|
+ || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP))
|
|
|
+ __switch_to_xtra(next_p, tss);
|
|
|
|
|
|
disable_tsc(prev_p, next_p);
|
|
|
|