From: Andrea Arcangeli akpm: needs new changelog. akpm: I can't see the fuss really - context switch simply isn't as much a fastpath as people think. If you're doing >10,000 switches/second/CPU then you've got problems anyway. Signed-off-by: Andrea Arcangeli Cc: Andi Kleen Signed-off-by: Andrew Morton --- arch/x86_64/kernel/process.c | 29 +++++++++++++++++++++++++++++ include/linux/sched.h | 3 ++- 2 files changed, 31 insertions(+), 1 deletion(-) diff -puN arch/x86_64/kernel/process.c~x86_64-disable-tsc-with-seccomp arch/x86_64/kernel/process.c --- devel/arch/x86_64/kernel/process.c~x86_64-disable-tsc-with-seccomp 2006-01-23 16:41:29.000000000 -0800 +++ devel-akpm/arch/x86_64/kernel/process.c 2006-01-23 16:41:29.000000000 -0800 @@ -506,6 +506,33 @@ out: } /* + * This function selects if the context switch from prev to next + * has to tweak the TSC disable bit in the cr4. + */ +static inline void disable_tsc(struct task_struct *prev_p, + struct task_struct *next_p) +{ + struct thread_info *prev, *next; + + /* + * gcc should eliminate the ->thread_info dereference if + * has_secure_computing returns 0 at compile time (SECCOMP=n). + */ + prev = prev_p->thread_info; + next = next_p->thread_info; + + if (has_secure_computing(prev) || has_secure_computing(next)) { + /* slow path here */ + if (has_secure_computing(prev) && + !has_secure_computing(next)) { + write_cr4(read_cr4() & ~X86_CR4_TSD); + } else if (!has_secure_computing(prev) && + has_secure_computing(next)) + write_cr4((read_cr4() | X86_CR4_TSD) & ~X86_CR4_PCE); + } +} + +/* * This special macro can be used to load a debugging register */ #define loaddebug(thread,r) set_debug(thread->debugreg ## r, r) @@ -625,6 +652,8 @@ __switch_to(struct task_struct *prev_p, } } + disable_tsc(prev_p, next_p); + return prev_p; } diff -puN include/linux/sched.h~x86_64-disable-tsc-with-seccomp include/linux/sched.h --- devel/include/linux/sched.h~x86_64-disable-tsc-with-seccomp 2006-01-23 16:41:29.000000000 -0800 +++ devel-akpm/include/linux/sched.h 2006-01-23 16:41:29.000000000 -0800 @@ -722,6 +722,8 @@ struct task_struct { struct sched_info sched_info; #endif + seccomp_t seccomp; + struct list_head tasks; /* * ptrace_list/ptrace_children forms the list of my children @@ -820,7 +822,6 @@ struct task_struct { void *security; struct audit_context *audit_context; - seccomp_t seccomp; /* Thread group tracking */ u32 parent_exec_id; _