aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrea Arcangeli <andrea@cpushare.com>2007-07-16 02:41:33 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-16 12:05:50 -0400
commitcf99abace7e07dd8491e7093a9a9ef11d48838ed (patch)
tree3b7cfd7c76c2c43e6ae3fdaaff3a50a752072424
parent1d9d02feeee89e9132034d504c9a45eeaf618a3d (diff)
make seccomp zerocost in schedule
This follows a suggestion from Chuck Ebbert on how to make seccomp absolutely zerocost in schedule too. The only remaining footprint of seccomp is in terms of the bzImage size that becomes a few bytes (perhaps even a few kbytes) larger, measure it if you care in the embedded. Signed-off-by: Andrea Arcangeli <andrea@cpushare.com> Cc: Andi Kleen <ak@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/i386/kernel/process.c73
-rw-r--r--include/asm-i386/processor.h4
-rw-r--r--include/asm-i386/thread_info.h5
-rw-r--r--include/linux/seccomp.h10
-rw-r--r--kernel/seccomp.c3
5 files changed, 50 insertions, 45 deletions
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 06dfa65ad180..6c49acb96982 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -538,8 +538,31 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
538 return 1; 538 return 1;
539} 539}
540 540
541static noinline void __switch_to_xtra(struct task_struct *next_p, 541#ifdef CONFIG_SECCOMP
542 struct tss_struct *tss) 542void hard_disable_TSC(void)
543{
544 write_cr4(read_cr4() | X86_CR4_TSD);
545}
546void disable_TSC(void)
547{
548 preempt_disable();
549 if (!test_and_set_thread_flag(TIF_NOTSC))
550 /*
551 * Must flip the CPU state synchronously with
552 * TIF_NOTSC in the current running context.
553 */
554 hard_disable_TSC();
555 preempt_enable();
556}
557void hard_enable_TSC(void)
558{
559 write_cr4(read_cr4() & ~X86_CR4_TSD);
560}
561#endif /* CONFIG_SECCOMP */
562
563static noinline void
564__switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
565 struct tss_struct *tss)
543{ 566{
544 struct thread_struct *next; 567 struct thread_struct *next;
545 568
@@ -555,6 +578,17 @@ static noinline void __switch_to_xtra(struct task_struct *next_p,
555 set_debugreg(next->debugreg[7], 7); 578 set_debugreg(next->debugreg[7], 7);
556 } 579 }
557 580
581#ifdef CONFIG_SECCOMP
582 if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
583 test_tsk_thread_flag(next_p, TIF_NOTSC)) {
584 /* prev and next are different */
585 if (test_tsk_thread_flag(next_p, TIF_NOTSC))
586 hard_disable_TSC();
587 else
588 hard_enable_TSC();
589 }
590#endif
591
558 if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { 592 if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
559 /* 593 /*
560 * Disable the bitmap via an invalid offset. We still cache 594 * Disable the bitmap via an invalid offset. We still cache
@@ -586,33 +620,6 @@ static noinline void __switch_to_xtra(struct task_struct *next_p,
586} 620}
587 621
588/* 622/*
589 * This function selects if the context switch from prev to next
590 * has to tweak the TSC disable bit in the cr4.
591 */
592static inline void disable_tsc(struct task_struct *prev_p,
593 struct task_struct *next_p)
594{
595 struct thread_info *prev, *next;
596
597 /*
598 * gcc should eliminate the ->thread_info dereference if
599 * has_secure_computing returns 0 at compile time (SECCOMP=n).
600 */
601 prev = task_thread_info(prev_p);
602 next = task_thread_info(next_p);
603
604 if (has_secure_computing(prev) || has_secure_computing(next)) {
605 /* slow path here */
606 if (has_secure_computing(prev) &&
607 !has_secure_computing(next)) {
608 write_cr4(read_cr4() & ~X86_CR4_TSD);
609 } else if (!has_secure_computing(prev) &&
610 has_secure_computing(next))
611 write_cr4(read_cr4() | X86_CR4_TSD);
612 }
613}
614
615/*
616 * switch_to(x,yn) should switch tasks from x to y. 623 * switch_to(x,yn) should switch tasks from x to y.
617 * 624 *
618 * We fsave/fwait so that an exception goes off at the right time 625 * We fsave/fwait so that an exception goes off at the right time
@@ -689,11 +696,9 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
689 /* 696 /*
690 * Now maybe handle debug registers and/or IO bitmaps 697 * Now maybe handle debug registers and/or IO bitmaps
691 */ 698 */
692 if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW) 699 if (unlikely(task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV ||
693 || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP))) 700 task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT))
694 __switch_to_xtra(next_p, tss); 701 __switch_to_xtra(prev_p, next_p, tss);
695
696 disable_tsc(prev_p, next_p);
697 702
698 /* 703 /*
699 * Leave lazy mode, flushing any hypercalls made here. 704 * Leave lazy mode, flushing any hypercalls made here.
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 94e0c147c165..422cffef00c9 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -228,6 +228,10 @@ extern int bootloader_type;
228 228
229#define HAVE_ARCH_PICK_MMAP_LAYOUT 229#define HAVE_ARCH_PICK_MMAP_LAYOUT
230 230
231extern void hard_disable_TSC(void);
232extern void disable_TSC(void);
233extern void hard_enable_TSC(void);
234
231/* 235/*
232 * Size of io_bitmap. 236 * Size of io_bitmap.
233 */ 237 */
diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
index 4cb0f91ae64f..54424e045e01 100644
--- a/include/asm-i386/thread_info.h
+++ b/include/asm-i386/thread_info.h
@@ -137,6 +137,7 @@ static inline struct thread_info *current_thread_info(void)
137#define TIF_DEBUG 17 /* uses debug registers */ 137#define TIF_DEBUG 17 /* uses debug registers */
138#define TIF_IO_BITMAP 18 /* uses I/O bitmap */ 138#define TIF_IO_BITMAP 18 /* uses I/O bitmap */
139#define TIF_FREEZE 19 /* is freezing for suspend */ 139#define TIF_FREEZE 19 /* is freezing for suspend */
140#define TIF_NOTSC 20 /* TSC is not accessible in userland */
140 141
141#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) 142#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
142#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) 143#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
@@ -151,6 +152,7 @@ static inline struct thread_info *current_thread_info(void)
151#define _TIF_DEBUG (1<<TIF_DEBUG) 152#define _TIF_DEBUG (1<<TIF_DEBUG)
152#define _TIF_IO_BITMAP (1<<TIF_IO_BITMAP) 153#define _TIF_IO_BITMAP (1<<TIF_IO_BITMAP)
153#define _TIF_FREEZE (1<<TIF_FREEZE) 154#define _TIF_FREEZE (1<<TIF_FREEZE)
155#define _TIF_NOTSC (1<<TIF_NOTSC)
154 156
155/* work to do on interrupt/exception return */ 157/* work to do on interrupt/exception return */
156#define _TIF_WORK_MASK \ 158#define _TIF_WORK_MASK \
@@ -160,7 +162,8 @@ static inline struct thread_info *current_thread_info(void)
160#define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP) 162#define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP)
161 163
162/* flags to check in __switch_to() */ 164/* flags to check in __switch_to() */
163#define _TIF_WORK_CTXSW (_TIF_DEBUG|_TIF_IO_BITMAP) 165#define _TIF_WORK_CTXSW_NEXT (_TIF_IO_BITMAP | _TIF_NOTSC | _TIF_DEBUG)
166#define _TIF_WORK_CTXSW_PREV (_TIF_IO_BITMAP | _TIF_NOTSC)
164 167
165/* 168/*
166 * Thread-synchronous status. 169 * Thread-synchronous status.
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index d708974dbfe3..262a8dccfa81 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -16,11 +16,6 @@ static inline void secure_computing(int this_syscall)
16 __secure_computing(this_syscall); 16 __secure_computing(this_syscall);
17} 17}
18 18
19static inline int has_secure_computing(struct thread_info *ti)
20{
21 return unlikely(test_ti_thread_flag(ti, TIF_SECCOMP));
22}
23
24extern long prctl_get_seccomp(void); 19extern long prctl_get_seccomp(void);
25extern long prctl_set_seccomp(unsigned long); 20extern long prctl_set_seccomp(unsigned long);
26 21
@@ -29,11 +24,6 @@ extern long prctl_set_seccomp(unsigned long);
29typedef struct { } seccomp_t; 24typedef struct { } seccomp_t;
30 25
31#define secure_computing(x) do { } while (0) 26#define secure_computing(x) do { } while (0)
32/* static inline to preserve typechecking */
33static inline int has_secure_computing(struct thread_info *ti)
34{
35 return 0;
36}
37 27
38static inline long prctl_get_seccomp(void) 28static inline long prctl_get_seccomp(void)
39{ 29{
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 1dfa8a509726..ad64fcb731f2 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -74,6 +74,9 @@ long prctl_set_seccomp(unsigned long seccomp_mode)
74 if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) { 74 if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
75 current->seccomp.mode = seccomp_mode; 75 current->seccomp.mode = seccomp_mode;
76 set_thread_flag(TIF_SECCOMP); 76 set_thread_flag(TIF_SECCOMP);
77#ifdef TIF_NOTSC
78 disable_TSC();
79#endif
77 ret = 0; 80 ret = 0;
78 } 81 }
79 82