diff options
author | mboton@gmail.com <mboton@gmail.com> | 2008-01-30 07:33:10 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:33:10 -0500 |
commit | ccafa59a0061d7c44d15d02403120fd02b52c667 (patch) | |
tree | 46783be3e882843ea2057697a28b97de4bdea1f8 /arch | |
parent | aaf230424204864e2833dcc1da23e2cb0b9f39cd (diff) |
x86: ioport_{32|64}.c unification
ioport_{32|64}.c unification.
This patch unifies the code from the ioport_32.c and ioport_64.c files.
Tested and working fine with i386 and x86_64 kernels.
Signed-off-by: Miguel Botón <mboton@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/kernel/ioport.c (renamed from arch/x86/kernel/ioport_32.c) | 37 | ||||
-rw-r--r-- | arch/x86/kernel/ioport_64.c | 117 |
3 files changed, 30 insertions, 126 deletions
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 3d23ccd366ea..c414c45a0f13 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -10,7 +10,7 @@ CFLAGS_vsyscall_64.o := $(PROFILING) -g0 | |||
10 | 10 | ||
11 | obj-y := process_$(BITS).o signal_$(BITS).o entry_$(BITS).o | 11 | obj-y := process_$(BITS).o signal_$(BITS).o entry_$(BITS).o |
12 | obj-y += traps_$(BITS).o irq_$(BITS).o | 12 | obj-y += traps_$(BITS).o irq_$(BITS).o |
13 | obj-y += time_$(BITS).o ioport_$(BITS).o ldt.o | 13 | obj-y += time_$(BITS).o ioport.o ldt.o |
14 | obj-y += setup_$(BITS).o i8259_$(BITS).o | 14 | obj-y += setup_$(BITS).o i8259_$(BITS).o |
15 | obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o | 15 | obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o |
16 | obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o | 16 | obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o |
diff --git a/arch/x86/kernel/ioport_32.c b/arch/x86/kernel/ioport.c index 9295e01ff49c..e723ff3b1d53 100644 --- a/arch/x86/kernel/ioport_32.c +++ b/arch/x86/kernel/ioport.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * This contains the io-permission bitmap code - written by obz, with changes | 2 | * This contains the io-permission bitmap code - written by obz, with changes |
3 | * by Linus. | 3 | * by Linus. 32/64 bits code unification by Miguel Botón. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/sched.h> | 6 | #include <linux/sched.h> |
@@ -36,7 +36,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) | |||
36 | { | 36 | { |
37 | struct thread_struct * t = ¤t->thread; | 37 | struct thread_struct * t = ¤t->thread; |
38 | struct tss_struct * tss; | 38 | struct tss_struct * tss; |
39 | unsigned long i, max_long; | 39 | unsigned int i, max_long, bytes, bytes_updated; |
40 | 40 | ||
41 | if ((from + num <= from) || (from + num > IO_BITMAP_BITS)) | 41 | if ((from + num <= from) || (from + num > IO_BITMAP_BITS)) |
42 | return -EINVAL; | 42 | return -EINVAL; |
@@ -79,8 +79,12 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) | |||
79 | if (t->io_bitmap_ptr[i] != ~0UL) | 79 | if (t->io_bitmap_ptr[i] != ~0UL) |
80 | max_long = i; | 80 | max_long = i; |
81 | 81 | ||
82 | t->io_bitmap_max = (max_long + 1) * sizeof(unsigned long); | 82 | bytes = (max_long + 1) * sizeof(unsigned long); |
83 | bytes_updated = max(bytes, t->io_bitmap_max); | ||
83 | 84 | ||
85 | t->io_bitmap_max = bytes; | ||
86 | |||
87 | #ifdef CONFIG_X86_32 | ||
84 | /* | 88 | /* |
85 | * Sets the lazy trigger so that the next I/O operation will | 89 | * Sets the lazy trigger so that the next I/O operation will |
86 | * reload the correct bitmap. | 90 | * reload the correct bitmap. |
@@ -89,6 +93,10 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) | |||
89 | */ | 93 | */ |
90 | tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY; | 94 | tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY; |
91 | tss->io_bitmap_owner = NULL; | 95 | tss->io_bitmap_owner = NULL; |
96 | #else | ||
97 | /* Update the TSS: */ | ||
98 | memcpy(tss->io_bitmap, t->io_bitmap_ptr, bytes_updated); | ||
99 | #endif | ||
92 | 100 | ||
93 | put_cpu(); | 101 | put_cpu(); |
94 | 102 | ||
@@ -105,13 +113,12 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) | |||
105 | * on system-call entry - see also fork() and the signal handling | 113 | * on system-call entry - see also fork() and the signal handling |
106 | * code. | 114 | * code. |
107 | */ | 115 | */ |
108 | 116 | #ifdef CONFIG_X86_32 | |
109 | asmlinkage long sys_iopl(unsigned long regsp) | 117 | asmlinkage long sys_iopl(unsigned long regsp) |
110 | { | 118 | { |
111 | volatile struct pt_regs *regs = (struct pt_regs *)®sp; | 119 | volatile struct pt_regs *regs = (struct pt_regs *)®sp; |
112 | unsigned int level = regs->bx; | 120 | unsigned int level = regs->bx; |
113 | unsigned int old = (regs->flags >> 12) & 3; | 121 | unsigned int old = (regs->flags >> 12) & 3; |
114 | struct thread_struct *t = ¤t->thread; | ||
115 | 122 | ||
116 | if (level > 3) | 123 | if (level > 3) |
117 | return -EINVAL; | 124 | return -EINVAL; |
@@ -120,10 +127,24 @@ asmlinkage long sys_iopl(unsigned long regsp) | |||
120 | if (!capable(CAP_SYS_RAWIO)) | 127 | if (!capable(CAP_SYS_RAWIO)) |
121 | return -EPERM; | 128 | return -EPERM; |
122 | } | 129 | } |
130 | regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | #else | ||
135 | asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs) | ||
136 | { | ||
137 | unsigned int old = (regs->flags >> 12) & 3; | ||
123 | 138 | ||
124 | t->iopl = level << 12; | 139 | if (level > 3) |
125 | regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | t->iopl; | 140 | return -EINVAL; |
126 | set_iopl_mask(t->iopl); | 141 | /* Trying to gain more privileges? */ |
142 | if (level > old) { | ||
143 | if (!capable(CAP_SYS_RAWIO)) | ||
144 | return -EPERM; | ||
145 | } | ||
146 | regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); | ||
127 | 147 | ||
128 | return 0; | 148 | return 0; |
129 | } | 149 | } |
150 | #endif | ||
diff --git a/arch/x86/kernel/ioport_64.c b/arch/x86/kernel/ioport_64.c deleted file mode 100644 index ff7514b757e5..000000000000 --- a/arch/x86/kernel/ioport_64.c +++ /dev/null | |||
@@ -1,117 +0,0 @@ | |||
1 | /* | ||
2 | * This contains the io-permission bitmap code - written by obz, with changes | ||
3 | * by Linus. | ||
4 | */ | ||
5 | |||
6 | #include <linux/sched.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/capability.h> | ||
9 | #include <linux/errno.h> | ||
10 | #include <linux/types.h> | ||
11 | #include <linux/ioport.h> | ||
12 | #include <linux/smp.h> | ||
13 | #include <linux/stddef.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/thread_info.h> | ||
16 | #include <linux/syscalls.h> | ||
17 | |||
18 | /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ | ||
19 | static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int extent, int new_value) | ||
20 | { | ||
21 | int i; | ||
22 | if (new_value) | ||
23 | for (i = base; i < base + extent; i++) | ||
24 | __set_bit(i, bitmap); | ||
25 | else | ||
26 | for (i = base; i < base + extent; i++) | ||
27 | clear_bit(i, bitmap); | ||
28 | } | ||
29 | |||
30 | /* | ||
31 | * this changes the io permissions bitmap in the current task. | ||
32 | */ | ||
33 | asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) | ||
34 | { | ||
35 | unsigned int i, max_long, bytes, bytes_updated; | ||
36 | struct thread_struct * t = ¤t->thread; | ||
37 | struct tss_struct * tss; | ||
38 | unsigned long *bitmap; | ||
39 | |||
40 | if ((from + num <= from) || (from + num > IO_BITMAP_BITS)) | ||
41 | return -EINVAL; | ||
42 | if (turn_on && !capable(CAP_SYS_RAWIO)) | ||
43 | return -EPERM; | ||
44 | |||
45 | /* | ||
46 | * If it's the first ioperm() call in this thread's lifetime, set the | ||
47 | * IO bitmap up. ioperm() is much less timing critical than clone(), | ||
48 | * this is why we delay this operation until now: | ||
49 | */ | ||
50 | if (!t->io_bitmap_ptr) { | ||
51 | bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); | ||
52 | if (!bitmap) | ||
53 | return -ENOMEM; | ||
54 | |||
55 | memset(bitmap, 0xff, IO_BITMAP_BYTES); | ||
56 | t->io_bitmap_ptr = bitmap; | ||
57 | set_thread_flag(TIF_IO_BITMAP); | ||
58 | } | ||
59 | |||
60 | /* | ||
61 | * do it in the per-thread copy and in the TSS ... | ||
62 | * | ||
63 | * Disable preemption via get_cpu() - we must not switch away | ||
64 | * because the ->io_bitmap_max value must match the bitmap | ||
65 | * contents: | ||
66 | */ | ||
67 | tss = &per_cpu(init_tss, get_cpu()); | ||
68 | |||
69 | set_bitmap(t->io_bitmap_ptr, from, num, !turn_on); | ||
70 | |||
71 | /* | ||
72 | * Search for a (possibly new) maximum. This is simple and stupid, | ||
73 | * to keep it obviously correct: | ||
74 | */ | ||
75 | max_long = 0; | ||
76 | for (i = 0; i < IO_BITMAP_LONGS; i++) | ||
77 | if (t->io_bitmap_ptr[i] != ~0UL) | ||
78 | max_long = i; | ||
79 | |||
80 | bytes = (max_long + 1) * sizeof(long); | ||
81 | bytes_updated = max(bytes, t->io_bitmap_max); | ||
82 | |||
83 | t->io_bitmap_max = bytes; | ||
84 | |||
85 | /* Update the TSS: */ | ||
86 | memcpy(tss->io_bitmap, t->io_bitmap_ptr, bytes_updated); | ||
87 | |||
88 | put_cpu(); | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | /* | ||
94 | * sys_iopl has to be used when you want to access the IO ports | ||
95 | * beyond the 0x3ff range: to get the full 65536 ports bitmapped | ||
96 | * you'd need 8kB of bitmaps/process, which is a bit excessive. | ||
97 | * | ||
98 | * Here we just change the flags value on the stack: we allow | ||
99 | * only the super-user to do it. This depends on the stack-layout | ||
100 | * on system-call entry - see also fork() and the signal handling | ||
101 | * code. | ||
102 | */ | ||
103 | |||
104 | asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs) | ||
105 | { | ||
106 | unsigned int old = (regs->flags >> 12) & 3; | ||
107 | |||
108 | if (level > 3) | ||
109 | return -EINVAL; | ||
110 | /* Trying to gain more privileges? */ | ||
111 | if (level > old) { | ||
112 | if (!capable(CAP_SYS_RAWIO)) | ||
113 | return -EPERM; | ||
114 | } | ||
115 | regs->flags = (regs->flags &~ X86_EFLAGS_IOPL) | (level << 12); | ||
116 | return 0; | ||
117 | } | ||