Commit 88fc241f54459ac3d86c5e13b449730199f66061
Committed by
Tony Luck
1 parent
0773a6cf67
Exists in
master
and in
7 other branches
[IA64] dump stack on kernel unaligned warnings
Often the cause of kernel unaligned access warnings is not obvious from just the ip displayed in the warning. This adds the option via proc to dump the stack in addition to the warning. The default is off (just display the 1 line warning). To enable the stack to be shown: echo 1 > /proc/sys/kernel/unaligned-dump-stack Signed-off-by: Doug Chapman <doug.chapman@hp.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
Showing 2 changed files with 14 additions and 1 deletions Inline Diff
arch/ia64/kernel/unaligned.c
1 | /* | 1 | /* |
2 | * Architecture-specific unaligned trap handling. | 2 | * Architecture-specific unaligned trap handling. |
3 | * | 3 | * |
4 | * Copyright (C) 1999-2002, 2004 Hewlett-Packard Co | 4 | * Copyright (C) 1999-2002, 2004 Hewlett-Packard Co |
5 | * Stephane Eranian <eranian@hpl.hp.com> | 5 | * Stephane Eranian <eranian@hpl.hp.com> |
6 | * David Mosberger-Tang <davidm@hpl.hp.com> | 6 | * David Mosberger-Tang <davidm@hpl.hp.com> |
7 | * | 7 | * |
8 | * 2002/12/09 Fix rotating register handling (off-by-1 error, missing fr-rotation). Fix | 8 | * 2002/12/09 Fix rotating register handling (off-by-1 error, missing fr-rotation). Fix |
9 | * get_rse_reg() to not leak kernel bits to user-level (reading an out-of-frame | 9 | * get_rse_reg() to not leak kernel bits to user-level (reading an out-of-frame |
10 | * stacked register returns an undefined value; it does NOT trigger a | 10 | * stacked register returns an undefined value; it does NOT trigger a |
11 | * "rsvd register fault"). | 11 | * "rsvd register fault"). |
12 | * 2001/10/11 Fix unaligned access to rotating registers in s/w pipelined loops. | 12 | * 2001/10/11 Fix unaligned access to rotating registers in s/w pipelined loops. |
13 | * 2001/08/13 Correct size of extended floats (float_fsz) from 16 to 10 bytes. | 13 | * 2001/08/13 Correct size of extended floats (float_fsz) from 16 to 10 bytes. |
14 | * 2001/01/17 Add support emulation of unaligned kernel accesses. | 14 | * 2001/01/17 Add support emulation of unaligned kernel accesses. |
15 | */ | 15 | */ |
16 | #include <linux/jiffies.h> | 16 | #include <linux/jiffies.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | #include <linux/tty.h> | 19 | #include <linux/tty.h> |
20 | 20 | ||
21 | #include <asm/intrinsics.h> | 21 | #include <asm/intrinsics.h> |
22 | #include <asm/processor.h> | 22 | #include <asm/processor.h> |
23 | #include <asm/rse.h> | 23 | #include <asm/rse.h> |
24 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
25 | #include <asm/unaligned.h> | 25 | #include <asm/unaligned.h> |
26 | 26 | ||
27 | extern int die_if_kernel(char *str, struct pt_regs *regs, long err); | 27 | extern int die_if_kernel(char *str, struct pt_regs *regs, long err); |
28 | 28 | ||
29 | #undef DEBUG_UNALIGNED_TRAP | 29 | #undef DEBUG_UNALIGNED_TRAP |
30 | 30 | ||
31 | #ifdef DEBUG_UNALIGNED_TRAP | 31 | #ifdef DEBUG_UNALIGNED_TRAP |
32 | # define DPRINT(a...) do { printk("%s %u: ", __func__, __LINE__); printk (a); } while (0) | 32 | # define DPRINT(a...) do { printk("%s %u: ", __func__, __LINE__); printk (a); } while (0) |
33 | # define DDUMP(str,vp,len) dump(str, vp, len) | 33 | # define DDUMP(str,vp,len) dump(str, vp, len) |
34 | 34 | ||
35 | static void | 35 | static void |
36 | dump (const char *str, void *vp, size_t len) | 36 | dump (const char *str, void *vp, size_t len) |
37 | { | 37 | { |
38 | unsigned char *cp = vp; | 38 | unsigned char *cp = vp; |
39 | int i; | 39 | int i; |
40 | 40 | ||
41 | printk("%s", str); | 41 | printk("%s", str); |
42 | for (i = 0; i < len; ++i) | 42 | for (i = 0; i < len; ++i) |
43 | printk (" %02x", *cp++); | 43 | printk (" %02x", *cp++); |
44 | printk("\n"); | 44 | printk("\n"); |
45 | } | 45 | } |
46 | #else | 46 | #else |
47 | # define DPRINT(a...) | 47 | # define DPRINT(a...) |
48 | # define DDUMP(str,vp,len) | 48 | # define DDUMP(str,vp,len) |
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | #define IA64_FIRST_STACKED_GR 32 | 51 | #define IA64_FIRST_STACKED_GR 32 |
52 | #define IA64_FIRST_ROTATING_FR 32 | 52 | #define IA64_FIRST_ROTATING_FR 32 |
53 | #define SIGN_EXT9 0xffffffffffffff00ul | 53 | #define SIGN_EXT9 0xffffffffffffff00ul |
54 | 54 | ||
55 | /* | 55 | /* |
56 | * sysctl settable hook which tells the kernel whether to honor the | 56 | * sysctl settable hook which tells the kernel whether to honor the |
57 | * IA64_THREAD_UAC_NOPRINT prctl. Because this is user settable, we want | 57 | * IA64_THREAD_UAC_NOPRINT prctl. Because this is user settable, we want |
58 | * to allow the super user to enable/disable this for security reasons | 58 | * to allow the super user to enable/disable this for security reasons |
59 | * (i.e. don't allow attacker to fill up logs with unaligned accesses). | 59 | * (i.e. don't allow attacker to fill up logs with unaligned accesses). |
60 | */ | 60 | */ |
61 | int no_unaligned_warning; | 61 | int no_unaligned_warning; |
62 | int unaligned_dump_stack; | ||
62 | static int noprint_warning; | 63 | static int noprint_warning; |
63 | 64 | ||
64 | /* | 65 | /* |
65 | * For M-unit: | 66 | * For M-unit: |
66 | * | 67 | * |
67 | * opcode | m | x6 | | 68 | * opcode | m | x6 | |
68 | * --------|------|---------| | 69 | * --------|------|---------| |
69 | * [40-37] | [36] | [35:30] | | 70 | * [40-37] | [36] | [35:30] | |
70 | * --------|------|---------| | 71 | * --------|------|---------| |
71 | * 4 | 1 | 6 | = 11 bits | 72 | * 4 | 1 | 6 | = 11 bits |
72 | * -------------------------- | 73 | * -------------------------- |
73 | * However bits [31:30] are not directly useful to distinguish between | 74 | * However bits [31:30] are not directly useful to distinguish between |
74 | * load/store so we can use [35:32] instead, which gives the following | 75 | * load/store so we can use [35:32] instead, which gives the following |
75 | * mask ([40:32]) using 9 bits. The 'e' comes from the fact that we defer | 76 | * mask ([40:32]) using 9 bits. The 'e' comes from the fact that we defer |
76 | * checking the m-bit until later in the load/store emulation. | 77 | * checking the m-bit until later in the load/store emulation. |
77 | */ | 78 | */ |
78 | #define IA64_OPCODE_MASK 0x1ef | 79 | #define IA64_OPCODE_MASK 0x1ef |
79 | #define IA64_OPCODE_SHIFT 32 | 80 | #define IA64_OPCODE_SHIFT 32 |
80 | 81 | ||
81 | /* | 82 | /* |
82 | * Table C-28 Integer Load/Store | 83 | * Table C-28 Integer Load/Store |
83 | * | 84 | * |
84 | * We ignore [35:32]= 0x6, 0x7, 0xE, 0xF | 85 | * We ignore [35:32]= 0x6, 0x7, 0xE, 0xF |
85 | * | 86 | * |
86 | * ld8.fill, st8.fill MUST be aligned because the RNATs are based on | 87 | * ld8.fill, st8.fill MUST be aligned because the RNATs are based on |
87 | * the address (bits [8:3]), so we must failed. | 88 | * the address (bits [8:3]), so we must failed. |
88 | */ | 89 | */ |
89 | #define LD_OP 0x080 | 90 | #define LD_OP 0x080 |
90 | #define LDS_OP 0x081 | 91 | #define LDS_OP 0x081 |
91 | #define LDA_OP 0x082 | 92 | #define LDA_OP 0x082 |
92 | #define LDSA_OP 0x083 | 93 | #define LDSA_OP 0x083 |
93 | #define LDBIAS_OP 0x084 | 94 | #define LDBIAS_OP 0x084 |
94 | #define LDACQ_OP 0x085 | 95 | #define LDACQ_OP 0x085 |
95 | /* 0x086, 0x087 are not relevant */ | 96 | /* 0x086, 0x087 are not relevant */ |
96 | #define LDCCLR_OP 0x088 | 97 | #define LDCCLR_OP 0x088 |
97 | #define LDCNC_OP 0x089 | 98 | #define LDCNC_OP 0x089 |
98 | #define LDCCLRACQ_OP 0x08a | 99 | #define LDCCLRACQ_OP 0x08a |
99 | #define ST_OP 0x08c | 100 | #define ST_OP 0x08c |
100 | #define STREL_OP 0x08d | 101 | #define STREL_OP 0x08d |
101 | /* 0x08e,0x8f are not relevant */ | 102 | /* 0x08e,0x8f are not relevant */ |
102 | 103 | ||
103 | /* | 104 | /* |
104 | * Table C-29 Integer Load +Reg | 105 | * Table C-29 Integer Load +Reg |
105 | * | 106 | * |
106 | * we use the ld->m (bit [36:36]) field to determine whether or not we have | 107 | * we use the ld->m (bit [36:36]) field to determine whether or not we have |
107 | * a load/store of this form. | 108 | * a load/store of this form. |
108 | */ | 109 | */ |
109 | 110 | ||
110 | /* | 111 | /* |
111 | * Table C-30 Integer Load/Store +Imm | 112 | * Table C-30 Integer Load/Store +Imm |
112 | * | 113 | * |
113 | * We ignore [35:32]= 0x6, 0x7, 0xE, 0xF | 114 | * We ignore [35:32]= 0x6, 0x7, 0xE, 0xF |
114 | * | 115 | * |
115 | * ld8.fill, st8.fill must be aligned because the Nat register are based on | 116 | * ld8.fill, st8.fill must be aligned because the Nat register are based on |
116 | * the address, so we must fail and the program must be fixed. | 117 | * the address, so we must fail and the program must be fixed. |
117 | */ | 118 | */ |
118 | #define LD_IMM_OP 0x0a0 | 119 | #define LD_IMM_OP 0x0a0 |
119 | #define LDS_IMM_OP 0x0a1 | 120 | #define LDS_IMM_OP 0x0a1 |
120 | #define LDA_IMM_OP 0x0a2 | 121 | #define LDA_IMM_OP 0x0a2 |
121 | #define LDSA_IMM_OP 0x0a3 | 122 | #define LDSA_IMM_OP 0x0a3 |
122 | #define LDBIAS_IMM_OP 0x0a4 | 123 | #define LDBIAS_IMM_OP 0x0a4 |
123 | #define LDACQ_IMM_OP 0x0a5 | 124 | #define LDACQ_IMM_OP 0x0a5 |
124 | /* 0x0a6, 0xa7 are not relevant */ | 125 | /* 0x0a6, 0xa7 are not relevant */ |
125 | #define LDCCLR_IMM_OP 0x0a8 | 126 | #define LDCCLR_IMM_OP 0x0a8 |
126 | #define LDCNC_IMM_OP 0x0a9 | 127 | #define LDCNC_IMM_OP 0x0a9 |
127 | #define LDCCLRACQ_IMM_OP 0x0aa | 128 | #define LDCCLRACQ_IMM_OP 0x0aa |
128 | #define ST_IMM_OP 0x0ac | 129 | #define ST_IMM_OP 0x0ac |
129 | #define STREL_IMM_OP 0x0ad | 130 | #define STREL_IMM_OP 0x0ad |
130 | /* 0x0ae,0xaf are not relevant */ | 131 | /* 0x0ae,0xaf are not relevant */ |
131 | 132 | ||
132 | /* | 133 | /* |
133 | * Table C-32 Floating-point Load/Store | 134 | * Table C-32 Floating-point Load/Store |
134 | */ | 135 | */ |
135 | #define LDF_OP 0x0c0 | 136 | #define LDF_OP 0x0c0 |
136 | #define LDFS_OP 0x0c1 | 137 | #define LDFS_OP 0x0c1 |
137 | #define LDFA_OP 0x0c2 | 138 | #define LDFA_OP 0x0c2 |
138 | #define LDFSA_OP 0x0c3 | 139 | #define LDFSA_OP 0x0c3 |
139 | /* 0x0c6 is irrelevant */ | 140 | /* 0x0c6 is irrelevant */ |
140 | #define LDFCCLR_OP 0x0c8 | 141 | #define LDFCCLR_OP 0x0c8 |
141 | #define LDFCNC_OP 0x0c9 | 142 | #define LDFCNC_OP 0x0c9 |
142 | /* 0x0cb is irrelevant */ | 143 | /* 0x0cb is irrelevant */ |
143 | #define STF_OP 0x0cc | 144 | #define STF_OP 0x0cc |
144 | 145 | ||
145 | /* | 146 | /* |
146 | * Table C-33 Floating-point Load +Reg | 147 | * Table C-33 Floating-point Load +Reg |
147 | * | 148 | * |
148 | * we use the ld->m (bit [36:36]) field to determine whether or not we have | 149 | * we use the ld->m (bit [36:36]) field to determine whether or not we have |
149 | * a load/store of this form. | 150 | * a load/store of this form. |
150 | */ | 151 | */ |
151 | 152 | ||
152 | /* | 153 | /* |
153 | * Table C-34 Floating-point Load/Store +Imm | 154 | * Table C-34 Floating-point Load/Store +Imm |
154 | */ | 155 | */ |
155 | #define LDF_IMM_OP 0x0e0 | 156 | #define LDF_IMM_OP 0x0e0 |
156 | #define LDFS_IMM_OP 0x0e1 | 157 | #define LDFS_IMM_OP 0x0e1 |
157 | #define LDFA_IMM_OP 0x0e2 | 158 | #define LDFA_IMM_OP 0x0e2 |
158 | #define LDFSA_IMM_OP 0x0e3 | 159 | #define LDFSA_IMM_OP 0x0e3 |
159 | /* 0x0e6 is irrelevant */ | 160 | /* 0x0e6 is irrelevant */ |
160 | #define LDFCCLR_IMM_OP 0x0e8 | 161 | #define LDFCCLR_IMM_OP 0x0e8 |
161 | #define LDFCNC_IMM_OP 0x0e9 | 162 | #define LDFCNC_IMM_OP 0x0e9 |
162 | #define STF_IMM_OP 0x0ec | 163 | #define STF_IMM_OP 0x0ec |
163 | 164 | ||
164 | typedef struct { | 165 | typedef struct { |
165 | unsigned long qp:6; /* [0:5] */ | 166 | unsigned long qp:6; /* [0:5] */ |
166 | unsigned long r1:7; /* [6:12] */ | 167 | unsigned long r1:7; /* [6:12] */ |
167 | unsigned long imm:7; /* [13:19] */ | 168 | unsigned long imm:7; /* [13:19] */ |
168 | unsigned long r3:7; /* [20:26] */ | 169 | unsigned long r3:7; /* [20:26] */ |
169 | unsigned long x:1; /* [27:27] */ | 170 | unsigned long x:1; /* [27:27] */ |
170 | unsigned long hint:2; /* [28:29] */ | 171 | unsigned long hint:2; /* [28:29] */ |
171 | unsigned long x6_sz:2; /* [30:31] */ | 172 | unsigned long x6_sz:2; /* [30:31] */ |
172 | unsigned long x6_op:4; /* [32:35], x6 = x6_sz|x6_op */ | 173 | unsigned long x6_op:4; /* [32:35], x6 = x6_sz|x6_op */ |
173 | unsigned long m:1; /* [36:36] */ | 174 | unsigned long m:1; /* [36:36] */ |
174 | unsigned long op:4; /* [37:40] */ | 175 | unsigned long op:4; /* [37:40] */ |
175 | unsigned long pad:23; /* [41:63] */ | 176 | unsigned long pad:23; /* [41:63] */ |
176 | } load_store_t; | 177 | } load_store_t; |
177 | 178 | ||
178 | 179 | ||
179 | typedef enum { | 180 | typedef enum { |
180 | UPD_IMMEDIATE, /* ldXZ r1=[r3],imm(9) */ | 181 | UPD_IMMEDIATE, /* ldXZ r1=[r3],imm(9) */ |
181 | UPD_REG /* ldXZ r1=[r3],r2 */ | 182 | UPD_REG /* ldXZ r1=[r3],r2 */ |
182 | } update_t; | 183 | } update_t; |
183 | 184 | ||
184 | /* | 185 | /* |
185 | * We use tables to keep track of the offsets of registers in the saved state. | 186 | * We use tables to keep track of the offsets of registers in the saved state. |
186 | * This way we save having big switch/case statements. | 187 | * This way we save having big switch/case statements. |
187 | * | 188 | * |
188 | * We use bit 0 to indicate switch_stack or pt_regs. | 189 | * We use bit 0 to indicate switch_stack or pt_regs. |
189 | * The offset is simply shifted by 1 bit. | 190 | * The offset is simply shifted by 1 bit. |
190 | * A 2-byte value should be enough to hold any kind of offset | 191 | * A 2-byte value should be enough to hold any kind of offset |
191 | * | 192 | * |
192 | * In case the calling convention changes (and thus pt_regs/switch_stack) | 193 | * In case the calling convention changes (and thus pt_regs/switch_stack) |
193 | * simply use RSW instead of RPT or vice-versa. | 194 | * simply use RSW instead of RPT or vice-versa. |
194 | */ | 195 | */ |
195 | 196 | ||
196 | #define RPO(x) ((size_t) &((struct pt_regs *)0)->x) | 197 | #define RPO(x) ((size_t) &((struct pt_regs *)0)->x) |
197 | #define RSO(x) ((size_t) &((struct switch_stack *)0)->x) | 198 | #define RSO(x) ((size_t) &((struct switch_stack *)0)->x) |
198 | 199 | ||
199 | #define RPT(x) (RPO(x) << 1) | 200 | #define RPT(x) (RPO(x) << 1) |
200 | #define RSW(x) (1| RSO(x)<<1) | 201 | #define RSW(x) (1| RSO(x)<<1) |
201 | 202 | ||
202 | #define GR_OFFS(x) (gr_info[x]>>1) | 203 | #define GR_OFFS(x) (gr_info[x]>>1) |
203 | #define GR_IN_SW(x) (gr_info[x] & 0x1) | 204 | #define GR_IN_SW(x) (gr_info[x] & 0x1) |
204 | 205 | ||
205 | #define FR_OFFS(x) (fr_info[x]>>1) | 206 | #define FR_OFFS(x) (fr_info[x]>>1) |
206 | #define FR_IN_SW(x) (fr_info[x] & 0x1) | 207 | #define FR_IN_SW(x) (fr_info[x] & 0x1) |
207 | 208 | ||
208 | static u16 gr_info[32]={ | 209 | static u16 gr_info[32]={ |
209 | 0, /* r0 is read-only : WE SHOULD NEVER GET THIS */ | 210 | 0, /* r0 is read-only : WE SHOULD NEVER GET THIS */ |
210 | 211 | ||
211 | RPT(r1), RPT(r2), RPT(r3), | 212 | RPT(r1), RPT(r2), RPT(r3), |
212 | 213 | ||
213 | RSW(r4), RSW(r5), RSW(r6), RSW(r7), | 214 | RSW(r4), RSW(r5), RSW(r6), RSW(r7), |
214 | 215 | ||
215 | RPT(r8), RPT(r9), RPT(r10), RPT(r11), | 216 | RPT(r8), RPT(r9), RPT(r10), RPT(r11), |
216 | RPT(r12), RPT(r13), RPT(r14), RPT(r15), | 217 | RPT(r12), RPT(r13), RPT(r14), RPT(r15), |
217 | 218 | ||
218 | RPT(r16), RPT(r17), RPT(r18), RPT(r19), | 219 | RPT(r16), RPT(r17), RPT(r18), RPT(r19), |
219 | RPT(r20), RPT(r21), RPT(r22), RPT(r23), | 220 | RPT(r20), RPT(r21), RPT(r22), RPT(r23), |
220 | RPT(r24), RPT(r25), RPT(r26), RPT(r27), | 221 | RPT(r24), RPT(r25), RPT(r26), RPT(r27), |
221 | RPT(r28), RPT(r29), RPT(r30), RPT(r31) | 222 | RPT(r28), RPT(r29), RPT(r30), RPT(r31) |
222 | }; | 223 | }; |
223 | 224 | ||
224 | static u16 fr_info[32]={ | 225 | static u16 fr_info[32]={ |
225 | 0, /* constant : WE SHOULD NEVER GET THIS */ | 226 | 0, /* constant : WE SHOULD NEVER GET THIS */ |
226 | 0, /* constant : WE SHOULD NEVER GET THIS */ | 227 | 0, /* constant : WE SHOULD NEVER GET THIS */ |
227 | 228 | ||
228 | RSW(f2), RSW(f3), RSW(f4), RSW(f5), | 229 | RSW(f2), RSW(f3), RSW(f4), RSW(f5), |
229 | 230 | ||
230 | RPT(f6), RPT(f7), RPT(f8), RPT(f9), | 231 | RPT(f6), RPT(f7), RPT(f8), RPT(f9), |
231 | RPT(f10), RPT(f11), | 232 | RPT(f10), RPT(f11), |
232 | 233 | ||
233 | RSW(f12), RSW(f13), RSW(f14), | 234 | RSW(f12), RSW(f13), RSW(f14), |
234 | RSW(f15), RSW(f16), RSW(f17), RSW(f18), RSW(f19), | 235 | RSW(f15), RSW(f16), RSW(f17), RSW(f18), RSW(f19), |
235 | RSW(f20), RSW(f21), RSW(f22), RSW(f23), RSW(f24), | 236 | RSW(f20), RSW(f21), RSW(f22), RSW(f23), RSW(f24), |
236 | RSW(f25), RSW(f26), RSW(f27), RSW(f28), RSW(f29), | 237 | RSW(f25), RSW(f26), RSW(f27), RSW(f28), RSW(f29), |
237 | RSW(f30), RSW(f31) | 238 | RSW(f30), RSW(f31) |
238 | }; | 239 | }; |
239 | 240 | ||
240 | /* Invalidate ALAT entry for integer register REGNO. */ | 241 | /* Invalidate ALAT entry for integer register REGNO. */ |
241 | static void | 242 | static void |
242 | invala_gr (int regno) | 243 | invala_gr (int regno) |
243 | { | 244 | { |
244 | # define F(reg) case reg: ia64_invala_gr(reg); break | 245 | # define F(reg) case reg: ia64_invala_gr(reg); break |
245 | 246 | ||
246 | switch (regno) { | 247 | switch (regno) { |
247 | F( 0); F( 1); F( 2); F( 3); F( 4); F( 5); F( 6); F( 7); | 248 | F( 0); F( 1); F( 2); F( 3); F( 4); F( 5); F( 6); F( 7); |
248 | F( 8); F( 9); F( 10); F( 11); F( 12); F( 13); F( 14); F( 15); | 249 | F( 8); F( 9); F( 10); F( 11); F( 12); F( 13); F( 14); F( 15); |
249 | F( 16); F( 17); F( 18); F( 19); F( 20); F( 21); F( 22); F( 23); | 250 | F( 16); F( 17); F( 18); F( 19); F( 20); F( 21); F( 22); F( 23); |
250 | F( 24); F( 25); F( 26); F( 27); F( 28); F( 29); F( 30); F( 31); | 251 | F( 24); F( 25); F( 26); F( 27); F( 28); F( 29); F( 30); F( 31); |
251 | F( 32); F( 33); F( 34); F( 35); F( 36); F( 37); F( 38); F( 39); | 252 | F( 32); F( 33); F( 34); F( 35); F( 36); F( 37); F( 38); F( 39); |
252 | F( 40); F( 41); F( 42); F( 43); F( 44); F( 45); F( 46); F( 47); | 253 | F( 40); F( 41); F( 42); F( 43); F( 44); F( 45); F( 46); F( 47); |
253 | F( 48); F( 49); F( 50); F( 51); F( 52); F( 53); F( 54); F( 55); | 254 | F( 48); F( 49); F( 50); F( 51); F( 52); F( 53); F( 54); F( 55); |
254 | F( 56); F( 57); F( 58); F( 59); F( 60); F( 61); F( 62); F( 63); | 255 | F( 56); F( 57); F( 58); F( 59); F( 60); F( 61); F( 62); F( 63); |
255 | F( 64); F( 65); F( 66); F( 67); F( 68); F( 69); F( 70); F( 71); | 256 | F( 64); F( 65); F( 66); F( 67); F( 68); F( 69); F( 70); F( 71); |
256 | F( 72); F( 73); F( 74); F( 75); F( 76); F( 77); F( 78); F( 79); | 257 | F( 72); F( 73); F( 74); F( 75); F( 76); F( 77); F( 78); F( 79); |
257 | F( 80); F( 81); F( 82); F( 83); F( 84); F( 85); F( 86); F( 87); | 258 | F( 80); F( 81); F( 82); F( 83); F( 84); F( 85); F( 86); F( 87); |
258 | F( 88); F( 89); F( 90); F( 91); F( 92); F( 93); F( 94); F( 95); | 259 | F( 88); F( 89); F( 90); F( 91); F( 92); F( 93); F( 94); F( 95); |
259 | F( 96); F( 97); F( 98); F( 99); F(100); F(101); F(102); F(103); | 260 | F( 96); F( 97); F( 98); F( 99); F(100); F(101); F(102); F(103); |
260 | F(104); F(105); F(106); F(107); F(108); F(109); F(110); F(111); | 261 | F(104); F(105); F(106); F(107); F(108); F(109); F(110); F(111); |
261 | F(112); F(113); F(114); F(115); F(116); F(117); F(118); F(119); | 262 | F(112); F(113); F(114); F(115); F(116); F(117); F(118); F(119); |
262 | F(120); F(121); F(122); F(123); F(124); F(125); F(126); F(127); | 263 | F(120); F(121); F(122); F(123); F(124); F(125); F(126); F(127); |
263 | } | 264 | } |
264 | # undef F | 265 | # undef F |
265 | } | 266 | } |
266 | 267 | ||
267 | /* Invalidate ALAT entry for floating-point register REGNO. */ | 268 | /* Invalidate ALAT entry for floating-point register REGNO. */ |
268 | static void | 269 | static void |
269 | invala_fr (int regno) | 270 | invala_fr (int regno) |
270 | { | 271 | { |
271 | # define F(reg) case reg: ia64_invala_fr(reg); break | 272 | # define F(reg) case reg: ia64_invala_fr(reg); break |
272 | 273 | ||
273 | switch (regno) { | 274 | switch (regno) { |
274 | F( 0); F( 1); F( 2); F( 3); F( 4); F( 5); F( 6); F( 7); | 275 | F( 0); F( 1); F( 2); F( 3); F( 4); F( 5); F( 6); F( 7); |
275 | F( 8); F( 9); F( 10); F( 11); F( 12); F( 13); F( 14); F( 15); | 276 | F( 8); F( 9); F( 10); F( 11); F( 12); F( 13); F( 14); F( 15); |
276 | F( 16); F( 17); F( 18); F( 19); F( 20); F( 21); F( 22); F( 23); | 277 | F( 16); F( 17); F( 18); F( 19); F( 20); F( 21); F( 22); F( 23); |
277 | F( 24); F( 25); F( 26); F( 27); F( 28); F( 29); F( 30); F( 31); | 278 | F( 24); F( 25); F( 26); F( 27); F( 28); F( 29); F( 30); F( 31); |
278 | F( 32); F( 33); F( 34); F( 35); F( 36); F( 37); F( 38); F( 39); | 279 | F( 32); F( 33); F( 34); F( 35); F( 36); F( 37); F( 38); F( 39); |
279 | F( 40); F( 41); F( 42); F( 43); F( 44); F( 45); F( 46); F( 47); | 280 | F( 40); F( 41); F( 42); F( 43); F( 44); F( 45); F( 46); F( 47); |
280 | F( 48); F( 49); F( 50); F( 51); F( 52); F( 53); F( 54); F( 55); | 281 | F( 48); F( 49); F( 50); F( 51); F( 52); F( 53); F( 54); F( 55); |
281 | F( 56); F( 57); F( 58); F( 59); F( 60); F( 61); F( 62); F( 63); | 282 | F( 56); F( 57); F( 58); F( 59); F( 60); F( 61); F( 62); F( 63); |
282 | F( 64); F( 65); F( 66); F( 67); F( 68); F( 69); F( 70); F( 71); | 283 | F( 64); F( 65); F( 66); F( 67); F( 68); F( 69); F( 70); F( 71); |
283 | F( 72); F( 73); F( 74); F( 75); F( 76); F( 77); F( 78); F( 79); | 284 | F( 72); F( 73); F( 74); F( 75); F( 76); F( 77); F( 78); F( 79); |
284 | F( 80); F( 81); F( 82); F( 83); F( 84); F( 85); F( 86); F( 87); | 285 | F( 80); F( 81); F( 82); F( 83); F( 84); F( 85); F( 86); F( 87); |
285 | F( 88); F( 89); F( 90); F( 91); F( 92); F( 93); F( 94); F( 95); | 286 | F( 88); F( 89); F( 90); F( 91); F( 92); F( 93); F( 94); F( 95); |
286 | F( 96); F( 97); F( 98); F( 99); F(100); F(101); F(102); F(103); | 287 | F( 96); F( 97); F( 98); F( 99); F(100); F(101); F(102); F(103); |
287 | F(104); F(105); F(106); F(107); F(108); F(109); F(110); F(111); | 288 | F(104); F(105); F(106); F(107); F(108); F(109); F(110); F(111); |
288 | F(112); F(113); F(114); F(115); F(116); F(117); F(118); F(119); | 289 | F(112); F(113); F(114); F(115); F(116); F(117); F(118); F(119); |
289 | F(120); F(121); F(122); F(123); F(124); F(125); F(126); F(127); | 290 | F(120); F(121); F(122); F(123); F(124); F(125); F(126); F(127); |
290 | } | 291 | } |
291 | # undef F | 292 | # undef F |
292 | } | 293 | } |
293 | 294 | ||
294 | static inline unsigned long | 295 | static inline unsigned long |
295 | rotate_reg (unsigned long sor, unsigned long rrb, unsigned long reg) | 296 | rotate_reg (unsigned long sor, unsigned long rrb, unsigned long reg) |
296 | { | 297 | { |
297 | reg += rrb; | 298 | reg += rrb; |
298 | if (reg >= sor) | 299 | if (reg >= sor) |
299 | reg -= sor; | 300 | reg -= sor; |
300 | return reg; | 301 | return reg; |
301 | } | 302 | } |
302 | 303 | ||
303 | static void | 304 | static void |
304 | set_rse_reg (struct pt_regs *regs, unsigned long r1, unsigned long val, int nat) | 305 | set_rse_reg (struct pt_regs *regs, unsigned long r1, unsigned long val, int nat) |
305 | { | 306 | { |
306 | struct switch_stack *sw = (struct switch_stack *) regs - 1; | 307 | struct switch_stack *sw = (struct switch_stack *) regs - 1; |
307 | unsigned long *bsp, *bspstore, *addr, *rnat_addr, *ubs_end; | 308 | unsigned long *bsp, *bspstore, *addr, *rnat_addr, *ubs_end; |
308 | unsigned long *kbs = (void *) current + IA64_RBS_OFFSET; | 309 | unsigned long *kbs = (void *) current + IA64_RBS_OFFSET; |
309 | unsigned long rnats, nat_mask; | 310 | unsigned long rnats, nat_mask; |
310 | unsigned long on_kbs; | 311 | unsigned long on_kbs; |
311 | long sof = (regs->cr_ifs) & 0x7f; | 312 | long sof = (regs->cr_ifs) & 0x7f; |
312 | long sor = 8 * ((regs->cr_ifs >> 14) & 0xf); | 313 | long sor = 8 * ((regs->cr_ifs >> 14) & 0xf); |
313 | long rrb_gr = (regs->cr_ifs >> 18) & 0x7f; | 314 | long rrb_gr = (regs->cr_ifs >> 18) & 0x7f; |
314 | long ridx = r1 - 32; | 315 | long ridx = r1 - 32; |
315 | 316 | ||
316 | if (ridx >= sof) { | 317 | if (ridx >= sof) { |
317 | /* this should never happen, as the "rsvd register fault" has higher priority */ | 318 | /* this should never happen, as the "rsvd register fault" has higher priority */ |
318 | DPRINT("ignoring write to r%lu; only %lu registers are allocated!\n", r1, sof); | 319 | DPRINT("ignoring write to r%lu; only %lu registers are allocated!\n", r1, sof); |
319 | return; | 320 | return; |
320 | } | 321 | } |
321 | 322 | ||
322 | if (ridx < sor) | 323 | if (ridx < sor) |
323 | ridx = rotate_reg(sor, rrb_gr, ridx); | 324 | ridx = rotate_reg(sor, rrb_gr, ridx); |
324 | 325 | ||
325 | DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld ridx=%ld\n", | 326 | DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld ridx=%ld\n", |
326 | r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f, ridx); | 327 | r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f, ridx); |
327 | 328 | ||
328 | on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore); | 329 | on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore); |
329 | addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + ridx); | 330 | addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + ridx); |
330 | if (addr >= kbs) { | 331 | if (addr >= kbs) { |
331 | /* the register is on the kernel backing store: easy... */ | 332 | /* the register is on the kernel backing store: easy... */ |
332 | rnat_addr = ia64_rse_rnat_addr(addr); | 333 | rnat_addr = ia64_rse_rnat_addr(addr); |
333 | if ((unsigned long) rnat_addr >= sw->ar_bspstore) | 334 | if ((unsigned long) rnat_addr >= sw->ar_bspstore) |
334 | rnat_addr = &sw->ar_rnat; | 335 | rnat_addr = &sw->ar_rnat; |
335 | nat_mask = 1UL << ia64_rse_slot_num(addr); | 336 | nat_mask = 1UL << ia64_rse_slot_num(addr); |
336 | 337 | ||
337 | *addr = val; | 338 | *addr = val; |
338 | if (nat) | 339 | if (nat) |
339 | *rnat_addr |= nat_mask; | 340 | *rnat_addr |= nat_mask; |
340 | else | 341 | else |
341 | *rnat_addr &= ~nat_mask; | 342 | *rnat_addr &= ~nat_mask; |
342 | return; | 343 | return; |
343 | } | 344 | } |
344 | 345 | ||
345 | if (!user_stack(current, regs)) { | 346 | if (!user_stack(current, regs)) { |
346 | DPRINT("ignoring kernel write to r%lu; register isn't on the kernel RBS!", r1); | 347 | DPRINT("ignoring kernel write to r%lu; register isn't on the kernel RBS!", r1); |
347 | return; | 348 | return; |
348 | } | 349 | } |
349 | 350 | ||
350 | bspstore = (unsigned long *)regs->ar_bspstore; | 351 | bspstore = (unsigned long *)regs->ar_bspstore; |
351 | ubs_end = ia64_rse_skip_regs(bspstore, on_kbs); | 352 | ubs_end = ia64_rse_skip_regs(bspstore, on_kbs); |
352 | bsp = ia64_rse_skip_regs(ubs_end, -sof); | 353 | bsp = ia64_rse_skip_regs(ubs_end, -sof); |
353 | addr = ia64_rse_skip_regs(bsp, ridx); | 354 | addr = ia64_rse_skip_regs(bsp, ridx); |
354 | 355 | ||
355 | DPRINT("ubs_end=%p bsp=%p addr=%p\n", (void *) ubs_end, (void *) bsp, (void *) addr); | 356 | DPRINT("ubs_end=%p bsp=%p addr=%p\n", (void *) ubs_end, (void *) bsp, (void *) addr); |
356 | 357 | ||
357 | ia64_poke(current, sw, (unsigned long) ubs_end, (unsigned long) addr, val); | 358 | ia64_poke(current, sw, (unsigned long) ubs_end, (unsigned long) addr, val); |
358 | 359 | ||
359 | rnat_addr = ia64_rse_rnat_addr(addr); | 360 | rnat_addr = ia64_rse_rnat_addr(addr); |
360 | 361 | ||
361 | ia64_peek(current, sw, (unsigned long) ubs_end, (unsigned long) rnat_addr, &rnats); | 362 | ia64_peek(current, sw, (unsigned long) ubs_end, (unsigned long) rnat_addr, &rnats); |
362 | DPRINT("rnat @%p = 0x%lx nat=%d old nat=%ld\n", | 363 | DPRINT("rnat @%p = 0x%lx nat=%d old nat=%ld\n", |
363 | (void *) rnat_addr, rnats, nat, (rnats >> ia64_rse_slot_num(addr)) & 1); | 364 | (void *) rnat_addr, rnats, nat, (rnats >> ia64_rse_slot_num(addr)) & 1); |
364 | 365 | ||
365 | nat_mask = 1UL << ia64_rse_slot_num(addr); | 366 | nat_mask = 1UL << ia64_rse_slot_num(addr); |
366 | if (nat) | 367 | if (nat) |
367 | rnats |= nat_mask; | 368 | rnats |= nat_mask; |
368 | else | 369 | else |
369 | rnats &= ~nat_mask; | 370 | rnats &= ~nat_mask; |
370 | ia64_poke(current, sw, (unsigned long) ubs_end, (unsigned long) rnat_addr, rnats); | 371 | ia64_poke(current, sw, (unsigned long) ubs_end, (unsigned long) rnat_addr, rnats); |
371 | 372 | ||
372 | DPRINT("rnat changed to @%p = 0x%lx\n", (void *) rnat_addr, rnats); | 373 | DPRINT("rnat changed to @%p = 0x%lx\n", (void *) rnat_addr, rnats); |
373 | } | 374 | } |
374 | 375 | ||
375 | 376 | ||
376 | static void | 377 | static void |
377 | get_rse_reg (struct pt_regs *regs, unsigned long r1, unsigned long *val, int *nat) | 378 | get_rse_reg (struct pt_regs *regs, unsigned long r1, unsigned long *val, int *nat) |
378 | { | 379 | { |
379 | struct switch_stack *sw = (struct switch_stack *) regs - 1; | 380 | struct switch_stack *sw = (struct switch_stack *) regs - 1; |
380 | unsigned long *bsp, *addr, *rnat_addr, *ubs_end, *bspstore; | 381 | unsigned long *bsp, *addr, *rnat_addr, *ubs_end, *bspstore; |
381 | unsigned long *kbs = (void *) current + IA64_RBS_OFFSET; | 382 | unsigned long *kbs = (void *) current + IA64_RBS_OFFSET; |
382 | unsigned long rnats, nat_mask; | 383 | unsigned long rnats, nat_mask; |
383 | unsigned long on_kbs; | 384 | unsigned long on_kbs; |
384 | long sof = (regs->cr_ifs) & 0x7f; | 385 | long sof = (regs->cr_ifs) & 0x7f; |
385 | long sor = 8 * ((regs->cr_ifs >> 14) & 0xf); | 386 | long sor = 8 * ((regs->cr_ifs >> 14) & 0xf); |
386 | long rrb_gr = (regs->cr_ifs >> 18) & 0x7f; | 387 | long rrb_gr = (regs->cr_ifs >> 18) & 0x7f; |
387 | long ridx = r1 - 32; | 388 | long ridx = r1 - 32; |
388 | 389 | ||
389 | if (ridx >= sof) { | 390 | if (ridx >= sof) { |
390 | /* read of out-of-frame register returns an undefined value; 0 in our case. */ | 391 | /* read of out-of-frame register returns an undefined value; 0 in our case. */ |
391 | DPRINT("ignoring read from r%lu; only %lu registers are allocated!\n", r1, sof); | 392 | DPRINT("ignoring read from r%lu; only %lu registers are allocated!\n", r1, sof); |
392 | goto fail; | 393 | goto fail; |
393 | } | 394 | } |
394 | 395 | ||
395 | if (ridx < sor) | 396 | if (ridx < sor) |
396 | ridx = rotate_reg(sor, rrb_gr, ridx); | 397 | ridx = rotate_reg(sor, rrb_gr, ridx); |
397 | 398 | ||
398 | DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld ridx=%ld\n", | 399 | DPRINT("r%lu, sw.bspstore=%lx pt.bspstore=%lx sof=%ld sol=%ld ridx=%ld\n", |
399 | r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f, ridx); | 400 | r1, sw->ar_bspstore, regs->ar_bspstore, sof, (regs->cr_ifs >> 7) & 0x7f, ridx); |
400 | 401 | ||
401 | on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore); | 402 | on_kbs = ia64_rse_num_regs(kbs, (unsigned long *) sw->ar_bspstore); |
402 | addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + ridx); | 403 | addr = ia64_rse_skip_regs((unsigned long *) sw->ar_bspstore, -sof + ridx); |
403 | if (addr >= kbs) { | 404 | if (addr >= kbs) { |
404 | /* the register is on the kernel backing store: easy... */ | 405 | /* the register is on the kernel backing store: easy... */ |
405 | *val = *addr; | 406 | *val = *addr; |
406 | if (nat) { | 407 | if (nat) { |
407 | rnat_addr = ia64_rse_rnat_addr(addr); | 408 | rnat_addr = ia64_rse_rnat_addr(addr); |
408 | if ((unsigned long) rnat_addr >= sw->ar_bspstore) | 409 | if ((unsigned long) rnat_addr >= sw->ar_bspstore) |
409 | rnat_addr = &sw->ar_rnat; | 410 | rnat_addr = &sw->ar_rnat; |
410 | nat_mask = 1UL << ia64_rse_slot_num(addr); | 411 | nat_mask = 1UL << ia64_rse_slot_num(addr); |
411 | *nat = (*rnat_addr & nat_mask) != 0; | 412 | *nat = (*rnat_addr & nat_mask) != 0; |
412 | } | 413 | } |
413 | return; | 414 | return; |
414 | } | 415 | } |
415 | 416 | ||
416 | if (!user_stack(current, regs)) { | 417 | if (!user_stack(current, regs)) { |
417 | DPRINT("ignoring kernel read of r%lu; register isn't on the RBS!", r1); | 418 | DPRINT("ignoring kernel read of r%lu; register isn't on the RBS!", r1); |
418 | goto fail; | 419 | goto fail; |
419 | } | 420 | } |
420 | 421 | ||
421 | bspstore = (unsigned long *)regs->ar_bspstore; | 422 | bspstore = (unsigned long *)regs->ar_bspstore; |
422 | ubs_end = ia64_rse_skip_regs(bspstore, on_kbs); | 423 | ubs_end = ia64_rse_skip_regs(bspstore, on_kbs); |
423 | bsp = ia64_rse_skip_regs(ubs_end, -sof); | 424 | bsp = ia64_rse_skip_regs(ubs_end, -sof); |
424 | addr = ia64_rse_skip_regs(bsp, ridx); | 425 | addr = ia64_rse_skip_regs(bsp, ridx); |
425 | 426 | ||
426 | DPRINT("ubs_end=%p bsp=%p addr=%p\n", (void *) ubs_end, (void *) bsp, (void *) addr); | 427 | DPRINT("ubs_end=%p bsp=%p addr=%p\n", (void *) ubs_end, (void *) bsp, (void *) addr); |
427 | 428 | ||
428 | ia64_peek(current, sw, (unsigned long) ubs_end, (unsigned long) addr, val); | 429 | ia64_peek(current, sw, (unsigned long) ubs_end, (unsigned long) addr, val); |
429 | 430 | ||
430 | if (nat) { | 431 | if (nat) { |
431 | rnat_addr = ia64_rse_rnat_addr(addr); | 432 | rnat_addr = ia64_rse_rnat_addr(addr); |
432 | nat_mask = 1UL << ia64_rse_slot_num(addr); | 433 | nat_mask = 1UL << ia64_rse_slot_num(addr); |
433 | 434 | ||
434 | DPRINT("rnat @%p = 0x%lx\n", (void *) rnat_addr, rnats); | 435 | DPRINT("rnat @%p = 0x%lx\n", (void *) rnat_addr, rnats); |
435 | 436 | ||
436 | ia64_peek(current, sw, (unsigned long) ubs_end, (unsigned long) rnat_addr, &rnats); | 437 | ia64_peek(current, sw, (unsigned long) ubs_end, (unsigned long) rnat_addr, &rnats); |
437 | *nat = (rnats & nat_mask) != 0; | 438 | *nat = (rnats & nat_mask) != 0; |
438 | } | 439 | } |
439 | return; | 440 | return; |
440 | 441 | ||
441 | fail: | 442 | fail: |
442 | *val = 0; | 443 | *val = 0; |
443 | if (nat) | 444 | if (nat) |
444 | *nat = 0; | 445 | *nat = 0; |
445 | return; | 446 | return; |
446 | } | 447 | } |
447 | 448 | ||
448 | 449 | ||
449 | static void | 450 | static void |
450 | setreg (unsigned long regnum, unsigned long val, int nat, struct pt_regs *regs) | 451 | setreg (unsigned long regnum, unsigned long val, int nat, struct pt_regs *regs) |
451 | { | 452 | { |
452 | struct switch_stack *sw = (struct switch_stack *) regs - 1; | 453 | struct switch_stack *sw = (struct switch_stack *) regs - 1; |
453 | unsigned long addr; | 454 | unsigned long addr; |
454 | unsigned long bitmask; | 455 | unsigned long bitmask; |
455 | unsigned long *unat; | 456 | unsigned long *unat; |
456 | 457 | ||
457 | /* | 458 | /* |
458 | * First takes care of stacked registers | 459 | * First takes care of stacked registers |
459 | */ | 460 | */ |
460 | if (regnum >= IA64_FIRST_STACKED_GR) { | 461 | if (regnum >= IA64_FIRST_STACKED_GR) { |
461 | set_rse_reg(regs, regnum, val, nat); | 462 | set_rse_reg(regs, regnum, val, nat); |
462 | return; | 463 | return; |
463 | } | 464 | } |
464 | 465 | ||
465 | /* | 466 | /* |
466 | * Using r0 as a target raises a General Exception fault which has higher priority | 467 | * Using r0 as a target raises a General Exception fault which has higher priority |
467 | * than the Unaligned Reference fault. | 468 | * than the Unaligned Reference fault. |
468 | */ | 469 | */ |
469 | 470 | ||
470 | /* | 471 | /* |
471 | * Now look at registers in [0-31] range and init correct UNAT | 472 | * Now look at registers in [0-31] range and init correct UNAT |
472 | */ | 473 | */ |
473 | if (GR_IN_SW(regnum)) { | 474 | if (GR_IN_SW(regnum)) { |
474 | addr = (unsigned long)sw; | 475 | addr = (unsigned long)sw; |
475 | unat = &sw->ar_unat; | 476 | unat = &sw->ar_unat; |
476 | } else { | 477 | } else { |
477 | addr = (unsigned long)regs; | 478 | addr = (unsigned long)regs; |
478 | unat = &sw->caller_unat; | 479 | unat = &sw->caller_unat; |
479 | } | 480 | } |
480 | DPRINT("tmp_base=%lx switch_stack=%s offset=%d\n", | 481 | DPRINT("tmp_base=%lx switch_stack=%s offset=%d\n", |
481 | addr, unat==&sw->ar_unat ? "yes":"no", GR_OFFS(regnum)); | 482 | addr, unat==&sw->ar_unat ? "yes":"no", GR_OFFS(regnum)); |
482 | /* | 483 | /* |
483 | * add offset from base of struct | 484 | * add offset from base of struct |
484 | * and do it ! | 485 | * and do it ! |
485 | */ | 486 | */ |
486 | addr += GR_OFFS(regnum); | 487 | addr += GR_OFFS(regnum); |
487 | 488 | ||
488 | *(unsigned long *)addr = val; | 489 | *(unsigned long *)addr = val; |
489 | 490 | ||
490 | /* | 491 | /* |
491 | * We need to clear the corresponding UNAT bit to fully emulate the load | 492 | * We need to clear the corresponding UNAT bit to fully emulate the load |
492 | * UNAT bit_pos = GR[r3]{8:3} form EAS-2.4 | 493 | * UNAT bit_pos = GR[r3]{8:3} form EAS-2.4 |
493 | */ | 494 | */ |
494 | bitmask = 1UL << (addr >> 3 & 0x3f); | 495 | bitmask = 1UL << (addr >> 3 & 0x3f); |
495 | DPRINT("*0x%lx=0x%lx NaT=%d prev_unat @%p=%lx\n", addr, val, nat, (void *) unat, *unat); | 496 | DPRINT("*0x%lx=0x%lx NaT=%d prev_unat @%p=%lx\n", addr, val, nat, (void *) unat, *unat); |
496 | if (nat) { | 497 | if (nat) { |
497 | *unat |= bitmask; | 498 | *unat |= bitmask; |
498 | } else { | 499 | } else { |
499 | *unat &= ~bitmask; | 500 | *unat &= ~bitmask; |
500 | } | 501 | } |
501 | DPRINT("*0x%lx=0x%lx NaT=%d new unat: %p=%lx\n", addr, val, nat, (void *) unat,*unat); | 502 | DPRINT("*0x%lx=0x%lx NaT=%d new unat: %p=%lx\n", addr, val, nat, (void *) unat,*unat); |
502 | } | 503 | } |
503 | 504 | ||
504 | /* | 505 | /* |
505 | * Return the (rotated) index for floating point register REGNUM (REGNUM must be in the | 506 | * Return the (rotated) index for floating point register REGNUM (REGNUM must be in the |
506 | * range from 32-127, result is in the range from 0-95. | 507 | * range from 32-127, result is in the range from 0-95. |
507 | */ | 508 | */ |
508 | static inline unsigned long | 509 | static inline unsigned long |
509 | fph_index (struct pt_regs *regs, long regnum) | 510 | fph_index (struct pt_regs *regs, long regnum) |
510 | { | 511 | { |
511 | unsigned long rrb_fr = (regs->cr_ifs >> 25) & 0x7f; | 512 | unsigned long rrb_fr = (regs->cr_ifs >> 25) & 0x7f; |
512 | return rotate_reg(96, rrb_fr, (regnum - IA64_FIRST_ROTATING_FR)); | 513 | return rotate_reg(96, rrb_fr, (regnum - IA64_FIRST_ROTATING_FR)); |
513 | } | 514 | } |
514 | 515 | ||
515 | static void | 516 | static void |
516 | setfpreg (unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs) | 517 | setfpreg (unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs) |
517 | { | 518 | { |
518 | struct switch_stack *sw = (struct switch_stack *)regs - 1; | 519 | struct switch_stack *sw = (struct switch_stack *)regs - 1; |
519 | unsigned long addr; | 520 | unsigned long addr; |
520 | 521 | ||
521 | /* | 522 | /* |
522 | * From EAS-2.5: FPDisableFault has higher priority than Unaligned | 523 | * From EAS-2.5: FPDisableFault has higher priority than Unaligned |
523 | * Fault. Thus, when we get here, we know the partition is enabled. | 524 | * Fault. Thus, when we get here, we know the partition is enabled. |
524 | * To update f32-f127, there are three choices: | 525 | * To update f32-f127, there are three choices: |
525 | * | 526 | * |
526 | * (1) save f32-f127 to thread.fph and update the values there | 527 | * (1) save f32-f127 to thread.fph and update the values there |
527 | * (2) use a gigantic switch statement to directly access the registers | 528 | * (2) use a gigantic switch statement to directly access the registers |
528 | * (3) generate code on the fly to update the desired register | 529 | * (3) generate code on the fly to update the desired register |
529 | * | 530 | * |
530 | * For now, we are using approach (1). | 531 | * For now, we are using approach (1). |
531 | */ | 532 | */ |
532 | if (regnum >= IA64_FIRST_ROTATING_FR) { | 533 | if (regnum >= IA64_FIRST_ROTATING_FR) { |
533 | ia64_sync_fph(current); | 534 | ia64_sync_fph(current); |
534 | current->thread.fph[fph_index(regs, regnum)] = *fpval; | 535 | current->thread.fph[fph_index(regs, regnum)] = *fpval; |
535 | } else { | 536 | } else { |
536 | /* | 537 | /* |
537 | * pt_regs or switch_stack ? | 538 | * pt_regs or switch_stack ? |
538 | */ | 539 | */ |
539 | if (FR_IN_SW(regnum)) { | 540 | if (FR_IN_SW(regnum)) { |
540 | addr = (unsigned long)sw; | 541 | addr = (unsigned long)sw; |
541 | } else { | 542 | } else { |
542 | addr = (unsigned long)regs; | 543 | addr = (unsigned long)regs; |
543 | } | 544 | } |
544 | 545 | ||
545 | DPRINT("tmp_base=%lx offset=%d\n", addr, FR_OFFS(regnum)); | 546 | DPRINT("tmp_base=%lx offset=%d\n", addr, FR_OFFS(regnum)); |
546 | 547 | ||
547 | addr += FR_OFFS(regnum); | 548 | addr += FR_OFFS(regnum); |
548 | *(struct ia64_fpreg *)addr = *fpval; | 549 | *(struct ia64_fpreg *)addr = *fpval; |
549 | 550 | ||
550 | /* | 551 | /* |
551 | * mark the low partition as being used now | 552 | * mark the low partition as being used now |
552 | * | 553 | * |
553 | * It is highly unlikely that this bit is not already set, but | 554 | * It is highly unlikely that this bit is not already set, but |
554 | * let's do it for safety. | 555 | * let's do it for safety. |
555 | */ | 556 | */ |
556 | regs->cr_ipsr |= IA64_PSR_MFL; | 557 | regs->cr_ipsr |= IA64_PSR_MFL; |
557 | } | 558 | } |
558 | } | 559 | } |
559 | 560 | ||
560 | /* | 561 | /* |
561 | * Those 2 inline functions generate the spilled versions of the constant floating point | 562 | * Those 2 inline functions generate the spilled versions of the constant floating point |
562 | * registers which can be used with stfX | 563 | * registers which can be used with stfX |
563 | */ | 564 | */ |
564 | static inline void | 565 | static inline void |
565 | float_spill_f0 (struct ia64_fpreg *final) | 566 | float_spill_f0 (struct ia64_fpreg *final) |
566 | { | 567 | { |
567 | ia64_stf_spill(final, 0); | 568 | ia64_stf_spill(final, 0); |
568 | } | 569 | } |
569 | 570 | ||
570 | static inline void | 571 | static inline void |
571 | float_spill_f1 (struct ia64_fpreg *final) | 572 | float_spill_f1 (struct ia64_fpreg *final) |
572 | { | 573 | { |
573 | ia64_stf_spill(final, 1); | 574 | ia64_stf_spill(final, 1); |
574 | } | 575 | } |
575 | 576 | ||
576 | static void | 577 | static void |
577 | getfpreg (unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs) | 578 | getfpreg (unsigned long regnum, struct ia64_fpreg *fpval, struct pt_regs *regs) |
578 | { | 579 | { |
579 | struct switch_stack *sw = (struct switch_stack *) regs - 1; | 580 | struct switch_stack *sw = (struct switch_stack *) regs - 1; |
580 | unsigned long addr; | 581 | unsigned long addr; |
581 | 582 | ||
582 | /* | 583 | /* |
583 | * From EAS-2.5: FPDisableFault has higher priority than | 584 | * From EAS-2.5: FPDisableFault has higher priority than |
584 | * Unaligned Fault. Thus, when we get here, we know the partition is | 585 | * Unaligned Fault. Thus, when we get here, we know the partition is |
585 | * enabled. | 586 | * enabled. |
586 | * | 587 | * |
587 | * When regnum > 31, the register is still live and we need to force a save | 588 | * When regnum > 31, the register is still live and we need to force a save |
588 | * to current->thread.fph to get access to it. See discussion in setfpreg() | 589 | * to current->thread.fph to get access to it. See discussion in setfpreg() |
589 | * for reasons and other ways of doing this. | 590 | * for reasons and other ways of doing this. |
590 | */ | 591 | */ |
591 | if (regnum >= IA64_FIRST_ROTATING_FR) { | 592 | if (regnum >= IA64_FIRST_ROTATING_FR) { |
592 | ia64_flush_fph(current); | 593 | ia64_flush_fph(current); |
593 | *fpval = current->thread.fph[fph_index(regs, regnum)]; | 594 | *fpval = current->thread.fph[fph_index(regs, regnum)]; |
594 | } else { | 595 | } else { |
595 | /* | 596 | /* |
596 | * f0 = 0.0, f1= 1.0. Those registers are constant and are thus | 597 | * f0 = 0.0, f1= 1.0. Those registers are constant and are thus |
597 | * not saved, we must generate their spilled form on the fly | 598 | * not saved, we must generate their spilled form on the fly |
598 | */ | 599 | */ |
599 | switch(regnum) { | 600 | switch(regnum) { |
600 | case 0: | 601 | case 0: |
601 | float_spill_f0(fpval); | 602 | float_spill_f0(fpval); |
602 | break; | 603 | break; |
603 | case 1: | 604 | case 1: |
604 | float_spill_f1(fpval); | 605 | float_spill_f1(fpval); |
605 | break; | 606 | break; |
606 | default: | 607 | default: |
607 | /* | 608 | /* |
608 | * pt_regs or switch_stack ? | 609 | * pt_regs or switch_stack ? |
609 | */ | 610 | */ |
610 | addr = FR_IN_SW(regnum) ? (unsigned long)sw | 611 | addr = FR_IN_SW(regnum) ? (unsigned long)sw |
611 | : (unsigned long)regs; | 612 | : (unsigned long)regs; |
612 | 613 | ||
613 | DPRINT("is_sw=%d tmp_base=%lx offset=0x%x\n", | 614 | DPRINT("is_sw=%d tmp_base=%lx offset=0x%x\n", |
614 | FR_IN_SW(regnum), addr, FR_OFFS(regnum)); | 615 | FR_IN_SW(regnum), addr, FR_OFFS(regnum)); |
615 | 616 | ||
616 | addr += FR_OFFS(regnum); | 617 | addr += FR_OFFS(regnum); |
617 | *fpval = *(struct ia64_fpreg *)addr; | 618 | *fpval = *(struct ia64_fpreg *)addr; |
618 | } | 619 | } |
619 | } | 620 | } |
620 | } | 621 | } |
621 | 622 | ||
622 | 623 | ||
623 | static void | 624 | static void |
624 | getreg (unsigned long regnum, unsigned long *val, int *nat, struct pt_regs *regs) | 625 | getreg (unsigned long regnum, unsigned long *val, int *nat, struct pt_regs *regs) |
625 | { | 626 | { |
626 | struct switch_stack *sw = (struct switch_stack *) regs - 1; | 627 | struct switch_stack *sw = (struct switch_stack *) regs - 1; |
627 | unsigned long addr, *unat; | 628 | unsigned long addr, *unat; |
628 | 629 | ||
629 | if (regnum >= IA64_FIRST_STACKED_GR) { | 630 | if (regnum >= IA64_FIRST_STACKED_GR) { |
630 | get_rse_reg(regs, regnum, val, nat); | 631 | get_rse_reg(regs, regnum, val, nat); |
631 | return; | 632 | return; |
632 | } | 633 | } |
633 | 634 | ||
634 | /* | 635 | /* |
635 | * take care of r0 (read-only always evaluate to 0) | 636 | * take care of r0 (read-only always evaluate to 0) |
636 | */ | 637 | */ |
637 | if (regnum == 0) { | 638 | if (regnum == 0) { |
638 | *val = 0; | 639 | *val = 0; |
639 | if (nat) | 640 | if (nat) |
640 | *nat = 0; | 641 | *nat = 0; |
641 | return; | 642 | return; |
642 | } | 643 | } |
643 | 644 | ||
644 | /* | 645 | /* |
645 | * Now look at registers in [0-31] range and init correct UNAT | 646 | * Now look at registers in [0-31] range and init correct UNAT |
646 | */ | 647 | */ |
647 | if (GR_IN_SW(regnum)) { | 648 | if (GR_IN_SW(regnum)) { |
648 | addr = (unsigned long)sw; | 649 | addr = (unsigned long)sw; |
649 | unat = &sw->ar_unat; | 650 | unat = &sw->ar_unat; |
650 | } else { | 651 | } else { |
651 | addr = (unsigned long)regs; | 652 | addr = (unsigned long)regs; |
652 | unat = &sw->caller_unat; | 653 | unat = &sw->caller_unat; |
653 | } | 654 | } |
654 | 655 | ||
655 | DPRINT("addr_base=%lx offset=0x%x\n", addr, GR_OFFS(regnum)); | 656 | DPRINT("addr_base=%lx offset=0x%x\n", addr, GR_OFFS(regnum)); |
656 | 657 | ||
657 | addr += GR_OFFS(regnum); | 658 | addr += GR_OFFS(regnum); |
658 | 659 | ||
659 | *val = *(unsigned long *)addr; | 660 | *val = *(unsigned long *)addr; |
660 | 661 | ||
661 | /* | 662 | /* |
662 | * do it only when requested | 663 | * do it only when requested |
663 | */ | 664 | */ |
664 | if (nat) | 665 | if (nat) |
665 | *nat = (*unat >> (addr >> 3 & 0x3f)) & 0x1UL; | 666 | *nat = (*unat >> (addr >> 3 & 0x3f)) & 0x1UL; |
666 | } | 667 | } |
667 | 668 | ||
668 | static void | 669 | static void |
669 | emulate_load_updates (update_t type, load_store_t ld, struct pt_regs *regs, unsigned long ifa) | 670 | emulate_load_updates (update_t type, load_store_t ld, struct pt_regs *regs, unsigned long ifa) |
670 | { | 671 | { |
671 | /* | 672 | /* |
672 | * IMPORTANT: | 673 | * IMPORTANT: |
673 | * Given the way we handle unaligned speculative loads, we should | 674 | * Given the way we handle unaligned speculative loads, we should |
674 | * not get to this point in the code but we keep this sanity check, | 675 | * not get to this point in the code but we keep this sanity check, |
675 | * just in case. | 676 | * just in case. |
676 | */ | 677 | */ |
677 | if (ld.x6_op == 1 || ld.x6_op == 3) { | 678 | if (ld.x6_op == 1 || ld.x6_op == 3) { |
678 | printk(KERN_ERR "%s: register update on speculative load, error\n", __func__); | 679 | printk(KERN_ERR "%s: register update on speculative load, error\n", __func__); |
679 | if (die_if_kernel("unaligned reference on speculative load with register update\n", | 680 | if (die_if_kernel("unaligned reference on speculative load with register update\n", |
680 | regs, 30)) | 681 | regs, 30)) |
681 | return; | 682 | return; |
682 | } | 683 | } |
683 | 684 | ||
684 | 685 | ||
685 | /* | 686 | /* |
686 | * at this point, we know that the base register to update is valid i.e., | 687 | * at this point, we know that the base register to update is valid i.e., |
687 | * it's not r0 | 688 | * it's not r0 |
688 | */ | 689 | */ |
689 | if (type == UPD_IMMEDIATE) { | 690 | if (type == UPD_IMMEDIATE) { |
690 | unsigned long imm; | 691 | unsigned long imm; |
691 | 692 | ||
692 | /* | 693 | /* |
693 | * Load +Imm: ldXZ r1=[r3],imm(9) | 694 | * Load +Imm: ldXZ r1=[r3],imm(9) |
694 | * | 695 | * |
695 | * | 696 | * |
696 | * form imm9: [13:19] contain the first 7 bits | 697 | * form imm9: [13:19] contain the first 7 bits |
697 | */ | 698 | */ |
698 | imm = ld.x << 7 | ld.imm; | 699 | imm = ld.x << 7 | ld.imm; |
699 | 700 | ||
700 | /* | 701 | /* |
701 | * sign extend (1+8bits) if m set | 702 | * sign extend (1+8bits) if m set |
702 | */ | 703 | */ |
703 | if (ld.m) imm |= SIGN_EXT9; | 704 | if (ld.m) imm |= SIGN_EXT9; |
704 | 705 | ||
705 | /* | 706 | /* |
706 | * ifa == r3 and we know that the NaT bit on r3 was clear so | 707 | * ifa == r3 and we know that the NaT bit on r3 was clear so |
707 | * we can directly use ifa. | 708 | * we can directly use ifa. |
708 | */ | 709 | */ |
709 | ifa += imm; | 710 | ifa += imm; |
710 | 711 | ||
711 | setreg(ld.r3, ifa, 0, regs); | 712 | setreg(ld.r3, ifa, 0, regs); |
712 | 713 | ||
713 | DPRINT("ld.x=%d ld.m=%d imm=%ld r3=0x%lx\n", ld.x, ld.m, imm, ifa); | 714 | DPRINT("ld.x=%d ld.m=%d imm=%ld r3=0x%lx\n", ld.x, ld.m, imm, ifa); |
714 | 715 | ||
715 | } else if (ld.m) { | 716 | } else if (ld.m) { |
716 | unsigned long r2; | 717 | unsigned long r2; |
717 | int nat_r2; | 718 | int nat_r2; |
718 | 719 | ||
719 | /* | 720 | /* |
720 | * Load +Reg Opcode: ldXZ r1=[r3],r2 | 721 | * Load +Reg Opcode: ldXZ r1=[r3],r2 |
721 | * | 722 | * |
722 | * Note: that we update r3 even in the case of ldfX.a | 723 | * Note: that we update r3 even in the case of ldfX.a |
723 | * (where the load does not happen) | 724 | * (where the load does not happen) |
724 | * | 725 | * |
725 | * The way the load algorithm works, we know that r3 does not | 726 | * The way the load algorithm works, we know that r3 does not |
726 | * have its NaT bit set (would have gotten NaT consumption | 727 | * have its NaT bit set (would have gotten NaT consumption |
727 | * before getting the unaligned fault). So we can use ifa | 728 | * before getting the unaligned fault). So we can use ifa |
728 | * which equals r3 at this point. | 729 | * which equals r3 at this point. |
729 | * | 730 | * |
730 | * IMPORTANT: | 731 | * IMPORTANT: |
731 | * The above statement holds ONLY because we know that we | 732 | * The above statement holds ONLY because we know that we |
732 | * never reach this code when trying to do a ldX.s. | 733 | * never reach this code when trying to do a ldX.s. |
733 | * If we ever make it to here on an ldfX.s then | 734 | * If we ever make it to here on an ldfX.s then |
734 | */ | 735 | */ |
735 | getreg(ld.imm, &r2, &nat_r2, regs); | 736 | getreg(ld.imm, &r2, &nat_r2, regs); |
736 | 737 | ||
737 | ifa += r2; | 738 | ifa += r2; |
738 | 739 | ||
739 | /* | 740 | /* |
740 | * propagate Nat r2 -> r3 | 741 | * propagate Nat r2 -> r3 |
741 | */ | 742 | */ |
742 | setreg(ld.r3, ifa, nat_r2, regs); | 743 | setreg(ld.r3, ifa, nat_r2, regs); |
743 | 744 | ||
744 | DPRINT("imm=%d r2=%ld r3=0x%lx nat_r2=%d\n",ld.imm, r2, ifa, nat_r2); | 745 | DPRINT("imm=%d r2=%ld r3=0x%lx nat_r2=%d\n",ld.imm, r2, ifa, nat_r2); |
745 | } | 746 | } |
746 | } | 747 | } |
747 | 748 | ||
748 | 749 | ||
749 | static int | 750 | static int |
750 | emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs) | 751 | emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs) |
751 | { | 752 | { |
752 | unsigned int len = 1 << ld.x6_sz; | 753 | unsigned int len = 1 << ld.x6_sz; |
753 | unsigned long val = 0; | 754 | unsigned long val = 0; |
754 | 755 | ||
755 | /* | 756 | /* |
756 | * r0, as target, doesn't need to be checked because Illegal Instruction | 757 | * r0, as target, doesn't need to be checked because Illegal Instruction |
757 | * faults have higher priority than unaligned faults. | 758 | * faults have higher priority than unaligned faults. |
758 | * | 759 | * |
759 | * r0 cannot be found as the base as it would never generate an | 760 | * r0 cannot be found as the base as it would never generate an |
760 | * unaligned reference. | 761 | * unaligned reference. |
761 | */ | 762 | */ |
762 | 763 | ||
763 | /* | 764 | /* |
764 | * ldX.a we will emulate load and also invalidate the ALAT entry. | 765 | * ldX.a we will emulate load and also invalidate the ALAT entry. |
765 | * See comment below for explanation on how we handle ldX.a | 766 | * See comment below for explanation on how we handle ldX.a |
766 | */ | 767 | */ |
767 | 768 | ||
768 | if (len != 2 && len != 4 && len != 8) { | 769 | if (len != 2 && len != 4 && len != 8) { |
769 | DPRINT("unknown size: x6=%d\n", ld.x6_sz); | 770 | DPRINT("unknown size: x6=%d\n", ld.x6_sz); |
770 | return -1; | 771 | return -1; |
771 | } | 772 | } |
772 | /* this assumes little-endian byte-order: */ | 773 | /* this assumes little-endian byte-order: */ |
773 | if (copy_from_user(&val, (void __user *) ifa, len)) | 774 | if (copy_from_user(&val, (void __user *) ifa, len)) |
774 | return -1; | 775 | return -1; |
775 | setreg(ld.r1, val, 0, regs); | 776 | setreg(ld.r1, val, 0, regs); |
776 | 777 | ||
777 | /* | 778 | /* |
778 | * check for updates on any kind of loads | 779 | * check for updates on any kind of loads |
779 | */ | 780 | */ |
780 | if (ld.op == 0x5 || ld.m) | 781 | if (ld.op == 0x5 || ld.m) |
781 | emulate_load_updates(ld.op == 0x5 ? UPD_IMMEDIATE: UPD_REG, ld, regs, ifa); | 782 | emulate_load_updates(ld.op == 0x5 ? UPD_IMMEDIATE: UPD_REG, ld, regs, ifa); |
782 | 783 | ||
783 | /* | 784 | /* |
784 | * handling of various loads (based on EAS2.4): | 785 | * handling of various loads (based on EAS2.4): |
785 | * | 786 | * |
786 | * ldX.acq (ordered load): | 787 | * ldX.acq (ordered load): |
787 | * - acquire semantics would have been used, so force fence instead. | 788 | * - acquire semantics would have been used, so force fence instead. |
788 | * | 789 | * |
789 | * ldX.c.clr (check load and clear): | 790 | * ldX.c.clr (check load and clear): |
790 | * - if we get to this handler, it's because the entry was not in the ALAT. | 791 | * - if we get to this handler, it's because the entry was not in the ALAT. |
791 | * Therefore the operation reverts to a normal load | 792 | * Therefore the operation reverts to a normal load |
792 | * | 793 | * |
793 | * ldX.c.nc (check load no clear): | 794 | * ldX.c.nc (check load no clear): |
794 | * - same as previous one | 795 | * - same as previous one |
795 | * | 796 | * |
796 | * ldX.c.clr.acq (ordered check load and clear): | 797 | * ldX.c.clr.acq (ordered check load and clear): |
797 | * - same as above for c.clr part. The load needs to have acquire semantics. So | 798 | * - same as above for c.clr part. The load needs to have acquire semantics. So |
798 | * we use the fence semantics which is stronger and thus ensures correctness. | 799 | * we use the fence semantics which is stronger and thus ensures correctness. |
799 | * | 800 | * |
800 | * ldX.a (advanced load): | 801 | * ldX.a (advanced load): |
801 | * - suppose ldX.a r1=[r3]. If we get to the unaligned trap it's because the | 802 | * - suppose ldX.a r1=[r3]. If we get to the unaligned trap it's because the |
802 | * address doesn't match requested size alignment. This means that we would | 803 | * address doesn't match requested size alignment. This means that we would |
803 | * possibly need more than one load to get the result. | 804 | * possibly need more than one load to get the result. |
804 | * | 805 | * |
805 | * The load part can be handled just like a normal load, however the difficult | 806 | * The load part can be handled just like a normal load, however the difficult |
806 | * part is to get the right thing into the ALAT. The critical piece of information | 807 | * part is to get the right thing into the ALAT. The critical piece of information |
807 | * in the base address of the load & size. To do that, a ld.a must be executed, | 808 | * in the base address of the load & size. To do that, a ld.a must be executed, |
808 | * clearly any address can be pushed into the table by using ld1.a r1=[r3]. Now | 809 | * clearly any address can be pushed into the table by using ld1.a r1=[r3]. Now |
809 | * if we use the same target register, we will be okay for the check.a instruction. | 810 | * if we use the same target register, we will be okay for the check.a instruction. |
810 | * If we look at the store, basically a stX [r3]=r1 checks the ALAT for any entry | 811 | * If we look at the store, basically a stX [r3]=r1 checks the ALAT for any entry |
811 | * which would overlap within [r3,r3+X] (the size of the load was store in the | 812 | * which would overlap within [r3,r3+X] (the size of the load was store in the |
812 | * ALAT). If such an entry is found the entry is invalidated. But this is not good | 813 | * ALAT). If such an entry is found the entry is invalidated. But this is not good |
813 | * enough, take the following example: | 814 | * enough, take the following example: |
814 | * r3=3 | 815 | * r3=3 |
815 | * ld4.a r1=[r3] | 816 | * ld4.a r1=[r3] |
816 | * | 817 | * |
817 | * Could be emulated by doing: | 818 | * Could be emulated by doing: |
818 | * ld1.a r1=[r3],1 | 819 | * ld1.a r1=[r3],1 |
819 | * store to temporary; | 820 | * store to temporary; |
820 | * ld1.a r1=[r3],1 | 821 | * ld1.a r1=[r3],1 |
821 | * store & shift to temporary; | 822 | * store & shift to temporary; |
822 | * ld1.a r1=[r3],1 | 823 | * ld1.a r1=[r3],1 |
823 | * store & shift to temporary; | 824 | * store & shift to temporary; |
824 | * ld1.a r1=[r3] | 825 | * ld1.a r1=[r3] |
825 | * store & shift to temporary; | 826 | * store & shift to temporary; |
826 | * r1=temporary | 827 | * r1=temporary |
827 | * | 828 | * |
828 | * So in this case, you would get the right value is r1 but the wrong info in | 829 | * So in this case, you would get the right value is r1 but the wrong info in |
829 | * the ALAT. Notice that you could do it in reverse to finish with address 3 | 830 | * the ALAT. Notice that you could do it in reverse to finish with address 3 |
830 | * but you would still get the size wrong. To get the size right, one needs to | 831 | * but you would still get the size wrong. To get the size right, one needs to |
831 | * execute exactly the same kind of load. You could do it from a aligned | 832 | * execute exactly the same kind of load. You could do it from a aligned |
832 | * temporary location, but you would get the address wrong. | 833 | * temporary location, but you would get the address wrong. |
833 | * | 834 | * |
834 | * So no matter what, it is not possible to emulate an advanced load | 835 | * So no matter what, it is not possible to emulate an advanced load |
835 | * correctly. But is that really critical ? | 836 | * correctly. But is that really critical ? |
836 | * | 837 | * |
837 | * We will always convert ld.a into a normal load with ALAT invalidated. This | 838 | * We will always convert ld.a into a normal load with ALAT invalidated. This |
838 | * will enable compiler to do optimization where certain code path after ld.a | 839 | * will enable compiler to do optimization where certain code path after ld.a |
839 | * is not required to have ld.c/chk.a, e.g., code path with no intervening stores. | 840 | * is not required to have ld.c/chk.a, e.g., code path with no intervening stores. |
840 | * | 841 | * |
841 | * If there is a store after the advanced load, one must either do a ld.c.* or | 842 | * If there is a store after the advanced load, one must either do a ld.c.* or |
842 | * chk.a.* to reuse the value stored in the ALAT. Both can "fail" (meaning no | 843 | * chk.a.* to reuse the value stored in the ALAT. Both can "fail" (meaning no |
843 | * entry found in ALAT), and that's perfectly ok because: | 844 | * entry found in ALAT), and that's perfectly ok because: |
844 | * | 845 | * |
845 | * - ld.c.*, if the entry is not present a normal load is executed | 846 | * - ld.c.*, if the entry is not present a normal load is executed |
846 | * - chk.a.*, if the entry is not present, execution jumps to recovery code | 847 | * - chk.a.*, if the entry is not present, execution jumps to recovery code |
847 | * | 848 | * |
848 | * In either case, the load can be potentially retried in another form. | 849 | * In either case, the load can be potentially retried in another form. |
849 | * | 850 | * |
850 | * ALAT must be invalidated for the register (so that chk.a or ld.c don't pick | 851 | * ALAT must be invalidated for the register (so that chk.a or ld.c don't pick |
851 | * up a stale entry later). The register base update MUST also be performed. | 852 | * up a stale entry later). The register base update MUST also be performed. |
852 | */ | 853 | */ |
853 | 854 | ||
854 | /* | 855 | /* |
855 | * when the load has the .acq completer then | 856 | * when the load has the .acq completer then |
856 | * use ordering fence. | 857 | * use ordering fence. |
857 | */ | 858 | */ |
858 | if (ld.x6_op == 0x5 || ld.x6_op == 0xa) | 859 | if (ld.x6_op == 0x5 || ld.x6_op == 0xa) |
859 | mb(); | 860 | mb(); |
860 | 861 | ||
861 | /* | 862 | /* |
862 | * invalidate ALAT entry in case of advanced load | 863 | * invalidate ALAT entry in case of advanced load |
863 | */ | 864 | */ |
864 | if (ld.x6_op == 0x2) | 865 | if (ld.x6_op == 0x2) |
865 | invala_gr(ld.r1); | 866 | invala_gr(ld.r1); |
866 | 867 | ||
867 | return 0; | 868 | return 0; |
868 | } | 869 | } |
869 | 870 | ||
870 | static int | 871 | static int |
871 | emulate_store_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs) | 872 | emulate_store_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs) |
872 | { | 873 | { |
873 | unsigned long r2; | 874 | unsigned long r2; |
874 | unsigned int len = 1 << ld.x6_sz; | 875 | unsigned int len = 1 << ld.x6_sz; |
875 | 876 | ||
876 | /* | 877 | /* |
877 | * if we get to this handler, Nat bits on both r3 and r2 have already | 878 | * if we get to this handler, Nat bits on both r3 and r2 have already |
878 | * been checked. so we don't need to do it | 879 | * been checked. so we don't need to do it |
879 | * | 880 | * |
880 | * extract the value to be stored | 881 | * extract the value to be stored |
881 | */ | 882 | */ |
882 | getreg(ld.imm, &r2, NULL, regs); | 883 | getreg(ld.imm, &r2, NULL, regs); |
883 | 884 | ||
884 | /* | 885 | /* |
885 | * we rely on the macros in unaligned.h for now i.e., | 886 | * we rely on the macros in unaligned.h for now i.e., |
886 | * we let the compiler figure out how to read memory gracefully. | 887 | * we let the compiler figure out how to read memory gracefully. |
887 | * | 888 | * |
888 | * We need this switch/case because the way the inline function | 889 | * We need this switch/case because the way the inline function |
889 | * works. The code is optimized by the compiler and looks like | 890 | * works. The code is optimized by the compiler and looks like |
890 | * a single switch/case. | 891 | * a single switch/case. |
891 | */ | 892 | */ |
892 | DPRINT("st%d [%lx]=%lx\n", len, ifa, r2); | 893 | DPRINT("st%d [%lx]=%lx\n", len, ifa, r2); |
893 | 894 | ||
894 | if (len != 2 && len != 4 && len != 8) { | 895 | if (len != 2 && len != 4 && len != 8) { |
895 | DPRINT("unknown size: x6=%d\n", ld.x6_sz); | 896 | DPRINT("unknown size: x6=%d\n", ld.x6_sz); |
896 | return -1; | 897 | return -1; |
897 | } | 898 | } |
898 | 899 | ||
899 | /* this assumes little-endian byte-order: */ | 900 | /* this assumes little-endian byte-order: */ |
900 | if (copy_to_user((void __user *) ifa, &r2, len)) | 901 | if (copy_to_user((void __user *) ifa, &r2, len)) |
901 | return -1; | 902 | return -1; |
902 | 903 | ||
903 | /* | 904 | /* |
904 | * stX [r3]=r2,imm(9) | 905 | * stX [r3]=r2,imm(9) |
905 | * | 906 | * |
906 | * NOTE: | 907 | * NOTE: |
907 | * ld.r3 can never be r0, because r0 would not generate an | 908 | * ld.r3 can never be r0, because r0 would not generate an |
908 | * unaligned access. | 909 | * unaligned access. |
909 | */ | 910 | */ |
910 | if (ld.op == 0x5) { | 911 | if (ld.op == 0x5) { |
911 | unsigned long imm; | 912 | unsigned long imm; |
912 | 913 | ||
913 | /* | 914 | /* |
914 | * form imm9: [12:6] contain first 7bits | 915 | * form imm9: [12:6] contain first 7bits |
915 | */ | 916 | */ |
916 | imm = ld.x << 7 | ld.r1; | 917 | imm = ld.x << 7 | ld.r1; |
917 | /* | 918 | /* |
918 | * sign extend (8bits) if m set | 919 | * sign extend (8bits) if m set |
919 | */ | 920 | */ |
920 | if (ld.m) imm |= SIGN_EXT9; | 921 | if (ld.m) imm |= SIGN_EXT9; |
921 | /* | 922 | /* |
922 | * ifa == r3 (NaT is necessarily cleared) | 923 | * ifa == r3 (NaT is necessarily cleared) |
923 | */ | 924 | */ |
924 | ifa += imm; | 925 | ifa += imm; |
925 | 926 | ||
926 | DPRINT("imm=%lx r3=%lx\n", imm, ifa); | 927 | DPRINT("imm=%lx r3=%lx\n", imm, ifa); |
927 | 928 | ||
928 | setreg(ld.r3, ifa, 0, regs); | 929 | setreg(ld.r3, ifa, 0, regs); |
929 | } | 930 | } |
930 | /* | 931 | /* |
931 | * we don't have alat_invalidate_multiple() so we need | 932 | * we don't have alat_invalidate_multiple() so we need |
932 | * to do the complete flush :-<< | 933 | * to do the complete flush :-<< |
933 | */ | 934 | */ |
934 | ia64_invala(); | 935 | ia64_invala(); |
935 | 936 | ||
936 | /* | 937 | /* |
937 | * stX.rel: use fence instead of release | 938 | * stX.rel: use fence instead of release |
938 | */ | 939 | */ |
939 | if (ld.x6_op == 0xd) | 940 | if (ld.x6_op == 0xd) |
940 | mb(); | 941 | mb(); |
941 | 942 | ||
942 | return 0; | 943 | return 0; |
943 | } | 944 | } |
944 | 945 | ||
945 | /* | 946 | /* |
946 | * floating point operations sizes in bytes | 947 | * floating point operations sizes in bytes |
947 | */ | 948 | */ |
948 | static const unsigned char float_fsz[4]={ | 949 | static const unsigned char float_fsz[4]={ |
949 | 10, /* extended precision (e) */ | 950 | 10, /* extended precision (e) */ |
950 | 8, /* integer (8) */ | 951 | 8, /* integer (8) */ |
951 | 4, /* single precision (s) */ | 952 | 4, /* single precision (s) */ |
952 | 8 /* double precision (d) */ | 953 | 8 /* double precision (d) */ |
953 | }; | 954 | }; |
954 | 955 | ||
955 | static inline void | 956 | static inline void |
956 | mem2float_extended (struct ia64_fpreg *init, struct ia64_fpreg *final) | 957 | mem2float_extended (struct ia64_fpreg *init, struct ia64_fpreg *final) |
957 | { | 958 | { |
958 | ia64_ldfe(6, init); | 959 | ia64_ldfe(6, init); |
959 | ia64_stop(); | 960 | ia64_stop(); |
960 | ia64_stf_spill(final, 6); | 961 | ia64_stf_spill(final, 6); |
961 | } | 962 | } |
962 | 963 | ||
963 | static inline void | 964 | static inline void |
964 | mem2float_integer (struct ia64_fpreg *init, struct ia64_fpreg *final) | 965 | mem2float_integer (struct ia64_fpreg *init, struct ia64_fpreg *final) |
965 | { | 966 | { |
966 | ia64_ldf8(6, init); | 967 | ia64_ldf8(6, init); |
967 | ia64_stop(); | 968 | ia64_stop(); |
968 | ia64_stf_spill(final, 6); | 969 | ia64_stf_spill(final, 6); |
969 | } | 970 | } |
970 | 971 | ||
971 | static inline void | 972 | static inline void |
972 | mem2float_single (struct ia64_fpreg *init, struct ia64_fpreg *final) | 973 | mem2float_single (struct ia64_fpreg *init, struct ia64_fpreg *final) |
973 | { | 974 | { |
974 | ia64_ldfs(6, init); | 975 | ia64_ldfs(6, init); |
975 | ia64_stop(); | 976 | ia64_stop(); |
976 | ia64_stf_spill(final, 6); | 977 | ia64_stf_spill(final, 6); |
977 | } | 978 | } |
978 | 979 | ||
979 | static inline void | 980 | static inline void |
980 | mem2float_double (struct ia64_fpreg *init, struct ia64_fpreg *final) | 981 | mem2float_double (struct ia64_fpreg *init, struct ia64_fpreg *final) |
981 | { | 982 | { |
982 | ia64_ldfd(6, init); | 983 | ia64_ldfd(6, init); |
983 | ia64_stop(); | 984 | ia64_stop(); |
984 | ia64_stf_spill(final, 6); | 985 | ia64_stf_spill(final, 6); |
985 | } | 986 | } |
986 | 987 | ||
987 | static inline void | 988 | static inline void |
988 | float2mem_extended (struct ia64_fpreg *init, struct ia64_fpreg *final) | 989 | float2mem_extended (struct ia64_fpreg *init, struct ia64_fpreg *final) |
989 | { | 990 | { |
990 | ia64_ldf_fill(6, init); | 991 | ia64_ldf_fill(6, init); |
991 | ia64_stop(); | 992 | ia64_stop(); |
992 | ia64_stfe(final, 6); | 993 | ia64_stfe(final, 6); |
993 | } | 994 | } |
994 | 995 | ||
995 | static inline void | 996 | static inline void |
996 | float2mem_integer (struct ia64_fpreg *init, struct ia64_fpreg *final) | 997 | float2mem_integer (struct ia64_fpreg *init, struct ia64_fpreg *final) |
997 | { | 998 | { |
998 | ia64_ldf_fill(6, init); | 999 | ia64_ldf_fill(6, init); |
999 | ia64_stop(); | 1000 | ia64_stop(); |
1000 | ia64_stf8(final, 6); | 1001 | ia64_stf8(final, 6); |
1001 | } | 1002 | } |
1002 | 1003 | ||
1003 | static inline void | 1004 | static inline void |
1004 | float2mem_single (struct ia64_fpreg *init, struct ia64_fpreg *final) | 1005 | float2mem_single (struct ia64_fpreg *init, struct ia64_fpreg *final) |
1005 | { | 1006 | { |
1006 | ia64_ldf_fill(6, init); | 1007 | ia64_ldf_fill(6, init); |
1007 | ia64_stop(); | 1008 | ia64_stop(); |
1008 | ia64_stfs(final, 6); | 1009 | ia64_stfs(final, 6); |
1009 | } | 1010 | } |
1010 | 1011 | ||
1011 | static inline void | 1012 | static inline void |
1012 | float2mem_double (struct ia64_fpreg *init, struct ia64_fpreg *final) | 1013 | float2mem_double (struct ia64_fpreg *init, struct ia64_fpreg *final) |
1013 | { | 1014 | { |
1014 | ia64_ldf_fill(6, init); | 1015 | ia64_ldf_fill(6, init); |
1015 | ia64_stop(); | 1016 | ia64_stop(); |
1016 | ia64_stfd(final, 6); | 1017 | ia64_stfd(final, 6); |
1017 | } | 1018 | } |
1018 | 1019 | ||
1019 | static int | 1020 | static int |
1020 | emulate_load_floatpair (unsigned long ifa, load_store_t ld, struct pt_regs *regs) | 1021 | emulate_load_floatpair (unsigned long ifa, load_store_t ld, struct pt_regs *regs) |
1021 | { | 1022 | { |
1022 | struct ia64_fpreg fpr_init[2]; | 1023 | struct ia64_fpreg fpr_init[2]; |
1023 | struct ia64_fpreg fpr_final[2]; | 1024 | struct ia64_fpreg fpr_final[2]; |
1024 | unsigned long len = float_fsz[ld.x6_sz]; | 1025 | unsigned long len = float_fsz[ld.x6_sz]; |
1025 | 1026 | ||
1026 | /* | 1027 | /* |
1027 | * fr0 & fr1 don't need to be checked because Illegal Instruction faults have | 1028 | * fr0 & fr1 don't need to be checked because Illegal Instruction faults have |
1028 | * higher priority than unaligned faults. | 1029 | * higher priority than unaligned faults. |
1029 | * | 1030 | * |
1030 | * r0 cannot be found as the base as it would never generate an unaligned | 1031 | * r0 cannot be found as the base as it would never generate an unaligned |
1031 | * reference. | 1032 | * reference. |
1032 | */ | 1033 | */ |
1033 | 1034 | ||
1034 | /* | 1035 | /* |
1035 | * make sure we get clean buffers | 1036 | * make sure we get clean buffers |
1036 | */ | 1037 | */ |
1037 | memset(&fpr_init, 0, sizeof(fpr_init)); | 1038 | memset(&fpr_init, 0, sizeof(fpr_init)); |
1038 | memset(&fpr_final, 0, sizeof(fpr_final)); | 1039 | memset(&fpr_final, 0, sizeof(fpr_final)); |
1039 | 1040 | ||
1040 | /* | 1041 | /* |
1041 | * ldfpX.a: we don't try to emulate anything but we must | 1042 | * ldfpX.a: we don't try to emulate anything but we must |
1042 | * invalidate the ALAT entry and execute updates, if any. | 1043 | * invalidate the ALAT entry and execute updates, if any. |
1043 | */ | 1044 | */ |
1044 | if (ld.x6_op != 0x2) { | 1045 | if (ld.x6_op != 0x2) { |
1045 | /* | 1046 | /* |
1046 | * This assumes little-endian byte-order. Note that there is no "ldfpe" | 1047 | * This assumes little-endian byte-order. Note that there is no "ldfpe" |
1047 | * instruction: | 1048 | * instruction: |
1048 | */ | 1049 | */ |
1049 | if (copy_from_user(&fpr_init[0], (void __user *) ifa, len) | 1050 | if (copy_from_user(&fpr_init[0], (void __user *) ifa, len) |
1050 | || copy_from_user(&fpr_init[1], (void __user *) (ifa + len), len)) | 1051 | || copy_from_user(&fpr_init[1], (void __user *) (ifa + len), len)) |
1051 | return -1; | 1052 | return -1; |
1052 | 1053 | ||
1053 | DPRINT("ld.r1=%d ld.imm=%d x6_sz=%d\n", ld.r1, ld.imm, ld.x6_sz); | 1054 | DPRINT("ld.r1=%d ld.imm=%d x6_sz=%d\n", ld.r1, ld.imm, ld.x6_sz); |
1054 | DDUMP("frp_init =", &fpr_init, 2*len); | 1055 | DDUMP("frp_init =", &fpr_init, 2*len); |
1055 | /* | 1056 | /* |
1056 | * XXX fixme | 1057 | * XXX fixme |
1057 | * Could optimize inlines by using ldfpX & 2 spills | 1058 | * Could optimize inlines by using ldfpX & 2 spills |
1058 | */ | 1059 | */ |
1059 | switch( ld.x6_sz ) { | 1060 | switch( ld.x6_sz ) { |
1060 | case 0: | 1061 | case 0: |
1061 | mem2float_extended(&fpr_init[0], &fpr_final[0]); | 1062 | mem2float_extended(&fpr_init[0], &fpr_final[0]); |
1062 | mem2float_extended(&fpr_init[1], &fpr_final[1]); | 1063 | mem2float_extended(&fpr_init[1], &fpr_final[1]); |
1063 | break; | 1064 | break; |
1064 | case 1: | 1065 | case 1: |
1065 | mem2float_integer(&fpr_init[0], &fpr_final[0]); | 1066 | mem2float_integer(&fpr_init[0], &fpr_final[0]); |
1066 | mem2float_integer(&fpr_init[1], &fpr_final[1]); | 1067 | mem2float_integer(&fpr_init[1], &fpr_final[1]); |
1067 | break; | 1068 | break; |
1068 | case 2: | 1069 | case 2: |
1069 | mem2float_single(&fpr_init[0], &fpr_final[0]); | 1070 | mem2float_single(&fpr_init[0], &fpr_final[0]); |
1070 | mem2float_single(&fpr_init[1], &fpr_final[1]); | 1071 | mem2float_single(&fpr_init[1], &fpr_final[1]); |
1071 | break; | 1072 | break; |
1072 | case 3: | 1073 | case 3: |
1073 | mem2float_double(&fpr_init[0], &fpr_final[0]); | 1074 | mem2float_double(&fpr_init[0], &fpr_final[0]); |
1074 | mem2float_double(&fpr_init[1], &fpr_final[1]); | 1075 | mem2float_double(&fpr_init[1], &fpr_final[1]); |
1075 | break; | 1076 | break; |
1076 | } | 1077 | } |
1077 | DDUMP("fpr_final =", &fpr_final, 2*len); | 1078 | DDUMP("fpr_final =", &fpr_final, 2*len); |
1078 | /* | 1079 | /* |
1079 | * XXX fixme | 1080 | * XXX fixme |
1080 | * | 1081 | * |
1081 | * A possible optimization would be to drop fpr_final and directly | 1082 | * A possible optimization would be to drop fpr_final and directly |
1082 | * use the storage from the saved context i.e., the actual final | 1083 | * use the storage from the saved context i.e., the actual final |
1083 | * destination (pt_regs, switch_stack or thread structure). | 1084 | * destination (pt_regs, switch_stack or thread structure). |
1084 | */ | 1085 | */ |
1085 | setfpreg(ld.r1, &fpr_final[0], regs); | 1086 | setfpreg(ld.r1, &fpr_final[0], regs); |
1086 | setfpreg(ld.imm, &fpr_final[1], regs); | 1087 | setfpreg(ld.imm, &fpr_final[1], regs); |
1087 | } | 1088 | } |
1088 | 1089 | ||
1089 | /* | 1090 | /* |
1090 | * Check for updates: only immediate updates are available for this | 1091 | * Check for updates: only immediate updates are available for this |
1091 | * instruction. | 1092 | * instruction. |
1092 | */ | 1093 | */ |
1093 | if (ld.m) { | 1094 | if (ld.m) { |
1094 | /* | 1095 | /* |
1095 | * the immediate is implicit given the ldsz of the operation: | 1096 | * the immediate is implicit given the ldsz of the operation: |
1096 | * single: 8 (2x4) and for all others it's 16 (2x8) | 1097 | * single: 8 (2x4) and for all others it's 16 (2x8) |
1097 | */ | 1098 | */ |
1098 | ifa += len<<1; | 1099 | ifa += len<<1; |
1099 | 1100 | ||
1100 | /* | 1101 | /* |
1101 | * IMPORTANT: | 1102 | * IMPORTANT: |
1102 | * the fact that we force the NaT of r3 to zero is ONLY valid | 1103 | * the fact that we force the NaT of r3 to zero is ONLY valid |
1103 | * as long as we don't come here with a ldfpX.s. | 1104 | * as long as we don't come here with a ldfpX.s. |
1104 | * For this reason we keep this sanity check | 1105 | * For this reason we keep this sanity check |
1105 | */ | 1106 | */ |
1106 | if (ld.x6_op == 1 || ld.x6_op == 3) | 1107 | if (ld.x6_op == 1 || ld.x6_op == 3) |
1107 | printk(KERN_ERR "%s: register update on speculative load pair, error\n", | 1108 | printk(KERN_ERR "%s: register update on speculative load pair, error\n", |
1108 | __func__); | 1109 | __func__); |
1109 | 1110 | ||
1110 | setreg(ld.r3, ifa, 0, regs); | 1111 | setreg(ld.r3, ifa, 0, regs); |
1111 | } | 1112 | } |
1112 | 1113 | ||
1113 | /* | 1114 | /* |
1114 | * Invalidate ALAT entries, if any, for both registers. | 1115 | * Invalidate ALAT entries, if any, for both registers. |
1115 | */ | 1116 | */ |
1116 | if (ld.x6_op == 0x2) { | 1117 | if (ld.x6_op == 0x2) { |
1117 | invala_fr(ld.r1); | 1118 | invala_fr(ld.r1); |
1118 | invala_fr(ld.imm); | 1119 | invala_fr(ld.imm); |
1119 | } | 1120 | } |
1120 | return 0; | 1121 | return 0; |
1121 | } | 1122 | } |
1122 | 1123 | ||
1123 | 1124 | ||
1124 | static int | 1125 | static int |
1125 | emulate_load_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs) | 1126 | emulate_load_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs) |
1126 | { | 1127 | { |
1127 | struct ia64_fpreg fpr_init; | 1128 | struct ia64_fpreg fpr_init; |
1128 | struct ia64_fpreg fpr_final; | 1129 | struct ia64_fpreg fpr_final; |
1129 | unsigned long len = float_fsz[ld.x6_sz]; | 1130 | unsigned long len = float_fsz[ld.x6_sz]; |
1130 | 1131 | ||
1131 | /* | 1132 | /* |
1132 | * fr0 & fr1 don't need to be checked because Illegal Instruction | 1133 | * fr0 & fr1 don't need to be checked because Illegal Instruction |
1133 | * faults have higher priority than unaligned faults. | 1134 | * faults have higher priority than unaligned faults. |
1134 | * | 1135 | * |
1135 | * r0 cannot be found as the base as it would never generate an | 1136 | * r0 cannot be found as the base as it would never generate an |
1136 | * unaligned reference. | 1137 | * unaligned reference. |
1137 | */ | 1138 | */ |
1138 | 1139 | ||
1139 | /* | 1140 | /* |
1140 | * make sure we get clean buffers | 1141 | * make sure we get clean buffers |
1141 | */ | 1142 | */ |
1142 | memset(&fpr_init,0, sizeof(fpr_init)); | 1143 | memset(&fpr_init,0, sizeof(fpr_init)); |
1143 | memset(&fpr_final,0, sizeof(fpr_final)); | 1144 | memset(&fpr_final,0, sizeof(fpr_final)); |
1144 | 1145 | ||
1145 | /* | 1146 | /* |
1146 | * ldfX.a we don't try to emulate anything but we must | 1147 | * ldfX.a we don't try to emulate anything but we must |
1147 | * invalidate the ALAT entry. | 1148 | * invalidate the ALAT entry. |
1148 | * See comments in ldX for descriptions on how the various loads are handled. | 1149 | * See comments in ldX for descriptions on how the various loads are handled. |
1149 | */ | 1150 | */ |
1150 | if (ld.x6_op != 0x2) { | 1151 | if (ld.x6_op != 0x2) { |
1151 | if (copy_from_user(&fpr_init, (void __user *) ifa, len)) | 1152 | if (copy_from_user(&fpr_init, (void __user *) ifa, len)) |
1152 | return -1; | 1153 | return -1; |
1153 | 1154 | ||
1154 | DPRINT("ld.r1=%d x6_sz=%d\n", ld.r1, ld.x6_sz); | 1155 | DPRINT("ld.r1=%d x6_sz=%d\n", ld.r1, ld.x6_sz); |
1155 | DDUMP("fpr_init =", &fpr_init, len); | 1156 | DDUMP("fpr_init =", &fpr_init, len); |
1156 | /* | 1157 | /* |
1157 | * we only do something for x6_op={0,8,9} | 1158 | * we only do something for x6_op={0,8,9} |
1158 | */ | 1159 | */ |
1159 | switch( ld.x6_sz ) { | 1160 | switch( ld.x6_sz ) { |
1160 | case 0: | 1161 | case 0: |
1161 | mem2float_extended(&fpr_init, &fpr_final); | 1162 | mem2float_extended(&fpr_init, &fpr_final); |
1162 | break; | 1163 | break; |
1163 | case 1: | 1164 | case 1: |
1164 | mem2float_integer(&fpr_init, &fpr_final); | 1165 | mem2float_integer(&fpr_init, &fpr_final); |
1165 | break; | 1166 | break; |
1166 | case 2: | 1167 | case 2: |
1167 | mem2float_single(&fpr_init, &fpr_final); | 1168 | mem2float_single(&fpr_init, &fpr_final); |
1168 | break; | 1169 | break; |
1169 | case 3: | 1170 | case 3: |
1170 | mem2float_double(&fpr_init, &fpr_final); | 1171 | mem2float_double(&fpr_init, &fpr_final); |
1171 | break; | 1172 | break; |
1172 | } | 1173 | } |
1173 | DDUMP("fpr_final =", &fpr_final, len); | 1174 | DDUMP("fpr_final =", &fpr_final, len); |
1174 | /* | 1175 | /* |
1175 | * XXX fixme | 1176 | * XXX fixme |
1176 | * | 1177 | * |
1177 | * A possible optimization would be to drop fpr_final and directly | 1178 | * A possible optimization would be to drop fpr_final and directly |
1178 | * use the storage from the saved context i.e., the actual final | 1179 | * use the storage from the saved context i.e., the actual final |
1179 | * destination (pt_regs, switch_stack or thread structure). | 1180 | * destination (pt_regs, switch_stack or thread structure). |
1180 | */ | 1181 | */ |
1181 | setfpreg(ld.r1, &fpr_final, regs); | 1182 | setfpreg(ld.r1, &fpr_final, regs); |
1182 | } | 1183 | } |
1183 | 1184 | ||
1184 | /* | 1185 | /* |
1185 | * check for updates on any loads | 1186 | * check for updates on any loads |
1186 | */ | 1187 | */ |
1187 | if (ld.op == 0x7 || ld.m) | 1188 | if (ld.op == 0x7 || ld.m) |
1188 | emulate_load_updates(ld.op == 0x7 ? UPD_IMMEDIATE: UPD_REG, ld, regs, ifa); | 1189 | emulate_load_updates(ld.op == 0x7 ? UPD_IMMEDIATE: UPD_REG, ld, regs, ifa); |
1189 | 1190 | ||
1190 | /* | 1191 | /* |
1191 | * invalidate ALAT entry in case of advanced floating point loads | 1192 | * invalidate ALAT entry in case of advanced floating point loads |
1192 | */ | 1193 | */ |
1193 | if (ld.x6_op == 0x2) | 1194 | if (ld.x6_op == 0x2) |
1194 | invala_fr(ld.r1); | 1195 | invala_fr(ld.r1); |
1195 | 1196 | ||
1196 | return 0; | 1197 | return 0; |
1197 | } | 1198 | } |
1198 | 1199 | ||
1199 | 1200 | ||
1200 | static int | 1201 | static int |
1201 | emulate_store_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs) | 1202 | emulate_store_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs) |
1202 | { | 1203 | { |
1203 | struct ia64_fpreg fpr_init; | 1204 | struct ia64_fpreg fpr_init; |
1204 | struct ia64_fpreg fpr_final; | 1205 | struct ia64_fpreg fpr_final; |
1205 | unsigned long len = float_fsz[ld.x6_sz]; | 1206 | unsigned long len = float_fsz[ld.x6_sz]; |
1206 | 1207 | ||
1207 | /* | 1208 | /* |
1208 | * make sure we get clean buffers | 1209 | * make sure we get clean buffers |
1209 | */ | 1210 | */ |
1210 | memset(&fpr_init,0, sizeof(fpr_init)); | 1211 | memset(&fpr_init,0, sizeof(fpr_init)); |
1211 | memset(&fpr_final,0, sizeof(fpr_final)); | 1212 | memset(&fpr_final,0, sizeof(fpr_final)); |
1212 | 1213 | ||
1213 | /* | 1214 | /* |
1214 | * if we get to this handler, Nat bits on both r3 and r2 have already | 1215 | * if we get to this handler, Nat bits on both r3 and r2 have already |
1215 | * been checked. so we don't need to do it | 1216 | * been checked. so we don't need to do it |
1216 | * | 1217 | * |
1217 | * extract the value to be stored | 1218 | * extract the value to be stored |
1218 | */ | 1219 | */ |
1219 | getfpreg(ld.imm, &fpr_init, regs); | 1220 | getfpreg(ld.imm, &fpr_init, regs); |
1220 | /* | 1221 | /* |
1221 | * during this step, we extract the spilled registers from the saved | 1222 | * during this step, we extract the spilled registers from the saved |
1222 | * context i.e., we refill. Then we store (no spill) to temporary | 1223 | * context i.e., we refill. Then we store (no spill) to temporary |
1223 | * aligned location | 1224 | * aligned location |
1224 | */ | 1225 | */ |
1225 | switch( ld.x6_sz ) { | 1226 | switch( ld.x6_sz ) { |
1226 | case 0: | 1227 | case 0: |
1227 | float2mem_extended(&fpr_init, &fpr_final); | 1228 | float2mem_extended(&fpr_init, &fpr_final); |
1228 | break; | 1229 | break; |
1229 | case 1: | 1230 | case 1: |
1230 | float2mem_integer(&fpr_init, &fpr_final); | 1231 | float2mem_integer(&fpr_init, &fpr_final); |
1231 | break; | 1232 | break; |
1232 | case 2: | 1233 | case 2: |
1233 | float2mem_single(&fpr_init, &fpr_final); | 1234 | float2mem_single(&fpr_init, &fpr_final); |
1234 | break; | 1235 | break; |
1235 | case 3: | 1236 | case 3: |
1236 | float2mem_double(&fpr_init, &fpr_final); | 1237 | float2mem_double(&fpr_init, &fpr_final); |
1237 | break; | 1238 | break; |
1238 | } | 1239 | } |
1239 | DPRINT("ld.r1=%d x6_sz=%d\n", ld.r1, ld.x6_sz); | 1240 | DPRINT("ld.r1=%d x6_sz=%d\n", ld.r1, ld.x6_sz); |
1240 | DDUMP("fpr_init =", &fpr_init, len); | 1241 | DDUMP("fpr_init =", &fpr_init, len); |
1241 | DDUMP("fpr_final =", &fpr_final, len); | 1242 | DDUMP("fpr_final =", &fpr_final, len); |
1242 | 1243 | ||
1243 | if (copy_to_user((void __user *) ifa, &fpr_final, len)) | 1244 | if (copy_to_user((void __user *) ifa, &fpr_final, len)) |
1244 | return -1; | 1245 | return -1; |
1245 | 1246 | ||
1246 | /* | 1247 | /* |
1247 | * stfX [r3]=r2,imm(9) | 1248 | * stfX [r3]=r2,imm(9) |
1248 | * | 1249 | * |
1249 | * NOTE: | 1250 | * NOTE: |
1250 | * ld.r3 can never be r0, because r0 would not generate an | 1251 | * ld.r3 can never be r0, because r0 would not generate an |
1251 | * unaligned access. | 1252 | * unaligned access. |
1252 | */ | 1253 | */ |
1253 | if (ld.op == 0x7) { | 1254 | if (ld.op == 0x7) { |
1254 | unsigned long imm; | 1255 | unsigned long imm; |
1255 | 1256 | ||
1256 | /* | 1257 | /* |
1257 | * form imm9: [12:6] contain first 7bits | 1258 | * form imm9: [12:6] contain first 7bits |
1258 | */ | 1259 | */ |
1259 | imm = ld.x << 7 | ld.r1; | 1260 | imm = ld.x << 7 | ld.r1; |
1260 | /* | 1261 | /* |
1261 | * sign extend (8bits) if m set | 1262 | * sign extend (8bits) if m set |
1262 | */ | 1263 | */ |
1263 | if (ld.m) | 1264 | if (ld.m) |
1264 | imm |= SIGN_EXT9; | 1265 | imm |= SIGN_EXT9; |
1265 | /* | 1266 | /* |
1266 | * ifa == r3 (NaT is necessarily cleared) | 1267 | * ifa == r3 (NaT is necessarily cleared) |
1267 | */ | 1268 | */ |
1268 | ifa += imm; | 1269 | ifa += imm; |
1269 | 1270 | ||
1270 | DPRINT("imm=%lx r3=%lx\n", imm, ifa); | 1271 | DPRINT("imm=%lx r3=%lx\n", imm, ifa); |
1271 | 1272 | ||
1272 | setreg(ld.r3, ifa, 0, regs); | 1273 | setreg(ld.r3, ifa, 0, regs); |
1273 | } | 1274 | } |
1274 | /* | 1275 | /* |
1275 | * we don't have alat_invalidate_multiple() so we need | 1276 | * we don't have alat_invalidate_multiple() so we need |
1276 | * to do the complete flush :-<< | 1277 | * to do the complete flush :-<< |
1277 | */ | 1278 | */ |
1278 | ia64_invala(); | 1279 | ia64_invala(); |
1279 | 1280 | ||
1280 | return 0; | 1281 | return 0; |
1281 | } | 1282 | } |
1282 | 1283 | ||
1283 | /* | 1284 | /* |
1284 | * Make sure we log the unaligned access, so that user/sysadmin can notice it and | 1285 | * Make sure we log the unaligned access, so that user/sysadmin can notice it and |
1285 | * eventually fix the program. However, we don't want to do that for every access so we | 1286 | * eventually fix the program. However, we don't want to do that for every access so we |
1286 | * pace it with jiffies. This isn't really MP-safe, but it doesn't really have to be | 1287 | * pace it with jiffies. This isn't really MP-safe, but it doesn't really have to be |
1287 | * either... | 1288 | * either... |
1288 | */ | 1289 | */ |
1289 | static int | 1290 | static int |
1290 | within_logging_rate_limit (void) | 1291 | within_logging_rate_limit (void) |
1291 | { | 1292 | { |
1292 | static unsigned long count, last_time; | 1293 | static unsigned long count, last_time; |
1293 | 1294 | ||
1294 | if (time_after(jiffies, last_time + 5 * HZ)) | 1295 | if (time_after(jiffies, last_time + 5 * HZ)) |
1295 | count = 0; | 1296 | count = 0; |
1296 | if (count < 5) { | 1297 | if (count < 5) { |
1297 | last_time = jiffies; | 1298 | last_time = jiffies; |
1298 | count++; | 1299 | count++; |
1299 | return 1; | 1300 | return 1; |
1300 | } | 1301 | } |
1301 | return 0; | 1302 | return 0; |
1302 | 1303 | ||
1303 | } | 1304 | } |
1304 | 1305 | ||
1305 | void | 1306 | void |
1306 | ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) | 1307 | ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) |
1307 | { | 1308 | { |
1308 | struct ia64_psr *ipsr = ia64_psr(regs); | 1309 | struct ia64_psr *ipsr = ia64_psr(regs); |
1309 | mm_segment_t old_fs = get_fs(); | 1310 | mm_segment_t old_fs = get_fs(); |
1310 | unsigned long bundle[2]; | 1311 | unsigned long bundle[2]; |
1311 | unsigned long opcode; | 1312 | unsigned long opcode; |
1312 | struct siginfo si; | 1313 | struct siginfo si; |
1313 | const struct exception_table_entry *eh = NULL; | 1314 | const struct exception_table_entry *eh = NULL; |
1314 | union { | 1315 | union { |
1315 | unsigned long l; | 1316 | unsigned long l; |
1316 | load_store_t insn; | 1317 | load_store_t insn; |
1317 | } u; | 1318 | } u; |
1318 | int ret = -1; | 1319 | int ret = -1; |
1319 | 1320 | ||
1320 | if (ia64_psr(regs)->be) { | 1321 | if (ia64_psr(regs)->be) { |
1321 | /* we don't support big-endian accesses */ | 1322 | /* we don't support big-endian accesses */ |
1322 | if (die_if_kernel("big-endian unaligned accesses are not supported", regs, 0)) | 1323 | if (die_if_kernel("big-endian unaligned accesses are not supported", regs, 0)) |
1323 | return; | 1324 | return; |
1324 | goto force_sigbus; | 1325 | goto force_sigbus; |
1325 | } | 1326 | } |
1326 | 1327 | ||
1327 | /* | 1328 | /* |
1328 | * Treat kernel accesses for which there is an exception handler entry the same as | 1329 | * Treat kernel accesses for which there is an exception handler entry the same as |
1329 | * user-level unaligned accesses. Otherwise, a clever program could trick this | 1330 | * user-level unaligned accesses. Otherwise, a clever program could trick this |
1330 | * handler into reading an arbitrary kernel addresses... | 1331 | * handler into reading an arbitrary kernel addresses... |
1331 | */ | 1332 | */ |
1332 | if (!user_mode(regs)) | 1333 | if (!user_mode(regs)) |
1333 | eh = search_exception_tables(regs->cr_iip + ia64_psr(regs)->ri); | 1334 | eh = search_exception_tables(regs->cr_iip + ia64_psr(regs)->ri); |
1334 | if (user_mode(regs) || eh) { | 1335 | if (user_mode(regs) || eh) { |
1335 | if ((current->thread.flags & IA64_THREAD_UAC_SIGBUS) != 0) | 1336 | if ((current->thread.flags & IA64_THREAD_UAC_SIGBUS) != 0) |
1336 | goto force_sigbus; | 1337 | goto force_sigbus; |
1337 | 1338 | ||
1338 | if (!no_unaligned_warning && | 1339 | if (!no_unaligned_warning && |
1339 | !(current->thread.flags & IA64_THREAD_UAC_NOPRINT) && | 1340 | !(current->thread.flags & IA64_THREAD_UAC_NOPRINT) && |
1340 | within_logging_rate_limit()) | 1341 | within_logging_rate_limit()) |
1341 | { | 1342 | { |
1342 | char buf[200]; /* comm[] is at most 16 bytes... */ | 1343 | char buf[200]; /* comm[] is at most 16 bytes... */ |
1343 | size_t len; | 1344 | size_t len; |
1344 | 1345 | ||
1345 | len = sprintf(buf, "%s(%d): unaligned access to 0x%016lx, " | 1346 | len = sprintf(buf, "%s(%d): unaligned access to 0x%016lx, " |
1346 | "ip=0x%016lx\n\r", current->comm, | 1347 | "ip=0x%016lx\n\r", current->comm, |
1347 | task_pid_nr(current), | 1348 | task_pid_nr(current), |
1348 | ifa, regs->cr_iip + ipsr->ri); | 1349 | ifa, regs->cr_iip + ipsr->ri); |
1349 | /* | 1350 | /* |
1350 | * Don't call tty_write_message() if we're in the kernel; we might | 1351 | * Don't call tty_write_message() if we're in the kernel; we might |
1351 | * be holding locks... | 1352 | * be holding locks... |
1352 | */ | 1353 | */ |
1353 | if (user_mode(regs)) | 1354 | if (user_mode(regs)) |
1354 | tty_write_message(current->signal->tty, buf); | 1355 | tty_write_message(current->signal->tty, buf); |
1355 | buf[len-1] = '\0'; /* drop '\r' */ | 1356 | buf[len-1] = '\0'; /* drop '\r' */ |
1356 | /* watch for command names containing %s */ | 1357 | /* watch for command names containing %s */ |
1357 | printk(KERN_WARNING "%s", buf); | 1358 | printk(KERN_WARNING "%s", buf); |
1358 | } else { | 1359 | } else { |
1359 | if (no_unaligned_warning && !noprint_warning) { | 1360 | if (no_unaligned_warning && !noprint_warning) { |
1360 | noprint_warning = 1; | 1361 | noprint_warning = 1; |
1361 | printk(KERN_WARNING "%s(%d) encountered an " | 1362 | printk(KERN_WARNING "%s(%d) encountered an " |
1362 | "unaligned exception which required\n" | 1363 | "unaligned exception which required\n" |
1363 | "kernel assistance, which degrades " | 1364 | "kernel assistance, which degrades " |
1364 | "the performance of the application.\n" | 1365 | "the performance of the application.\n" |
1365 | "Unaligned exception warnings have " | 1366 | "Unaligned exception warnings have " |
1366 | "been disabled by the system " | 1367 | "been disabled by the system " |
1367 | "administrator\n" | 1368 | "administrator\n" |
1368 | "echo 0 > /proc/sys/kernel/ignore-" | 1369 | "echo 0 > /proc/sys/kernel/ignore-" |
1369 | "unaligned-usertrap to re-enable\n", | 1370 | "unaligned-usertrap to re-enable\n", |
1370 | current->comm, task_pid_nr(current)); | 1371 | current->comm, task_pid_nr(current)); |
1371 | } | 1372 | } |
1372 | } | 1373 | } |
1373 | } else { | 1374 | } else { |
1374 | if (within_logging_rate_limit()) | 1375 | if (within_logging_rate_limit()) { |
1375 | printk(KERN_WARNING "kernel unaligned access to 0x%016lx, ip=0x%016lx\n", | 1376 | printk(KERN_WARNING "kernel unaligned access to 0x%016lx, ip=0x%016lx\n", |
1376 | ifa, regs->cr_iip + ipsr->ri); | 1377 | ifa, regs->cr_iip + ipsr->ri); |
1378 | if (unaligned_dump_stack) | ||
1379 | dump_stack(); | ||
1380 | } | ||
1377 | set_fs(KERNEL_DS); | 1381 | set_fs(KERNEL_DS); |
1378 | } | 1382 | } |
1379 | 1383 | ||
1380 | DPRINT("iip=%lx ifa=%lx isr=%lx (ei=%d, sp=%d)\n", | 1384 | DPRINT("iip=%lx ifa=%lx isr=%lx (ei=%d, sp=%d)\n", |
1381 | regs->cr_iip, ifa, regs->cr_ipsr, ipsr->ri, ipsr->it); | 1385 | regs->cr_iip, ifa, regs->cr_ipsr, ipsr->ri, ipsr->it); |
1382 | 1386 | ||
1383 | if (__copy_from_user(bundle, (void __user *) regs->cr_iip, 16)) | 1387 | if (__copy_from_user(bundle, (void __user *) regs->cr_iip, 16)) |
1384 | goto failure; | 1388 | goto failure; |
1385 | 1389 | ||
1386 | /* | 1390 | /* |
1387 | * extract the instruction from the bundle given the slot number | 1391 | * extract the instruction from the bundle given the slot number |
1388 | */ | 1392 | */ |
1389 | switch (ipsr->ri) { | 1393 | switch (ipsr->ri) { |
1390 | case 0: u.l = (bundle[0] >> 5); break; | 1394 | case 0: u.l = (bundle[0] >> 5); break; |
1391 | case 1: u.l = (bundle[0] >> 46) | (bundle[1] << 18); break; | 1395 | case 1: u.l = (bundle[0] >> 46) | (bundle[1] << 18); break; |
1392 | case 2: u.l = (bundle[1] >> 23); break; | 1396 | case 2: u.l = (bundle[1] >> 23); break; |
1393 | } | 1397 | } |
1394 | opcode = (u.l >> IA64_OPCODE_SHIFT) & IA64_OPCODE_MASK; | 1398 | opcode = (u.l >> IA64_OPCODE_SHIFT) & IA64_OPCODE_MASK; |
1395 | 1399 | ||
1396 | DPRINT("opcode=%lx ld.qp=%d ld.r1=%d ld.imm=%d ld.r3=%d ld.x=%d ld.hint=%d " | 1400 | DPRINT("opcode=%lx ld.qp=%d ld.r1=%d ld.imm=%d ld.r3=%d ld.x=%d ld.hint=%d " |
1397 | "ld.x6=0x%x ld.m=%d ld.op=%d\n", opcode, u.insn.qp, u.insn.r1, u.insn.imm, | 1401 | "ld.x6=0x%x ld.m=%d ld.op=%d\n", opcode, u.insn.qp, u.insn.r1, u.insn.imm, |
1398 | u.insn.r3, u.insn.x, u.insn.hint, u.insn.x6_sz, u.insn.m, u.insn.op); | 1402 | u.insn.r3, u.insn.x, u.insn.hint, u.insn.x6_sz, u.insn.m, u.insn.op); |
1399 | 1403 | ||
1400 | /* | 1404 | /* |
1401 | * IMPORTANT: | 1405 | * IMPORTANT: |
1402 | * Notice that the switch statement DOES not cover all possible instructions | 1406 | * Notice that the switch statement DOES not cover all possible instructions |
1403 | * that DO generate unaligned references. This is made on purpose because for some | 1407 | * that DO generate unaligned references. This is made on purpose because for some |
1404 | * instructions it DOES NOT make sense to try and emulate the access. Sometimes it | 1408 | * instructions it DOES NOT make sense to try and emulate the access. Sometimes it |
1405 | * is WRONG to try and emulate. Here is a list of instruction we don't emulate i.e., | 1409 | * is WRONG to try and emulate. Here is a list of instruction we don't emulate i.e., |
1406 | * the program will get a signal and die: | 1410 | * the program will get a signal and die: |
1407 | * | 1411 | * |
1408 | * load/store: | 1412 | * load/store: |
1409 | * - ldX.spill | 1413 | * - ldX.spill |
1410 | * - stX.spill | 1414 | * - stX.spill |
1411 | * Reason: RNATs are based on addresses | 1415 | * Reason: RNATs are based on addresses |
1412 | * - ld16 | 1416 | * - ld16 |
1413 | * - st16 | 1417 | * - st16 |
1414 | * Reason: ld16 and st16 are supposed to occur in a single | 1418 | * Reason: ld16 and st16 are supposed to occur in a single |
1415 | * memory op | 1419 | * memory op |
1416 | * | 1420 | * |
1417 | * synchronization: | 1421 | * synchronization: |
1418 | * - cmpxchg | 1422 | * - cmpxchg |
1419 | * - fetchadd | 1423 | * - fetchadd |
1420 | * - xchg | 1424 | * - xchg |
1421 | * Reason: ATOMIC operations cannot be emulated properly using multiple | 1425 | * Reason: ATOMIC operations cannot be emulated properly using multiple |
1422 | * instructions. | 1426 | * instructions. |
1423 | * | 1427 | * |
1424 | * speculative loads: | 1428 | * speculative loads: |
1425 | * - ldX.sZ | 1429 | * - ldX.sZ |
1426 | * Reason: side effects, code must be ready to deal with failure so simpler | 1430 | * Reason: side effects, code must be ready to deal with failure so simpler |
1427 | * to let the load fail. | 1431 | * to let the load fail. |
1428 | * --------------------------------------------------------------------------------- | 1432 | * --------------------------------------------------------------------------------- |
1429 | * XXX fixme | 1433 | * XXX fixme |
1430 | * | 1434 | * |
1431 | * I would like to get rid of this switch case and do something | 1435 | * I would like to get rid of this switch case and do something |
1432 | * more elegant. | 1436 | * more elegant. |
1433 | */ | 1437 | */ |
1434 | switch (opcode) { | 1438 | switch (opcode) { |
1435 | case LDS_OP: | 1439 | case LDS_OP: |
1436 | case LDSA_OP: | 1440 | case LDSA_OP: |
1437 | if (u.insn.x) | 1441 | if (u.insn.x) |
1438 | /* oops, really a semaphore op (cmpxchg, etc) */ | 1442 | /* oops, really a semaphore op (cmpxchg, etc) */ |
1439 | goto failure; | 1443 | goto failure; |
1440 | /* no break */ | 1444 | /* no break */ |
1441 | case LDS_IMM_OP: | 1445 | case LDS_IMM_OP: |
1442 | case LDSA_IMM_OP: | 1446 | case LDSA_IMM_OP: |
1443 | case LDFS_OP: | 1447 | case LDFS_OP: |
1444 | case LDFSA_OP: | 1448 | case LDFSA_OP: |
1445 | case LDFS_IMM_OP: | 1449 | case LDFS_IMM_OP: |
1446 | /* | 1450 | /* |
1447 | * The instruction will be retried with deferred exceptions turned on, and | 1451 | * The instruction will be retried with deferred exceptions turned on, and |
1448 | * we should get Nat bit installed | 1452 | * we should get Nat bit installed |
1449 | * | 1453 | * |
1450 | * IMPORTANT: When PSR_ED is set, the register & immediate update forms | 1454 | * IMPORTANT: When PSR_ED is set, the register & immediate update forms |
1451 | * are actually executed even though the operation failed. So we don't | 1455 | * are actually executed even though the operation failed. So we don't |
1452 | * need to take care of this. | 1456 | * need to take care of this. |
1453 | */ | 1457 | */ |
1454 | DPRINT("forcing PSR_ED\n"); | 1458 | DPRINT("forcing PSR_ED\n"); |
1455 | regs->cr_ipsr |= IA64_PSR_ED; | 1459 | regs->cr_ipsr |= IA64_PSR_ED; |
1456 | goto done; | 1460 | goto done; |
1457 | 1461 | ||
1458 | case LD_OP: | 1462 | case LD_OP: |
1459 | case LDA_OP: | 1463 | case LDA_OP: |
1460 | case LDBIAS_OP: | 1464 | case LDBIAS_OP: |
1461 | case LDACQ_OP: | 1465 | case LDACQ_OP: |
1462 | case LDCCLR_OP: | 1466 | case LDCCLR_OP: |
1463 | case LDCNC_OP: | 1467 | case LDCNC_OP: |
1464 | case LDCCLRACQ_OP: | 1468 | case LDCCLRACQ_OP: |
1465 | if (u.insn.x) | 1469 | if (u.insn.x) |
1466 | /* oops, really a semaphore op (cmpxchg, etc) */ | 1470 | /* oops, really a semaphore op (cmpxchg, etc) */ |
1467 | goto failure; | 1471 | goto failure; |
1468 | /* no break */ | 1472 | /* no break */ |
1469 | case LD_IMM_OP: | 1473 | case LD_IMM_OP: |
1470 | case LDA_IMM_OP: | 1474 | case LDA_IMM_OP: |
1471 | case LDBIAS_IMM_OP: | 1475 | case LDBIAS_IMM_OP: |
1472 | case LDACQ_IMM_OP: | 1476 | case LDACQ_IMM_OP: |
1473 | case LDCCLR_IMM_OP: | 1477 | case LDCCLR_IMM_OP: |
1474 | case LDCNC_IMM_OP: | 1478 | case LDCNC_IMM_OP: |
1475 | case LDCCLRACQ_IMM_OP: | 1479 | case LDCCLRACQ_IMM_OP: |
1476 | ret = emulate_load_int(ifa, u.insn, regs); | 1480 | ret = emulate_load_int(ifa, u.insn, regs); |
1477 | break; | 1481 | break; |
1478 | 1482 | ||
1479 | case ST_OP: | 1483 | case ST_OP: |
1480 | case STREL_OP: | 1484 | case STREL_OP: |
1481 | if (u.insn.x) | 1485 | if (u.insn.x) |
1482 | /* oops, really a semaphore op (cmpxchg, etc) */ | 1486 | /* oops, really a semaphore op (cmpxchg, etc) */ |
1483 | goto failure; | 1487 | goto failure; |
1484 | /* no break */ | 1488 | /* no break */ |
1485 | case ST_IMM_OP: | 1489 | case ST_IMM_OP: |
1486 | case STREL_IMM_OP: | 1490 | case STREL_IMM_OP: |
1487 | ret = emulate_store_int(ifa, u.insn, regs); | 1491 | ret = emulate_store_int(ifa, u.insn, regs); |
1488 | break; | 1492 | break; |
1489 | 1493 | ||
1490 | case LDF_OP: | 1494 | case LDF_OP: |
1491 | case LDFA_OP: | 1495 | case LDFA_OP: |
1492 | case LDFCCLR_OP: | 1496 | case LDFCCLR_OP: |
1493 | case LDFCNC_OP: | 1497 | case LDFCNC_OP: |
1494 | if (u.insn.x) | 1498 | if (u.insn.x) |
1495 | ret = emulate_load_floatpair(ifa, u.insn, regs); | 1499 | ret = emulate_load_floatpair(ifa, u.insn, regs); |
1496 | else | 1500 | else |
1497 | ret = emulate_load_float(ifa, u.insn, regs); | 1501 | ret = emulate_load_float(ifa, u.insn, regs); |
1498 | break; | 1502 | break; |
1499 | 1503 | ||
1500 | case LDF_IMM_OP: | 1504 | case LDF_IMM_OP: |
1501 | case LDFA_IMM_OP: | 1505 | case LDFA_IMM_OP: |
1502 | case LDFCCLR_IMM_OP: | 1506 | case LDFCCLR_IMM_OP: |
1503 | case LDFCNC_IMM_OP: | 1507 | case LDFCNC_IMM_OP: |
1504 | ret = emulate_load_float(ifa, u.insn, regs); | 1508 | ret = emulate_load_float(ifa, u.insn, regs); |
1505 | break; | 1509 | break; |
1506 | 1510 | ||
1507 | case STF_OP: | 1511 | case STF_OP: |
1508 | case STF_IMM_OP: | 1512 | case STF_IMM_OP: |
1509 | ret = emulate_store_float(ifa, u.insn, regs); | 1513 | ret = emulate_store_float(ifa, u.insn, regs); |
1510 | break; | 1514 | break; |
1511 | 1515 | ||
1512 | default: | 1516 | default: |
1513 | goto failure; | 1517 | goto failure; |
1514 | } | 1518 | } |
1515 | DPRINT("ret=%d\n", ret); | 1519 | DPRINT("ret=%d\n", ret); |
1516 | if (ret) | 1520 | if (ret) |
1517 | goto failure; | 1521 | goto failure; |
1518 | 1522 | ||
1519 | if (ipsr->ri == 2) | 1523 | if (ipsr->ri == 2) |
1520 | /* | 1524 | /* |
1521 | * given today's architecture this case is not likely to happen because a | 1525 | * given today's architecture this case is not likely to happen because a |
1522 | * memory access instruction (M) can never be in the last slot of a | 1526 | * memory access instruction (M) can never be in the last slot of a |
1523 | * bundle. But let's keep it for now. | 1527 | * bundle. But let's keep it for now. |
1524 | */ | 1528 | */ |
1525 | regs->cr_iip += 16; | 1529 | regs->cr_iip += 16; |
1526 | ipsr->ri = (ipsr->ri + 1) & 0x3; | 1530 | ipsr->ri = (ipsr->ri + 1) & 0x3; |
1527 | 1531 | ||
1528 | DPRINT("ipsr->ri=%d iip=%lx\n", ipsr->ri, regs->cr_iip); | 1532 | DPRINT("ipsr->ri=%d iip=%lx\n", ipsr->ri, regs->cr_iip); |
1529 | done: | 1533 | done: |
1530 | set_fs(old_fs); /* restore original address limit */ | 1534 | set_fs(old_fs); /* restore original address limit */ |
1531 | return; | 1535 | return; |
1532 | 1536 | ||
1533 | failure: | 1537 | failure: |
1534 | /* something went wrong... */ | 1538 | /* something went wrong... */ |
1535 | if (!user_mode(regs)) { | 1539 | if (!user_mode(regs)) { |
1536 | if (eh) { | 1540 | if (eh) { |
1537 | ia64_handle_exception(regs, eh); | 1541 | ia64_handle_exception(regs, eh); |
1538 | goto done; | 1542 | goto done; |
1539 | } | 1543 | } |
1540 | if (die_if_kernel("error during unaligned kernel access\n", regs, ret)) | 1544 | if (die_if_kernel("error during unaligned kernel access\n", regs, ret)) |
1541 | return; | 1545 | return; |
1542 | /* NOT_REACHED */ | 1546 | /* NOT_REACHED */ |
1543 | } | 1547 | } |
1544 | force_sigbus: | 1548 | force_sigbus: |
1545 | si.si_signo = SIGBUS; | 1549 | si.si_signo = SIGBUS; |
1546 | si.si_errno = 0; | 1550 | si.si_errno = 0; |
1547 | si.si_code = BUS_ADRALN; | 1551 | si.si_code = BUS_ADRALN; |
1548 | si.si_addr = (void __user *) ifa; | 1552 | si.si_addr = (void __user *) ifa; |
1549 | si.si_flags = 0; | 1553 | si.si_flags = 0; |
1550 | si.si_isr = 0; | 1554 | si.si_isr = 0; |
1551 | si.si_imm = 0; | 1555 | si.si_imm = 0; |
1552 | force_sig_info(SIGBUS, &si, current); | 1556 | force_sig_info(SIGBUS, &si, current); |
1553 | goto done; | 1557 | goto done; |
1554 | } | 1558 | } |
1555 | 1559 |
kernel/sysctl.c
1 | /* | 1 | /* |
2 | * sysctl.c: General linux system control interface | 2 | * sysctl.c: General linux system control interface |
3 | * | 3 | * |
4 | * Begun 24 March 1995, Stephen Tweedie | 4 | * Begun 24 March 1995, Stephen Tweedie |
5 | * Added /proc support, Dec 1995 | 5 | * Added /proc support, Dec 1995 |
6 | * Added bdflush entry and intvec min/max checking, 2/23/96, Tom Dyas. | 6 | * Added bdflush entry and intvec min/max checking, 2/23/96, Tom Dyas. |
7 | * Added hooks for /proc/sys/net (minor, minor patch), 96/4/1, Mike Shaver. | 7 | * Added hooks for /proc/sys/net (minor, minor patch), 96/4/1, Mike Shaver. |
8 | * Added kernel/java-{interpreter,appletviewer}, 96/5/10, Mike Shaver. | 8 | * Added kernel/java-{interpreter,appletviewer}, 96/5/10, Mike Shaver. |
9 | * Dynamic registration fixes, Stephen Tweedie. | 9 | * Dynamic registration fixes, Stephen Tweedie. |
10 | * Added kswapd-interval, ctrl-alt-del, printk stuff, 1/8/97, Chris Horn. | 10 | * Added kswapd-interval, ctrl-alt-del, printk stuff, 1/8/97, Chris Horn. |
11 | * Made sysctl support optional via CONFIG_SYSCTL, 1/10/97, Chris | 11 | * Made sysctl support optional via CONFIG_SYSCTL, 1/10/97, Chris |
12 | * Horn. | 12 | * Horn. |
13 | * Added proc_doulongvec_ms_jiffies_minmax, 09/08/99, Carlos H. Bauer. | 13 | * Added proc_doulongvec_ms_jiffies_minmax, 09/08/99, Carlos H. Bauer. |
14 | * Added proc_doulongvec_minmax, 09/08/99, Carlos H. Bauer. | 14 | * Added proc_doulongvec_minmax, 09/08/99, Carlos H. Bauer. |
15 | * Changed linked lists to use list.h instead of lists.h, 02/24/00, Bill | 15 | * Changed linked lists to use list.h instead of lists.h, 02/24/00, Bill |
16 | * Wendling. | 16 | * Wendling. |
17 | * The list_for_each() macro wasn't appropriate for the sysctl loop. | 17 | * The list_for_each() macro wasn't appropriate for the sysctl loop. |
18 | * Removed it and replaced it with older style, 03/23/00, Bill Wendling | 18 | * Removed it and replaced it with older style, 03/23/00, Bill Wendling |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
23 | #include <linux/swap.h> | 23 | #include <linux/swap.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/sysctl.h> | 25 | #include <linux/sysctl.h> |
26 | #include <linux/proc_fs.h> | 26 | #include <linux/proc_fs.h> |
27 | #include <linux/security.h> | 27 | #include <linux/security.h> |
28 | #include <linux/ctype.h> | 28 | #include <linux/ctype.h> |
29 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
30 | #include <linux/smp_lock.h> | 30 | #include <linux/smp_lock.h> |
31 | #include <linux/fs.h> | 31 | #include <linux/fs.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
34 | #include <linux/kobject.h> | 34 | #include <linux/kobject.h> |
35 | #include <linux/net.h> | 35 | #include <linux/net.h> |
36 | #include <linux/sysrq.h> | 36 | #include <linux/sysrq.h> |
37 | #include <linux/highuid.h> | 37 | #include <linux/highuid.h> |
38 | #include <linux/writeback.h> | 38 | #include <linux/writeback.h> |
39 | #include <linux/hugetlb.h> | 39 | #include <linux/hugetlb.h> |
40 | #include <linux/initrd.h> | 40 | #include <linux/initrd.h> |
41 | #include <linux/key.h> | 41 | #include <linux/key.h> |
42 | #include <linux/times.h> | 42 | #include <linux/times.h> |
43 | #include <linux/limits.h> | 43 | #include <linux/limits.h> |
44 | #include <linux/dcache.h> | 44 | #include <linux/dcache.h> |
45 | #include <linux/syscalls.h> | 45 | #include <linux/syscalls.h> |
46 | #include <linux/vmstat.h> | 46 | #include <linux/vmstat.h> |
47 | #include <linux/nfs_fs.h> | 47 | #include <linux/nfs_fs.h> |
48 | #include <linux/acpi.h> | 48 | #include <linux/acpi.h> |
49 | #include <linux/reboot.h> | 49 | #include <linux/reboot.h> |
50 | #include <linux/ftrace.h> | 50 | #include <linux/ftrace.h> |
51 | 51 | ||
52 | #include <asm/uaccess.h> | 52 | #include <asm/uaccess.h> |
53 | #include <asm/processor.h> | 53 | #include <asm/processor.h> |
54 | 54 | ||
55 | #ifdef CONFIG_X86 | 55 | #ifdef CONFIG_X86 |
56 | #include <asm/nmi.h> | 56 | #include <asm/nmi.h> |
57 | #include <asm/stacktrace.h> | 57 | #include <asm/stacktrace.h> |
58 | #include <asm/io.h> | 58 | #include <asm/io.h> |
59 | #endif | 59 | #endif |
60 | 60 | ||
61 | static int deprecated_sysctl_warning(struct __sysctl_args *args); | 61 | static int deprecated_sysctl_warning(struct __sysctl_args *args); |
62 | 62 | ||
63 | #if defined(CONFIG_SYSCTL) | 63 | #if defined(CONFIG_SYSCTL) |
64 | 64 | ||
65 | /* External variables not in a header file. */ | 65 | /* External variables not in a header file. */ |
66 | extern int C_A_D; | 66 | extern int C_A_D; |
67 | extern int print_fatal_signals; | 67 | extern int print_fatal_signals; |
68 | extern int sysctl_overcommit_memory; | 68 | extern int sysctl_overcommit_memory; |
69 | extern int sysctl_overcommit_ratio; | 69 | extern int sysctl_overcommit_ratio; |
70 | extern int sysctl_panic_on_oom; | 70 | extern int sysctl_panic_on_oom; |
71 | extern int sysctl_oom_kill_allocating_task; | 71 | extern int sysctl_oom_kill_allocating_task; |
72 | extern int sysctl_oom_dump_tasks; | 72 | extern int sysctl_oom_dump_tasks; |
73 | extern int max_threads; | 73 | extern int max_threads; |
74 | extern int core_uses_pid; | 74 | extern int core_uses_pid; |
75 | extern int suid_dumpable; | 75 | extern int suid_dumpable; |
76 | extern char core_pattern[]; | 76 | extern char core_pattern[]; |
77 | extern int pid_max; | 77 | extern int pid_max; |
78 | extern int min_free_kbytes; | 78 | extern int min_free_kbytes; |
79 | extern int pid_max_min, pid_max_max; | 79 | extern int pid_max_min, pid_max_max; |
80 | extern int sysctl_drop_caches; | 80 | extern int sysctl_drop_caches; |
81 | extern int percpu_pagelist_fraction; | 81 | extern int percpu_pagelist_fraction; |
82 | extern int compat_log; | 82 | extern int compat_log; |
83 | extern int latencytop_enabled; | 83 | extern int latencytop_enabled; |
84 | extern int sysctl_nr_open_min, sysctl_nr_open_max; | 84 | extern int sysctl_nr_open_min, sysctl_nr_open_max; |
85 | #ifndef CONFIG_MMU | 85 | #ifndef CONFIG_MMU |
86 | extern int sysctl_nr_trim_pages; | 86 | extern int sysctl_nr_trim_pages; |
87 | #endif | 87 | #endif |
88 | #ifdef CONFIG_RCU_TORTURE_TEST | 88 | #ifdef CONFIG_RCU_TORTURE_TEST |
89 | extern int rcutorture_runnable; | 89 | extern int rcutorture_runnable; |
90 | #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ | 90 | #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ |
91 | 91 | ||
92 | /* Constants used for minimum and maximum */ | 92 | /* Constants used for minimum and maximum */ |
93 | #ifdef CONFIG_DETECT_SOFTLOCKUP | 93 | #ifdef CONFIG_DETECT_SOFTLOCKUP |
94 | static int sixty = 60; | 94 | static int sixty = 60; |
95 | static int neg_one = -1; | 95 | static int neg_one = -1; |
96 | #endif | 96 | #endif |
97 | 97 | ||
98 | #if defined(CONFIG_MMU) && defined(CONFIG_FILE_LOCKING) | 98 | #if defined(CONFIG_MMU) && defined(CONFIG_FILE_LOCKING) |
99 | static int two = 2; | 99 | static int two = 2; |
100 | #endif | 100 | #endif |
101 | 101 | ||
102 | static int zero; | 102 | static int zero; |
103 | static int one = 1; | 103 | static int one = 1; |
104 | static int one_hundred = 100; | 104 | static int one_hundred = 100; |
105 | 105 | ||
106 | /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */ | 106 | /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */ |
107 | static int maxolduid = 65535; | 107 | static int maxolduid = 65535; |
108 | static int minolduid; | 108 | static int minolduid; |
109 | static int min_percpu_pagelist_fract = 8; | 109 | static int min_percpu_pagelist_fract = 8; |
110 | 110 | ||
111 | static int ngroups_max = NGROUPS_MAX; | 111 | static int ngroups_max = NGROUPS_MAX; |
112 | 112 | ||
113 | #ifdef CONFIG_MODULES | 113 | #ifdef CONFIG_MODULES |
114 | extern char modprobe_path[]; | 114 | extern char modprobe_path[]; |
115 | #endif | 115 | #endif |
116 | #ifdef CONFIG_CHR_DEV_SG | 116 | #ifdef CONFIG_CHR_DEV_SG |
117 | extern int sg_big_buff; | 117 | extern int sg_big_buff; |
118 | #endif | 118 | #endif |
119 | 119 | ||
120 | #ifdef CONFIG_SPARC | 120 | #ifdef CONFIG_SPARC |
121 | #include <asm/system.h> | 121 | #include <asm/system.h> |
122 | #endif | 122 | #endif |
123 | 123 | ||
124 | #ifdef CONFIG_SPARC64 | 124 | #ifdef CONFIG_SPARC64 |
125 | extern int sysctl_tsb_ratio; | 125 | extern int sysctl_tsb_ratio; |
126 | #endif | 126 | #endif |
127 | 127 | ||
128 | #ifdef __hppa__ | 128 | #ifdef __hppa__ |
129 | extern int pwrsw_enabled; | 129 | extern int pwrsw_enabled; |
130 | extern int unaligned_enabled; | 130 | extern int unaligned_enabled; |
131 | #endif | 131 | #endif |
132 | 132 | ||
133 | #ifdef CONFIG_S390 | 133 | #ifdef CONFIG_S390 |
134 | #ifdef CONFIG_MATHEMU | 134 | #ifdef CONFIG_MATHEMU |
135 | extern int sysctl_ieee_emulation_warnings; | 135 | extern int sysctl_ieee_emulation_warnings; |
136 | #endif | 136 | #endif |
137 | extern int sysctl_userprocess_debug; | 137 | extern int sysctl_userprocess_debug; |
138 | extern int spin_retry; | 138 | extern int spin_retry; |
139 | #endif | 139 | #endif |
140 | 140 | ||
141 | #ifdef CONFIG_BSD_PROCESS_ACCT | 141 | #ifdef CONFIG_BSD_PROCESS_ACCT |
142 | extern int acct_parm[]; | 142 | extern int acct_parm[]; |
143 | #endif | 143 | #endif |
144 | 144 | ||
145 | #ifdef CONFIG_IA64 | 145 | #ifdef CONFIG_IA64 |
146 | extern int no_unaligned_warning; | 146 | extern int no_unaligned_warning; |
147 | extern int unaligned_dump_stack; | ||
147 | #endif | 148 | #endif |
148 | 149 | ||
149 | #ifdef CONFIG_RT_MUTEXES | 150 | #ifdef CONFIG_RT_MUTEXES |
150 | extern int max_lock_depth; | 151 | extern int max_lock_depth; |
151 | #endif | 152 | #endif |
152 | 153 | ||
153 | #ifdef CONFIG_PROC_SYSCTL | 154 | #ifdef CONFIG_PROC_SYSCTL |
154 | static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp, | 155 | static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp, |
155 | void __user *buffer, size_t *lenp, loff_t *ppos); | 156 | void __user *buffer, size_t *lenp, loff_t *ppos); |
156 | static int proc_taint(struct ctl_table *table, int write, struct file *filp, | 157 | static int proc_taint(struct ctl_table *table, int write, struct file *filp, |
157 | void __user *buffer, size_t *lenp, loff_t *ppos); | 158 | void __user *buffer, size_t *lenp, loff_t *ppos); |
158 | #endif | 159 | #endif |
159 | 160 | ||
160 | static struct ctl_table root_table[]; | 161 | static struct ctl_table root_table[]; |
161 | static struct ctl_table_root sysctl_table_root; | 162 | static struct ctl_table_root sysctl_table_root; |
162 | static struct ctl_table_header root_table_header = { | 163 | static struct ctl_table_header root_table_header = { |
163 | .count = 1, | 164 | .count = 1, |
164 | .ctl_table = root_table, | 165 | .ctl_table = root_table, |
165 | .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.list), | 166 | .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.list), |
166 | .root = &sysctl_table_root, | 167 | .root = &sysctl_table_root, |
167 | .set = &sysctl_table_root.default_set, | 168 | .set = &sysctl_table_root.default_set, |
168 | }; | 169 | }; |
169 | static struct ctl_table_root sysctl_table_root = { | 170 | static struct ctl_table_root sysctl_table_root = { |
170 | .root_list = LIST_HEAD_INIT(sysctl_table_root.root_list), | 171 | .root_list = LIST_HEAD_INIT(sysctl_table_root.root_list), |
171 | .default_set.list = LIST_HEAD_INIT(root_table_header.ctl_entry), | 172 | .default_set.list = LIST_HEAD_INIT(root_table_header.ctl_entry), |
172 | }; | 173 | }; |
173 | 174 | ||
174 | static struct ctl_table kern_table[]; | 175 | static struct ctl_table kern_table[]; |
175 | static struct ctl_table vm_table[]; | 176 | static struct ctl_table vm_table[]; |
176 | static struct ctl_table fs_table[]; | 177 | static struct ctl_table fs_table[]; |
177 | static struct ctl_table debug_table[]; | 178 | static struct ctl_table debug_table[]; |
178 | static struct ctl_table dev_table[]; | 179 | static struct ctl_table dev_table[]; |
179 | extern struct ctl_table random_table[]; | 180 | extern struct ctl_table random_table[]; |
180 | #ifdef CONFIG_INOTIFY_USER | 181 | #ifdef CONFIG_INOTIFY_USER |
181 | extern struct ctl_table inotify_table[]; | 182 | extern struct ctl_table inotify_table[]; |
182 | #endif | 183 | #endif |
183 | #ifdef CONFIG_EPOLL | 184 | #ifdef CONFIG_EPOLL |
184 | extern struct ctl_table epoll_table[]; | 185 | extern struct ctl_table epoll_table[]; |
185 | #endif | 186 | #endif |
186 | 187 | ||
187 | #ifdef HAVE_ARCH_PICK_MMAP_LAYOUT | 188 | #ifdef HAVE_ARCH_PICK_MMAP_LAYOUT |
188 | int sysctl_legacy_va_layout; | 189 | int sysctl_legacy_va_layout; |
189 | #endif | 190 | #endif |
190 | 191 | ||
191 | extern int prove_locking; | 192 | extern int prove_locking; |
192 | extern int lock_stat; | 193 | extern int lock_stat; |
193 | 194 | ||
194 | /* The default sysctl tables: */ | 195 | /* The default sysctl tables: */ |
195 | 196 | ||
196 | static struct ctl_table root_table[] = { | 197 | static struct ctl_table root_table[] = { |
197 | { | 198 | { |
198 | .ctl_name = CTL_KERN, | 199 | .ctl_name = CTL_KERN, |
199 | .procname = "kernel", | 200 | .procname = "kernel", |
200 | .mode = 0555, | 201 | .mode = 0555, |
201 | .child = kern_table, | 202 | .child = kern_table, |
202 | }, | 203 | }, |
203 | { | 204 | { |
204 | .ctl_name = CTL_VM, | 205 | .ctl_name = CTL_VM, |
205 | .procname = "vm", | 206 | .procname = "vm", |
206 | .mode = 0555, | 207 | .mode = 0555, |
207 | .child = vm_table, | 208 | .child = vm_table, |
208 | }, | 209 | }, |
209 | { | 210 | { |
210 | .ctl_name = CTL_FS, | 211 | .ctl_name = CTL_FS, |
211 | .procname = "fs", | 212 | .procname = "fs", |
212 | .mode = 0555, | 213 | .mode = 0555, |
213 | .child = fs_table, | 214 | .child = fs_table, |
214 | }, | 215 | }, |
215 | { | 216 | { |
216 | .ctl_name = CTL_DEBUG, | 217 | .ctl_name = CTL_DEBUG, |
217 | .procname = "debug", | 218 | .procname = "debug", |
218 | .mode = 0555, | 219 | .mode = 0555, |
219 | .child = debug_table, | 220 | .child = debug_table, |
220 | }, | 221 | }, |
221 | { | 222 | { |
222 | .ctl_name = CTL_DEV, | 223 | .ctl_name = CTL_DEV, |
223 | .procname = "dev", | 224 | .procname = "dev", |
224 | .mode = 0555, | 225 | .mode = 0555, |
225 | .child = dev_table, | 226 | .child = dev_table, |
226 | }, | 227 | }, |
227 | /* | 228 | /* |
228 | * NOTE: do not add new entries to this table unless you have read | 229 | * NOTE: do not add new entries to this table unless you have read |
229 | * Documentation/sysctl/ctl_unnumbered.txt | 230 | * Documentation/sysctl/ctl_unnumbered.txt |
230 | */ | 231 | */ |
231 | { .ctl_name = 0 } | 232 | { .ctl_name = 0 } |
232 | }; | 233 | }; |
233 | 234 | ||
234 | #ifdef CONFIG_SCHED_DEBUG | 235 | #ifdef CONFIG_SCHED_DEBUG |
235 | static int min_sched_granularity_ns = 100000; /* 100 usecs */ | 236 | static int min_sched_granularity_ns = 100000; /* 100 usecs */ |
236 | static int max_sched_granularity_ns = NSEC_PER_SEC; /* 1 second */ | 237 | static int max_sched_granularity_ns = NSEC_PER_SEC; /* 1 second */ |
237 | static int min_wakeup_granularity_ns; /* 0 usecs */ | 238 | static int min_wakeup_granularity_ns; /* 0 usecs */ |
238 | static int max_wakeup_granularity_ns = NSEC_PER_SEC; /* 1 second */ | 239 | static int max_wakeup_granularity_ns = NSEC_PER_SEC; /* 1 second */ |
239 | #endif | 240 | #endif |
240 | 241 | ||
241 | static struct ctl_table kern_table[] = { | 242 | static struct ctl_table kern_table[] = { |
242 | #ifdef CONFIG_SCHED_DEBUG | 243 | #ifdef CONFIG_SCHED_DEBUG |
243 | { | 244 | { |
244 | .ctl_name = CTL_UNNUMBERED, | 245 | .ctl_name = CTL_UNNUMBERED, |
245 | .procname = "sched_min_granularity_ns", | 246 | .procname = "sched_min_granularity_ns", |
246 | .data = &sysctl_sched_min_granularity, | 247 | .data = &sysctl_sched_min_granularity, |
247 | .maxlen = sizeof(unsigned int), | 248 | .maxlen = sizeof(unsigned int), |
248 | .mode = 0644, | 249 | .mode = 0644, |
249 | .proc_handler = &sched_nr_latency_handler, | 250 | .proc_handler = &sched_nr_latency_handler, |
250 | .strategy = &sysctl_intvec, | 251 | .strategy = &sysctl_intvec, |
251 | .extra1 = &min_sched_granularity_ns, | 252 | .extra1 = &min_sched_granularity_ns, |
252 | .extra2 = &max_sched_granularity_ns, | 253 | .extra2 = &max_sched_granularity_ns, |
253 | }, | 254 | }, |
254 | { | 255 | { |
255 | .ctl_name = CTL_UNNUMBERED, | 256 | .ctl_name = CTL_UNNUMBERED, |
256 | .procname = "sched_latency_ns", | 257 | .procname = "sched_latency_ns", |
257 | .data = &sysctl_sched_latency, | 258 | .data = &sysctl_sched_latency, |
258 | .maxlen = sizeof(unsigned int), | 259 | .maxlen = sizeof(unsigned int), |
259 | .mode = 0644, | 260 | .mode = 0644, |
260 | .proc_handler = &sched_nr_latency_handler, | 261 | .proc_handler = &sched_nr_latency_handler, |
261 | .strategy = &sysctl_intvec, | 262 | .strategy = &sysctl_intvec, |
262 | .extra1 = &min_sched_granularity_ns, | 263 | .extra1 = &min_sched_granularity_ns, |
263 | .extra2 = &max_sched_granularity_ns, | 264 | .extra2 = &max_sched_granularity_ns, |
264 | }, | 265 | }, |
265 | { | 266 | { |
266 | .ctl_name = CTL_UNNUMBERED, | 267 | .ctl_name = CTL_UNNUMBERED, |
267 | .procname = "sched_wakeup_granularity_ns", | 268 | .procname = "sched_wakeup_granularity_ns", |
268 | .data = &sysctl_sched_wakeup_granularity, | 269 | .data = &sysctl_sched_wakeup_granularity, |
269 | .maxlen = sizeof(unsigned int), | 270 | .maxlen = sizeof(unsigned int), |
270 | .mode = 0644, | 271 | .mode = 0644, |
271 | .proc_handler = &proc_dointvec_minmax, | 272 | .proc_handler = &proc_dointvec_minmax, |
272 | .strategy = &sysctl_intvec, | 273 | .strategy = &sysctl_intvec, |
273 | .extra1 = &min_wakeup_granularity_ns, | 274 | .extra1 = &min_wakeup_granularity_ns, |
274 | .extra2 = &max_wakeup_granularity_ns, | 275 | .extra2 = &max_wakeup_granularity_ns, |
275 | }, | 276 | }, |
276 | { | 277 | { |
277 | .ctl_name = CTL_UNNUMBERED, | 278 | .ctl_name = CTL_UNNUMBERED, |
278 | .procname = "sched_shares_ratelimit", | 279 | .procname = "sched_shares_ratelimit", |
279 | .data = &sysctl_sched_shares_ratelimit, | 280 | .data = &sysctl_sched_shares_ratelimit, |
280 | .maxlen = sizeof(unsigned int), | 281 | .maxlen = sizeof(unsigned int), |
281 | .mode = 0644, | 282 | .mode = 0644, |
282 | .proc_handler = &proc_dointvec, | 283 | .proc_handler = &proc_dointvec, |
283 | }, | 284 | }, |
284 | { | 285 | { |
285 | .ctl_name = CTL_UNNUMBERED, | 286 | .ctl_name = CTL_UNNUMBERED, |
286 | .procname = "sched_shares_thresh", | 287 | .procname = "sched_shares_thresh", |
287 | .data = &sysctl_sched_shares_thresh, | 288 | .data = &sysctl_sched_shares_thresh, |
288 | .maxlen = sizeof(unsigned int), | 289 | .maxlen = sizeof(unsigned int), |
289 | .mode = 0644, | 290 | .mode = 0644, |
290 | .proc_handler = &proc_dointvec_minmax, | 291 | .proc_handler = &proc_dointvec_minmax, |
291 | .strategy = &sysctl_intvec, | 292 | .strategy = &sysctl_intvec, |
292 | .extra1 = &zero, | 293 | .extra1 = &zero, |
293 | }, | 294 | }, |
294 | { | 295 | { |
295 | .ctl_name = CTL_UNNUMBERED, | 296 | .ctl_name = CTL_UNNUMBERED, |
296 | .procname = "sched_child_runs_first", | 297 | .procname = "sched_child_runs_first", |
297 | .data = &sysctl_sched_child_runs_first, | 298 | .data = &sysctl_sched_child_runs_first, |
298 | .maxlen = sizeof(unsigned int), | 299 | .maxlen = sizeof(unsigned int), |
299 | .mode = 0644, | 300 | .mode = 0644, |
300 | .proc_handler = &proc_dointvec, | 301 | .proc_handler = &proc_dointvec, |
301 | }, | 302 | }, |
302 | { | 303 | { |
303 | .ctl_name = CTL_UNNUMBERED, | 304 | .ctl_name = CTL_UNNUMBERED, |
304 | .procname = "sched_features", | 305 | .procname = "sched_features", |
305 | .data = &sysctl_sched_features, | 306 | .data = &sysctl_sched_features, |
306 | .maxlen = sizeof(unsigned int), | 307 | .maxlen = sizeof(unsigned int), |
307 | .mode = 0644, | 308 | .mode = 0644, |
308 | .proc_handler = &proc_dointvec, | 309 | .proc_handler = &proc_dointvec, |
309 | }, | 310 | }, |
310 | { | 311 | { |
311 | .ctl_name = CTL_UNNUMBERED, | 312 | .ctl_name = CTL_UNNUMBERED, |
312 | .procname = "sched_migration_cost", | 313 | .procname = "sched_migration_cost", |
313 | .data = &sysctl_sched_migration_cost, | 314 | .data = &sysctl_sched_migration_cost, |
314 | .maxlen = sizeof(unsigned int), | 315 | .maxlen = sizeof(unsigned int), |
315 | .mode = 0644, | 316 | .mode = 0644, |
316 | .proc_handler = &proc_dointvec, | 317 | .proc_handler = &proc_dointvec, |
317 | }, | 318 | }, |
318 | { | 319 | { |
319 | .ctl_name = CTL_UNNUMBERED, | 320 | .ctl_name = CTL_UNNUMBERED, |
320 | .procname = "sched_nr_migrate", | 321 | .procname = "sched_nr_migrate", |
321 | .data = &sysctl_sched_nr_migrate, | 322 | .data = &sysctl_sched_nr_migrate, |
322 | .maxlen = sizeof(unsigned int), | 323 | .maxlen = sizeof(unsigned int), |
323 | .mode = 0644, | 324 | .mode = 0644, |
324 | .proc_handler = &proc_dointvec, | 325 | .proc_handler = &proc_dointvec, |
325 | }, | 326 | }, |
326 | #endif | 327 | #endif |
327 | { | 328 | { |
328 | .ctl_name = CTL_UNNUMBERED, | 329 | .ctl_name = CTL_UNNUMBERED, |
329 | .procname = "sched_rt_period_us", | 330 | .procname = "sched_rt_period_us", |
330 | .data = &sysctl_sched_rt_period, | 331 | .data = &sysctl_sched_rt_period, |
331 | .maxlen = sizeof(unsigned int), | 332 | .maxlen = sizeof(unsigned int), |
332 | .mode = 0644, | 333 | .mode = 0644, |
333 | .proc_handler = &sched_rt_handler, | 334 | .proc_handler = &sched_rt_handler, |
334 | }, | 335 | }, |
335 | { | 336 | { |
336 | .ctl_name = CTL_UNNUMBERED, | 337 | .ctl_name = CTL_UNNUMBERED, |
337 | .procname = "sched_rt_runtime_us", | 338 | .procname = "sched_rt_runtime_us", |
338 | .data = &sysctl_sched_rt_runtime, | 339 | .data = &sysctl_sched_rt_runtime, |
339 | .maxlen = sizeof(int), | 340 | .maxlen = sizeof(int), |
340 | .mode = 0644, | 341 | .mode = 0644, |
341 | .proc_handler = &sched_rt_handler, | 342 | .proc_handler = &sched_rt_handler, |
342 | }, | 343 | }, |
343 | { | 344 | { |
344 | .ctl_name = CTL_UNNUMBERED, | 345 | .ctl_name = CTL_UNNUMBERED, |
345 | .procname = "sched_compat_yield", | 346 | .procname = "sched_compat_yield", |
346 | .data = &sysctl_sched_compat_yield, | 347 | .data = &sysctl_sched_compat_yield, |
347 | .maxlen = sizeof(unsigned int), | 348 | .maxlen = sizeof(unsigned int), |
348 | .mode = 0644, | 349 | .mode = 0644, |
349 | .proc_handler = &proc_dointvec, | 350 | .proc_handler = &proc_dointvec, |
350 | }, | 351 | }, |
351 | #ifdef CONFIG_PROVE_LOCKING | 352 | #ifdef CONFIG_PROVE_LOCKING |
352 | { | 353 | { |
353 | .ctl_name = CTL_UNNUMBERED, | 354 | .ctl_name = CTL_UNNUMBERED, |
354 | .procname = "prove_locking", | 355 | .procname = "prove_locking", |
355 | .data = &prove_locking, | 356 | .data = &prove_locking, |
356 | .maxlen = sizeof(int), | 357 | .maxlen = sizeof(int), |
357 | .mode = 0644, | 358 | .mode = 0644, |
358 | .proc_handler = &proc_dointvec, | 359 | .proc_handler = &proc_dointvec, |
359 | }, | 360 | }, |
360 | #endif | 361 | #endif |
361 | #ifdef CONFIG_LOCK_STAT | 362 | #ifdef CONFIG_LOCK_STAT |
362 | { | 363 | { |
363 | .ctl_name = CTL_UNNUMBERED, | 364 | .ctl_name = CTL_UNNUMBERED, |
364 | .procname = "lock_stat", | 365 | .procname = "lock_stat", |
365 | .data = &lock_stat, | 366 | .data = &lock_stat, |
366 | .maxlen = sizeof(int), | 367 | .maxlen = sizeof(int), |
367 | .mode = 0644, | 368 | .mode = 0644, |
368 | .proc_handler = &proc_dointvec, | 369 | .proc_handler = &proc_dointvec, |
369 | }, | 370 | }, |
370 | #endif | 371 | #endif |
371 | { | 372 | { |
372 | .ctl_name = KERN_PANIC, | 373 | .ctl_name = KERN_PANIC, |
373 | .procname = "panic", | 374 | .procname = "panic", |
374 | .data = &panic_timeout, | 375 | .data = &panic_timeout, |
375 | .maxlen = sizeof(int), | 376 | .maxlen = sizeof(int), |
376 | .mode = 0644, | 377 | .mode = 0644, |
377 | .proc_handler = &proc_dointvec, | 378 | .proc_handler = &proc_dointvec, |
378 | }, | 379 | }, |
379 | { | 380 | { |
380 | .ctl_name = KERN_CORE_USES_PID, | 381 | .ctl_name = KERN_CORE_USES_PID, |
381 | .procname = "core_uses_pid", | 382 | .procname = "core_uses_pid", |
382 | .data = &core_uses_pid, | 383 | .data = &core_uses_pid, |
383 | .maxlen = sizeof(int), | 384 | .maxlen = sizeof(int), |
384 | .mode = 0644, | 385 | .mode = 0644, |
385 | .proc_handler = &proc_dointvec, | 386 | .proc_handler = &proc_dointvec, |
386 | }, | 387 | }, |
387 | { | 388 | { |
388 | .ctl_name = KERN_CORE_PATTERN, | 389 | .ctl_name = KERN_CORE_PATTERN, |
389 | .procname = "core_pattern", | 390 | .procname = "core_pattern", |
390 | .data = core_pattern, | 391 | .data = core_pattern, |
391 | .maxlen = CORENAME_MAX_SIZE, | 392 | .maxlen = CORENAME_MAX_SIZE, |
392 | .mode = 0644, | 393 | .mode = 0644, |
393 | .proc_handler = &proc_dostring, | 394 | .proc_handler = &proc_dostring, |
394 | .strategy = &sysctl_string, | 395 | .strategy = &sysctl_string, |
395 | }, | 396 | }, |
396 | #ifdef CONFIG_PROC_SYSCTL | 397 | #ifdef CONFIG_PROC_SYSCTL |
397 | { | 398 | { |
398 | .procname = "tainted", | 399 | .procname = "tainted", |
399 | .maxlen = sizeof(long), | 400 | .maxlen = sizeof(long), |
400 | .mode = 0644, | 401 | .mode = 0644, |
401 | .proc_handler = &proc_taint, | 402 | .proc_handler = &proc_taint, |
402 | }, | 403 | }, |
403 | #endif | 404 | #endif |
404 | #ifdef CONFIG_LATENCYTOP | 405 | #ifdef CONFIG_LATENCYTOP |
405 | { | 406 | { |
406 | .procname = "latencytop", | 407 | .procname = "latencytop", |
407 | .data = &latencytop_enabled, | 408 | .data = &latencytop_enabled, |
408 | .maxlen = sizeof(int), | 409 | .maxlen = sizeof(int), |
409 | .mode = 0644, | 410 | .mode = 0644, |
410 | .proc_handler = &proc_dointvec, | 411 | .proc_handler = &proc_dointvec, |
411 | }, | 412 | }, |
412 | #endif | 413 | #endif |
413 | #ifdef CONFIG_BLK_DEV_INITRD | 414 | #ifdef CONFIG_BLK_DEV_INITRD |
414 | { | 415 | { |
415 | .ctl_name = KERN_REALROOTDEV, | 416 | .ctl_name = KERN_REALROOTDEV, |
416 | .procname = "real-root-dev", | 417 | .procname = "real-root-dev", |
417 | .data = &real_root_dev, | 418 | .data = &real_root_dev, |
418 | .maxlen = sizeof(int), | 419 | .maxlen = sizeof(int), |
419 | .mode = 0644, | 420 | .mode = 0644, |
420 | .proc_handler = &proc_dointvec, | 421 | .proc_handler = &proc_dointvec, |
421 | }, | 422 | }, |
422 | #endif | 423 | #endif |
423 | { | 424 | { |
424 | .ctl_name = CTL_UNNUMBERED, | 425 | .ctl_name = CTL_UNNUMBERED, |
425 | .procname = "print-fatal-signals", | 426 | .procname = "print-fatal-signals", |
426 | .data = &print_fatal_signals, | 427 | .data = &print_fatal_signals, |
427 | .maxlen = sizeof(int), | 428 | .maxlen = sizeof(int), |
428 | .mode = 0644, | 429 | .mode = 0644, |
429 | .proc_handler = &proc_dointvec, | 430 | .proc_handler = &proc_dointvec, |
430 | }, | 431 | }, |
431 | #ifdef CONFIG_SPARC | 432 | #ifdef CONFIG_SPARC |
432 | { | 433 | { |
433 | .ctl_name = KERN_SPARC_REBOOT, | 434 | .ctl_name = KERN_SPARC_REBOOT, |
434 | .procname = "reboot-cmd", | 435 | .procname = "reboot-cmd", |
435 | .data = reboot_command, | 436 | .data = reboot_command, |
436 | .maxlen = 256, | 437 | .maxlen = 256, |
437 | .mode = 0644, | 438 | .mode = 0644, |
438 | .proc_handler = &proc_dostring, | 439 | .proc_handler = &proc_dostring, |
439 | .strategy = &sysctl_string, | 440 | .strategy = &sysctl_string, |
440 | }, | 441 | }, |
441 | { | 442 | { |
442 | .ctl_name = KERN_SPARC_STOP_A, | 443 | .ctl_name = KERN_SPARC_STOP_A, |
443 | .procname = "stop-a", | 444 | .procname = "stop-a", |
444 | .data = &stop_a_enabled, | 445 | .data = &stop_a_enabled, |
445 | .maxlen = sizeof (int), | 446 | .maxlen = sizeof (int), |
446 | .mode = 0644, | 447 | .mode = 0644, |
447 | .proc_handler = &proc_dointvec, | 448 | .proc_handler = &proc_dointvec, |
448 | }, | 449 | }, |
449 | { | 450 | { |
450 | .ctl_name = KERN_SPARC_SCONS_PWROFF, | 451 | .ctl_name = KERN_SPARC_SCONS_PWROFF, |
451 | .procname = "scons-poweroff", | 452 | .procname = "scons-poweroff", |
452 | .data = &scons_pwroff, | 453 | .data = &scons_pwroff, |
453 | .maxlen = sizeof (int), | 454 | .maxlen = sizeof (int), |
454 | .mode = 0644, | 455 | .mode = 0644, |
455 | .proc_handler = &proc_dointvec, | 456 | .proc_handler = &proc_dointvec, |
456 | }, | 457 | }, |
457 | #endif | 458 | #endif |
458 | #ifdef CONFIG_SPARC64 | 459 | #ifdef CONFIG_SPARC64 |
459 | { | 460 | { |
460 | .ctl_name = CTL_UNNUMBERED, | 461 | .ctl_name = CTL_UNNUMBERED, |
461 | .procname = "tsb-ratio", | 462 | .procname = "tsb-ratio", |
462 | .data = &sysctl_tsb_ratio, | 463 | .data = &sysctl_tsb_ratio, |
463 | .maxlen = sizeof (int), | 464 | .maxlen = sizeof (int), |
464 | .mode = 0644, | 465 | .mode = 0644, |
465 | .proc_handler = &proc_dointvec, | 466 | .proc_handler = &proc_dointvec, |
466 | }, | 467 | }, |
467 | #endif | 468 | #endif |
468 | #ifdef __hppa__ | 469 | #ifdef __hppa__ |
469 | { | 470 | { |
470 | .ctl_name = KERN_HPPA_PWRSW, | 471 | .ctl_name = KERN_HPPA_PWRSW, |
471 | .procname = "soft-power", | 472 | .procname = "soft-power", |
472 | .data = &pwrsw_enabled, | 473 | .data = &pwrsw_enabled, |
473 | .maxlen = sizeof (int), | 474 | .maxlen = sizeof (int), |
474 | .mode = 0644, | 475 | .mode = 0644, |
475 | .proc_handler = &proc_dointvec, | 476 | .proc_handler = &proc_dointvec, |
476 | }, | 477 | }, |
477 | { | 478 | { |
478 | .ctl_name = KERN_HPPA_UNALIGNED, | 479 | .ctl_name = KERN_HPPA_UNALIGNED, |
479 | .procname = "unaligned-trap", | 480 | .procname = "unaligned-trap", |
480 | .data = &unaligned_enabled, | 481 | .data = &unaligned_enabled, |
481 | .maxlen = sizeof (int), | 482 | .maxlen = sizeof (int), |
482 | .mode = 0644, | 483 | .mode = 0644, |
483 | .proc_handler = &proc_dointvec, | 484 | .proc_handler = &proc_dointvec, |
484 | }, | 485 | }, |
485 | #endif | 486 | #endif |
486 | { | 487 | { |
487 | .ctl_name = KERN_CTLALTDEL, | 488 | .ctl_name = KERN_CTLALTDEL, |
488 | .procname = "ctrl-alt-del", | 489 | .procname = "ctrl-alt-del", |
489 | .data = &C_A_D, | 490 | .data = &C_A_D, |
490 | .maxlen = sizeof(int), | 491 | .maxlen = sizeof(int), |
491 | .mode = 0644, | 492 | .mode = 0644, |
492 | .proc_handler = &proc_dointvec, | 493 | .proc_handler = &proc_dointvec, |
493 | }, | 494 | }, |
494 | #ifdef CONFIG_FUNCTION_TRACER | 495 | #ifdef CONFIG_FUNCTION_TRACER |
495 | { | 496 | { |
496 | .ctl_name = CTL_UNNUMBERED, | 497 | .ctl_name = CTL_UNNUMBERED, |
497 | .procname = "ftrace_enabled", | 498 | .procname = "ftrace_enabled", |
498 | .data = &ftrace_enabled, | 499 | .data = &ftrace_enabled, |
499 | .maxlen = sizeof(int), | 500 | .maxlen = sizeof(int), |
500 | .mode = 0644, | 501 | .mode = 0644, |
501 | .proc_handler = &ftrace_enable_sysctl, | 502 | .proc_handler = &ftrace_enable_sysctl, |
502 | }, | 503 | }, |
503 | #endif | 504 | #endif |
504 | #ifdef CONFIG_STACK_TRACER | 505 | #ifdef CONFIG_STACK_TRACER |
505 | { | 506 | { |
506 | .ctl_name = CTL_UNNUMBERED, | 507 | .ctl_name = CTL_UNNUMBERED, |
507 | .procname = "stack_tracer_enabled", | 508 | .procname = "stack_tracer_enabled", |
508 | .data = &stack_tracer_enabled, | 509 | .data = &stack_tracer_enabled, |
509 | .maxlen = sizeof(int), | 510 | .maxlen = sizeof(int), |
510 | .mode = 0644, | 511 | .mode = 0644, |
511 | .proc_handler = &stack_trace_sysctl, | 512 | .proc_handler = &stack_trace_sysctl, |
512 | }, | 513 | }, |
513 | #endif | 514 | #endif |
514 | #ifdef CONFIG_TRACING | 515 | #ifdef CONFIG_TRACING |
515 | { | 516 | { |
516 | .ctl_name = CTL_UNNUMBERED, | 517 | .ctl_name = CTL_UNNUMBERED, |
517 | .procname = "ftrace_dump_on_oops", | 518 | .procname = "ftrace_dump_on_oops", |
518 | .data = &ftrace_dump_on_oops, | 519 | .data = &ftrace_dump_on_oops, |
519 | .maxlen = sizeof(int), | 520 | .maxlen = sizeof(int), |
520 | .mode = 0644, | 521 | .mode = 0644, |
521 | .proc_handler = &proc_dointvec, | 522 | .proc_handler = &proc_dointvec, |
522 | }, | 523 | }, |
523 | #endif | 524 | #endif |
524 | #ifdef CONFIG_MODULES | 525 | #ifdef CONFIG_MODULES |
525 | { | 526 | { |
526 | .ctl_name = KERN_MODPROBE, | 527 | .ctl_name = KERN_MODPROBE, |
527 | .procname = "modprobe", | 528 | .procname = "modprobe", |
528 | .data = &modprobe_path, | 529 | .data = &modprobe_path, |
529 | .maxlen = KMOD_PATH_LEN, | 530 | .maxlen = KMOD_PATH_LEN, |
530 | .mode = 0644, | 531 | .mode = 0644, |
531 | .proc_handler = &proc_dostring, | 532 | .proc_handler = &proc_dostring, |
532 | .strategy = &sysctl_string, | 533 | .strategy = &sysctl_string, |
533 | }, | 534 | }, |
534 | #endif | 535 | #endif |
535 | #if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET) | 536 | #if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET) |
536 | { | 537 | { |
537 | .ctl_name = KERN_HOTPLUG, | 538 | .ctl_name = KERN_HOTPLUG, |
538 | .procname = "hotplug", | 539 | .procname = "hotplug", |
539 | .data = &uevent_helper, | 540 | .data = &uevent_helper, |
540 | .maxlen = UEVENT_HELPER_PATH_LEN, | 541 | .maxlen = UEVENT_HELPER_PATH_LEN, |
541 | .mode = 0644, | 542 | .mode = 0644, |
542 | .proc_handler = &proc_dostring, | 543 | .proc_handler = &proc_dostring, |
543 | .strategy = &sysctl_string, | 544 | .strategy = &sysctl_string, |
544 | }, | 545 | }, |
545 | #endif | 546 | #endif |
546 | #ifdef CONFIG_CHR_DEV_SG | 547 | #ifdef CONFIG_CHR_DEV_SG |
547 | { | 548 | { |
548 | .ctl_name = KERN_SG_BIG_BUFF, | 549 | .ctl_name = KERN_SG_BIG_BUFF, |
549 | .procname = "sg-big-buff", | 550 | .procname = "sg-big-buff", |
550 | .data = &sg_big_buff, | 551 | .data = &sg_big_buff, |
551 | .maxlen = sizeof (int), | 552 | .maxlen = sizeof (int), |
552 | .mode = 0444, | 553 | .mode = 0444, |
553 | .proc_handler = &proc_dointvec, | 554 | .proc_handler = &proc_dointvec, |
554 | }, | 555 | }, |
555 | #endif | 556 | #endif |
556 | #ifdef CONFIG_BSD_PROCESS_ACCT | 557 | #ifdef CONFIG_BSD_PROCESS_ACCT |
557 | { | 558 | { |
558 | .ctl_name = KERN_ACCT, | 559 | .ctl_name = KERN_ACCT, |
559 | .procname = "acct", | 560 | .procname = "acct", |
560 | .data = &acct_parm, | 561 | .data = &acct_parm, |
561 | .maxlen = 3*sizeof(int), | 562 | .maxlen = 3*sizeof(int), |
562 | .mode = 0644, | 563 | .mode = 0644, |
563 | .proc_handler = &proc_dointvec, | 564 | .proc_handler = &proc_dointvec, |
564 | }, | 565 | }, |
565 | #endif | 566 | #endif |
566 | #ifdef CONFIG_MAGIC_SYSRQ | 567 | #ifdef CONFIG_MAGIC_SYSRQ |
567 | { | 568 | { |
568 | .ctl_name = KERN_SYSRQ, | 569 | .ctl_name = KERN_SYSRQ, |
569 | .procname = "sysrq", | 570 | .procname = "sysrq", |
570 | .data = &__sysrq_enabled, | 571 | .data = &__sysrq_enabled, |
571 | .maxlen = sizeof (int), | 572 | .maxlen = sizeof (int), |
572 | .mode = 0644, | 573 | .mode = 0644, |
573 | .proc_handler = &proc_dointvec, | 574 | .proc_handler = &proc_dointvec, |
574 | }, | 575 | }, |
575 | #endif | 576 | #endif |
576 | #ifdef CONFIG_PROC_SYSCTL | 577 | #ifdef CONFIG_PROC_SYSCTL |
577 | { | 578 | { |
578 | .procname = "cad_pid", | 579 | .procname = "cad_pid", |
579 | .data = NULL, | 580 | .data = NULL, |
580 | .maxlen = sizeof (int), | 581 | .maxlen = sizeof (int), |
581 | .mode = 0600, | 582 | .mode = 0600, |
582 | .proc_handler = &proc_do_cad_pid, | 583 | .proc_handler = &proc_do_cad_pid, |
583 | }, | 584 | }, |
584 | #endif | 585 | #endif |
585 | { | 586 | { |
586 | .ctl_name = KERN_MAX_THREADS, | 587 | .ctl_name = KERN_MAX_THREADS, |
587 | .procname = "threads-max", | 588 | .procname = "threads-max", |
588 | .data = &max_threads, | 589 | .data = &max_threads, |
589 | .maxlen = sizeof(int), | 590 | .maxlen = sizeof(int), |
590 | .mode = 0644, | 591 | .mode = 0644, |
591 | .proc_handler = &proc_dointvec, | 592 | .proc_handler = &proc_dointvec, |
592 | }, | 593 | }, |
593 | { | 594 | { |
594 | .ctl_name = KERN_RANDOM, | 595 | .ctl_name = KERN_RANDOM, |
595 | .procname = "random", | 596 | .procname = "random", |
596 | .mode = 0555, | 597 | .mode = 0555, |
597 | .child = random_table, | 598 | .child = random_table, |
598 | }, | 599 | }, |
599 | { | 600 | { |
600 | .ctl_name = KERN_OVERFLOWUID, | 601 | .ctl_name = KERN_OVERFLOWUID, |
601 | .procname = "overflowuid", | 602 | .procname = "overflowuid", |
602 | .data = &overflowuid, | 603 | .data = &overflowuid, |
603 | .maxlen = sizeof(int), | 604 | .maxlen = sizeof(int), |
604 | .mode = 0644, | 605 | .mode = 0644, |
605 | .proc_handler = &proc_dointvec_minmax, | 606 | .proc_handler = &proc_dointvec_minmax, |
606 | .strategy = &sysctl_intvec, | 607 | .strategy = &sysctl_intvec, |
607 | .extra1 = &minolduid, | 608 | .extra1 = &minolduid, |
608 | .extra2 = &maxolduid, | 609 | .extra2 = &maxolduid, |
609 | }, | 610 | }, |
610 | { | 611 | { |
611 | .ctl_name = KERN_OVERFLOWGID, | 612 | .ctl_name = KERN_OVERFLOWGID, |
612 | .procname = "overflowgid", | 613 | .procname = "overflowgid", |
613 | .data = &overflowgid, | 614 | .data = &overflowgid, |
614 | .maxlen = sizeof(int), | 615 | .maxlen = sizeof(int), |
615 | .mode = 0644, | 616 | .mode = 0644, |
616 | .proc_handler = &proc_dointvec_minmax, | 617 | .proc_handler = &proc_dointvec_minmax, |
617 | .strategy = &sysctl_intvec, | 618 | .strategy = &sysctl_intvec, |
618 | .extra1 = &minolduid, | 619 | .extra1 = &minolduid, |
619 | .extra2 = &maxolduid, | 620 | .extra2 = &maxolduid, |
620 | }, | 621 | }, |
621 | #ifdef CONFIG_S390 | 622 | #ifdef CONFIG_S390 |
622 | #ifdef CONFIG_MATHEMU | 623 | #ifdef CONFIG_MATHEMU |
623 | { | 624 | { |
624 | .ctl_name = KERN_IEEE_EMULATION_WARNINGS, | 625 | .ctl_name = KERN_IEEE_EMULATION_WARNINGS, |
625 | .procname = "ieee_emulation_warnings", | 626 | .procname = "ieee_emulation_warnings", |
626 | .data = &sysctl_ieee_emulation_warnings, | 627 | .data = &sysctl_ieee_emulation_warnings, |
627 | .maxlen = sizeof(int), | 628 | .maxlen = sizeof(int), |
628 | .mode = 0644, | 629 | .mode = 0644, |
629 | .proc_handler = &proc_dointvec, | 630 | .proc_handler = &proc_dointvec, |
630 | }, | 631 | }, |
631 | #endif | 632 | #endif |
632 | { | 633 | { |
633 | .ctl_name = KERN_S390_USER_DEBUG_LOGGING, | 634 | .ctl_name = KERN_S390_USER_DEBUG_LOGGING, |
634 | .procname = "userprocess_debug", | 635 | .procname = "userprocess_debug", |
635 | .data = &sysctl_userprocess_debug, | 636 | .data = &sysctl_userprocess_debug, |
636 | .maxlen = sizeof(int), | 637 | .maxlen = sizeof(int), |
637 | .mode = 0644, | 638 | .mode = 0644, |
638 | .proc_handler = &proc_dointvec, | 639 | .proc_handler = &proc_dointvec, |
639 | }, | 640 | }, |
640 | #endif | 641 | #endif |
641 | { | 642 | { |
642 | .ctl_name = KERN_PIDMAX, | 643 | .ctl_name = KERN_PIDMAX, |
643 | .procname = "pid_max", | 644 | .procname = "pid_max", |
644 | .data = &pid_max, | 645 | .data = &pid_max, |
645 | .maxlen = sizeof (int), | 646 | .maxlen = sizeof (int), |
646 | .mode = 0644, | 647 | .mode = 0644, |
647 | .proc_handler = &proc_dointvec_minmax, | 648 | .proc_handler = &proc_dointvec_minmax, |
648 | .strategy = sysctl_intvec, | 649 | .strategy = sysctl_intvec, |
649 | .extra1 = &pid_max_min, | 650 | .extra1 = &pid_max_min, |
650 | .extra2 = &pid_max_max, | 651 | .extra2 = &pid_max_max, |
651 | }, | 652 | }, |
652 | { | 653 | { |
653 | .ctl_name = KERN_PANIC_ON_OOPS, | 654 | .ctl_name = KERN_PANIC_ON_OOPS, |
654 | .procname = "panic_on_oops", | 655 | .procname = "panic_on_oops", |
655 | .data = &panic_on_oops, | 656 | .data = &panic_on_oops, |
656 | .maxlen = sizeof(int), | 657 | .maxlen = sizeof(int), |
657 | .mode = 0644, | 658 | .mode = 0644, |
658 | .proc_handler = &proc_dointvec, | 659 | .proc_handler = &proc_dointvec, |
659 | }, | 660 | }, |
660 | #if defined CONFIG_PRINTK | 661 | #if defined CONFIG_PRINTK |
661 | { | 662 | { |
662 | .ctl_name = KERN_PRINTK, | 663 | .ctl_name = KERN_PRINTK, |
663 | .procname = "printk", | 664 | .procname = "printk", |
664 | .data = &console_loglevel, | 665 | .data = &console_loglevel, |
665 | .maxlen = 4*sizeof(int), | 666 | .maxlen = 4*sizeof(int), |
666 | .mode = 0644, | 667 | .mode = 0644, |
667 | .proc_handler = &proc_dointvec, | 668 | .proc_handler = &proc_dointvec, |
668 | }, | 669 | }, |
669 | { | 670 | { |
670 | .ctl_name = KERN_PRINTK_RATELIMIT, | 671 | .ctl_name = KERN_PRINTK_RATELIMIT, |
671 | .procname = "printk_ratelimit", | 672 | .procname = "printk_ratelimit", |
672 | .data = &printk_ratelimit_state.interval, | 673 | .data = &printk_ratelimit_state.interval, |
673 | .maxlen = sizeof(int), | 674 | .maxlen = sizeof(int), |
674 | .mode = 0644, | 675 | .mode = 0644, |
675 | .proc_handler = &proc_dointvec_jiffies, | 676 | .proc_handler = &proc_dointvec_jiffies, |
676 | .strategy = &sysctl_jiffies, | 677 | .strategy = &sysctl_jiffies, |
677 | }, | 678 | }, |
678 | { | 679 | { |
679 | .ctl_name = KERN_PRINTK_RATELIMIT_BURST, | 680 | .ctl_name = KERN_PRINTK_RATELIMIT_BURST, |
680 | .procname = "printk_ratelimit_burst", | 681 | .procname = "printk_ratelimit_burst", |
681 | .data = &printk_ratelimit_state.burst, | 682 | .data = &printk_ratelimit_state.burst, |
682 | .maxlen = sizeof(int), | 683 | .maxlen = sizeof(int), |
683 | .mode = 0644, | 684 | .mode = 0644, |
684 | .proc_handler = &proc_dointvec, | 685 | .proc_handler = &proc_dointvec, |
685 | }, | 686 | }, |
686 | #endif | 687 | #endif |
687 | { | 688 | { |
688 | .ctl_name = KERN_NGROUPS_MAX, | 689 | .ctl_name = KERN_NGROUPS_MAX, |
689 | .procname = "ngroups_max", | 690 | .procname = "ngroups_max", |
690 | .data = &ngroups_max, | 691 | .data = &ngroups_max, |
691 | .maxlen = sizeof (int), | 692 | .maxlen = sizeof (int), |
692 | .mode = 0444, | 693 | .mode = 0444, |
693 | .proc_handler = &proc_dointvec, | 694 | .proc_handler = &proc_dointvec, |
694 | }, | 695 | }, |
695 | #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86) | 696 | #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86) |
696 | { | 697 | { |
697 | .ctl_name = KERN_UNKNOWN_NMI_PANIC, | 698 | .ctl_name = KERN_UNKNOWN_NMI_PANIC, |
698 | .procname = "unknown_nmi_panic", | 699 | .procname = "unknown_nmi_panic", |
699 | .data = &unknown_nmi_panic, | 700 | .data = &unknown_nmi_panic, |
700 | .maxlen = sizeof (int), | 701 | .maxlen = sizeof (int), |
701 | .mode = 0644, | 702 | .mode = 0644, |
702 | .proc_handler = &proc_dointvec, | 703 | .proc_handler = &proc_dointvec, |
703 | }, | 704 | }, |
704 | { | 705 | { |
705 | .procname = "nmi_watchdog", | 706 | .procname = "nmi_watchdog", |
706 | .data = &nmi_watchdog_enabled, | 707 | .data = &nmi_watchdog_enabled, |
707 | .maxlen = sizeof (int), | 708 | .maxlen = sizeof (int), |
708 | .mode = 0644, | 709 | .mode = 0644, |
709 | .proc_handler = &proc_nmi_enabled, | 710 | .proc_handler = &proc_nmi_enabled, |
710 | }, | 711 | }, |
711 | #endif | 712 | #endif |
712 | #if defined(CONFIG_X86) | 713 | #if defined(CONFIG_X86) |
713 | { | 714 | { |
714 | .ctl_name = KERN_PANIC_ON_NMI, | 715 | .ctl_name = KERN_PANIC_ON_NMI, |
715 | .procname = "panic_on_unrecovered_nmi", | 716 | .procname = "panic_on_unrecovered_nmi", |
716 | .data = &panic_on_unrecovered_nmi, | 717 | .data = &panic_on_unrecovered_nmi, |
717 | .maxlen = sizeof(int), | 718 | .maxlen = sizeof(int), |
718 | .mode = 0644, | 719 | .mode = 0644, |
719 | .proc_handler = &proc_dointvec, | 720 | .proc_handler = &proc_dointvec, |
720 | }, | 721 | }, |
721 | { | 722 | { |
722 | .ctl_name = KERN_BOOTLOADER_TYPE, | 723 | .ctl_name = KERN_BOOTLOADER_TYPE, |
723 | .procname = "bootloader_type", | 724 | .procname = "bootloader_type", |
724 | .data = &bootloader_type, | 725 | .data = &bootloader_type, |
725 | .maxlen = sizeof (int), | 726 | .maxlen = sizeof (int), |
726 | .mode = 0444, | 727 | .mode = 0444, |
727 | .proc_handler = &proc_dointvec, | 728 | .proc_handler = &proc_dointvec, |
728 | }, | 729 | }, |
729 | { | 730 | { |
730 | .ctl_name = CTL_UNNUMBERED, | 731 | .ctl_name = CTL_UNNUMBERED, |
731 | .procname = "kstack_depth_to_print", | 732 | .procname = "kstack_depth_to_print", |
732 | .data = &kstack_depth_to_print, | 733 | .data = &kstack_depth_to_print, |
733 | .maxlen = sizeof(int), | 734 | .maxlen = sizeof(int), |
734 | .mode = 0644, | 735 | .mode = 0644, |
735 | .proc_handler = &proc_dointvec, | 736 | .proc_handler = &proc_dointvec, |
736 | }, | 737 | }, |
737 | { | 738 | { |
738 | .ctl_name = CTL_UNNUMBERED, | 739 | .ctl_name = CTL_UNNUMBERED, |
739 | .procname = "io_delay_type", | 740 | .procname = "io_delay_type", |
740 | .data = &io_delay_type, | 741 | .data = &io_delay_type, |
741 | .maxlen = sizeof(int), | 742 | .maxlen = sizeof(int), |
742 | .mode = 0644, | 743 | .mode = 0644, |
743 | .proc_handler = &proc_dointvec, | 744 | .proc_handler = &proc_dointvec, |
744 | }, | 745 | }, |
745 | #endif | 746 | #endif |
746 | #if defined(CONFIG_MMU) | 747 | #if defined(CONFIG_MMU) |
747 | { | 748 | { |
748 | .ctl_name = KERN_RANDOMIZE, | 749 | .ctl_name = KERN_RANDOMIZE, |
749 | .procname = "randomize_va_space", | 750 | .procname = "randomize_va_space", |
750 | .data = &randomize_va_space, | 751 | .data = &randomize_va_space, |
751 | .maxlen = sizeof(int), | 752 | .maxlen = sizeof(int), |
752 | .mode = 0644, | 753 | .mode = 0644, |
753 | .proc_handler = &proc_dointvec, | 754 | .proc_handler = &proc_dointvec, |
754 | }, | 755 | }, |
755 | #endif | 756 | #endif |
756 | #if defined(CONFIG_S390) && defined(CONFIG_SMP) | 757 | #if defined(CONFIG_S390) && defined(CONFIG_SMP) |
757 | { | 758 | { |
758 | .ctl_name = KERN_SPIN_RETRY, | 759 | .ctl_name = KERN_SPIN_RETRY, |
759 | .procname = "spin_retry", | 760 | .procname = "spin_retry", |
760 | .data = &spin_retry, | 761 | .data = &spin_retry, |
761 | .maxlen = sizeof (int), | 762 | .maxlen = sizeof (int), |
762 | .mode = 0644, | 763 | .mode = 0644, |
763 | .proc_handler = &proc_dointvec, | 764 | .proc_handler = &proc_dointvec, |
764 | }, | 765 | }, |
765 | #endif | 766 | #endif |
766 | #if defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86) | 767 | #if defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86) |
767 | { | 768 | { |
768 | .procname = "acpi_video_flags", | 769 | .procname = "acpi_video_flags", |
769 | .data = &acpi_realmode_flags, | 770 | .data = &acpi_realmode_flags, |
770 | .maxlen = sizeof (unsigned long), | 771 | .maxlen = sizeof (unsigned long), |
771 | .mode = 0644, | 772 | .mode = 0644, |
772 | .proc_handler = &proc_doulongvec_minmax, | 773 | .proc_handler = &proc_doulongvec_minmax, |
773 | }, | 774 | }, |
774 | #endif | 775 | #endif |
775 | #ifdef CONFIG_IA64 | 776 | #ifdef CONFIG_IA64 |
776 | { | 777 | { |
777 | .ctl_name = KERN_IA64_UNALIGNED, | 778 | .ctl_name = KERN_IA64_UNALIGNED, |
778 | .procname = "ignore-unaligned-usertrap", | 779 | .procname = "ignore-unaligned-usertrap", |
779 | .data = &no_unaligned_warning, | 780 | .data = &no_unaligned_warning, |
780 | .maxlen = sizeof (int), | 781 | .maxlen = sizeof (int), |
781 | .mode = 0644, | 782 | .mode = 0644, |
783 | .proc_handler = &proc_dointvec, | ||
784 | }, | ||
785 | { | ||
786 | .ctl_name = CTL_UNNUMBERED, | ||
787 | .procname = "unaligned-dump-stack", | ||
788 | .data = &unaligned_dump_stack, | ||
789 | .maxlen = sizeof (int), | ||
790 | .mode = 0644, | ||
782 | .proc_handler = &proc_dointvec, | 791 | .proc_handler = &proc_dointvec, |
783 | }, | 792 | }, |
784 | #endif | 793 | #endif |
785 | #ifdef CONFIG_DETECT_SOFTLOCKUP | 794 | #ifdef CONFIG_DETECT_SOFTLOCKUP |
786 | { | 795 | { |
787 | .ctl_name = CTL_UNNUMBERED, | 796 | .ctl_name = CTL_UNNUMBERED, |
788 | .procname = "softlockup_panic", | 797 | .procname = "softlockup_panic", |
789 | .data = &softlockup_panic, | 798 | .data = &softlockup_panic, |
790 | .maxlen = sizeof(int), | 799 | .maxlen = sizeof(int), |
791 | .mode = 0644, | 800 | .mode = 0644, |
792 | .proc_handler = &proc_dointvec_minmax, | 801 | .proc_handler = &proc_dointvec_minmax, |
793 | .strategy = &sysctl_intvec, | 802 | .strategy = &sysctl_intvec, |
794 | .extra1 = &zero, | 803 | .extra1 = &zero, |
795 | .extra2 = &one, | 804 | .extra2 = &one, |
796 | }, | 805 | }, |
797 | { | 806 | { |
798 | .ctl_name = CTL_UNNUMBERED, | 807 | .ctl_name = CTL_UNNUMBERED, |
799 | .procname = "softlockup_thresh", | 808 | .procname = "softlockup_thresh", |
800 | .data = &softlockup_thresh, | 809 | .data = &softlockup_thresh, |
801 | .maxlen = sizeof(int), | 810 | .maxlen = sizeof(int), |
802 | .mode = 0644, | 811 | .mode = 0644, |
803 | .proc_handler = &proc_dointvec_minmax, | 812 | .proc_handler = &proc_dointvec_minmax, |
804 | .strategy = &sysctl_intvec, | 813 | .strategy = &sysctl_intvec, |
805 | .extra1 = &neg_one, | 814 | .extra1 = &neg_one, |
806 | .extra2 = &sixty, | 815 | .extra2 = &sixty, |
807 | }, | 816 | }, |
808 | { | 817 | { |
809 | .ctl_name = CTL_UNNUMBERED, | 818 | .ctl_name = CTL_UNNUMBERED, |
810 | .procname = "hung_task_check_count", | 819 | .procname = "hung_task_check_count", |
811 | .data = &sysctl_hung_task_check_count, | 820 | .data = &sysctl_hung_task_check_count, |
812 | .maxlen = sizeof(unsigned long), | 821 | .maxlen = sizeof(unsigned long), |
813 | .mode = 0644, | 822 | .mode = 0644, |
814 | .proc_handler = &proc_doulongvec_minmax, | 823 | .proc_handler = &proc_doulongvec_minmax, |
815 | .strategy = &sysctl_intvec, | 824 | .strategy = &sysctl_intvec, |
816 | }, | 825 | }, |
817 | { | 826 | { |
818 | .ctl_name = CTL_UNNUMBERED, | 827 | .ctl_name = CTL_UNNUMBERED, |
819 | .procname = "hung_task_timeout_secs", | 828 | .procname = "hung_task_timeout_secs", |
820 | .data = &sysctl_hung_task_timeout_secs, | 829 | .data = &sysctl_hung_task_timeout_secs, |
821 | .maxlen = sizeof(unsigned long), | 830 | .maxlen = sizeof(unsigned long), |
822 | .mode = 0644, | 831 | .mode = 0644, |
823 | .proc_handler = &proc_doulongvec_minmax, | 832 | .proc_handler = &proc_doulongvec_minmax, |
824 | .strategy = &sysctl_intvec, | 833 | .strategy = &sysctl_intvec, |
825 | }, | 834 | }, |
826 | { | 835 | { |
827 | .ctl_name = CTL_UNNUMBERED, | 836 | .ctl_name = CTL_UNNUMBERED, |
828 | .procname = "hung_task_warnings", | 837 | .procname = "hung_task_warnings", |
829 | .data = &sysctl_hung_task_warnings, | 838 | .data = &sysctl_hung_task_warnings, |
830 | .maxlen = sizeof(unsigned long), | 839 | .maxlen = sizeof(unsigned long), |
831 | .mode = 0644, | 840 | .mode = 0644, |
832 | .proc_handler = &proc_doulongvec_minmax, | 841 | .proc_handler = &proc_doulongvec_minmax, |
833 | .strategy = &sysctl_intvec, | 842 | .strategy = &sysctl_intvec, |
834 | }, | 843 | }, |
835 | #endif | 844 | #endif |
836 | #ifdef CONFIG_COMPAT | 845 | #ifdef CONFIG_COMPAT |
837 | { | 846 | { |
838 | .ctl_name = KERN_COMPAT_LOG, | 847 | .ctl_name = KERN_COMPAT_LOG, |
839 | .procname = "compat-log", | 848 | .procname = "compat-log", |
840 | .data = &compat_log, | 849 | .data = &compat_log, |
841 | .maxlen = sizeof (int), | 850 | .maxlen = sizeof (int), |
842 | .mode = 0644, | 851 | .mode = 0644, |
843 | .proc_handler = &proc_dointvec, | 852 | .proc_handler = &proc_dointvec, |
844 | }, | 853 | }, |
845 | #endif | 854 | #endif |
846 | #ifdef CONFIG_RT_MUTEXES | 855 | #ifdef CONFIG_RT_MUTEXES |
847 | { | 856 | { |
848 | .ctl_name = KERN_MAX_LOCK_DEPTH, | 857 | .ctl_name = KERN_MAX_LOCK_DEPTH, |
849 | .procname = "max_lock_depth", | 858 | .procname = "max_lock_depth", |
850 | .data = &max_lock_depth, | 859 | .data = &max_lock_depth, |
851 | .maxlen = sizeof(int), | 860 | .maxlen = sizeof(int), |
852 | .mode = 0644, | 861 | .mode = 0644, |
853 | .proc_handler = &proc_dointvec, | 862 | .proc_handler = &proc_dointvec, |
854 | }, | 863 | }, |
855 | #endif | 864 | #endif |
856 | { | 865 | { |
857 | .ctl_name = CTL_UNNUMBERED, | 866 | .ctl_name = CTL_UNNUMBERED, |
858 | .procname = "poweroff_cmd", | 867 | .procname = "poweroff_cmd", |
859 | .data = &poweroff_cmd, | 868 | .data = &poweroff_cmd, |
860 | .maxlen = POWEROFF_CMD_PATH_LEN, | 869 | .maxlen = POWEROFF_CMD_PATH_LEN, |
861 | .mode = 0644, | 870 | .mode = 0644, |
862 | .proc_handler = &proc_dostring, | 871 | .proc_handler = &proc_dostring, |
863 | .strategy = &sysctl_string, | 872 | .strategy = &sysctl_string, |
864 | }, | 873 | }, |
865 | #ifdef CONFIG_KEYS | 874 | #ifdef CONFIG_KEYS |
866 | { | 875 | { |
867 | .ctl_name = CTL_UNNUMBERED, | 876 | .ctl_name = CTL_UNNUMBERED, |
868 | .procname = "keys", | 877 | .procname = "keys", |
869 | .mode = 0555, | 878 | .mode = 0555, |
870 | .child = key_sysctls, | 879 | .child = key_sysctls, |
871 | }, | 880 | }, |
872 | #endif | 881 | #endif |
873 | #ifdef CONFIG_RCU_TORTURE_TEST | 882 | #ifdef CONFIG_RCU_TORTURE_TEST |
874 | { | 883 | { |
875 | .ctl_name = CTL_UNNUMBERED, | 884 | .ctl_name = CTL_UNNUMBERED, |
876 | .procname = "rcutorture_runnable", | 885 | .procname = "rcutorture_runnable", |
877 | .data = &rcutorture_runnable, | 886 | .data = &rcutorture_runnable, |
878 | .maxlen = sizeof(int), | 887 | .maxlen = sizeof(int), |
879 | .mode = 0644, | 888 | .mode = 0644, |
880 | .proc_handler = &proc_dointvec, | 889 | .proc_handler = &proc_dointvec, |
881 | }, | 890 | }, |
882 | #endif | 891 | #endif |
883 | #ifdef CONFIG_UNEVICTABLE_LRU | 892 | #ifdef CONFIG_UNEVICTABLE_LRU |
884 | { | 893 | { |
885 | .ctl_name = CTL_UNNUMBERED, | 894 | .ctl_name = CTL_UNNUMBERED, |
886 | .procname = "scan_unevictable_pages", | 895 | .procname = "scan_unevictable_pages", |
887 | .data = &scan_unevictable_pages, | 896 | .data = &scan_unevictable_pages, |
888 | .maxlen = sizeof(scan_unevictable_pages), | 897 | .maxlen = sizeof(scan_unevictable_pages), |
889 | .mode = 0644, | 898 | .mode = 0644, |
890 | .proc_handler = &scan_unevictable_handler, | 899 | .proc_handler = &scan_unevictable_handler, |
891 | }, | 900 | }, |
892 | #endif | 901 | #endif |
893 | /* | 902 | /* |
894 | * NOTE: do not add new entries to this table unless you have read | 903 | * NOTE: do not add new entries to this table unless you have read |
895 | * Documentation/sysctl/ctl_unnumbered.txt | 904 | * Documentation/sysctl/ctl_unnumbered.txt |
896 | */ | 905 | */ |
897 | { .ctl_name = 0 } | 906 | { .ctl_name = 0 } |
898 | }; | 907 | }; |
899 | 908 | ||
900 | static struct ctl_table vm_table[] = { | 909 | static struct ctl_table vm_table[] = { |
901 | { | 910 | { |
902 | .ctl_name = VM_OVERCOMMIT_MEMORY, | 911 | .ctl_name = VM_OVERCOMMIT_MEMORY, |
903 | .procname = "overcommit_memory", | 912 | .procname = "overcommit_memory", |
904 | .data = &sysctl_overcommit_memory, | 913 | .data = &sysctl_overcommit_memory, |
905 | .maxlen = sizeof(sysctl_overcommit_memory), | 914 | .maxlen = sizeof(sysctl_overcommit_memory), |
906 | .mode = 0644, | 915 | .mode = 0644, |
907 | .proc_handler = &proc_dointvec, | 916 | .proc_handler = &proc_dointvec, |
908 | }, | 917 | }, |
909 | { | 918 | { |
910 | .ctl_name = VM_PANIC_ON_OOM, | 919 | .ctl_name = VM_PANIC_ON_OOM, |
911 | .procname = "panic_on_oom", | 920 | .procname = "panic_on_oom", |
912 | .data = &sysctl_panic_on_oom, | 921 | .data = &sysctl_panic_on_oom, |
913 | .maxlen = sizeof(sysctl_panic_on_oom), | 922 | .maxlen = sizeof(sysctl_panic_on_oom), |
914 | .mode = 0644, | 923 | .mode = 0644, |
915 | .proc_handler = &proc_dointvec, | 924 | .proc_handler = &proc_dointvec, |
916 | }, | 925 | }, |
917 | { | 926 | { |
918 | .ctl_name = CTL_UNNUMBERED, | 927 | .ctl_name = CTL_UNNUMBERED, |
919 | .procname = "oom_kill_allocating_task", | 928 | .procname = "oom_kill_allocating_task", |
920 | .data = &sysctl_oom_kill_allocating_task, | 929 | .data = &sysctl_oom_kill_allocating_task, |
921 | .maxlen = sizeof(sysctl_oom_kill_allocating_task), | 930 | .maxlen = sizeof(sysctl_oom_kill_allocating_task), |
922 | .mode = 0644, | 931 | .mode = 0644, |
923 | .proc_handler = &proc_dointvec, | 932 | .proc_handler = &proc_dointvec, |
924 | }, | 933 | }, |
925 | { | 934 | { |
926 | .ctl_name = CTL_UNNUMBERED, | 935 | .ctl_name = CTL_UNNUMBERED, |
927 | .procname = "oom_dump_tasks", | 936 | .procname = "oom_dump_tasks", |
928 | .data = &sysctl_oom_dump_tasks, | 937 | .data = &sysctl_oom_dump_tasks, |
929 | .maxlen = sizeof(sysctl_oom_dump_tasks), | 938 | .maxlen = sizeof(sysctl_oom_dump_tasks), |
930 | .mode = 0644, | 939 | .mode = 0644, |
931 | .proc_handler = &proc_dointvec, | 940 | .proc_handler = &proc_dointvec, |
932 | }, | 941 | }, |
933 | { | 942 | { |
934 | .ctl_name = VM_OVERCOMMIT_RATIO, | 943 | .ctl_name = VM_OVERCOMMIT_RATIO, |
935 | .procname = "overcommit_ratio", | 944 | .procname = "overcommit_ratio", |
936 | .data = &sysctl_overcommit_ratio, | 945 | .data = &sysctl_overcommit_ratio, |
937 | .maxlen = sizeof(sysctl_overcommit_ratio), | 946 | .maxlen = sizeof(sysctl_overcommit_ratio), |
938 | .mode = 0644, | 947 | .mode = 0644, |
939 | .proc_handler = &proc_dointvec, | 948 | .proc_handler = &proc_dointvec, |
940 | }, | 949 | }, |
941 | { | 950 | { |
942 | .ctl_name = VM_PAGE_CLUSTER, | 951 | .ctl_name = VM_PAGE_CLUSTER, |
943 | .procname = "page-cluster", | 952 | .procname = "page-cluster", |
944 | .data = &page_cluster, | 953 | .data = &page_cluster, |
945 | .maxlen = sizeof(int), | 954 | .maxlen = sizeof(int), |
946 | .mode = 0644, | 955 | .mode = 0644, |
947 | .proc_handler = &proc_dointvec, | 956 | .proc_handler = &proc_dointvec, |
948 | }, | 957 | }, |
949 | { | 958 | { |
950 | .ctl_name = VM_DIRTY_BACKGROUND, | 959 | .ctl_name = VM_DIRTY_BACKGROUND, |
951 | .procname = "dirty_background_ratio", | 960 | .procname = "dirty_background_ratio", |
952 | .data = &dirty_background_ratio, | 961 | .data = &dirty_background_ratio, |
953 | .maxlen = sizeof(dirty_background_ratio), | 962 | .maxlen = sizeof(dirty_background_ratio), |
954 | .mode = 0644, | 963 | .mode = 0644, |
955 | .proc_handler = &dirty_background_ratio_handler, | 964 | .proc_handler = &dirty_background_ratio_handler, |
956 | .strategy = &sysctl_intvec, | 965 | .strategy = &sysctl_intvec, |
957 | .extra1 = &zero, | 966 | .extra1 = &zero, |
958 | .extra2 = &one_hundred, | 967 | .extra2 = &one_hundred, |
959 | }, | 968 | }, |
960 | { | 969 | { |
961 | .ctl_name = CTL_UNNUMBERED, | 970 | .ctl_name = CTL_UNNUMBERED, |
962 | .procname = "dirty_background_bytes", | 971 | .procname = "dirty_background_bytes", |
963 | .data = &dirty_background_bytes, | 972 | .data = &dirty_background_bytes, |
964 | .maxlen = sizeof(dirty_background_bytes), | 973 | .maxlen = sizeof(dirty_background_bytes), |
965 | .mode = 0644, | 974 | .mode = 0644, |
966 | .proc_handler = &dirty_background_bytes_handler, | 975 | .proc_handler = &dirty_background_bytes_handler, |
967 | .strategy = &sysctl_intvec, | 976 | .strategy = &sysctl_intvec, |
968 | .extra1 = &one, | 977 | .extra1 = &one, |
969 | }, | 978 | }, |
970 | { | 979 | { |
971 | .ctl_name = VM_DIRTY_RATIO, | 980 | .ctl_name = VM_DIRTY_RATIO, |
972 | .procname = "dirty_ratio", | 981 | .procname = "dirty_ratio", |
973 | .data = &vm_dirty_ratio, | 982 | .data = &vm_dirty_ratio, |
974 | .maxlen = sizeof(vm_dirty_ratio), | 983 | .maxlen = sizeof(vm_dirty_ratio), |
975 | .mode = 0644, | 984 | .mode = 0644, |
976 | .proc_handler = &dirty_ratio_handler, | 985 | .proc_handler = &dirty_ratio_handler, |
977 | .strategy = &sysctl_intvec, | 986 | .strategy = &sysctl_intvec, |
978 | .extra1 = &zero, | 987 | .extra1 = &zero, |
979 | .extra2 = &one_hundred, | 988 | .extra2 = &one_hundred, |
980 | }, | 989 | }, |
981 | { | 990 | { |
982 | .ctl_name = CTL_UNNUMBERED, | 991 | .ctl_name = CTL_UNNUMBERED, |
983 | .procname = "dirty_bytes", | 992 | .procname = "dirty_bytes", |
984 | .data = &vm_dirty_bytes, | 993 | .data = &vm_dirty_bytes, |
985 | .maxlen = sizeof(vm_dirty_bytes), | 994 | .maxlen = sizeof(vm_dirty_bytes), |
986 | .mode = 0644, | 995 | .mode = 0644, |
987 | .proc_handler = &dirty_bytes_handler, | 996 | .proc_handler = &dirty_bytes_handler, |
988 | .strategy = &sysctl_intvec, | 997 | .strategy = &sysctl_intvec, |
989 | .extra1 = &one, | 998 | .extra1 = &one, |
990 | }, | 999 | }, |
991 | { | 1000 | { |
992 | .procname = "dirty_writeback_centisecs", | 1001 | .procname = "dirty_writeback_centisecs", |
993 | .data = &dirty_writeback_interval, | 1002 | .data = &dirty_writeback_interval, |
994 | .maxlen = sizeof(dirty_writeback_interval), | 1003 | .maxlen = sizeof(dirty_writeback_interval), |
995 | .mode = 0644, | 1004 | .mode = 0644, |
996 | .proc_handler = &dirty_writeback_centisecs_handler, | 1005 | .proc_handler = &dirty_writeback_centisecs_handler, |
997 | }, | 1006 | }, |
998 | { | 1007 | { |
999 | .procname = "dirty_expire_centisecs", | 1008 | .procname = "dirty_expire_centisecs", |
1000 | .data = &dirty_expire_interval, | 1009 | .data = &dirty_expire_interval, |
1001 | .maxlen = sizeof(dirty_expire_interval), | 1010 | .maxlen = sizeof(dirty_expire_interval), |
1002 | .mode = 0644, | 1011 | .mode = 0644, |
1003 | .proc_handler = &proc_dointvec_userhz_jiffies, | 1012 | .proc_handler = &proc_dointvec_userhz_jiffies, |
1004 | }, | 1013 | }, |
1005 | { | 1014 | { |
1006 | .ctl_name = VM_NR_PDFLUSH_THREADS, | 1015 | .ctl_name = VM_NR_PDFLUSH_THREADS, |
1007 | .procname = "nr_pdflush_threads", | 1016 | .procname = "nr_pdflush_threads", |
1008 | .data = &nr_pdflush_threads, | 1017 | .data = &nr_pdflush_threads, |
1009 | .maxlen = sizeof nr_pdflush_threads, | 1018 | .maxlen = sizeof nr_pdflush_threads, |
1010 | .mode = 0444 /* read-only*/, | 1019 | .mode = 0444 /* read-only*/, |
1011 | .proc_handler = &proc_dointvec, | 1020 | .proc_handler = &proc_dointvec, |
1012 | }, | 1021 | }, |
1013 | { | 1022 | { |
1014 | .ctl_name = VM_SWAPPINESS, | 1023 | .ctl_name = VM_SWAPPINESS, |
1015 | .procname = "swappiness", | 1024 | .procname = "swappiness", |
1016 | .data = &vm_swappiness, | 1025 | .data = &vm_swappiness, |
1017 | .maxlen = sizeof(vm_swappiness), | 1026 | .maxlen = sizeof(vm_swappiness), |
1018 | .mode = 0644, | 1027 | .mode = 0644, |
1019 | .proc_handler = &proc_dointvec_minmax, | 1028 | .proc_handler = &proc_dointvec_minmax, |
1020 | .strategy = &sysctl_intvec, | 1029 | .strategy = &sysctl_intvec, |
1021 | .extra1 = &zero, | 1030 | .extra1 = &zero, |
1022 | .extra2 = &one_hundred, | 1031 | .extra2 = &one_hundred, |
1023 | }, | 1032 | }, |
1024 | #ifdef CONFIG_HUGETLB_PAGE | 1033 | #ifdef CONFIG_HUGETLB_PAGE |
1025 | { | 1034 | { |
1026 | .procname = "nr_hugepages", | 1035 | .procname = "nr_hugepages", |
1027 | .data = NULL, | 1036 | .data = NULL, |
1028 | .maxlen = sizeof(unsigned long), | 1037 | .maxlen = sizeof(unsigned long), |
1029 | .mode = 0644, | 1038 | .mode = 0644, |
1030 | .proc_handler = &hugetlb_sysctl_handler, | 1039 | .proc_handler = &hugetlb_sysctl_handler, |
1031 | .extra1 = (void *)&hugetlb_zero, | 1040 | .extra1 = (void *)&hugetlb_zero, |
1032 | .extra2 = (void *)&hugetlb_infinity, | 1041 | .extra2 = (void *)&hugetlb_infinity, |
1033 | }, | 1042 | }, |
1034 | { | 1043 | { |
1035 | .ctl_name = VM_HUGETLB_GROUP, | 1044 | .ctl_name = VM_HUGETLB_GROUP, |
1036 | .procname = "hugetlb_shm_group", | 1045 | .procname = "hugetlb_shm_group", |
1037 | .data = &sysctl_hugetlb_shm_group, | 1046 | .data = &sysctl_hugetlb_shm_group, |
1038 | .maxlen = sizeof(gid_t), | 1047 | .maxlen = sizeof(gid_t), |
1039 | .mode = 0644, | 1048 | .mode = 0644, |
1040 | .proc_handler = &proc_dointvec, | 1049 | .proc_handler = &proc_dointvec, |
1041 | }, | 1050 | }, |
1042 | { | 1051 | { |
1043 | .ctl_name = CTL_UNNUMBERED, | 1052 | .ctl_name = CTL_UNNUMBERED, |
1044 | .procname = "hugepages_treat_as_movable", | 1053 | .procname = "hugepages_treat_as_movable", |
1045 | .data = &hugepages_treat_as_movable, | 1054 | .data = &hugepages_treat_as_movable, |
1046 | .maxlen = sizeof(int), | 1055 | .maxlen = sizeof(int), |
1047 | .mode = 0644, | 1056 | .mode = 0644, |
1048 | .proc_handler = &hugetlb_treat_movable_handler, | 1057 | .proc_handler = &hugetlb_treat_movable_handler, |
1049 | }, | 1058 | }, |
1050 | { | 1059 | { |
1051 | .ctl_name = CTL_UNNUMBERED, | 1060 | .ctl_name = CTL_UNNUMBERED, |
1052 | .procname = "nr_overcommit_hugepages", | 1061 | .procname = "nr_overcommit_hugepages", |
1053 | .data = NULL, | 1062 | .data = NULL, |
1054 | .maxlen = sizeof(unsigned long), | 1063 | .maxlen = sizeof(unsigned long), |
1055 | .mode = 0644, | 1064 | .mode = 0644, |
1056 | .proc_handler = &hugetlb_overcommit_handler, | 1065 | .proc_handler = &hugetlb_overcommit_handler, |
1057 | .extra1 = (void *)&hugetlb_zero, | 1066 | .extra1 = (void *)&hugetlb_zero, |
1058 | .extra2 = (void *)&hugetlb_infinity, | 1067 | .extra2 = (void *)&hugetlb_infinity, |
1059 | }, | 1068 | }, |
1060 | #endif | 1069 | #endif |
1061 | { | 1070 | { |
1062 | .ctl_name = VM_LOWMEM_RESERVE_RATIO, | 1071 | .ctl_name = VM_LOWMEM_RESERVE_RATIO, |
1063 | .procname = "lowmem_reserve_ratio", | 1072 | .procname = "lowmem_reserve_ratio", |
1064 | .data = &sysctl_lowmem_reserve_ratio, | 1073 | .data = &sysctl_lowmem_reserve_ratio, |
1065 | .maxlen = sizeof(sysctl_lowmem_reserve_ratio), | 1074 | .maxlen = sizeof(sysctl_lowmem_reserve_ratio), |
1066 | .mode = 0644, | 1075 | .mode = 0644, |
1067 | .proc_handler = &lowmem_reserve_ratio_sysctl_handler, | 1076 | .proc_handler = &lowmem_reserve_ratio_sysctl_handler, |
1068 | .strategy = &sysctl_intvec, | 1077 | .strategy = &sysctl_intvec, |
1069 | }, | 1078 | }, |
1070 | { | 1079 | { |
1071 | .ctl_name = VM_DROP_PAGECACHE, | 1080 | .ctl_name = VM_DROP_PAGECACHE, |
1072 | .procname = "drop_caches", | 1081 | .procname = "drop_caches", |
1073 | .data = &sysctl_drop_caches, | 1082 | .data = &sysctl_drop_caches, |
1074 | .maxlen = sizeof(int), | 1083 | .maxlen = sizeof(int), |
1075 | .mode = 0644, | 1084 | .mode = 0644, |
1076 | .proc_handler = drop_caches_sysctl_handler, | 1085 | .proc_handler = drop_caches_sysctl_handler, |
1077 | .strategy = &sysctl_intvec, | 1086 | .strategy = &sysctl_intvec, |
1078 | }, | 1087 | }, |
1079 | { | 1088 | { |
1080 | .ctl_name = VM_MIN_FREE_KBYTES, | 1089 | .ctl_name = VM_MIN_FREE_KBYTES, |
1081 | .procname = "min_free_kbytes", | 1090 | .procname = "min_free_kbytes", |
1082 | .data = &min_free_kbytes, | 1091 | .data = &min_free_kbytes, |
1083 | .maxlen = sizeof(min_free_kbytes), | 1092 | .maxlen = sizeof(min_free_kbytes), |
1084 | .mode = 0644, | 1093 | .mode = 0644, |
1085 | .proc_handler = &min_free_kbytes_sysctl_handler, | 1094 | .proc_handler = &min_free_kbytes_sysctl_handler, |
1086 | .strategy = &sysctl_intvec, | 1095 | .strategy = &sysctl_intvec, |
1087 | .extra1 = &zero, | 1096 | .extra1 = &zero, |
1088 | }, | 1097 | }, |
1089 | { | 1098 | { |
1090 | .ctl_name = VM_PERCPU_PAGELIST_FRACTION, | 1099 | .ctl_name = VM_PERCPU_PAGELIST_FRACTION, |
1091 | .procname = "percpu_pagelist_fraction", | 1100 | .procname = "percpu_pagelist_fraction", |
1092 | .data = &percpu_pagelist_fraction, | 1101 | .data = &percpu_pagelist_fraction, |
1093 | .maxlen = sizeof(percpu_pagelist_fraction), | 1102 | .maxlen = sizeof(percpu_pagelist_fraction), |
1094 | .mode = 0644, | 1103 | .mode = 0644, |
1095 | .proc_handler = &percpu_pagelist_fraction_sysctl_handler, | 1104 | .proc_handler = &percpu_pagelist_fraction_sysctl_handler, |
1096 | .strategy = &sysctl_intvec, | 1105 | .strategy = &sysctl_intvec, |
1097 | .extra1 = &min_percpu_pagelist_fract, | 1106 | .extra1 = &min_percpu_pagelist_fract, |
1098 | }, | 1107 | }, |
1099 | #ifdef CONFIG_MMU | 1108 | #ifdef CONFIG_MMU |
1100 | { | 1109 | { |
1101 | .ctl_name = VM_MAX_MAP_COUNT, | 1110 | .ctl_name = VM_MAX_MAP_COUNT, |
1102 | .procname = "max_map_count", | 1111 | .procname = "max_map_count", |
1103 | .data = &sysctl_max_map_count, | 1112 | .data = &sysctl_max_map_count, |
1104 | .maxlen = sizeof(sysctl_max_map_count), | 1113 | .maxlen = sizeof(sysctl_max_map_count), |
1105 | .mode = 0644, | 1114 | .mode = 0644, |
1106 | .proc_handler = &proc_dointvec | 1115 | .proc_handler = &proc_dointvec |
1107 | }, | 1116 | }, |
1108 | #else | 1117 | #else |
1109 | { | 1118 | { |
1110 | .ctl_name = CTL_UNNUMBERED, | 1119 | .ctl_name = CTL_UNNUMBERED, |
1111 | .procname = "nr_trim_pages", | 1120 | .procname = "nr_trim_pages", |
1112 | .data = &sysctl_nr_trim_pages, | 1121 | .data = &sysctl_nr_trim_pages, |
1113 | .maxlen = sizeof(sysctl_nr_trim_pages), | 1122 | .maxlen = sizeof(sysctl_nr_trim_pages), |
1114 | .mode = 0644, | 1123 | .mode = 0644, |
1115 | .proc_handler = &proc_dointvec_minmax, | 1124 | .proc_handler = &proc_dointvec_minmax, |
1116 | .strategy = &sysctl_intvec, | 1125 | .strategy = &sysctl_intvec, |
1117 | .extra1 = &zero, | 1126 | .extra1 = &zero, |
1118 | }, | 1127 | }, |
1119 | #endif | 1128 | #endif |
1120 | { | 1129 | { |
1121 | .ctl_name = VM_LAPTOP_MODE, | 1130 | .ctl_name = VM_LAPTOP_MODE, |
1122 | .procname = "laptop_mode", | 1131 | .procname = "laptop_mode", |
1123 | .data = &laptop_mode, | 1132 | .data = &laptop_mode, |
1124 | .maxlen = sizeof(laptop_mode), | 1133 | .maxlen = sizeof(laptop_mode), |
1125 | .mode = 0644, | 1134 | .mode = 0644, |
1126 | .proc_handler = &proc_dointvec_jiffies, | 1135 | .proc_handler = &proc_dointvec_jiffies, |
1127 | .strategy = &sysctl_jiffies, | 1136 | .strategy = &sysctl_jiffies, |
1128 | }, | 1137 | }, |
1129 | { | 1138 | { |
1130 | .ctl_name = VM_BLOCK_DUMP, | 1139 | .ctl_name = VM_BLOCK_DUMP, |
1131 | .procname = "block_dump", | 1140 | .procname = "block_dump", |
1132 | .data = &block_dump, | 1141 | .data = &block_dump, |
1133 | .maxlen = sizeof(block_dump), | 1142 | .maxlen = sizeof(block_dump), |
1134 | .mode = 0644, | 1143 | .mode = 0644, |
1135 | .proc_handler = &proc_dointvec, | 1144 | .proc_handler = &proc_dointvec, |
1136 | .strategy = &sysctl_intvec, | 1145 | .strategy = &sysctl_intvec, |
1137 | .extra1 = &zero, | 1146 | .extra1 = &zero, |
1138 | }, | 1147 | }, |
1139 | { | 1148 | { |
1140 | .ctl_name = VM_VFS_CACHE_PRESSURE, | 1149 | .ctl_name = VM_VFS_CACHE_PRESSURE, |
1141 | .procname = "vfs_cache_pressure", | 1150 | .procname = "vfs_cache_pressure", |
1142 | .data = &sysctl_vfs_cache_pressure, | 1151 | .data = &sysctl_vfs_cache_pressure, |
1143 | .maxlen = sizeof(sysctl_vfs_cache_pressure), | 1152 | .maxlen = sizeof(sysctl_vfs_cache_pressure), |
1144 | .mode = 0644, | 1153 | .mode = 0644, |
1145 | .proc_handler = &proc_dointvec, | 1154 | .proc_handler = &proc_dointvec, |
1146 | .strategy = &sysctl_intvec, | 1155 | .strategy = &sysctl_intvec, |
1147 | .extra1 = &zero, | 1156 | .extra1 = &zero, |
1148 | }, | 1157 | }, |
1149 | #ifdef HAVE_ARCH_PICK_MMAP_LAYOUT | 1158 | #ifdef HAVE_ARCH_PICK_MMAP_LAYOUT |
1150 | { | 1159 | { |
1151 | .ctl_name = VM_LEGACY_VA_LAYOUT, | 1160 | .ctl_name = VM_LEGACY_VA_LAYOUT, |
1152 | .procname = "legacy_va_layout", | 1161 | .procname = "legacy_va_layout", |
1153 | .data = &sysctl_legacy_va_layout, | 1162 | .data = &sysctl_legacy_va_layout, |
1154 | .maxlen = sizeof(sysctl_legacy_va_layout), | 1163 | .maxlen = sizeof(sysctl_legacy_va_layout), |
1155 | .mode = 0644, | 1164 | .mode = 0644, |
1156 | .proc_handler = &proc_dointvec, | 1165 | .proc_handler = &proc_dointvec, |
1157 | .strategy = &sysctl_intvec, | 1166 | .strategy = &sysctl_intvec, |
1158 | .extra1 = &zero, | 1167 | .extra1 = &zero, |
1159 | }, | 1168 | }, |
1160 | #endif | 1169 | #endif |
1161 | #ifdef CONFIG_NUMA | 1170 | #ifdef CONFIG_NUMA |
1162 | { | 1171 | { |
1163 | .ctl_name = VM_ZONE_RECLAIM_MODE, | 1172 | .ctl_name = VM_ZONE_RECLAIM_MODE, |
1164 | .procname = "zone_reclaim_mode", | 1173 | .procname = "zone_reclaim_mode", |
1165 | .data = &zone_reclaim_mode, | 1174 | .data = &zone_reclaim_mode, |
1166 | .maxlen = sizeof(zone_reclaim_mode), | 1175 | .maxlen = sizeof(zone_reclaim_mode), |
1167 | .mode = 0644, | 1176 | .mode = 0644, |
1168 | .proc_handler = &proc_dointvec, | 1177 | .proc_handler = &proc_dointvec, |
1169 | .strategy = &sysctl_intvec, | 1178 | .strategy = &sysctl_intvec, |
1170 | .extra1 = &zero, | 1179 | .extra1 = &zero, |
1171 | }, | 1180 | }, |
1172 | { | 1181 | { |
1173 | .ctl_name = VM_MIN_UNMAPPED, | 1182 | .ctl_name = VM_MIN_UNMAPPED, |
1174 | .procname = "min_unmapped_ratio", | 1183 | .procname = "min_unmapped_ratio", |
1175 | .data = &sysctl_min_unmapped_ratio, | 1184 | .data = &sysctl_min_unmapped_ratio, |
1176 | .maxlen = sizeof(sysctl_min_unmapped_ratio), | 1185 | .maxlen = sizeof(sysctl_min_unmapped_ratio), |
1177 | .mode = 0644, | 1186 | .mode = 0644, |
1178 | .proc_handler = &sysctl_min_unmapped_ratio_sysctl_handler, | 1187 | .proc_handler = &sysctl_min_unmapped_ratio_sysctl_handler, |
1179 | .strategy = &sysctl_intvec, | 1188 | .strategy = &sysctl_intvec, |
1180 | .extra1 = &zero, | 1189 | .extra1 = &zero, |
1181 | .extra2 = &one_hundred, | 1190 | .extra2 = &one_hundred, |
1182 | }, | 1191 | }, |
1183 | { | 1192 | { |
1184 | .ctl_name = VM_MIN_SLAB, | 1193 | .ctl_name = VM_MIN_SLAB, |
1185 | .procname = "min_slab_ratio", | 1194 | .procname = "min_slab_ratio", |
1186 | .data = &sysctl_min_slab_ratio, | 1195 | .data = &sysctl_min_slab_ratio, |
1187 | .maxlen = sizeof(sysctl_min_slab_ratio), | 1196 | .maxlen = sizeof(sysctl_min_slab_ratio), |
1188 | .mode = 0644, | 1197 | .mode = 0644, |
1189 | .proc_handler = &sysctl_min_slab_ratio_sysctl_handler, | 1198 | .proc_handler = &sysctl_min_slab_ratio_sysctl_handler, |
1190 | .strategy = &sysctl_intvec, | 1199 | .strategy = &sysctl_intvec, |
1191 | .extra1 = &zero, | 1200 | .extra1 = &zero, |
1192 | .extra2 = &one_hundred, | 1201 | .extra2 = &one_hundred, |
1193 | }, | 1202 | }, |
1194 | #endif | 1203 | #endif |
1195 | #ifdef CONFIG_SMP | 1204 | #ifdef CONFIG_SMP |
1196 | { | 1205 | { |
1197 | .ctl_name = CTL_UNNUMBERED, | 1206 | .ctl_name = CTL_UNNUMBERED, |
1198 | .procname = "stat_interval", | 1207 | .procname = "stat_interval", |
1199 | .data = &sysctl_stat_interval, | 1208 | .data = &sysctl_stat_interval, |
1200 | .maxlen = sizeof(sysctl_stat_interval), | 1209 | .maxlen = sizeof(sysctl_stat_interval), |
1201 | .mode = 0644, | 1210 | .mode = 0644, |
1202 | .proc_handler = &proc_dointvec_jiffies, | 1211 | .proc_handler = &proc_dointvec_jiffies, |
1203 | .strategy = &sysctl_jiffies, | 1212 | .strategy = &sysctl_jiffies, |
1204 | }, | 1213 | }, |
1205 | #endif | 1214 | #endif |
1206 | #ifdef CONFIG_SECURITY | 1215 | #ifdef CONFIG_SECURITY |
1207 | { | 1216 | { |
1208 | .ctl_name = CTL_UNNUMBERED, | 1217 | .ctl_name = CTL_UNNUMBERED, |
1209 | .procname = "mmap_min_addr", | 1218 | .procname = "mmap_min_addr", |
1210 | .data = &mmap_min_addr, | 1219 | .data = &mmap_min_addr, |
1211 | .maxlen = sizeof(unsigned long), | 1220 | .maxlen = sizeof(unsigned long), |
1212 | .mode = 0644, | 1221 | .mode = 0644, |
1213 | .proc_handler = &proc_doulongvec_minmax, | 1222 | .proc_handler = &proc_doulongvec_minmax, |
1214 | }, | 1223 | }, |
1215 | #endif | 1224 | #endif |
1216 | #ifdef CONFIG_NUMA | 1225 | #ifdef CONFIG_NUMA |
1217 | { | 1226 | { |
1218 | .ctl_name = CTL_UNNUMBERED, | 1227 | .ctl_name = CTL_UNNUMBERED, |
1219 | .procname = "numa_zonelist_order", | 1228 | .procname = "numa_zonelist_order", |
1220 | .data = &numa_zonelist_order, | 1229 | .data = &numa_zonelist_order, |
1221 | .maxlen = NUMA_ZONELIST_ORDER_LEN, | 1230 | .maxlen = NUMA_ZONELIST_ORDER_LEN, |
1222 | .mode = 0644, | 1231 | .mode = 0644, |
1223 | .proc_handler = &numa_zonelist_order_handler, | 1232 | .proc_handler = &numa_zonelist_order_handler, |
1224 | .strategy = &sysctl_string, | 1233 | .strategy = &sysctl_string, |
1225 | }, | 1234 | }, |
1226 | #endif | 1235 | #endif |
1227 | #if (defined(CONFIG_X86_32) && !defined(CONFIG_UML))|| \ | 1236 | #if (defined(CONFIG_X86_32) && !defined(CONFIG_UML))|| \ |
1228 | (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL)) | 1237 | (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL)) |
1229 | { | 1238 | { |
1230 | .ctl_name = VM_VDSO_ENABLED, | 1239 | .ctl_name = VM_VDSO_ENABLED, |
1231 | .procname = "vdso_enabled", | 1240 | .procname = "vdso_enabled", |
1232 | .data = &vdso_enabled, | 1241 | .data = &vdso_enabled, |
1233 | .maxlen = sizeof(vdso_enabled), | 1242 | .maxlen = sizeof(vdso_enabled), |
1234 | .mode = 0644, | 1243 | .mode = 0644, |
1235 | .proc_handler = &proc_dointvec, | 1244 | .proc_handler = &proc_dointvec, |
1236 | .strategy = &sysctl_intvec, | 1245 | .strategy = &sysctl_intvec, |
1237 | .extra1 = &zero, | 1246 | .extra1 = &zero, |
1238 | }, | 1247 | }, |
1239 | #endif | 1248 | #endif |
1240 | #ifdef CONFIG_HIGHMEM | 1249 | #ifdef CONFIG_HIGHMEM |
1241 | { | 1250 | { |
1242 | .ctl_name = CTL_UNNUMBERED, | 1251 | .ctl_name = CTL_UNNUMBERED, |
1243 | .procname = "highmem_is_dirtyable", | 1252 | .procname = "highmem_is_dirtyable", |
1244 | .data = &vm_highmem_is_dirtyable, | 1253 | .data = &vm_highmem_is_dirtyable, |
1245 | .maxlen = sizeof(vm_highmem_is_dirtyable), | 1254 | .maxlen = sizeof(vm_highmem_is_dirtyable), |
1246 | .mode = 0644, | 1255 | .mode = 0644, |
1247 | .proc_handler = &proc_dointvec_minmax, | 1256 | .proc_handler = &proc_dointvec_minmax, |
1248 | .strategy = &sysctl_intvec, | 1257 | .strategy = &sysctl_intvec, |
1249 | .extra1 = &zero, | 1258 | .extra1 = &zero, |
1250 | .extra2 = &one, | 1259 | .extra2 = &one, |
1251 | }, | 1260 | }, |
1252 | #endif | 1261 | #endif |
1253 | /* | 1262 | /* |
1254 | * NOTE: do not add new entries to this table unless you have read | 1263 | * NOTE: do not add new entries to this table unless you have read |
1255 | * Documentation/sysctl/ctl_unnumbered.txt | 1264 | * Documentation/sysctl/ctl_unnumbered.txt |
1256 | */ | 1265 | */ |
1257 | { .ctl_name = 0 } | 1266 | { .ctl_name = 0 } |
1258 | }; | 1267 | }; |
1259 | 1268 | ||
1260 | #if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE) | 1269 | #if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE) |
1261 | static struct ctl_table binfmt_misc_table[] = { | 1270 | static struct ctl_table binfmt_misc_table[] = { |
1262 | { .ctl_name = 0 } | 1271 | { .ctl_name = 0 } |
1263 | }; | 1272 | }; |
1264 | #endif | 1273 | #endif |
1265 | 1274 | ||
1266 | static struct ctl_table fs_table[] = { | 1275 | static struct ctl_table fs_table[] = { |
1267 | { | 1276 | { |
1268 | .ctl_name = FS_NRINODE, | 1277 | .ctl_name = FS_NRINODE, |
1269 | .procname = "inode-nr", | 1278 | .procname = "inode-nr", |
1270 | .data = &inodes_stat, | 1279 | .data = &inodes_stat, |
1271 | .maxlen = 2*sizeof(int), | 1280 | .maxlen = 2*sizeof(int), |
1272 | .mode = 0444, | 1281 | .mode = 0444, |
1273 | .proc_handler = &proc_dointvec, | 1282 | .proc_handler = &proc_dointvec, |
1274 | }, | 1283 | }, |
1275 | { | 1284 | { |
1276 | .ctl_name = FS_STATINODE, | 1285 | .ctl_name = FS_STATINODE, |
1277 | .procname = "inode-state", | 1286 | .procname = "inode-state", |
1278 | .data = &inodes_stat, | 1287 | .data = &inodes_stat, |
1279 | .maxlen = 7*sizeof(int), | 1288 | .maxlen = 7*sizeof(int), |
1280 | .mode = 0444, | 1289 | .mode = 0444, |
1281 | .proc_handler = &proc_dointvec, | 1290 | .proc_handler = &proc_dointvec, |
1282 | }, | 1291 | }, |
1283 | { | 1292 | { |
1284 | .procname = "file-nr", | 1293 | .procname = "file-nr", |
1285 | .data = &files_stat, | 1294 | .data = &files_stat, |
1286 | .maxlen = 3*sizeof(int), | 1295 | .maxlen = 3*sizeof(int), |
1287 | .mode = 0444, | 1296 | .mode = 0444, |
1288 | .proc_handler = &proc_nr_files, | 1297 | .proc_handler = &proc_nr_files, |
1289 | }, | 1298 | }, |
1290 | { | 1299 | { |
1291 | .ctl_name = FS_MAXFILE, | 1300 | .ctl_name = FS_MAXFILE, |
1292 | .procname = "file-max", | 1301 | .procname = "file-max", |
1293 | .data = &files_stat.max_files, | 1302 | .data = &files_stat.max_files, |
1294 | .maxlen = sizeof(int), | 1303 | .maxlen = sizeof(int), |
1295 | .mode = 0644, | 1304 | .mode = 0644, |
1296 | .proc_handler = &proc_dointvec, | 1305 | .proc_handler = &proc_dointvec, |
1297 | }, | 1306 | }, |
1298 | { | 1307 | { |
1299 | .ctl_name = CTL_UNNUMBERED, | 1308 | .ctl_name = CTL_UNNUMBERED, |
1300 | .procname = "nr_open", | 1309 | .procname = "nr_open", |
1301 | .data = &sysctl_nr_open, | 1310 | .data = &sysctl_nr_open, |
1302 | .maxlen = sizeof(int), | 1311 | .maxlen = sizeof(int), |
1303 | .mode = 0644, | 1312 | .mode = 0644, |
1304 | .proc_handler = &proc_dointvec_minmax, | 1313 | .proc_handler = &proc_dointvec_minmax, |
1305 | .extra1 = &sysctl_nr_open_min, | 1314 | .extra1 = &sysctl_nr_open_min, |
1306 | .extra2 = &sysctl_nr_open_max, | 1315 | .extra2 = &sysctl_nr_open_max, |
1307 | }, | 1316 | }, |
1308 | { | 1317 | { |
1309 | .ctl_name = FS_DENTRY, | 1318 | .ctl_name = FS_DENTRY, |
1310 | .procname = "dentry-state", | 1319 | .procname = "dentry-state", |
1311 | .data = &dentry_stat, | 1320 | .data = &dentry_stat, |
1312 | .maxlen = 6*sizeof(int), | 1321 | .maxlen = 6*sizeof(int), |
1313 | .mode = 0444, | 1322 | .mode = 0444, |
1314 | .proc_handler = &proc_dointvec, | 1323 | .proc_handler = &proc_dointvec, |
1315 | }, | 1324 | }, |
1316 | { | 1325 | { |
1317 | .ctl_name = FS_OVERFLOWUID, | 1326 | .ctl_name = FS_OVERFLOWUID, |
1318 | .procname = "overflowuid", | 1327 | .procname = "overflowuid", |
1319 | .data = &fs_overflowuid, | 1328 | .data = &fs_overflowuid, |
1320 | .maxlen = sizeof(int), | 1329 | .maxlen = sizeof(int), |
1321 | .mode = 0644, | 1330 | .mode = 0644, |
1322 | .proc_handler = &proc_dointvec_minmax, | 1331 | .proc_handler = &proc_dointvec_minmax, |
1323 | .strategy = &sysctl_intvec, | 1332 | .strategy = &sysctl_intvec, |
1324 | .extra1 = &minolduid, | 1333 | .extra1 = &minolduid, |
1325 | .extra2 = &maxolduid, | 1334 | .extra2 = &maxolduid, |
1326 | }, | 1335 | }, |
1327 | { | 1336 | { |
1328 | .ctl_name = FS_OVERFLOWGID, | 1337 | .ctl_name = FS_OVERFLOWGID, |
1329 | .procname = "overflowgid", | 1338 | .procname = "overflowgid", |
1330 | .data = &fs_overflowgid, | 1339 | .data = &fs_overflowgid, |
1331 | .maxlen = sizeof(int), | 1340 | .maxlen = sizeof(int), |
1332 | .mode = 0644, | 1341 | .mode = 0644, |
1333 | .proc_handler = &proc_dointvec_minmax, | 1342 | .proc_handler = &proc_dointvec_minmax, |
1334 | .strategy = &sysctl_intvec, | 1343 | .strategy = &sysctl_intvec, |
1335 | .extra1 = &minolduid, | 1344 | .extra1 = &minolduid, |
1336 | .extra2 = &maxolduid, | 1345 | .extra2 = &maxolduid, |
1337 | }, | 1346 | }, |
1338 | #ifdef CONFIG_FILE_LOCKING | 1347 | #ifdef CONFIG_FILE_LOCKING |
1339 | { | 1348 | { |
1340 | .ctl_name = FS_LEASES, | 1349 | .ctl_name = FS_LEASES, |
1341 | .procname = "leases-enable", | 1350 | .procname = "leases-enable", |
1342 | .data = &leases_enable, | 1351 | .data = &leases_enable, |
1343 | .maxlen = sizeof(int), | 1352 | .maxlen = sizeof(int), |
1344 | .mode = 0644, | 1353 | .mode = 0644, |
1345 | .proc_handler = &proc_dointvec, | 1354 | .proc_handler = &proc_dointvec, |
1346 | }, | 1355 | }, |
1347 | #endif | 1356 | #endif |
1348 | #ifdef CONFIG_DNOTIFY | 1357 | #ifdef CONFIG_DNOTIFY |
1349 | { | 1358 | { |
1350 | .ctl_name = FS_DIR_NOTIFY, | 1359 | .ctl_name = FS_DIR_NOTIFY, |
1351 | .procname = "dir-notify-enable", | 1360 | .procname = "dir-notify-enable", |
1352 | .data = &dir_notify_enable, | 1361 | .data = &dir_notify_enable, |
1353 | .maxlen = sizeof(int), | 1362 | .maxlen = sizeof(int), |
1354 | .mode = 0644, | 1363 | .mode = 0644, |
1355 | .proc_handler = &proc_dointvec, | 1364 | .proc_handler = &proc_dointvec, |
1356 | }, | 1365 | }, |
1357 | #endif | 1366 | #endif |
1358 | #ifdef CONFIG_MMU | 1367 | #ifdef CONFIG_MMU |
1359 | #ifdef CONFIG_FILE_LOCKING | 1368 | #ifdef CONFIG_FILE_LOCKING |
1360 | { | 1369 | { |
1361 | .ctl_name = FS_LEASE_TIME, | 1370 | .ctl_name = FS_LEASE_TIME, |
1362 | .procname = "lease-break-time", | 1371 | .procname = "lease-break-time", |
1363 | .data = &lease_break_time, | 1372 | .data = &lease_break_time, |
1364 | .maxlen = sizeof(int), | 1373 | .maxlen = sizeof(int), |
1365 | .mode = 0644, | 1374 | .mode = 0644, |
1366 | .proc_handler = &proc_dointvec_minmax, | 1375 | .proc_handler = &proc_dointvec_minmax, |
1367 | .strategy = &sysctl_intvec, | 1376 | .strategy = &sysctl_intvec, |
1368 | .extra1 = &zero, | 1377 | .extra1 = &zero, |
1369 | .extra2 = &two, | 1378 | .extra2 = &two, |
1370 | }, | 1379 | }, |
1371 | #endif | 1380 | #endif |
1372 | #ifdef CONFIG_AIO | 1381 | #ifdef CONFIG_AIO |
1373 | { | 1382 | { |
1374 | .procname = "aio-nr", | 1383 | .procname = "aio-nr", |
1375 | .data = &aio_nr, | 1384 | .data = &aio_nr, |
1376 | .maxlen = sizeof(aio_nr), | 1385 | .maxlen = sizeof(aio_nr), |
1377 | .mode = 0444, | 1386 | .mode = 0444, |
1378 | .proc_handler = &proc_doulongvec_minmax, | 1387 | .proc_handler = &proc_doulongvec_minmax, |
1379 | }, | 1388 | }, |
1380 | { | 1389 | { |
1381 | .procname = "aio-max-nr", | 1390 | .procname = "aio-max-nr", |
1382 | .data = &aio_max_nr, | 1391 | .data = &aio_max_nr, |
1383 | .maxlen = sizeof(aio_max_nr), | 1392 | .maxlen = sizeof(aio_max_nr), |
1384 | .mode = 0644, | 1393 | .mode = 0644, |
1385 | .proc_handler = &proc_doulongvec_minmax, | 1394 | .proc_handler = &proc_doulongvec_minmax, |
1386 | }, | 1395 | }, |
1387 | #endif /* CONFIG_AIO */ | 1396 | #endif /* CONFIG_AIO */ |
1388 | #ifdef CONFIG_INOTIFY_USER | 1397 | #ifdef CONFIG_INOTIFY_USER |
1389 | { | 1398 | { |
1390 | .ctl_name = FS_INOTIFY, | 1399 | .ctl_name = FS_INOTIFY, |
1391 | .procname = "inotify", | 1400 | .procname = "inotify", |
1392 | .mode = 0555, | 1401 | .mode = 0555, |
1393 | .child = inotify_table, | 1402 | .child = inotify_table, |
1394 | }, | 1403 | }, |
1395 | #endif | 1404 | #endif |
1396 | #ifdef CONFIG_EPOLL | 1405 | #ifdef CONFIG_EPOLL |
1397 | { | 1406 | { |
1398 | .procname = "epoll", | 1407 | .procname = "epoll", |
1399 | .mode = 0555, | 1408 | .mode = 0555, |
1400 | .child = epoll_table, | 1409 | .child = epoll_table, |
1401 | }, | 1410 | }, |
1402 | #endif | 1411 | #endif |
1403 | #endif | 1412 | #endif |
1404 | { | 1413 | { |
1405 | .ctl_name = KERN_SETUID_DUMPABLE, | 1414 | .ctl_name = KERN_SETUID_DUMPABLE, |
1406 | .procname = "suid_dumpable", | 1415 | .procname = "suid_dumpable", |
1407 | .data = &suid_dumpable, | 1416 | .data = &suid_dumpable, |
1408 | .maxlen = sizeof(int), | 1417 | .maxlen = sizeof(int), |
1409 | .mode = 0644, | 1418 | .mode = 0644, |
1410 | .proc_handler = &proc_dointvec, | 1419 | .proc_handler = &proc_dointvec, |
1411 | }, | 1420 | }, |
1412 | #if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE) | 1421 | #if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE) |
1413 | { | 1422 | { |
1414 | .ctl_name = CTL_UNNUMBERED, | 1423 | .ctl_name = CTL_UNNUMBERED, |
1415 | .procname = "binfmt_misc", | 1424 | .procname = "binfmt_misc", |
1416 | .mode = 0555, | 1425 | .mode = 0555, |
1417 | .child = binfmt_misc_table, | 1426 | .child = binfmt_misc_table, |
1418 | }, | 1427 | }, |
1419 | #endif | 1428 | #endif |
1420 | /* | 1429 | /* |
1421 | * NOTE: do not add new entries to this table unless you have read | 1430 | * NOTE: do not add new entries to this table unless you have read |
1422 | * Documentation/sysctl/ctl_unnumbered.txt | 1431 | * Documentation/sysctl/ctl_unnumbered.txt |
1423 | */ | 1432 | */ |
1424 | { .ctl_name = 0 } | 1433 | { .ctl_name = 0 } |
1425 | }; | 1434 | }; |
1426 | 1435 | ||
1427 | static struct ctl_table debug_table[] = { | 1436 | static struct ctl_table debug_table[] = { |
1428 | #if defined(CONFIG_X86) || defined(CONFIG_PPC) | 1437 | #if defined(CONFIG_X86) || defined(CONFIG_PPC) |
1429 | { | 1438 | { |
1430 | .ctl_name = CTL_UNNUMBERED, | 1439 | .ctl_name = CTL_UNNUMBERED, |
1431 | .procname = "exception-trace", | 1440 | .procname = "exception-trace", |
1432 | .data = &show_unhandled_signals, | 1441 | .data = &show_unhandled_signals, |
1433 | .maxlen = sizeof(int), | 1442 | .maxlen = sizeof(int), |
1434 | .mode = 0644, | 1443 | .mode = 0644, |
1435 | .proc_handler = proc_dointvec | 1444 | .proc_handler = proc_dointvec |
1436 | }, | 1445 | }, |
1437 | #endif | 1446 | #endif |
1438 | { .ctl_name = 0 } | 1447 | { .ctl_name = 0 } |
1439 | }; | 1448 | }; |
1440 | 1449 | ||
1441 | static struct ctl_table dev_table[] = { | 1450 | static struct ctl_table dev_table[] = { |
1442 | { .ctl_name = 0 } | 1451 | { .ctl_name = 0 } |
1443 | }; | 1452 | }; |
1444 | 1453 | ||
1445 | static DEFINE_SPINLOCK(sysctl_lock); | 1454 | static DEFINE_SPINLOCK(sysctl_lock); |
1446 | 1455 | ||
1447 | /* called under sysctl_lock */ | 1456 | /* called under sysctl_lock */ |
1448 | static int use_table(struct ctl_table_header *p) | 1457 | static int use_table(struct ctl_table_header *p) |
1449 | { | 1458 | { |
1450 | if (unlikely(p->unregistering)) | 1459 | if (unlikely(p->unregistering)) |
1451 | return 0; | 1460 | return 0; |
1452 | p->used++; | 1461 | p->used++; |
1453 | return 1; | 1462 | return 1; |
1454 | } | 1463 | } |
1455 | 1464 | ||
1456 | /* called under sysctl_lock */ | 1465 | /* called under sysctl_lock */ |
1457 | static void unuse_table(struct ctl_table_header *p) | 1466 | static void unuse_table(struct ctl_table_header *p) |
1458 | { | 1467 | { |
1459 | if (!--p->used) | 1468 | if (!--p->used) |
1460 | if (unlikely(p->unregistering)) | 1469 | if (unlikely(p->unregistering)) |
1461 | complete(p->unregistering); | 1470 | complete(p->unregistering); |
1462 | } | 1471 | } |
1463 | 1472 | ||
1464 | /* called under sysctl_lock, will reacquire if has to wait */ | 1473 | /* called under sysctl_lock, will reacquire if has to wait */ |
1465 | static void start_unregistering(struct ctl_table_header *p) | 1474 | static void start_unregistering(struct ctl_table_header *p) |
1466 | { | 1475 | { |
1467 | /* | 1476 | /* |
1468 | * if p->used is 0, nobody will ever touch that entry again; | 1477 | * if p->used is 0, nobody will ever touch that entry again; |
1469 | * we'll eliminate all paths to it before dropping sysctl_lock | 1478 | * we'll eliminate all paths to it before dropping sysctl_lock |
1470 | */ | 1479 | */ |
1471 | if (unlikely(p->used)) { | 1480 | if (unlikely(p->used)) { |
1472 | struct completion wait; | 1481 | struct completion wait; |
1473 | init_completion(&wait); | 1482 | init_completion(&wait); |
1474 | p->unregistering = &wait; | 1483 | p->unregistering = &wait; |
1475 | spin_unlock(&sysctl_lock); | 1484 | spin_unlock(&sysctl_lock); |
1476 | wait_for_completion(&wait); | 1485 | wait_for_completion(&wait); |
1477 | spin_lock(&sysctl_lock); | 1486 | spin_lock(&sysctl_lock); |
1478 | } else { | 1487 | } else { |
1479 | /* anything non-NULL; we'll never dereference it */ | 1488 | /* anything non-NULL; we'll never dereference it */ |
1480 | p->unregistering = ERR_PTR(-EINVAL); | 1489 | p->unregistering = ERR_PTR(-EINVAL); |
1481 | } | 1490 | } |
1482 | /* | 1491 | /* |
1483 | * do not remove from the list until nobody holds it; walking the | 1492 | * do not remove from the list until nobody holds it; walking the |
1484 | * list in do_sysctl() relies on that. | 1493 | * list in do_sysctl() relies on that. |
1485 | */ | 1494 | */ |
1486 | list_del_init(&p->ctl_entry); | 1495 | list_del_init(&p->ctl_entry); |
1487 | } | 1496 | } |
1488 | 1497 | ||
1489 | void sysctl_head_get(struct ctl_table_header *head) | 1498 | void sysctl_head_get(struct ctl_table_header *head) |
1490 | { | 1499 | { |
1491 | spin_lock(&sysctl_lock); | 1500 | spin_lock(&sysctl_lock); |
1492 | head->count++; | 1501 | head->count++; |
1493 | spin_unlock(&sysctl_lock); | 1502 | spin_unlock(&sysctl_lock); |
1494 | } | 1503 | } |
1495 | 1504 | ||
1496 | void sysctl_head_put(struct ctl_table_header *head) | 1505 | void sysctl_head_put(struct ctl_table_header *head) |
1497 | { | 1506 | { |
1498 | spin_lock(&sysctl_lock); | 1507 | spin_lock(&sysctl_lock); |
1499 | if (!--head->count) | 1508 | if (!--head->count) |
1500 | kfree(head); | 1509 | kfree(head); |
1501 | spin_unlock(&sysctl_lock); | 1510 | spin_unlock(&sysctl_lock); |
1502 | } | 1511 | } |
1503 | 1512 | ||
1504 | struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head) | 1513 | struct ctl_table_header *sysctl_head_grab(struct ctl_table_header *head) |
1505 | { | 1514 | { |
1506 | if (!head) | 1515 | if (!head) |
1507 | BUG(); | 1516 | BUG(); |
1508 | spin_lock(&sysctl_lock); | 1517 | spin_lock(&sysctl_lock); |
1509 | if (!use_table(head)) | 1518 | if (!use_table(head)) |
1510 | head = ERR_PTR(-ENOENT); | 1519 | head = ERR_PTR(-ENOENT); |
1511 | spin_unlock(&sysctl_lock); | 1520 | spin_unlock(&sysctl_lock); |
1512 | return head; | 1521 | return head; |
1513 | } | 1522 | } |
1514 | 1523 | ||
1515 | void sysctl_head_finish(struct ctl_table_header *head) | 1524 | void sysctl_head_finish(struct ctl_table_header *head) |
1516 | { | 1525 | { |
1517 | if (!head) | 1526 | if (!head) |
1518 | return; | 1527 | return; |
1519 | spin_lock(&sysctl_lock); | 1528 | spin_lock(&sysctl_lock); |
1520 | unuse_table(head); | 1529 | unuse_table(head); |
1521 | spin_unlock(&sysctl_lock); | 1530 | spin_unlock(&sysctl_lock); |
1522 | } | 1531 | } |
1523 | 1532 | ||
1524 | static struct ctl_table_set * | 1533 | static struct ctl_table_set * |
1525 | lookup_header_set(struct ctl_table_root *root, struct nsproxy *namespaces) | 1534 | lookup_header_set(struct ctl_table_root *root, struct nsproxy *namespaces) |
1526 | { | 1535 | { |
1527 | struct ctl_table_set *set = &root->default_set; | 1536 | struct ctl_table_set *set = &root->default_set; |
1528 | if (root->lookup) | 1537 | if (root->lookup) |
1529 | set = root->lookup(root, namespaces); | 1538 | set = root->lookup(root, namespaces); |
1530 | return set; | 1539 | return set; |
1531 | } | 1540 | } |
1532 | 1541 | ||
1533 | static struct list_head * | 1542 | static struct list_head * |
1534 | lookup_header_list(struct ctl_table_root *root, struct nsproxy *namespaces) | 1543 | lookup_header_list(struct ctl_table_root *root, struct nsproxy *namespaces) |
1535 | { | 1544 | { |
1536 | struct ctl_table_set *set = lookup_header_set(root, namespaces); | 1545 | struct ctl_table_set *set = lookup_header_set(root, namespaces); |
1537 | return &set->list; | 1546 | return &set->list; |
1538 | } | 1547 | } |
1539 | 1548 | ||
1540 | struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces, | 1549 | struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces, |
1541 | struct ctl_table_header *prev) | 1550 | struct ctl_table_header *prev) |
1542 | { | 1551 | { |
1543 | struct ctl_table_root *root; | 1552 | struct ctl_table_root *root; |
1544 | struct list_head *header_list; | 1553 | struct list_head *header_list; |
1545 | struct ctl_table_header *head; | 1554 | struct ctl_table_header *head; |
1546 | struct list_head *tmp; | 1555 | struct list_head *tmp; |
1547 | 1556 | ||
1548 | spin_lock(&sysctl_lock); | 1557 | spin_lock(&sysctl_lock); |
1549 | if (prev) { | 1558 | if (prev) { |
1550 | head = prev; | 1559 | head = prev; |
1551 | tmp = &prev->ctl_entry; | 1560 | tmp = &prev->ctl_entry; |
1552 | unuse_table(prev); | 1561 | unuse_table(prev); |
1553 | goto next; | 1562 | goto next; |
1554 | } | 1563 | } |
1555 | tmp = &root_table_header.ctl_entry; | 1564 | tmp = &root_table_header.ctl_entry; |
1556 | for (;;) { | 1565 | for (;;) { |
1557 | head = list_entry(tmp, struct ctl_table_header, ctl_entry); | 1566 | head = list_entry(tmp, struct ctl_table_header, ctl_entry); |
1558 | 1567 | ||
1559 | if (!use_table(head)) | 1568 | if (!use_table(head)) |
1560 | goto next; | 1569 | goto next; |
1561 | spin_unlock(&sysctl_lock); | 1570 | spin_unlock(&sysctl_lock); |
1562 | return head; | 1571 | return head; |
1563 | next: | 1572 | next: |
1564 | root = head->root; | 1573 | root = head->root; |
1565 | tmp = tmp->next; | 1574 | tmp = tmp->next; |
1566 | header_list = lookup_header_list(root, namespaces); | 1575 | header_list = lookup_header_list(root, namespaces); |
1567 | if (tmp != header_list) | 1576 | if (tmp != header_list) |
1568 | continue; | 1577 | continue; |
1569 | 1578 | ||
1570 | do { | 1579 | do { |
1571 | root = list_entry(root->root_list.next, | 1580 | root = list_entry(root->root_list.next, |
1572 | struct ctl_table_root, root_list); | 1581 | struct ctl_table_root, root_list); |
1573 | if (root == &sysctl_table_root) | 1582 | if (root == &sysctl_table_root) |
1574 | goto out; | 1583 | goto out; |
1575 | header_list = lookup_header_list(root, namespaces); | 1584 | header_list = lookup_header_list(root, namespaces); |
1576 | } while (list_empty(header_list)); | 1585 | } while (list_empty(header_list)); |
1577 | tmp = header_list->next; | 1586 | tmp = header_list->next; |
1578 | } | 1587 | } |
1579 | out: | 1588 | out: |
1580 | spin_unlock(&sysctl_lock); | 1589 | spin_unlock(&sysctl_lock); |
1581 | return NULL; | 1590 | return NULL; |
1582 | } | 1591 | } |
1583 | 1592 | ||
1584 | struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev) | 1593 | struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev) |
1585 | { | 1594 | { |
1586 | return __sysctl_head_next(current->nsproxy, prev); | 1595 | return __sysctl_head_next(current->nsproxy, prev); |
1587 | } | 1596 | } |
1588 | 1597 | ||
1589 | void register_sysctl_root(struct ctl_table_root *root) | 1598 | void register_sysctl_root(struct ctl_table_root *root) |
1590 | { | 1599 | { |
1591 | spin_lock(&sysctl_lock); | 1600 | spin_lock(&sysctl_lock); |
1592 | list_add_tail(&root->root_list, &sysctl_table_root.root_list); | 1601 | list_add_tail(&root->root_list, &sysctl_table_root.root_list); |
1593 | spin_unlock(&sysctl_lock); | 1602 | spin_unlock(&sysctl_lock); |
1594 | } | 1603 | } |
1595 | 1604 | ||
1596 | #ifdef CONFIG_SYSCTL_SYSCALL | 1605 | #ifdef CONFIG_SYSCTL_SYSCALL |
1597 | /* Perform the actual read/write of a sysctl table entry. */ | 1606 | /* Perform the actual read/write of a sysctl table entry. */ |
1598 | static int do_sysctl_strategy(struct ctl_table_root *root, | 1607 | static int do_sysctl_strategy(struct ctl_table_root *root, |
1599 | struct ctl_table *table, | 1608 | struct ctl_table *table, |
1600 | void __user *oldval, size_t __user *oldlenp, | 1609 | void __user *oldval, size_t __user *oldlenp, |
1601 | void __user *newval, size_t newlen) | 1610 | void __user *newval, size_t newlen) |
1602 | { | 1611 | { |
1603 | int op = 0, rc; | 1612 | int op = 0, rc; |
1604 | 1613 | ||
1605 | if (oldval) | 1614 | if (oldval) |
1606 | op |= MAY_READ; | 1615 | op |= MAY_READ; |
1607 | if (newval) | 1616 | if (newval) |
1608 | op |= MAY_WRITE; | 1617 | op |= MAY_WRITE; |
1609 | if (sysctl_perm(root, table, op)) | 1618 | if (sysctl_perm(root, table, op)) |
1610 | return -EPERM; | 1619 | return -EPERM; |
1611 | 1620 | ||
1612 | if (table->strategy) { | 1621 | if (table->strategy) { |
1613 | rc = table->strategy(table, oldval, oldlenp, newval, newlen); | 1622 | rc = table->strategy(table, oldval, oldlenp, newval, newlen); |
1614 | if (rc < 0) | 1623 | if (rc < 0) |
1615 | return rc; | 1624 | return rc; |
1616 | if (rc > 0) | 1625 | if (rc > 0) |
1617 | return 0; | 1626 | return 0; |
1618 | } | 1627 | } |
1619 | 1628 | ||
1620 | /* If there is no strategy routine, or if the strategy returns | 1629 | /* If there is no strategy routine, or if the strategy returns |
1621 | * zero, proceed with automatic r/w */ | 1630 | * zero, proceed with automatic r/w */ |
1622 | if (table->data && table->maxlen) { | 1631 | if (table->data && table->maxlen) { |
1623 | rc = sysctl_data(table, oldval, oldlenp, newval, newlen); | 1632 | rc = sysctl_data(table, oldval, oldlenp, newval, newlen); |
1624 | if (rc < 0) | 1633 | if (rc < 0) |
1625 | return rc; | 1634 | return rc; |
1626 | } | 1635 | } |
1627 | return 0; | 1636 | return 0; |
1628 | } | 1637 | } |
1629 | 1638 | ||
1630 | static int parse_table(int __user *name, int nlen, | 1639 | static int parse_table(int __user *name, int nlen, |
1631 | void __user *oldval, size_t __user *oldlenp, | 1640 | void __user *oldval, size_t __user *oldlenp, |
1632 | void __user *newval, size_t newlen, | 1641 | void __user *newval, size_t newlen, |
1633 | struct ctl_table_root *root, | 1642 | struct ctl_table_root *root, |
1634 | struct ctl_table *table) | 1643 | struct ctl_table *table) |
1635 | { | 1644 | { |
1636 | int n; | 1645 | int n; |
1637 | repeat: | 1646 | repeat: |
1638 | if (!nlen) | 1647 | if (!nlen) |
1639 | return -ENOTDIR; | 1648 | return -ENOTDIR; |
1640 | if (get_user(n, name)) | 1649 | if (get_user(n, name)) |
1641 | return -EFAULT; | 1650 | return -EFAULT; |
1642 | for ( ; table->ctl_name || table->procname; table++) { | 1651 | for ( ; table->ctl_name || table->procname; table++) { |
1643 | if (!table->ctl_name) | 1652 | if (!table->ctl_name) |
1644 | continue; | 1653 | continue; |
1645 | if (n == table->ctl_name) { | 1654 | if (n == table->ctl_name) { |
1646 | int error; | 1655 | int error; |
1647 | if (table->child) { | 1656 | if (table->child) { |
1648 | if (sysctl_perm(root, table, MAY_EXEC)) | 1657 | if (sysctl_perm(root, table, MAY_EXEC)) |
1649 | return -EPERM; | 1658 | return -EPERM; |
1650 | name++; | 1659 | name++; |
1651 | nlen--; | 1660 | nlen--; |
1652 | table = table->child; | 1661 | table = table->child; |
1653 | goto repeat; | 1662 | goto repeat; |
1654 | } | 1663 | } |
1655 | error = do_sysctl_strategy(root, table, | 1664 | error = do_sysctl_strategy(root, table, |
1656 | oldval, oldlenp, | 1665 | oldval, oldlenp, |
1657 | newval, newlen); | 1666 | newval, newlen); |
1658 | return error; | 1667 | return error; |
1659 | } | 1668 | } |
1660 | } | 1669 | } |
1661 | return -ENOTDIR; | 1670 | return -ENOTDIR; |
1662 | } | 1671 | } |
1663 | 1672 | ||
1664 | int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, | 1673 | int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, |
1665 | void __user *newval, size_t newlen) | 1674 | void __user *newval, size_t newlen) |
1666 | { | 1675 | { |
1667 | struct ctl_table_header *head; | 1676 | struct ctl_table_header *head; |
1668 | int error = -ENOTDIR; | 1677 | int error = -ENOTDIR; |
1669 | 1678 | ||
1670 | if (nlen <= 0 || nlen >= CTL_MAXNAME) | 1679 | if (nlen <= 0 || nlen >= CTL_MAXNAME) |
1671 | return -ENOTDIR; | 1680 | return -ENOTDIR; |
1672 | if (oldval) { | 1681 | if (oldval) { |
1673 | int old_len; | 1682 | int old_len; |
1674 | if (!oldlenp || get_user(old_len, oldlenp)) | 1683 | if (!oldlenp || get_user(old_len, oldlenp)) |
1675 | return -EFAULT; | 1684 | return -EFAULT; |
1676 | } | 1685 | } |
1677 | 1686 | ||
1678 | for (head = sysctl_head_next(NULL); head; | 1687 | for (head = sysctl_head_next(NULL); head; |
1679 | head = sysctl_head_next(head)) { | 1688 | head = sysctl_head_next(head)) { |
1680 | error = parse_table(name, nlen, oldval, oldlenp, | 1689 | error = parse_table(name, nlen, oldval, oldlenp, |
1681 | newval, newlen, | 1690 | newval, newlen, |
1682 | head->root, head->ctl_table); | 1691 | head->root, head->ctl_table); |
1683 | if (error != -ENOTDIR) { | 1692 | if (error != -ENOTDIR) { |
1684 | sysctl_head_finish(head); | 1693 | sysctl_head_finish(head); |
1685 | break; | 1694 | break; |
1686 | } | 1695 | } |
1687 | } | 1696 | } |
1688 | return error; | 1697 | return error; |
1689 | } | 1698 | } |
1690 | 1699 | ||
1691 | SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args) | 1700 | SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args) |
1692 | { | 1701 | { |
1693 | struct __sysctl_args tmp; | 1702 | struct __sysctl_args tmp; |
1694 | int error; | 1703 | int error; |
1695 | 1704 | ||
1696 | if (copy_from_user(&tmp, args, sizeof(tmp))) | 1705 | if (copy_from_user(&tmp, args, sizeof(tmp))) |
1697 | return -EFAULT; | 1706 | return -EFAULT; |
1698 | 1707 | ||
1699 | error = deprecated_sysctl_warning(&tmp); | 1708 | error = deprecated_sysctl_warning(&tmp); |
1700 | if (error) | 1709 | if (error) |
1701 | goto out; | 1710 | goto out; |
1702 | 1711 | ||
1703 | lock_kernel(); | 1712 | lock_kernel(); |
1704 | error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp, | 1713 | error = do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp, |
1705 | tmp.newval, tmp.newlen); | 1714 | tmp.newval, tmp.newlen); |
1706 | unlock_kernel(); | 1715 | unlock_kernel(); |
1707 | out: | 1716 | out: |
1708 | return error; | 1717 | return error; |
1709 | } | 1718 | } |
1710 | #endif /* CONFIG_SYSCTL_SYSCALL */ | 1719 | #endif /* CONFIG_SYSCTL_SYSCALL */ |
1711 | 1720 | ||
1712 | /* | 1721 | /* |
1713 | * sysctl_perm does NOT grant the superuser all rights automatically, because | 1722 | * sysctl_perm does NOT grant the superuser all rights automatically, because |
1714 | * some sysctl variables are readonly even to root. | 1723 | * some sysctl variables are readonly even to root. |
1715 | */ | 1724 | */ |
1716 | 1725 | ||
1717 | static int test_perm(int mode, int op) | 1726 | static int test_perm(int mode, int op) |
1718 | { | 1727 | { |
1719 | if (!current_euid()) | 1728 | if (!current_euid()) |
1720 | mode >>= 6; | 1729 | mode >>= 6; |
1721 | else if (in_egroup_p(0)) | 1730 | else if (in_egroup_p(0)) |
1722 | mode >>= 3; | 1731 | mode >>= 3; |
1723 | if ((op & ~mode & (MAY_READ|MAY_WRITE|MAY_EXEC)) == 0) | 1732 | if ((op & ~mode & (MAY_READ|MAY_WRITE|MAY_EXEC)) == 0) |
1724 | return 0; | 1733 | return 0; |
1725 | return -EACCES; | 1734 | return -EACCES; |
1726 | } | 1735 | } |
1727 | 1736 | ||
1728 | int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op) | 1737 | int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op) |
1729 | { | 1738 | { |
1730 | int error; | 1739 | int error; |
1731 | int mode; | 1740 | int mode; |
1732 | 1741 | ||
1733 | error = security_sysctl(table, op & (MAY_READ | MAY_WRITE | MAY_EXEC)); | 1742 | error = security_sysctl(table, op & (MAY_READ | MAY_WRITE | MAY_EXEC)); |
1734 | if (error) | 1743 | if (error) |
1735 | return error; | 1744 | return error; |
1736 | 1745 | ||
1737 | if (root->permissions) | 1746 | if (root->permissions) |
1738 | mode = root->permissions(root, current->nsproxy, table); | 1747 | mode = root->permissions(root, current->nsproxy, table); |
1739 | else | 1748 | else |
1740 | mode = table->mode; | 1749 | mode = table->mode; |
1741 | 1750 | ||
1742 | return test_perm(mode, op); | 1751 | return test_perm(mode, op); |
1743 | } | 1752 | } |
1744 | 1753 | ||
1745 | static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table) | 1754 | static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table) |
1746 | { | 1755 | { |
1747 | for (; table->ctl_name || table->procname; table++) { | 1756 | for (; table->ctl_name || table->procname; table++) { |
1748 | table->parent = parent; | 1757 | table->parent = parent; |
1749 | if (table->child) | 1758 | if (table->child) |
1750 | sysctl_set_parent(table, table->child); | 1759 | sysctl_set_parent(table, table->child); |
1751 | } | 1760 | } |
1752 | } | 1761 | } |
1753 | 1762 | ||
1754 | static __init int sysctl_init(void) | 1763 | static __init int sysctl_init(void) |
1755 | { | 1764 | { |
1756 | sysctl_set_parent(NULL, root_table); | 1765 | sysctl_set_parent(NULL, root_table); |
1757 | #ifdef CONFIG_SYSCTL_SYSCALL_CHECK | 1766 | #ifdef CONFIG_SYSCTL_SYSCALL_CHECK |
1758 | { | 1767 | { |
1759 | int err; | 1768 | int err; |
1760 | err = sysctl_check_table(current->nsproxy, root_table); | 1769 | err = sysctl_check_table(current->nsproxy, root_table); |
1761 | } | 1770 | } |
1762 | #endif | 1771 | #endif |
1763 | return 0; | 1772 | return 0; |
1764 | } | 1773 | } |
1765 | 1774 | ||
1766 | core_initcall(sysctl_init); | 1775 | core_initcall(sysctl_init); |
1767 | 1776 | ||
1768 | static struct ctl_table *is_branch_in(struct ctl_table *branch, | 1777 | static struct ctl_table *is_branch_in(struct ctl_table *branch, |
1769 | struct ctl_table *table) | 1778 | struct ctl_table *table) |
1770 | { | 1779 | { |
1771 | struct ctl_table *p; | 1780 | struct ctl_table *p; |
1772 | const char *s = branch->procname; | 1781 | const char *s = branch->procname; |
1773 | 1782 | ||
1774 | /* branch should have named subdirectory as its first element */ | 1783 | /* branch should have named subdirectory as its first element */ |
1775 | if (!s || !branch->child) | 1784 | if (!s || !branch->child) |
1776 | return NULL; | 1785 | return NULL; |
1777 | 1786 | ||
1778 | /* ... and nothing else */ | 1787 | /* ... and nothing else */ |
1779 | if (branch[1].procname || branch[1].ctl_name) | 1788 | if (branch[1].procname || branch[1].ctl_name) |
1780 | return NULL; | 1789 | return NULL; |
1781 | 1790 | ||
1782 | /* table should contain subdirectory with the same name */ | 1791 | /* table should contain subdirectory with the same name */ |
1783 | for (p = table; p->procname || p->ctl_name; p++) { | 1792 | for (p = table; p->procname || p->ctl_name; p++) { |
1784 | if (!p->child) | 1793 | if (!p->child) |
1785 | continue; | 1794 | continue; |
1786 | if (p->procname && strcmp(p->procname, s) == 0) | 1795 | if (p->procname && strcmp(p->procname, s) == 0) |
1787 | return p; | 1796 | return p; |
1788 | } | 1797 | } |
1789 | return NULL; | 1798 | return NULL; |
1790 | } | 1799 | } |
1791 | 1800 | ||
1792 | /* see if attaching q to p would be an improvement */ | 1801 | /* see if attaching q to p would be an improvement */ |
1793 | static void try_attach(struct ctl_table_header *p, struct ctl_table_header *q) | 1802 | static void try_attach(struct ctl_table_header *p, struct ctl_table_header *q) |
1794 | { | 1803 | { |
1795 | struct ctl_table *to = p->ctl_table, *by = q->ctl_table; | 1804 | struct ctl_table *to = p->ctl_table, *by = q->ctl_table; |
1796 | struct ctl_table *next; | 1805 | struct ctl_table *next; |
1797 | int is_better = 0; | 1806 | int is_better = 0; |
1798 | int not_in_parent = !p->attached_by; | 1807 | int not_in_parent = !p->attached_by; |
1799 | 1808 | ||
1800 | while ((next = is_branch_in(by, to)) != NULL) { | 1809 | while ((next = is_branch_in(by, to)) != NULL) { |
1801 | if (by == q->attached_by) | 1810 | if (by == q->attached_by) |
1802 | is_better = 1; | 1811 | is_better = 1; |
1803 | if (to == p->attached_by) | 1812 | if (to == p->attached_by) |
1804 | not_in_parent = 1; | 1813 | not_in_parent = 1; |
1805 | by = by->child; | 1814 | by = by->child; |
1806 | to = next->child; | 1815 | to = next->child; |
1807 | } | 1816 | } |
1808 | 1817 | ||
1809 | if (is_better && not_in_parent) { | 1818 | if (is_better && not_in_parent) { |
1810 | q->attached_by = by; | 1819 | q->attached_by = by; |
1811 | q->attached_to = to; | 1820 | q->attached_to = to; |
1812 | q->parent = p; | 1821 | q->parent = p; |
1813 | } | 1822 | } |
1814 | } | 1823 | } |
1815 | 1824 | ||
1816 | /** | 1825 | /** |
1817 | * __register_sysctl_paths - register a sysctl hierarchy | 1826 | * __register_sysctl_paths - register a sysctl hierarchy |
1818 | * @root: List of sysctl headers to register on | 1827 | * @root: List of sysctl headers to register on |
1819 | * @namespaces: Data to compute which lists of sysctl entries are visible | 1828 | * @namespaces: Data to compute which lists of sysctl entries are visible |
1820 | * @path: The path to the directory the sysctl table is in. | 1829 | * @path: The path to the directory the sysctl table is in. |
1821 | * @table: the top-level table structure | 1830 | * @table: the top-level table structure |
1822 | * | 1831 | * |
1823 | * Register a sysctl table hierarchy. @table should be a filled in ctl_table | 1832 | * Register a sysctl table hierarchy. @table should be a filled in ctl_table |
1824 | * array. A completely 0 filled entry terminates the table. | 1833 | * array. A completely 0 filled entry terminates the table. |
1825 | * | 1834 | * |
1826 | * The members of the &struct ctl_table structure are used as follows: | 1835 | * The members of the &struct ctl_table structure are used as follows: |
1827 | * | 1836 | * |
1828 | * ctl_name - This is the numeric sysctl value used by sysctl(2). The number | 1837 | * ctl_name - This is the numeric sysctl value used by sysctl(2). The number |
1829 | * must be unique within that level of sysctl | 1838 | * must be unique within that level of sysctl |
1830 | * | 1839 | * |
1831 | * procname - the name of the sysctl file under /proc/sys. Set to %NULL to not | 1840 | * procname - the name of the sysctl file under /proc/sys. Set to %NULL to not |
1832 | * enter a sysctl file | 1841 | * enter a sysctl file |
1833 | * | 1842 | * |
1834 | * data - a pointer to data for use by proc_handler | 1843 | * data - a pointer to data for use by proc_handler |
1835 | * | 1844 | * |
1836 | * maxlen - the maximum size in bytes of the data | 1845 | * maxlen - the maximum size in bytes of the data |
1837 | * | 1846 | * |
1838 | * mode - the file permissions for the /proc/sys file, and for sysctl(2) | 1847 | * mode - the file permissions for the /proc/sys file, and for sysctl(2) |
1839 | * | 1848 | * |
1840 | * child - a pointer to the child sysctl table if this entry is a directory, or | 1849 | * child - a pointer to the child sysctl table if this entry is a directory, or |
1841 | * %NULL. | 1850 | * %NULL. |
1842 | * | 1851 | * |
1843 | * proc_handler - the text handler routine (described below) | 1852 | * proc_handler - the text handler routine (described below) |
1844 | * | 1853 | * |
1845 | * strategy - the strategy routine (described below) | 1854 | * strategy - the strategy routine (described below) |
1846 | * | 1855 | * |
1847 | * de - for internal use by the sysctl routines | 1856 | * de - for internal use by the sysctl routines |
1848 | * | 1857 | * |
1849 | * extra1, extra2 - extra pointers usable by the proc handler routines | 1858 | * extra1, extra2 - extra pointers usable by the proc handler routines |
1850 | * | 1859 | * |
1851 | * Leaf nodes in the sysctl tree will be represented by a single file | 1860 | * Leaf nodes in the sysctl tree will be represented by a single file |
1852 | * under /proc; non-leaf nodes will be represented by directories. | 1861 | * under /proc; non-leaf nodes will be represented by directories. |
1853 | * | 1862 | * |
1854 | * sysctl(2) can automatically manage read and write requests through | 1863 | * sysctl(2) can automatically manage read and write requests through |
1855 | * the sysctl table. The data and maxlen fields of the ctl_table | 1864 | * the sysctl table. The data and maxlen fields of the ctl_table |
1856 | * struct enable minimal validation of the values being written to be | 1865 | * struct enable minimal validation of the values being written to be |
1857 | * performed, and the mode field allows minimal authentication. | 1866 | * performed, and the mode field allows minimal authentication. |
1858 | * | 1867 | * |
1859 | * More sophisticated management can be enabled by the provision of a | 1868 | * More sophisticated management can be enabled by the provision of a |
1860 | * strategy routine with the table entry. This will be called before | 1869 | * strategy routine with the table entry. This will be called before |
1861 | * any automatic read or write of the data is performed. | 1870 | * any automatic read or write of the data is performed. |
1862 | * | 1871 | * |
1863 | * The strategy routine may return | 1872 | * The strategy routine may return |
1864 | * | 1873 | * |
1865 | * < 0 - Error occurred (error is passed to user process) | 1874 | * < 0 - Error occurred (error is passed to user process) |
1866 | * | 1875 | * |
1867 | * 0 - OK - proceed with automatic read or write. | 1876 | * 0 - OK - proceed with automatic read or write. |
1868 | * | 1877 | * |
1869 | * > 0 - OK - read or write has been done by the strategy routine, so | 1878 | * > 0 - OK - read or write has been done by the strategy routine, so |
1870 | * return immediately. | 1879 | * return immediately. |
1871 | * | 1880 | * |
1872 | * There must be a proc_handler routine for any terminal nodes | 1881 | * There must be a proc_handler routine for any terminal nodes |
1873 | * mirrored under /proc/sys (non-terminals are handled by a built-in | 1882 | * mirrored under /proc/sys (non-terminals are handled by a built-in |
1874 | * directory handler). Several default handlers are available to | 1883 | * directory handler). Several default handlers are available to |
1875 | * cover common cases - | 1884 | * cover common cases - |
1876 | * | 1885 | * |
1877 | * proc_dostring(), proc_dointvec(), proc_dointvec_jiffies(), | 1886 | * proc_dostring(), proc_dointvec(), proc_dointvec_jiffies(), |
1878 | * proc_dointvec_userhz_jiffies(), proc_dointvec_minmax(), | 1887 | * proc_dointvec_userhz_jiffies(), proc_dointvec_minmax(), |
1879 | * proc_doulongvec_ms_jiffies_minmax(), proc_doulongvec_minmax() | 1888 | * proc_doulongvec_ms_jiffies_minmax(), proc_doulongvec_minmax() |
1880 | * | 1889 | * |
1881 | * It is the handler's job to read the input buffer from user memory | 1890 | * It is the handler's job to read the input buffer from user memory |
1882 | * and process it. The handler should return 0 on success. | 1891 | * and process it. The handler should return 0 on success. |
1883 | * | 1892 | * |
1884 | * This routine returns %NULL on a failure to register, and a pointer | 1893 | * This routine returns %NULL on a failure to register, and a pointer |
1885 | * to the table header on success. | 1894 | * to the table header on success. |
1886 | */ | 1895 | */ |
1887 | struct ctl_table_header *__register_sysctl_paths( | 1896 | struct ctl_table_header *__register_sysctl_paths( |
1888 | struct ctl_table_root *root, | 1897 | struct ctl_table_root *root, |
1889 | struct nsproxy *namespaces, | 1898 | struct nsproxy *namespaces, |
1890 | const struct ctl_path *path, struct ctl_table *table) | 1899 | const struct ctl_path *path, struct ctl_table *table) |
1891 | { | 1900 | { |
1892 | struct ctl_table_header *header; | 1901 | struct ctl_table_header *header; |
1893 | struct ctl_table *new, **prevp; | 1902 | struct ctl_table *new, **prevp; |
1894 | unsigned int n, npath; | 1903 | unsigned int n, npath; |
1895 | struct ctl_table_set *set; | 1904 | struct ctl_table_set *set; |
1896 | 1905 | ||
1897 | /* Count the path components */ | 1906 | /* Count the path components */ |
1898 | for (npath = 0; path[npath].ctl_name || path[npath].procname; ++npath) | 1907 | for (npath = 0; path[npath].ctl_name || path[npath].procname; ++npath) |
1899 | ; | 1908 | ; |
1900 | 1909 | ||
1901 | /* | 1910 | /* |
1902 | * For each path component, allocate a 2-element ctl_table array. | 1911 | * For each path component, allocate a 2-element ctl_table array. |
1903 | * The first array element will be filled with the sysctl entry | 1912 | * The first array element will be filled with the sysctl entry |
1904 | * for this, the second will be the sentinel (ctl_name == 0). | 1913 | * for this, the second will be the sentinel (ctl_name == 0). |
1905 | * | 1914 | * |
1906 | * We allocate everything in one go so that we don't have to | 1915 | * We allocate everything in one go so that we don't have to |
1907 | * worry about freeing additional memory in unregister_sysctl_table. | 1916 | * worry about freeing additional memory in unregister_sysctl_table. |
1908 | */ | 1917 | */ |
1909 | header = kzalloc(sizeof(struct ctl_table_header) + | 1918 | header = kzalloc(sizeof(struct ctl_table_header) + |
1910 | (2 * npath * sizeof(struct ctl_table)), GFP_KERNEL); | 1919 | (2 * npath * sizeof(struct ctl_table)), GFP_KERNEL); |
1911 | if (!header) | 1920 | if (!header) |
1912 | return NULL; | 1921 | return NULL; |
1913 | 1922 | ||
1914 | new = (struct ctl_table *) (header + 1); | 1923 | new = (struct ctl_table *) (header + 1); |
1915 | 1924 | ||
1916 | /* Now connect the dots */ | 1925 | /* Now connect the dots */ |
1917 | prevp = &header->ctl_table; | 1926 | prevp = &header->ctl_table; |
1918 | for (n = 0; n < npath; ++n, ++path) { | 1927 | for (n = 0; n < npath; ++n, ++path) { |
1919 | /* Copy the procname */ | 1928 | /* Copy the procname */ |
1920 | new->procname = path->procname; | 1929 | new->procname = path->procname; |
1921 | new->ctl_name = path->ctl_name; | 1930 | new->ctl_name = path->ctl_name; |
1922 | new->mode = 0555; | 1931 | new->mode = 0555; |
1923 | 1932 | ||
1924 | *prevp = new; | 1933 | *prevp = new; |
1925 | prevp = &new->child; | 1934 | prevp = &new->child; |
1926 | 1935 | ||
1927 | new += 2; | 1936 | new += 2; |
1928 | } | 1937 | } |
1929 | *prevp = table; | 1938 | *prevp = table; |
1930 | header->ctl_table_arg = table; | 1939 | header->ctl_table_arg = table; |
1931 | 1940 | ||
1932 | INIT_LIST_HEAD(&header->ctl_entry); | 1941 | INIT_LIST_HEAD(&header->ctl_entry); |
1933 | header->used = 0; | 1942 | header->used = 0; |
1934 | header->unregistering = NULL; | 1943 | header->unregistering = NULL; |
1935 | header->root = root; | 1944 | header->root = root; |
1936 | sysctl_set_parent(NULL, header->ctl_table); | 1945 | sysctl_set_parent(NULL, header->ctl_table); |
1937 | header->count = 1; | 1946 | header->count = 1; |
1938 | #ifdef CONFIG_SYSCTL_SYSCALL_CHECK | 1947 | #ifdef CONFIG_SYSCTL_SYSCALL_CHECK |
1939 | if (sysctl_check_table(namespaces, header->ctl_table)) { | 1948 | if (sysctl_check_table(namespaces, header->ctl_table)) { |
1940 | kfree(header); | 1949 | kfree(header); |
1941 | return NULL; | 1950 | return NULL; |
1942 | } | 1951 | } |
1943 | #endif | 1952 | #endif |
1944 | spin_lock(&sysctl_lock); | 1953 | spin_lock(&sysctl_lock); |
1945 | header->set = lookup_header_set(root, namespaces); | 1954 | header->set = lookup_header_set(root, namespaces); |
1946 | header->attached_by = header->ctl_table; | 1955 | header->attached_by = header->ctl_table; |
1947 | header->attached_to = root_table; | 1956 | header->attached_to = root_table; |
1948 | header->parent = &root_table_header; | 1957 | header->parent = &root_table_header; |
1949 | for (set = header->set; set; set = set->parent) { | 1958 | for (set = header->set; set; set = set->parent) { |
1950 | struct ctl_table_header *p; | 1959 | struct ctl_table_header *p; |
1951 | list_for_each_entry(p, &set->list, ctl_entry) { | 1960 | list_for_each_entry(p, &set->list, ctl_entry) { |
1952 | if (p->unregistering) | 1961 | if (p->unregistering) |
1953 | continue; | 1962 | continue; |
1954 | try_attach(p, header); | 1963 | try_attach(p, header); |
1955 | } | 1964 | } |
1956 | } | 1965 | } |
1957 | header->parent->count++; | 1966 | header->parent->count++; |
1958 | list_add_tail(&header->ctl_entry, &header->set->list); | 1967 | list_add_tail(&header->ctl_entry, &header->set->list); |
1959 | spin_unlock(&sysctl_lock); | 1968 | spin_unlock(&sysctl_lock); |
1960 | 1969 | ||
1961 | return header; | 1970 | return header; |
1962 | } | 1971 | } |
1963 | 1972 | ||
1964 | /** | 1973 | /** |
1965 | * register_sysctl_table_path - register a sysctl table hierarchy | 1974 | * register_sysctl_table_path - register a sysctl table hierarchy |
1966 | * @path: The path to the directory the sysctl table is in. | 1975 | * @path: The path to the directory the sysctl table is in. |
1967 | * @table: the top-level table structure | 1976 | * @table: the top-level table structure |
1968 | * | 1977 | * |
1969 | * Register a sysctl table hierarchy. @table should be a filled in ctl_table | 1978 | * Register a sysctl table hierarchy. @table should be a filled in ctl_table |
1970 | * array. A completely 0 filled entry terminates the table. | 1979 | * array. A completely 0 filled entry terminates the table. |
1971 | * | 1980 | * |
1972 | * See __register_sysctl_paths for more details. | 1981 | * See __register_sysctl_paths for more details. |
1973 | */ | 1982 | */ |
1974 | struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path, | 1983 | struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path, |
1975 | struct ctl_table *table) | 1984 | struct ctl_table *table) |
1976 | { | 1985 | { |
1977 | return __register_sysctl_paths(&sysctl_table_root, current->nsproxy, | 1986 | return __register_sysctl_paths(&sysctl_table_root, current->nsproxy, |
1978 | path, table); | 1987 | path, table); |
1979 | } | 1988 | } |
1980 | 1989 | ||
1981 | /** | 1990 | /** |
1982 | * register_sysctl_table - register a sysctl table hierarchy | 1991 | * register_sysctl_table - register a sysctl table hierarchy |
1983 | * @table: the top-level table structure | 1992 | * @table: the top-level table structure |
1984 | * | 1993 | * |
1985 | * Register a sysctl table hierarchy. @table should be a filled in ctl_table | 1994 | * Register a sysctl table hierarchy. @table should be a filled in ctl_table |
1986 | * array. A completely 0 filled entry terminates the table. | 1995 | * array. A completely 0 filled entry terminates the table. |
1987 | * | 1996 | * |
1988 | * See register_sysctl_paths for more details. | 1997 | * See register_sysctl_paths for more details. |
1989 | */ | 1998 | */ |
1990 | struct ctl_table_header *register_sysctl_table(struct ctl_table *table) | 1999 | struct ctl_table_header *register_sysctl_table(struct ctl_table *table) |
1991 | { | 2000 | { |
1992 | static const struct ctl_path null_path[] = { {} }; | 2001 | static const struct ctl_path null_path[] = { {} }; |
1993 | 2002 | ||
1994 | return register_sysctl_paths(null_path, table); | 2003 | return register_sysctl_paths(null_path, table); |
1995 | } | 2004 | } |
1996 | 2005 | ||
1997 | /** | 2006 | /** |
1998 | * unregister_sysctl_table - unregister a sysctl table hierarchy | 2007 | * unregister_sysctl_table - unregister a sysctl table hierarchy |
1999 | * @header: the header returned from register_sysctl_table | 2008 | * @header: the header returned from register_sysctl_table |
2000 | * | 2009 | * |
2001 | * Unregisters the sysctl table and all children. proc entries may not | 2010 | * Unregisters the sysctl table and all children. proc entries may not |
2002 | * actually be removed until they are no longer used by anyone. | 2011 | * actually be removed until they are no longer used by anyone. |
2003 | */ | 2012 | */ |
2004 | void unregister_sysctl_table(struct ctl_table_header * header) | 2013 | void unregister_sysctl_table(struct ctl_table_header * header) |
2005 | { | 2014 | { |
2006 | might_sleep(); | 2015 | might_sleep(); |
2007 | 2016 | ||
2008 | if (header == NULL) | 2017 | if (header == NULL) |
2009 | return; | 2018 | return; |
2010 | 2019 | ||
2011 | spin_lock(&sysctl_lock); | 2020 | spin_lock(&sysctl_lock); |
2012 | start_unregistering(header); | 2021 | start_unregistering(header); |
2013 | if (!--header->parent->count) { | 2022 | if (!--header->parent->count) { |
2014 | WARN_ON(1); | 2023 | WARN_ON(1); |
2015 | kfree(header->parent); | 2024 | kfree(header->parent); |
2016 | } | 2025 | } |
2017 | if (!--header->count) | 2026 | if (!--header->count) |
2018 | kfree(header); | 2027 | kfree(header); |
2019 | spin_unlock(&sysctl_lock); | 2028 | spin_unlock(&sysctl_lock); |
2020 | } | 2029 | } |
2021 | 2030 | ||
2022 | int sysctl_is_seen(struct ctl_table_header *p) | 2031 | int sysctl_is_seen(struct ctl_table_header *p) |
2023 | { | 2032 | { |
2024 | struct ctl_table_set *set = p->set; | 2033 | struct ctl_table_set *set = p->set; |
2025 | int res; | 2034 | int res; |
2026 | spin_lock(&sysctl_lock); | 2035 | spin_lock(&sysctl_lock); |
2027 | if (p->unregistering) | 2036 | if (p->unregistering) |
2028 | res = 0; | 2037 | res = 0; |
2029 | else if (!set->is_seen) | 2038 | else if (!set->is_seen) |
2030 | res = 1; | 2039 | res = 1; |
2031 | else | 2040 | else |
2032 | res = set->is_seen(set); | 2041 | res = set->is_seen(set); |
2033 | spin_unlock(&sysctl_lock); | 2042 | spin_unlock(&sysctl_lock); |
2034 | return res; | 2043 | return res; |
2035 | } | 2044 | } |
2036 | 2045 | ||
2037 | void setup_sysctl_set(struct ctl_table_set *p, | 2046 | void setup_sysctl_set(struct ctl_table_set *p, |
2038 | struct ctl_table_set *parent, | 2047 | struct ctl_table_set *parent, |
2039 | int (*is_seen)(struct ctl_table_set *)) | 2048 | int (*is_seen)(struct ctl_table_set *)) |
2040 | { | 2049 | { |
2041 | INIT_LIST_HEAD(&p->list); | 2050 | INIT_LIST_HEAD(&p->list); |
2042 | p->parent = parent ? parent : &sysctl_table_root.default_set; | 2051 | p->parent = parent ? parent : &sysctl_table_root.default_set; |
2043 | p->is_seen = is_seen; | 2052 | p->is_seen = is_seen; |
2044 | } | 2053 | } |
2045 | 2054 | ||
2046 | #else /* !CONFIG_SYSCTL */ | 2055 | #else /* !CONFIG_SYSCTL */ |
2047 | struct ctl_table_header *register_sysctl_table(struct ctl_table * table) | 2056 | struct ctl_table_header *register_sysctl_table(struct ctl_table * table) |
2048 | { | 2057 | { |
2049 | return NULL; | 2058 | return NULL; |
2050 | } | 2059 | } |
2051 | 2060 | ||
2052 | struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path, | 2061 | struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path, |
2053 | struct ctl_table *table) | 2062 | struct ctl_table *table) |
2054 | { | 2063 | { |
2055 | return NULL; | 2064 | return NULL; |
2056 | } | 2065 | } |
2057 | 2066 | ||
2058 | void unregister_sysctl_table(struct ctl_table_header * table) | 2067 | void unregister_sysctl_table(struct ctl_table_header * table) |
2059 | { | 2068 | { |
2060 | } | 2069 | } |
2061 | 2070 | ||
2062 | void setup_sysctl_set(struct ctl_table_set *p, | 2071 | void setup_sysctl_set(struct ctl_table_set *p, |
2063 | struct ctl_table_set *parent, | 2072 | struct ctl_table_set *parent, |
2064 | int (*is_seen)(struct ctl_table_set *)) | 2073 | int (*is_seen)(struct ctl_table_set *)) |
2065 | { | 2074 | { |
2066 | } | 2075 | } |
2067 | 2076 | ||
2068 | void sysctl_head_put(struct ctl_table_header *head) | 2077 | void sysctl_head_put(struct ctl_table_header *head) |
2069 | { | 2078 | { |
2070 | } | 2079 | } |
2071 | 2080 | ||
2072 | #endif /* CONFIG_SYSCTL */ | 2081 | #endif /* CONFIG_SYSCTL */ |
2073 | 2082 | ||
2074 | /* | 2083 | /* |
2075 | * /proc/sys support | 2084 | * /proc/sys support |
2076 | */ | 2085 | */ |
2077 | 2086 | ||
2078 | #ifdef CONFIG_PROC_SYSCTL | 2087 | #ifdef CONFIG_PROC_SYSCTL |
2079 | 2088 | ||
2080 | static int _proc_do_string(void* data, int maxlen, int write, | 2089 | static int _proc_do_string(void* data, int maxlen, int write, |
2081 | struct file *filp, void __user *buffer, | 2090 | struct file *filp, void __user *buffer, |
2082 | size_t *lenp, loff_t *ppos) | 2091 | size_t *lenp, loff_t *ppos) |
2083 | { | 2092 | { |
2084 | size_t len; | 2093 | size_t len; |
2085 | char __user *p; | 2094 | char __user *p; |
2086 | char c; | 2095 | char c; |
2087 | 2096 | ||
2088 | if (!data || !maxlen || !*lenp) { | 2097 | if (!data || !maxlen || !*lenp) { |
2089 | *lenp = 0; | 2098 | *lenp = 0; |
2090 | return 0; | 2099 | return 0; |
2091 | } | 2100 | } |
2092 | 2101 | ||
2093 | if (write) { | 2102 | if (write) { |
2094 | len = 0; | 2103 | len = 0; |
2095 | p = buffer; | 2104 | p = buffer; |
2096 | while (len < *lenp) { | 2105 | while (len < *lenp) { |
2097 | if (get_user(c, p++)) | 2106 | if (get_user(c, p++)) |
2098 | return -EFAULT; | 2107 | return -EFAULT; |
2099 | if (c == 0 || c == '\n') | 2108 | if (c == 0 || c == '\n') |
2100 | break; | 2109 | break; |
2101 | len++; | 2110 | len++; |
2102 | } | 2111 | } |
2103 | if (len >= maxlen) | 2112 | if (len >= maxlen) |
2104 | len = maxlen-1; | 2113 | len = maxlen-1; |
2105 | if(copy_from_user(data, buffer, len)) | 2114 | if(copy_from_user(data, buffer, len)) |
2106 | return -EFAULT; | 2115 | return -EFAULT; |
2107 | ((char *) data)[len] = 0; | 2116 | ((char *) data)[len] = 0; |
2108 | *ppos += *lenp; | 2117 | *ppos += *lenp; |
2109 | } else { | 2118 | } else { |
2110 | len = strlen(data); | 2119 | len = strlen(data); |
2111 | if (len > maxlen) | 2120 | if (len > maxlen) |
2112 | len = maxlen; | 2121 | len = maxlen; |
2113 | 2122 | ||
2114 | if (*ppos > len) { | 2123 | if (*ppos > len) { |
2115 | *lenp = 0; | 2124 | *lenp = 0; |
2116 | return 0; | 2125 | return 0; |
2117 | } | 2126 | } |
2118 | 2127 | ||
2119 | data += *ppos; | 2128 | data += *ppos; |
2120 | len -= *ppos; | 2129 | len -= *ppos; |
2121 | 2130 | ||
2122 | if (len > *lenp) | 2131 | if (len > *lenp) |
2123 | len = *lenp; | 2132 | len = *lenp; |
2124 | if (len) | 2133 | if (len) |
2125 | if(copy_to_user(buffer, data, len)) | 2134 | if(copy_to_user(buffer, data, len)) |
2126 | return -EFAULT; | 2135 | return -EFAULT; |
2127 | if (len < *lenp) { | 2136 | if (len < *lenp) { |
2128 | if(put_user('\n', ((char __user *) buffer) + len)) | 2137 | if(put_user('\n', ((char __user *) buffer) + len)) |
2129 | return -EFAULT; | 2138 | return -EFAULT; |
2130 | len++; | 2139 | len++; |
2131 | } | 2140 | } |
2132 | *lenp = len; | 2141 | *lenp = len; |
2133 | *ppos += len; | 2142 | *ppos += len; |
2134 | } | 2143 | } |
2135 | return 0; | 2144 | return 0; |
2136 | } | 2145 | } |
2137 | 2146 | ||
2138 | /** | 2147 | /** |
2139 | * proc_dostring - read a string sysctl | 2148 | * proc_dostring - read a string sysctl |
2140 | * @table: the sysctl table | 2149 | * @table: the sysctl table |
2141 | * @write: %TRUE if this is a write to the sysctl file | 2150 | * @write: %TRUE if this is a write to the sysctl file |
2142 | * @filp: the file structure | 2151 | * @filp: the file structure |
2143 | * @buffer: the user buffer | 2152 | * @buffer: the user buffer |
2144 | * @lenp: the size of the user buffer | 2153 | * @lenp: the size of the user buffer |
2145 | * @ppos: file position | 2154 | * @ppos: file position |
2146 | * | 2155 | * |
2147 | * Reads/writes a string from/to the user buffer. If the kernel | 2156 | * Reads/writes a string from/to the user buffer. If the kernel |
2148 | * buffer provided is not large enough to hold the string, the | 2157 | * buffer provided is not large enough to hold the string, the |
2149 | * string is truncated. The copied string is %NULL-terminated. | 2158 | * string is truncated. The copied string is %NULL-terminated. |
2150 | * If the string is being read by the user process, it is copied | 2159 | * If the string is being read by the user process, it is copied |
2151 | * and a newline '\n' is added. It is truncated if the buffer is | 2160 | * and a newline '\n' is added. It is truncated if the buffer is |
2152 | * not large enough. | 2161 | * not large enough. |
2153 | * | 2162 | * |
2154 | * Returns 0 on success. | 2163 | * Returns 0 on success. |
2155 | */ | 2164 | */ |
2156 | int proc_dostring(struct ctl_table *table, int write, struct file *filp, | 2165 | int proc_dostring(struct ctl_table *table, int write, struct file *filp, |
2157 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2166 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2158 | { | 2167 | { |
2159 | return _proc_do_string(table->data, table->maxlen, write, filp, | 2168 | return _proc_do_string(table->data, table->maxlen, write, filp, |
2160 | buffer, lenp, ppos); | 2169 | buffer, lenp, ppos); |
2161 | } | 2170 | } |
2162 | 2171 | ||
2163 | 2172 | ||
2164 | static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp, | 2173 | static int do_proc_dointvec_conv(int *negp, unsigned long *lvalp, |
2165 | int *valp, | 2174 | int *valp, |
2166 | int write, void *data) | 2175 | int write, void *data) |
2167 | { | 2176 | { |
2168 | if (write) { | 2177 | if (write) { |
2169 | *valp = *negp ? -*lvalp : *lvalp; | 2178 | *valp = *negp ? -*lvalp : *lvalp; |
2170 | } else { | 2179 | } else { |
2171 | int val = *valp; | 2180 | int val = *valp; |
2172 | if (val < 0) { | 2181 | if (val < 0) { |
2173 | *negp = -1; | 2182 | *negp = -1; |
2174 | *lvalp = (unsigned long)-val; | 2183 | *lvalp = (unsigned long)-val; |
2175 | } else { | 2184 | } else { |
2176 | *negp = 0; | 2185 | *negp = 0; |
2177 | *lvalp = (unsigned long)val; | 2186 | *lvalp = (unsigned long)val; |
2178 | } | 2187 | } |
2179 | } | 2188 | } |
2180 | return 0; | 2189 | return 0; |
2181 | } | 2190 | } |
2182 | 2191 | ||
2183 | static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table, | 2192 | static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table, |
2184 | int write, struct file *filp, void __user *buffer, | 2193 | int write, struct file *filp, void __user *buffer, |
2185 | size_t *lenp, loff_t *ppos, | 2194 | size_t *lenp, loff_t *ppos, |
2186 | int (*conv)(int *negp, unsigned long *lvalp, int *valp, | 2195 | int (*conv)(int *negp, unsigned long *lvalp, int *valp, |
2187 | int write, void *data), | 2196 | int write, void *data), |
2188 | void *data) | 2197 | void *data) |
2189 | { | 2198 | { |
2190 | #define TMPBUFLEN 21 | 2199 | #define TMPBUFLEN 21 |
2191 | int *i, vleft, first=1, neg, val; | 2200 | int *i, vleft, first=1, neg, val; |
2192 | unsigned long lval; | 2201 | unsigned long lval; |
2193 | size_t left, len; | 2202 | size_t left, len; |
2194 | 2203 | ||
2195 | char buf[TMPBUFLEN], *p; | 2204 | char buf[TMPBUFLEN], *p; |
2196 | char __user *s = buffer; | 2205 | char __user *s = buffer; |
2197 | 2206 | ||
2198 | if (!tbl_data || !table->maxlen || !*lenp || | 2207 | if (!tbl_data || !table->maxlen || !*lenp || |
2199 | (*ppos && !write)) { | 2208 | (*ppos && !write)) { |
2200 | *lenp = 0; | 2209 | *lenp = 0; |
2201 | return 0; | 2210 | return 0; |
2202 | } | 2211 | } |
2203 | 2212 | ||
2204 | i = (int *) tbl_data; | 2213 | i = (int *) tbl_data; |
2205 | vleft = table->maxlen / sizeof(*i); | 2214 | vleft = table->maxlen / sizeof(*i); |
2206 | left = *lenp; | 2215 | left = *lenp; |
2207 | 2216 | ||
2208 | if (!conv) | 2217 | if (!conv) |
2209 | conv = do_proc_dointvec_conv; | 2218 | conv = do_proc_dointvec_conv; |
2210 | 2219 | ||
2211 | for (; left && vleft--; i++, first=0) { | 2220 | for (; left && vleft--; i++, first=0) { |
2212 | if (write) { | 2221 | if (write) { |
2213 | while (left) { | 2222 | while (left) { |
2214 | char c; | 2223 | char c; |
2215 | if (get_user(c, s)) | 2224 | if (get_user(c, s)) |
2216 | return -EFAULT; | 2225 | return -EFAULT; |
2217 | if (!isspace(c)) | 2226 | if (!isspace(c)) |
2218 | break; | 2227 | break; |
2219 | left--; | 2228 | left--; |
2220 | s++; | 2229 | s++; |
2221 | } | 2230 | } |
2222 | if (!left) | 2231 | if (!left) |
2223 | break; | 2232 | break; |
2224 | neg = 0; | 2233 | neg = 0; |
2225 | len = left; | 2234 | len = left; |
2226 | if (len > sizeof(buf) - 1) | 2235 | if (len > sizeof(buf) - 1) |
2227 | len = sizeof(buf) - 1; | 2236 | len = sizeof(buf) - 1; |
2228 | if (copy_from_user(buf, s, len)) | 2237 | if (copy_from_user(buf, s, len)) |
2229 | return -EFAULT; | 2238 | return -EFAULT; |
2230 | buf[len] = 0; | 2239 | buf[len] = 0; |
2231 | p = buf; | 2240 | p = buf; |
2232 | if (*p == '-' && left > 1) { | 2241 | if (*p == '-' && left > 1) { |
2233 | neg = 1; | 2242 | neg = 1; |
2234 | p++; | 2243 | p++; |
2235 | } | 2244 | } |
2236 | if (*p < '0' || *p > '9') | 2245 | if (*p < '0' || *p > '9') |
2237 | break; | 2246 | break; |
2238 | 2247 | ||
2239 | lval = simple_strtoul(p, &p, 0); | 2248 | lval = simple_strtoul(p, &p, 0); |
2240 | 2249 | ||
2241 | len = p-buf; | 2250 | len = p-buf; |
2242 | if ((len < left) && *p && !isspace(*p)) | 2251 | if ((len < left) && *p && !isspace(*p)) |
2243 | break; | 2252 | break; |
2244 | if (neg) | 2253 | if (neg) |
2245 | val = -val; | 2254 | val = -val; |
2246 | s += len; | 2255 | s += len; |
2247 | left -= len; | 2256 | left -= len; |
2248 | 2257 | ||
2249 | if (conv(&neg, &lval, i, 1, data)) | 2258 | if (conv(&neg, &lval, i, 1, data)) |
2250 | break; | 2259 | break; |
2251 | } else { | 2260 | } else { |
2252 | p = buf; | 2261 | p = buf; |
2253 | if (!first) | 2262 | if (!first) |
2254 | *p++ = '\t'; | 2263 | *p++ = '\t'; |
2255 | 2264 | ||
2256 | if (conv(&neg, &lval, i, 0, data)) | 2265 | if (conv(&neg, &lval, i, 0, data)) |
2257 | break; | 2266 | break; |
2258 | 2267 | ||
2259 | sprintf(p, "%s%lu", neg ? "-" : "", lval); | 2268 | sprintf(p, "%s%lu", neg ? "-" : "", lval); |
2260 | len = strlen(buf); | 2269 | len = strlen(buf); |
2261 | if (len > left) | 2270 | if (len > left) |
2262 | len = left; | 2271 | len = left; |
2263 | if(copy_to_user(s, buf, len)) | 2272 | if(copy_to_user(s, buf, len)) |
2264 | return -EFAULT; | 2273 | return -EFAULT; |
2265 | left -= len; | 2274 | left -= len; |
2266 | s += len; | 2275 | s += len; |
2267 | } | 2276 | } |
2268 | } | 2277 | } |
2269 | 2278 | ||
2270 | if (!write && !first && left) { | 2279 | if (!write && !first && left) { |
2271 | if(put_user('\n', s)) | 2280 | if(put_user('\n', s)) |
2272 | return -EFAULT; | 2281 | return -EFAULT; |
2273 | left--, s++; | 2282 | left--, s++; |
2274 | } | 2283 | } |
2275 | if (write) { | 2284 | if (write) { |
2276 | while (left) { | 2285 | while (left) { |
2277 | char c; | 2286 | char c; |
2278 | if (get_user(c, s++)) | 2287 | if (get_user(c, s++)) |
2279 | return -EFAULT; | 2288 | return -EFAULT; |
2280 | if (!isspace(c)) | 2289 | if (!isspace(c)) |
2281 | break; | 2290 | break; |
2282 | left--; | 2291 | left--; |
2283 | } | 2292 | } |
2284 | } | 2293 | } |
2285 | if (write && first) | 2294 | if (write && first) |
2286 | return -EINVAL; | 2295 | return -EINVAL; |
2287 | *lenp -= left; | 2296 | *lenp -= left; |
2288 | *ppos += *lenp; | 2297 | *ppos += *lenp; |
2289 | return 0; | 2298 | return 0; |
2290 | #undef TMPBUFLEN | 2299 | #undef TMPBUFLEN |
2291 | } | 2300 | } |
2292 | 2301 | ||
2293 | static int do_proc_dointvec(struct ctl_table *table, int write, struct file *filp, | 2302 | static int do_proc_dointvec(struct ctl_table *table, int write, struct file *filp, |
2294 | void __user *buffer, size_t *lenp, loff_t *ppos, | 2303 | void __user *buffer, size_t *lenp, loff_t *ppos, |
2295 | int (*conv)(int *negp, unsigned long *lvalp, int *valp, | 2304 | int (*conv)(int *negp, unsigned long *lvalp, int *valp, |
2296 | int write, void *data), | 2305 | int write, void *data), |
2297 | void *data) | 2306 | void *data) |
2298 | { | 2307 | { |
2299 | return __do_proc_dointvec(table->data, table, write, filp, | 2308 | return __do_proc_dointvec(table->data, table, write, filp, |
2300 | buffer, lenp, ppos, conv, data); | 2309 | buffer, lenp, ppos, conv, data); |
2301 | } | 2310 | } |
2302 | 2311 | ||
2303 | /** | 2312 | /** |
2304 | * proc_dointvec - read a vector of integers | 2313 | * proc_dointvec - read a vector of integers |
2305 | * @table: the sysctl table | 2314 | * @table: the sysctl table |
2306 | * @write: %TRUE if this is a write to the sysctl file | 2315 | * @write: %TRUE if this is a write to the sysctl file |
2307 | * @filp: the file structure | 2316 | * @filp: the file structure |
2308 | * @buffer: the user buffer | 2317 | * @buffer: the user buffer |
2309 | * @lenp: the size of the user buffer | 2318 | * @lenp: the size of the user buffer |
2310 | * @ppos: file position | 2319 | * @ppos: file position |
2311 | * | 2320 | * |
2312 | * Reads/writes up to table->maxlen/sizeof(unsigned int) integer | 2321 | * Reads/writes up to table->maxlen/sizeof(unsigned int) integer |
2313 | * values from/to the user buffer, treated as an ASCII string. | 2322 | * values from/to the user buffer, treated as an ASCII string. |
2314 | * | 2323 | * |
2315 | * Returns 0 on success. | 2324 | * Returns 0 on success. |
2316 | */ | 2325 | */ |
2317 | int proc_dointvec(struct ctl_table *table, int write, struct file *filp, | 2326 | int proc_dointvec(struct ctl_table *table, int write, struct file *filp, |
2318 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2327 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2319 | { | 2328 | { |
2320 | return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, | 2329 | return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, |
2321 | NULL,NULL); | 2330 | NULL,NULL); |
2322 | } | 2331 | } |
2323 | 2332 | ||
2324 | /* | 2333 | /* |
2325 | * Taint values can only be increased | 2334 | * Taint values can only be increased |
2326 | * This means we can safely use a temporary. | 2335 | * This means we can safely use a temporary. |
2327 | */ | 2336 | */ |
2328 | static int proc_taint(struct ctl_table *table, int write, struct file *filp, | 2337 | static int proc_taint(struct ctl_table *table, int write, struct file *filp, |
2329 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2338 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2330 | { | 2339 | { |
2331 | struct ctl_table t; | 2340 | struct ctl_table t; |
2332 | unsigned long tmptaint = get_taint(); | 2341 | unsigned long tmptaint = get_taint(); |
2333 | int err; | 2342 | int err; |
2334 | 2343 | ||
2335 | if (write && !capable(CAP_SYS_ADMIN)) | 2344 | if (write && !capable(CAP_SYS_ADMIN)) |
2336 | return -EPERM; | 2345 | return -EPERM; |
2337 | 2346 | ||
2338 | t = *table; | 2347 | t = *table; |
2339 | t.data = &tmptaint; | 2348 | t.data = &tmptaint; |
2340 | err = proc_doulongvec_minmax(&t, write, filp, buffer, lenp, ppos); | 2349 | err = proc_doulongvec_minmax(&t, write, filp, buffer, lenp, ppos); |
2341 | if (err < 0) | 2350 | if (err < 0) |
2342 | return err; | 2351 | return err; |
2343 | 2352 | ||
2344 | if (write) { | 2353 | if (write) { |
2345 | /* | 2354 | /* |
2346 | * Poor man's atomic or. Not worth adding a primitive | 2355 | * Poor man's atomic or. Not worth adding a primitive |
2347 | * to everyone's atomic.h for this | 2356 | * to everyone's atomic.h for this |
2348 | */ | 2357 | */ |
2349 | int i; | 2358 | int i; |
2350 | for (i = 0; i < BITS_PER_LONG && tmptaint >> i; i++) { | 2359 | for (i = 0; i < BITS_PER_LONG && tmptaint >> i; i++) { |
2351 | if ((tmptaint >> i) & 1) | 2360 | if ((tmptaint >> i) & 1) |
2352 | add_taint(i); | 2361 | add_taint(i); |
2353 | } | 2362 | } |
2354 | } | 2363 | } |
2355 | 2364 | ||
2356 | return err; | 2365 | return err; |
2357 | } | 2366 | } |
2358 | 2367 | ||
2359 | struct do_proc_dointvec_minmax_conv_param { | 2368 | struct do_proc_dointvec_minmax_conv_param { |
2360 | int *min; | 2369 | int *min; |
2361 | int *max; | 2370 | int *max; |
2362 | }; | 2371 | }; |
2363 | 2372 | ||
2364 | static int do_proc_dointvec_minmax_conv(int *negp, unsigned long *lvalp, | 2373 | static int do_proc_dointvec_minmax_conv(int *negp, unsigned long *lvalp, |
2365 | int *valp, | 2374 | int *valp, |
2366 | int write, void *data) | 2375 | int write, void *data) |
2367 | { | 2376 | { |
2368 | struct do_proc_dointvec_minmax_conv_param *param = data; | 2377 | struct do_proc_dointvec_minmax_conv_param *param = data; |
2369 | if (write) { | 2378 | if (write) { |
2370 | int val = *negp ? -*lvalp : *lvalp; | 2379 | int val = *negp ? -*lvalp : *lvalp; |
2371 | if ((param->min && *param->min > val) || | 2380 | if ((param->min && *param->min > val) || |
2372 | (param->max && *param->max < val)) | 2381 | (param->max && *param->max < val)) |
2373 | return -EINVAL; | 2382 | return -EINVAL; |
2374 | *valp = val; | 2383 | *valp = val; |
2375 | } else { | 2384 | } else { |
2376 | int val = *valp; | 2385 | int val = *valp; |
2377 | if (val < 0) { | 2386 | if (val < 0) { |
2378 | *negp = -1; | 2387 | *negp = -1; |
2379 | *lvalp = (unsigned long)-val; | 2388 | *lvalp = (unsigned long)-val; |
2380 | } else { | 2389 | } else { |
2381 | *negp = 0; | 2390 | *negp = 0; |
2382 | *lvalp = (unsigned long)val; | 2391 | *lvalp = (unsigned long)val; |
2383 | } | 2392 | } |
2384 | } | 2393 | } |
2385 | return 0; | 2394 | return 0; |
2386 | } | 2395 | } |
2387 | 2396 | ||
2388 | /** | 2397 | /** |
2389 | * proc_dointvec_minmax - read a vector of integers with min/max values | 2398 | * proc_dointvec_minmax - read a vector of integers with min/max values |
2390 | * @table: the sysctl table | 2399 | * @table: the sysctl table |
2391 | * @write: %TRUE if this is a write to the sysctl file | 2400 | * @write: %TRUE if this is a write to the sysctl file |
2392 | * @filp: the file structure | 2401 | * @filp: the file structure |
2393 | * @buffer: the user buffer | 2402 | * @buffer: the user buffer |
2394 | * @lenp: the size of the user buffer | 2403 | * @lenp: the size of the user buffer |
2395 | * @ppos: file position | 2404 | * @ppos: file position |
2396 | * | 2405 | * |
2397 | * Reads/writes up to table->maxlen/sizeof(unsigned int) integer | 2406 | * Reads/writes up to table->maxlen/sizeof(unsigned int) integer |
2398 | * values from/to the user buffer, treated as an ASCII string. | 2407 | * values from/to the user buffer, treated as an ASCII string. |
2399 | * | 2408 | * |
2400 | * This routine will ensure the values are within the range specified by | 2409 | * This routine will ensure the values are within the range specified by |
2401 | * table->extra1 (min) and table->extra2 (max). | 2410 | * table->extra1 (min) and table->extra2 (max). |
2402 | * | 2411 | * |
2403 | * Returns 0 on success. | 2412 | * Returns 0 on success. |
2404 | */ | 2413 | */ |
2405 | int proc_dointvec_minmax(struct ctl_table *table, int write, struct file *filp, | 2414 | int proc_dointvec_minmax(struct ctl_table *table, int write, struct file *filp, |
2406 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2415 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2407 | { | 2416 | { |
2408 | struct do_proc_dointvec_minmax_conv_param param = { | 2417 | struct do_proc_dointvec_minmax_conv_param param = { |
2409 | .min = (int *) table->extra1, | 2418 | .min = (int *) table->extra1, |
2410 | .max = (int *) table->extra2, | 2419 | .max = (int *) table->extra2, |
2411 | }; | 2420 | }; |
2412 | return do_proc_dointvec(table, write, filp, buffer, lenp, ppos, | 2421 | return do_proc_dointvec(table, write, filp, buffer, lenp, ppos, |
2413 | do_proc_dointvec_minmax_conv, ¶m); | 2422 | do_proc_dointvec_minmax_conv, ¶m); |
2414 | } | 2423 | } |
2415 | 2424 | ||
2416 | static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int write, | 2425 | static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int write, |
2417 | struct file *filp, | 2426 | struct file *filp, |
2418 | void __user *buffer, | 2427 | void __user *buffer, |
2419 | size_t *lenp, loff_t *ppos, | 2428 | size_t *lenp, loff_t *ppos, |
2420 | unsigned long convmul, | 2429 | unsigned long convmul, |
2421 | unsigned long convdiv) | 2430 | unsigned long convdiv) |
2422 | { | 2431 | { |
2423 | #define TMPBUFLEN 21 | 2432 | #define TMPBUFLEN 21 |
2424 | unsigned long *i, *min, *max, val; | 2433 | unsigned long *i, *min, *max, val; |
2425 | int vleft, first=1, neg; | 2434 | int vleft, first=1, neg; |
2426 | size_t len, left; | 2435 | size_t len, left; |
2427 | char buf[TMPBUFLEN], *p; | 2436 | char buf[TMPBUFLEN], *p; |
2428 | char __user *s = buffer; | 2437 | char __user *s = buffer; |
2429 | 2438 | ||
2430 | if (!data || !table->maxlen || !*lenp || | 2439 | if (!data || !table->maxlen || !*lenp || |
2431 | (*ppos && !write)) { | 2440 | (*ppos && !write)) { |
2432 | *lenp = 0; | 2441 | *lenp = 0; |
2433 | return 0; | 2442 | return 0; |
2434 | } | 2443 | } |
2435 | 2444 | ||
2436 | i = (unsigned long *) data; | 2445 | i = (unsigned long *) data; |
2437 | min = (unsigned long *) table->extra1; | 2446 | min = (unsigned long *) table->extra1; |
2438 | max = (unsigned long *) table->extra2; | 2447 | max = (unsigned long *) table->extra2; |
2439 | vleft = table->maxlen / sizeof(unsigned long); | 2448 | vleft = table->maxlen / sizeof(unsigned long); |
2440 | left = *lenp; | 2449 | left = *lenp; |
2441 | 2450 | ||
2442 | for (; left && vleft--; i++, min++, max++, first=0) { | 2451 | for (; left && vleft--; i++, min++, max++, first=0) { |
2443 | if (write) { | 2452 | if (write) { |
2444 | while (left) { | 2453 | while (left) { |
2445 | char c; | 2454 | char c; |
2446 | if (get_user(c, s)) | 2455 | if (get_user(c, s)) |
2447 | return -EFAULT; | 2456 | return -EFAULT; |
2448 | if (!isspace(c)) | 2457 | if (!isspace(c)) |
2449 | break; | 2458 | break; |
2450 | left--; | 2459 | left--; |
2451 | s++; | 2460 | s++; |
2452 | } | 2461 | } |
2453 | if (!left) | 2462 | if (!left) |
2454 | break; | 2463 | break; |
2455 | neg = 0; | 2464 | neg = 0; |
2456 | len = left; | 2465 | len = left; |
2457 | if (len > TMPBUFLEN-1) | 2466 | if (len > TMPBUFLEN-1) |
2458 | len = TMPBUFLEN-1; | 2467 | len = TMPBUFLEN-1; |
2459 | if (copy_from_user(buf, s, len)) | 2468 | if (copy_from_user(buf, s, len)) |
2460 | return -EFAULT; | 2469 | return -EFAULT; |
2461 | buf[len] = 0; | 2470 | buf[len] = 0; |
2462 | p = buf; | 2471 | p = buf; |
2463 | if (*p == '-' && left > 1) { | 2472 | if (*p == '-' && left > 1) { |
2464 | neg = 1; | 2473 | neg = 1; |
2465 | p++; | 2474 | p++; |
2466 | } | 2475 | } |
2467 | if (*p < '0' || *p > '9') | 2476 | if (*p < '0' || *p > '9') |
2468 | break; | 2477 | break; |
2469 | val = simple_strtoul(p, &p, 0) * convmul / convdiv ; | 2478 | val = simple_strtoul(p, &p, 0) * convmul / convdiv ; |
2470 | len = p-buf; | 2479 | len = p-buf; |
2471 | if ((len < left) && *p && !isspace(*p)) | 2480 | if ((len < left) && *p && !isspace(*p)) |
2472 | break; | 2481 | break; |
2473 | if (neg) | 2482 | if (neg) |
2474 | val = -val; | 2483 | val = -val; |
2475 | s += len; | 2484 | s += len; |
2476 | left -= len; | 2485 | left -= len; |
2477 | 2486 | ||
2478 | if(neg) | 2487 | if(neg) |
2479 | continue; | 2488 | continue; |
2480 | if ((min && val < *min) || (max && val > *max)) | 2489 | if ((min && val < *min) || (max && val > *max)) |
2481 | continue; | 2490 | continue; |
2482 | *i = val; | 2491 | *i = val; |
2483 | } else { | 2492 | } else { |
2484 | p = buf; | 2493 | p = buf; |
2485 | if (!first) | 2494 | if (!first) |
2486 | *p++ = '\t'; | 2495 | *p++ = '\t'; |
2487 | sprintf(p, "%lu", convdiv * (*i) / convmul); | 2496 | sprintf(p, "%lu", convdiv * (*i) / convmul); |
2488 | len = strlen(buf); | 2497 | len = strlen(buf); |
2489 | if (len > left) | 2498 | if (len > left) |
2490 | len = left; | 2499 | len = left; |
2491 | if(copy_to_user(s, buf, len)) | 2500 | if(copy_to_user(s, buf, len)) |
2492 | return -EFAULT; | 2501 | return -EFAULT; |
2493 | left -= len; | 2502 | left -= len; |
2494 | s += len; | 2503 | s += len; |
2495 | } | 2504 | } |
2496 | } | 2505 | } |
2497 | 2506 | ||
2498 | if (!write && !first && left) { | 2507 | if (!write && !first && left) { |
2499 | if(put_user('\n', s)) | 2508 | if(put_user('\n', s)) |
2500 | return -EFAULT; | 2509 | return -EFAULT; |
2501 | left--, s++; | 2510 | left--, s++; |
2502 | } | 2511 | } |
2503 | if (write) { | 2512 | if (write) { |
2504 | while (left) { | 2513 | while (left) { |
2505 | char c; | 2514 | char c; |
2506 | if (get_user(c, s++)) | 2515 | if (get_user(c, s++)) |
2507 | return -EFAULT; | 2516 | return -EFAULT; |
2508 | if (!isspace(c)) | 2517 | if (!isspace(c)) |
2509 | break; | 2518 | break; |
2510 | left--; | 2519 | left--; |
2511 | } | 2520 | } |
2512 | } | 2521 | } |
2513 | if (write && first) | 2522 | if (write && first) |
2514 | return -EINVAL; | 2523 | return -EINVAL; |
2515 | *lenp -= left; | 2524 | *lenp -= left; |
2516 | *ppos += *lenp; | 2525 | *ppos += *lenp; |
2517 | return 0; | 2526 | return 0; |
2518 | #undef TMPBUFLEN | 2527 | #undef TMPBUFLEN |
2519 | } | 2528 | } |
2520 | 2529 | ||
2521 | static int do_proc_doulongvec_minmax(struct ctl_table *table, int write, | 2530 | static int do_proc_doulongvec_minmax(struct ctl_table *table, int write, |
2522 | struct file *filp, | 2531 | struct file *filp, |
2523 | void __user *buffer, | 2532 | void __user *buffer, |
2524 | size_t *lenp, loff_t *ppos, | 2533 | size_t *lenp, loff_t *ppos, |
2525 | unsigned long convmul, | 2534 | unsigned long convmul, |
2526 | unsigned long convdiv) | 2535 | unsigned long convdiv) |
2527 | { | 2536 | { |
2528 | return __do_proc_doulongvec_minmax(table->data, table, write, | 2537 | return __do_proc_doulongvec_minmax(table->data, table, write, |
2529 | filp, buffer, lenp, ppos, convmul, convdiv); | 2538 | filp, buffer, lenp, ppos, convmul, convdiv); |
2530 | } | 2539 | } |
2531 | 2540 | ||
2532 | /** | 2541 | /** |
2533 | * proc_doulongvec_minmax - read a vector of long integers with min/max values | 2542 | * proc_doulongvec_minmax - read a vector of long integers with min/max values |
2534 | * @table: the sysctl table | 2543 | * @table: the sysctl table |
2535 | * @write: %TRUE if this is a write to the sysctl file | 2544 | * @write: %TRUE if this is a write to the sysctl file |
2536 | * @filp: the file structure | 2545 | * @filp: the file structure |
2537 | * @buffer: the user buffer | 2546 | * @buffer: the user buffer |
2538 | * @lenp: the size of the user buffer | 2547 | * @lenp: the size of the user buffer |
2539 | * @ppos: file position | 2548 | * @ppos: file position |
2540 | * | 2549 | * |
2541 | * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long | 2550 | * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long |
2542 | * values from/to the user buffer, treated as an ASCII string. | 2551 | * values from/to the user buffer, treated as an ASCII string. |
2543 | * | 2552 | * |
2544 | * This routine will ensure the values are within the range specified by | 2553 | * This routine will ensure the values are within the range specified by |
2545 | * table->extra1 (min) and table->extra2 (max). | 2554 | * table->extra1 (min) and table->extra2 (max). |
2546 | * | 2555 | * |
2547 | * Returns 0 on success. | 2556 | * Returns 0 on success. |
2548 | */ | 2557 | */ |
2549 | int proc_doulongvec_minmax(struct ctl_table *table, int write, struct file *filp, | 2558 | int proc_doulongvec_minmax(struct ctl_table *table, int write, struct file *filp, |
2550 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2559 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2551 | { | 2560 | { |
2552 | return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, ppos, 1l, 1l); | 2561 | return do_proc_doulongvec_minmax(table, write, filp, buffer, lenp, ppos, 1l, 1l); |
2553 | } | 2562 | } |
2554 | 2563 | ||
2555 | /** | 2564 | /** |
2556 | * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values | 2565 | * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values |
2557 | * @table: the sysctl table | 2566 | * @table: the sysctl table |
2558 | * @write: %TRUE if this is a write to the sysctl file | 2567 | * @write: %TRUE if this is a write to the sysctl file |
2559 | * @filp: the file structure | 2568 | * @filp: the file structure |
2560 | * @buffer: the user buffer | 2569 | * @buffer: the user buffer |
2561 | * @lenp: the size of the user buffer | 2570 | * @lenp: the size of the user buffer |
2562 | * @ppos: file position | 2571 | * @ppos: file position |
2563 | * | 2572 | * |
2564 | * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long | 2573 | * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long |
2565 | * values from/to the user buffer, treated as an ASCII string. The values | 2574 | * values from/to the user buffer, treated as an ASCII string. The values |
2566 | * are treated as milliseconds, and converted to jiffies when they are stored. | 2575 | * are treated as milliseconds, and converted to jiffies when they are stored. |
2567 | * | 2576 | * |
2568 | * This routine will ensure the values are within the range specified by | 2577 | * This routine will ensure the values are within the range specified by |
2569 | * table->extra1 (min) and table->extra2 (max). | 2578 | * table->extra1 (min) and table->extra2 (max). |
2570 | * | 2579 | * |
2571 | * Returns 0 on success. | 2580 | * Returns 0 on success. |
2572 | */ | 2581 | */ |
2573 | int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write, | 2582 | int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write, |
2574 | struct file *filp, | 2583 | struct file *filp, |
2575 | void __user *buffer, | 2584 | void __user *buffer, |
2576 | size_t *lenp, loff_t *ppos) | 2585 | size_t *lenp, loff_t *ppos) |
2577 | { | 2586 | { |
2578 | return do_proc_doulongvec_minmax(table, write, filp, buffer, | 2587 | return do_proc_doulongvec_minmax(table, write, filp, buffer, |
2579 | lenp, ppos, HZ, 1000l); | 2588 | lenp, ppos, HZ, 1000l); |
2580 | } | 2589 | } |
2581 | 2590 | ||
2582 | 2591 | ||
2583 | static int do_proc_dointvec_jiffies_conv(int *negp, unsigned long *lvalp, | 2592 | static int do_proc_dointvec_jiffies_conv(int *negp, unsigned long *lvalp, |
2584 | int *valp, | 2593 | int *valp, |
2585 | int write, void *data) | 2594 | int write, void *data) |
2586 | { | 2595 | { |
2587 | if (write) { | 2596 | if (write) { |
2588 | if (*lvalp > LONG_MAX / HZ) | 2597 | if (*lvalp > LONG_MAX / HZ) |
2589 | return 1; | 2598 | return 1; |
2590 | *valp = *negp ? -(*lvalp*HZ) : (*lvalp*HZ); | 2599 | *valp = *negp ? -(*lvalp*HZ) : (*lvalp*HZ); |
2591 | } else { | 2600 | } else { |
2592 | int val = *valp; | 2601 | int val = *valp; |
2593 | unsigned long lval; | 2602 | unsigned long lval; |
2594 | if (val < 0) { | 2603 | if (val < 0) { |
2595 | *negp = -1; | 2604 | *negp = -1; |
2596 | lval = (unsigned long)-val; | 2605 | lval = (unsigned long)-val; |
2597 | } else { | 2606 | } else { |
2598 | *negp = 0; | 2607 | *negp = 0; |
2599 | lval = (unsigned long)val; | 2608 | lval = (unsigned long)val; |
2600 | } | 2609 | } |
2601 | *lvalp = lval / HZ; | 2610 | *lvalp = lval / HZ; |
2602 | } | 2611 | } |
2603 | return 0; | 2612 | return 0; |
2604 | } | 2613 | } |
2605 | 2614 | ||
2606 | static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp, | 2615 | static int do_proc_dointvec_userhz_jiffies_conv(int *negp, unsigned long *lvalp, |
2607 | int *valp, | 2616 | int *valp, |
2608 | int write, void *data) | 2617 | int write, void *data) |
2609 | { | 2618 | { |
2610 | if (write) { | 2619 | if (write) { |
2611 | if (USER_HZ < HZ && *lvalp > (LONG_MAX / HZ) * USER_HZ) | 2620 | if (USER_HZ < HZ && *lvalp > (LONG_MAX / HZ) * USER_HZ) |
2612 | return 1; | 2621 | return 1; |
2613 | *valp = clock_t_to_jiffies(*negp ? -*lvalp : *lvalp); | 2622 | *valp = clock_t_to_jiffies(*negp ? -*lvalp : *lvalp); |
2614 | } else { | 2623 | } else { |
2615 | int val = *valp; | 2624 | int val = *valp; |
2616 | unsigned long lval; | 2625 | unsigned long lval; |
2617 | if (val < 0) { | 2626 | if (val < 0) { |
2618 | *negp = -1; | 2627 | *negp = -1; |
2619 | lval = (unsigned long)-val; | 2628 | lval = (unsigned long)-val; |
2620 | } else { | 2629 | } else { |
2621 | *negp = 0; | 2630 | *negp = 0; |
2622 | lval = (unsigned long)val; | 2631 | lval = (unsigned long)val; |
2623 | } | 2632 | } |
2624 | *lvalp = jiffies_to_clock_t(lval); | 2633 | *lvalp = jiffies_to_clock_t(lval); |
2625 | } | 2634 | } |
2626 | return 0; | 2635 | return 0; |
2627 | } | 2636 | } |
2628 | 2637 | ||
2629 | static int do_proc_dointvec_ms_jiffies_conv(int *negp, unsigned long *lvalp, | 2638 | static int do_proc_dointvec_ms_jiffies_conv(int *negp, unsigned long *lvalp, |
2630 | int *valp, | 2639 | int *valp, |
2631 | int write, void *data) | 2640 | int write, void *data) |
2632 | { | 2641 | { |
2633 | if (write) { | 2642 | if (write) { |
2634 | *valp = msecs_to_jiffies(*negp ? -*lvalp : *lvalp); | 2643 | *valp = msecs_to_jiffies(*negp ? -*lvalp : *lvalp); |
2635 | } else { | 2644 | } else { |
2636 | int val = *valp; | 2645 | int val = *valp; |
2637 | unsigned long lval; | 2646 | unsigned long lval; |
2638 | if (val < 0) { | 2647 | if (val < 0) { |
2639 | *negp = -1; | 2648 | *negp = -1; |
2640 | lval = (unsigned long)-val; | 2649 | lval = (unsigned long)-val; |
2641 | } else { | 2650 | } else { |
2642 | *negp = 0; | 2651 | *negp = 0; |
2643 | lval = (unsigned long)val; | 2652 | lval = (unsigned long)val; |
2644 | } | 2653 | } |
2645 | *lvalp = jiffies_to_msecs(lval); | 2654 | *lvalp = jiffies_to_msecs(lval); |
2646 | } | 2655 | } |
2647 | return 0; | 2656 | return 0; |
2648 | } | 2657 | } |
2649 | 2658 | ||
2650 | /** | 2659 | /** |
2651 | * proc_dointvec_jiffies - read a vector of integers as seconds | 2660 | * proc_dointvec_jiffies - read a vector of integers as seconds |
2652 | * @table: the sysctl table | 2661 | * @table: the sysctl table |
2653 | * @write: %TRUE if this is a write to the sysctl file | 2662 | * @write: %TRUE if this is a write to the sysctl file |
2654 | * @filp: the file structure | 2663 | * @filp: the file structure |
2655 | * @buffer: the user buffer | 2664 | * @buffer: the user buffer |
2656 | * @lenp: the size of the user buffer | 2665 | * @lenp: the size of the user buffer |
2657 | * @ppos: file position | 2666 | * @ppos: file position |
2658 | * | 2667 | * |
2659 | * Reads/writes up to table->maxlen/sizeof(unsigned int) integer | 2668 | * Reads/writes up to table->maxlen/sizeof(unsigned int) integer |
2660 | * values from/to the user buffer, treated as an ASCII string. | 2669 | * values from/to the user buffer, treated as an ASCII string. |
2661 | * The values read are assumed to be in seconds, and are converted into | 2670 | * The values read are assumed to be in seconds, and are converted into |
2662 | * jiffies. | 2671 | * jiffies. |
2663 | * | 2672 | * |
2664 | * Returns 0 on success. | 2673 | * Returns 0 on success. |
2665 | */ | 2674 | */ |
2666 | int proc_dointvec_jiffies(struct ctl_table *table, int write, struct file *filp, | 2675 | int proc_dointvec_jiffies(struct ctl_table *table, int write, struct file *filp, |
2667 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2676 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2668 | { | 2677 | { |
2669 | return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, | 2678 | return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, |
2670 | do_proc_dointvec_jiffies_conv,NULL); | 2679 | do_proc_dointvec_jiffies_conv,NULL); |
2671 | } | 2680 | } |
2672 | 2681 | ||
2673 | /** | 2682 | /** |
2674 | * proc_dointvec_userhz_jiffies - read a vector of integers as 1/USER_HZ seconds | 2683 | * proc_dointvec_userhz_jiffies - read a vector of integers as 1/USER_HZ seconds |
2675 | * @table: the sysctl table | 2684 | * @table: the sysctl table |
2676 | * @write: %TRUE if this is a write to the sysctl file | 2685 | * @write: %TRUE if this is a write to the sysctl file |
2677 | * @filp: the file structure | 2686 | * @filp: the file structure |
2678 | * @buffer: the user buffer | 2687 | * @buffer: the user buffer |
2679 | * @lenp: the size of the user buffer | 2688 | * @lenp: the size of the user buffer |
2680 | * @ppos: pointer to the file position | 2689 | * @ppos: pointer to the file position |
2681 | * | 2690 | * |
2682 | * Reads/writes up to table->maxlen/sizeof(unsigned int) integer | 2691 | * Reads/writes up to table->maxlen/sizeof(unsigned int) integer |
2683 | * values from/to the user buffer, treated as an ASCII string. | 2692 | * values from/to the user buffer, treated as an ASCII string. |
2684 | * The values read are assumed to be in 1/USER_HZ seconds, and | 2693 | * The values read are assumed to be in 1/USER_HZ seconds, and |
2685 | * are converted into jiffies. | 2694 | * are converted into jiffies. |
2686 | * | 2695 | * |
2687 | * Returns 0 on success. | 2696 | * Returns 0 on success. |
2688 | */ | 2697 | */ |
2689 | int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write, struct file *filp, | 2698 | int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write, struct file *filp, |
2690 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2699 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2691 | { | 2700 | { |
2692 | return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, | 2701 | return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, |
2693 | do_proc_dointvec_userhz_jiffies_conv,NULL); | 2702 | do_proc_dointvec_userhz_jiffies_conv,NULL); |
2694 | } | 2703 | } |
2695 | 2704 | ||
2696 | /** | 2705 | /** |
2697 | * proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds | 2706 | * proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds |
2698 | * @table: the sysctl table | 2707 | * @table: the sysctl table |
2699 | * @write: %TRUE if this is a write to the sysctl file | 2708 | * @write: %TRUE if this is a write to the sysctl file |
2700 | * @filp: the file structure | 2709 | * @filp: the file structure |
2701 | * @buffer: the user buffer | 2710 | * @buffer: the user buffer |
2702 | * @lenp: the size of the user buffer | 2711 | * @lenp: the size of the user buffer |
2703 | * @ppos: file position | 2712 | * @ppos: file position |
2704 | * @ppos: the current position in the file | 2713 | * @ppos: the current position in the file |
2705 | * | 2714 | * |
2706 | * Reads/writes up to table->maxlen/sizeof(unsigned int) integer | 2715 | * Reads/writes up to table->maxlen/sizeof(unsigned int) integer |
2707 | * values from/to the user buffer, treated as an ASCII string. | 2716 | * values from/to the user buffer, treated as an ASCII string. |
2708 | * The values read are assumed to be in 1/1000 seconds, and | 2717 | * The values read are assumed to be in 1/1000 seconds, and |
2709 | * are converted into jiffies. | 2718 | * are converted into jiffies. |
2710 | * | 2719 | * |
2711 | * Returns 0 on success. | 2720 | * Returns 0 on success. |
2712 | */ | 2721 | */ |
2713 | int proc_dointvec_ms_jiffies(struct ctl_table *table, int write, struct file *filp, | 2722 | int proc_dointvec_ms_jiffies(struct ctl_table *table, int write, struct file *filp, |
2714 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2723 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2715 | { | 2724 | { |
2716 | return do_proc_dointvec(table, write, filp, buffer, lenp, ppos, | 2725 | return do_proc_dointvec(table, write, filp, buffer, lenp, ppos, |
2717 | do_proc_dointvec_ms_jiffies_conv, NULL); | 2726 | do_proc_dointvec_ms_jiffies_conv, NULL); |
2718 | } | 2727 | } |
2719 | 2728 | ||
2720 | static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp, | 2729 | static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp, |
2721 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2730 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2722 | { | 2731 | { |
2723 | struct pid *new_pid; | 2732 | struct pid *new_pid; |
2724 | pid_t tmp; | 2733 | pid_t tmp; |
2725 | int r; | 2734 | int r; |
2726 | 2735 | ||
2727 | tmp = pid_vnr(cad_pid); | 2736 | tmp = pid_vnr(cad_pid); |
2728 | 2737 | ||
2729 | r = __do_proc_dointvec(&tmp, table, write, filp, buffer, | 2738 | r = __do_proc_dointvec(&tmp, table, write, filp, buffer, |
2730 | lenp, ppos, NULL, NULL); | 2739 | lenp, ppos, NULL, NULL); |
2731 | if (r || !write) | 2740 | if (r || !write) |
2732 | return r; | 2741 | return r; |
2733 | 2742 | ||
2734 | new_pid = find_get_pid(tmp); | 2743 | new_pid = find_get_pid(tmp); |
2735 | if (!new_pid) | 2744 | if (!new_pid) |
2736 | return -ESRCH; | 2745 | return -ESRCH; |
2737 | 2746 | ||
2738 | put_pid(xchg(&cad_pid, new_pid)); | 2747 | put_pid(xchg(&cad_pid, new_pid)); |
2739 | return 0; | 2748 | return 0; |
2740 | } | 2749 | } |
2741 | 2750 | ||
2742 | #else /* CONFIG_PROC_FS */ | 2751 | #else /* CONFIG_PROC_FS */ |
2743 | 2752 | ||
2744 | int proc_dostring(struct ctl_table *table, int write, struct file *filp, | 2753 | int proc_dostring(struct ctl_table *table, int write, struct file *filp, |
2745 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2754 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2746 | { | 2755 | { |
2747 | return -ENOSYS; | 2756 | return -ENOSYS; |
2748 | } | 2757 | } |
2749 | 2758 | ||
2750 | int proc_dointvec(struct ctl_table *table, int write, struct file *filp, | 2759 | int proc_dointvec(struct ctl_table *table, int write, struct file *filp, |
2751 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2760 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2752 | { | 2761 | { |
2753 | return -ENOSYS; | 2762 | return -ENOSYS; |
2754 | } | 2763 | } |
2755 | 2764 | ||
2756 | int proc_dointvec_minmax(struct ctl_table *table, int write, struct file *filp, | 2765 | int proc_dointvec_minmax(struct ctl_table *table, int write, struct file *filp, |
2757 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2766 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2758 | { | 2767 | { |
2759 | return -ENOSYS; | 2768 | return -ENOSYS; |
2760 | } | 2769 | } |
2761 | 2770 | ||
2762 | int proc_dointvec_jiffies(struct ctl_table *table, int write, struct file *filp, | 2771 | int proc_dointvec_jiffies(struct ctl_table *table, int write, struct file *filp, |
2763 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2772 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2764 | { | 2773 | { |
2765 | return -ENOSYS; | 2774 | return -ENOSYS; |
2766 | } | 2775 | } |
2767 | 2776 | ||
2768 | int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write, struct file *filp, | 2777 | int proc_dointvec_userhz_jiffies(struct ctl_table *table, int write, struct file *filp, |
2769 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2778 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2770 | { | 2779 | { |
2771 | return -ENOSYS; | 2780 | return -ENOSYS; |
2772 | } | 2781 | } |
2773 | 2782 | ||
2774 | int proc_dointvec_ms_jiffies(struct ctl_table *table, int write, struct file *filp, | 2783 | int proc_dointvec_ms_jiffies(struct ctl_table *table, int write, struct file *filp, |
2775 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2784 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2776 | { | 2785 | { |
2777 | return -ENOSYS; | 2786 | return -ENOSYS; |
2778 | } | 2787 | } |
2779 | 2788 | ||
2780 | int proc_doulongvec_minmax(struct ctl_table *table, int write, struct file *filp, | 2789 | int proc_doulongvec_minmax(struct ctl_table *table, int write, struct file *filp, |
2781 | void __user *buffer, size_t *lenp, loff_t *ppos) | 2790 | void __user *buffer, size_t *lenp, loff_t *ppos) |
2782 | { | 2791 | { |
2783 | return -ENOSYS; | 2792 | return -ENOSYS; |
2784 | } | 2793 | } |
2785 | 2794 | ||
2786 | int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write, | 2795 | int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int write, |
2787 | struct file *filp, | 2796 | struct file *filp, |
2788 | void __user *buffer, | 2797 | void __user *buffer, |
2789 | size_t *lenp, loff_t *ppos) | 2798 | size_t *lenp, loff_t *ppos) |
2790 | { | 2799 | { |
2791 | return -ENOSYS; | 2800 | return -ENOSYS; |
2792 | } | 2801 | } |
2793 | 2802 | ||
2794 | 2803 | ||
2795 | #endif /* CONFIG_PROC_FS */ | 2804 | #endif /* CONFIG_PROC_FS */ |
2796 | 2805 | ||
2797 | 2806 | ||
2798 | #ifdef CONFIG_SYSCTL_SYSCALL | 2807 | #ifdef CONFIG_SYSCTL_SYSCALL |
2799 | /* | 2808 | /* |
2800 | * General sysctl support routines | 2809 | * General sysctl support routines |
2801 | */ | 2810 | */ |
2802 | 2811 | ||
2803 | /* The generic sysctl data routine (used if no strategy routine supplied) */ | 2812 | /* The generic sysctl data routine (used if no strategy routine supplied) */ |
2804 | int sysctl_data(struct ctl_table *table, | 2813 | int sysctl_data(struct ctl_table *table, |
2805 | void __user *oldval, size_t __user *oldlenp, | 2814 | void __user *oldval, size_t __user *oldlenp, |
2806 | void __user *newval, size_t newlen) | 2815 | void __user *newval, size_t newlen) |
2807 | { | 2816 | { |
2808 | size_t len; | 2817 | size_t len; |
2809 | 2818 | ||
2810 | /* Get out of I don't have a variable */ | 2819 | /* Get out of I don't have a variable */ |
2811 | if (!table->data || !table->maxlen) | 2820 | if (!table->data || !table->maxlen) |
2812 | return -ENOTDIR; | 2821 | return -ENOTDIR; |
2813 | 2822 | ||
2814 | if (oldval && oldlenp) { | 2823 | if (oldval && oldlenp) { |
2815 | if (get_user(len, oldlenp)) | 2824 | if (get_user(len, oldlenp)) |
2816 | return -EFAULT; | 2825 | return -EFAULT; |
2817 | if (len) { | 2826 | if (len) { |
2818 | if (len > table->maxlen) | 2827 | if (len > table->maxlen) |
2819 | len = table->maxlen; | 2828 | len = table->maxlen; |
2820 | if (copy_to_user(oldval, table->data, len)) | 2829 | if (copy_to_user(oldval, table->data, len)) |
2821 | return -EFAULT; | 2830 | return -EFAULT; |
2822 | if (put_user(len, oldlenp)) | 2831 | if (put_user(len, oldlenp)) |
2823 | return -EFAULT; | 2832 | return -EFAULT; |
2824 | } | 2833 | } |
2825 | } | 2834 | } |
2826 | 2835 | ||
2827 | if (newval && newlen) { | 2836 | if (newval && newlen) { |
2828 | if (newlen > table->maxlen) | 2837 | if (newlen > table->maxlen) |
2829 | newlen = table->maxlen; | 2838 | newlen = table->maxlen; |
2830 | 2839 | ||
2831 | if (copy_from_user(table->data, newval, newlen)) | 2840 | if (copy_from_user(table->data, newval, newlen)) |
2832 | return -EFAULT; | 2841 | return -EFAULT; |
2833 | } | 2842 | } |
2834 | return 1; | 2843 | return 1; |
2835 | } | 2844 | } |
2836 | 2845 | ||
2837 | /* The generic string strategy routine: */ | 2846 | /* The generic string strategy routine: */ |
2838 | int sysctl_string(struct ctl_table *table, | 2847 | int sysctl_string(struct ctl_table *table, |
2839 | void __user *oldval, size_t __user *oldlenp, | 2848 | void __user *oldval, size_t __user *oldlenp, |
2840 | void __user *newval, size_t newlen) | 2849 | void __user *newval, size_t newlen) |
2841 | { | 2850 | { |
2842 | if (!table->data || !table->maxlen) | 2851 | if (!table->data || !table->maxlen) |
2843 | return -ENOTDIR; | 2852 | return -ENOTDIR; |
2844 | 2853 | ||
2845 | if (oldval && oldlenp) { | 2854 | if (oldval && oldlenp) { |
2846 | size_t bufsize; | 2855 | size_t bufsize; |
2847 | if (get_user(bufsize, oldlenp)) | 2856 | if (get_user(bufsize, oldlenp)) |
2848 | return -EFAULT; | 2857 | return -EFAULT; |
2849 | if (bufsize) { | 2858 | if (bufsize) { |
2850 | size_t len = strlen(table->data), copied; | 2859 | size_t len = strlen(table->data), copied; |
2851 | 2860 | ||
2852 | /* This shouldn't trigger for a well-formed sysctl */ | 2861 | /* This shouldn't trigger for a well-formed sysctl */ |
2853 | if (len > table->maxlen) | 2862 | if (len > table->maxlen) |
2854 | len = table->maxlen; | 2863 | len = table->maxlen; |
2855 | 2864 | ||
2856 | /* Copy up to a max of bufsize-1 bytes of the string */ | 2865 | /* Copy up to a max of bufsize-1 bytes of the string */ |
2857 | copied = (len >= bufsize) ? bufsize - 1 : len; | 2866 | copied = (len >= bufsize) ? bufsize - 1 : len; |
2858 | 2867 | ||
2859 | if (copy_to_user(oldval, table->data, copied) || | 2868 | if (copy_to_user(oldval, table->data, copied) || |
2860 | put_user(0, (char __user *)(oldval + copied))) | 2869 | put_user(0, (char __user *)(oldval + copied))) |
2861 | return -EFAULT; | 2870 | return -EFAULT; |
2862 | if (put_user(len, oldlenp)) | 2871 | if (put_user(len, oldlenp)) |
2863 | return -EFAULT; | 2872 | return -EFAULT; |
2864 | } | 2873 | } |
2865 | } | 2874 | } |
2866 | if (newval && newlen) { | 2875 | if (newval && newlen) { |
2867 | size_t len = newlen; | 2876 | size_t len = newlen; |
2868 | if (len > table->maxlen) | 2877 | if (len > table->maxlen) |
2869 | len = table->maxlen; | 2878 | len = table->maxlen; |
2870 | if(copy_from_user(table->data, newval, len)) | 2879 | if(copy_from_user(table->data, newval, len)) |
2871 | return -EFAULT; | 2880 | return -EFAULT; |
2872 | if (len == table->maxlen) | 2881 | if (len == table->maxlen) |
2873 | len--; | 2882 | len--; |
2874 | ((char *) table->data)[len] = 0; | 2883 | ((char *) table->data)[len] = 0; |
2875 | } | 2884 | } |
2876 | return 1; | 2885 | return 1; |
2877 | } | 2886 | } |
2878 | 2887 | ||
2879 | /* | 2888 | /* |
2880 | * This function makes sure that all of the integers in the vector | 2889 | * This function makes sure that all of the integers in the vector |
2881 | * are between the minimum and maximum values given in the arrays | 2890 | * are between the minimum and maximum values given in the arrays |
2882 | * table->extra1 and table->extra2, respectively. | 2891 | * table->extra1 and table->extra2, respectively. |
2883 | */ | 2892 | */ |
2884 | int sysctl_intvec(struct ctl_table *table, | 2893 | int sysctl_intvec(struct ctl_table *table, |
2885 | void __user *oldval, size_t __user *oldlenp, | 2894 | void __user *oldval, size_t __user *oldlenp, |
2886 | void __user *newval, size_t newlen) | 2895 | void __user *newval, size_t newlen) |
2887 | { | 2896 | { |
2888 | 2897 | ||
2889 | if (newval && newlen) { | 2898 | if (newval && newlen) { |
2890 | int __user *vec = (int __user *) newval; | 2899 | int __user *vec = (int __user *) newval; |
2891 | int *min = (int *) table->extra1; | 2900 | int *min = (int *) table->extra1; |
2892 | int *max = (int *) table->extra2; | 2901 | int *max = (int *) table->extra2; |
2893 | size_t length; | 2902 | size_t length; |
2894 | int i; | 2903 | int i; |
2895 | 2904 | ||
2896 | if (newlen % sizeof(int) != 0) | 2905 | if (newlen % sizeof(int) != 0) |
2897 | return -EINVAL; | 2906 | return -EINVAL; |
2898 | 2907 | ||
2899 | if (!table->extra1 && !table->extra2) | 2908 | if (!table->extra1 && !table->extra2) |
2900 | return 0; | 2909 | return 0; |
2901 | 2910 | ||
2902 | if (newlen > table->maxlen) | 2911 | if (newlen > table->maxlen) |
2903 | newlen = table->maxlen; | 2912 | newlen = table->maxlen; |
2904 | length = newlen / sizeof(int); | 2913 | length = newlen / sizeof(int); |
2905 | 2914 | ||
2906 | for (i = 0; i < length; i++) { | 2915 | for (i = 0; i < length; i++) { |
2907 | int value; | 2916 | int value; |
2908 | if (get_user(value, vec + i)) | 2917 | if (get_user(value, vec + i)) |
2909 | return -EFAULT; | 2918 | return -EFAULT; |
2910 | if (min && value < min[i]) | 2919 | if (min && value < min[i]) |
2911 | return -EINVAL; | 2920 | return -EINVAL; |
2912 | if (max && value > max[i]) | 2921 | if (max && value > max[i]) |
2913 | return -EINVAL; | 2922 | return -EINVAL; |
2914 | } | 2923 | } |
2915 | } | 2924 | } |
2916 | return 0; | 2925 | return 0; |
2917 | } | 2926 | } |
2918 | 2927 | ||
2919 | /* Strategy function to convert jiffies to seconds */ | 2928 | /* Strategy function to convert jiffies to seconds */ |
2920 | int sysctl_jiffies(struct ctl_table *table, | 2929 | int sysctl_jiffies(struct ctl_table *table, |
2921 | void __user *oldval, size_t __user *oldlenp, | 2930 | void __user *oldval, size_t __user *oldlenp, |
2922 | void __user *newval, size_t newlen) | 2931 | void __user *newval, size_t newlen) |
2923 | { | 2932 | { |
2924 | if (oldval && oldlenp) { | 2933 | if (oldval && oldlenp) { |
2925 | size_t olen; | 2934 | size_t olen; |
2926 | 2935 | ||
2927 | if (get_user(olen, oldlenp)) | 2936 | if (get_user(olen, oldlenp)) |
2928 | return -EFAULT; | 2937 | return -EFAULT; |
2929 | if (olen) { | 2938 | if (olen) { |
2930 | int val; | 2939 | int val; |
2931 | 2940 | ||
2932 | if (olen < sizeof(int)) | 2941 | if (olen < sizeof(int)) |
2933 | return -EINVAL; | 2942 | return -EINVAL; |
2934 | 2943 | ||
2935 | val = *(int *)(table->data) / HZ; | 2944 | val = *(int *)(table->data) / HZ; |
2936 | if (put_user(val, (int __user *)oldval)) | 2945 | if (put_user(val, (int __user *)oldval)) |
2937 | return -EFAULT; | 2946 | return -EFAULT; |
2938 | if (put_user(sizeof(int), oldlenp)) | 2947 | if (put_user(sizeof(int), oldlenp)) |
2939 | return -EFAULT; | 2948 | return -EFAULT; |
2940 | } | 2949 | } |
2941 | } | 2950 | } |
2942 | if (newval && newlen) { | 2951 | if (newval && newlen) { |
2943 | int new; | 2952 | int new; |
2944 | if (newlen != sizeof(int)) | 2953 | if (newlen != sizeof(int)) |
2945 | return -EINVAL; | 2954 | return -EINVAL; |
2946 | if (get_user(new, (int __user *)newval)) | 2955 | if (get_user(new, (int __user *)newval)) |
2947 | return -EFAULT; | 2956 | return -EFAULT; |
2948 | *(int *)(table->data) = new*HZ; | 2957 | *(int *)(table->data) = new*HZ; |
2949 | } | 2958 | } |
2950 | return 1; | 2959 | return 1; |
2951 | } | 2960 | } |
2952 | 2961 | ||
2953 | /* Strategy function to convert jiffies to seconds */ | 2962 | /* Strategy function to convert jiffies to seconds */ |
2954 | int sysctl_ms_jiffies(struct ctl_table *table, | 2963 | int sysctl_ms_jiffies(struct ctl_table *table, |
2955 | void __user *oldval, size_t __user *oldlenp, | 2964 | void __user *oldval, size_t __user *oldlenp, |
2956 | void __user *newval, size_t newlen) | 2965 | void __user *newval, size_t newlen) |
2957 | { | 2966 | { |
2958 | if (oldval && oldlenp) { | 2967 | if (oldval && oldlenp) { |
2959 | size_t olen; | 2968 | size_t olen; |
2960 | 2969 | ||
2961 | if (get_user(olen, oldlenp)) | 2970 | if (get_user(olen, oldlenp)) |
2962 | return -EFAULT; | 2971 | return -EFAULT; |
2963 | if (olen) { | 2972 | if (olen) { |
2964 | int val; | 2973 | int val; |
2965 | 2974 | ||
2966 | if (olen < sizeof(int)) | 2975 | if (olen < sizeof(int)) |
2967 | return -EINVAL; | 2976 | return -EINVAL; |
2968 | 2977 | ||
2969 | val = jiffies_to_msecs(*(int *)(table->data)); | 2978 | val = jiffies_to_msecs(*(int *)(table->data)); |
2970 | if (put_user(val, (int __user *)oldval)) | 2979 | if (put_user(val, (int __user *)oldval)) |
2971 | return -EFAULT; | 2980 | return -EFAULT; |
2972 | if (put_user(sizeof(int), oldlenp)) | 2981 | if (put_user(sizeof(int), oldlenp)) |
2973 | return -EFAULT; | 2982 | return -EFAULT; |
2974 | } | 2983 | } |
2975 | } | 2984 | } |
2976 | if (newval && newlen) { | 2985 | if (newval && newlen) { |
2977 | int new; | 2986 | int new; |
2978 | if (newlen != sizeof(int)) | 2987 | if (newlen != sizeof(int)) |
2979 | return -EINVAL; | 2988 | return -EINVAL; |
2980 | if (get_user(new, (int __user *)newval)) | 2989 | if (get_user(new, (int __user *)newval)) |
2981 | return -EFAULT; | 2990 | return -EFAULT; |
2982 | *(int *)(table->data) = msecs_to_jiffies(new); | 2991 | *(int *)(table->data) = msecs_to_jiffies(new); |
2983 | } | 2992 | } |
2984 | return 1; | 2993 | return 1; |
2985 | } | 2994 | } |
2986 | 2995 | ||
2987 | 2996 | ||
2988 | 2997 | ||
2989 | #else /* CONFIG_SYSCTL_SYSCALL */ | 2998 | #else /* CONFIG_SYSCTL_SYSCALL */ |
2990 | 2999 | ||
2991 | 3000 | ||
2992 | SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args) | 3001 | SYSCALL_DEFINE1(sysctl, struct __sysctl_args __user *, args) |
2993 | { | 3002 | { |
2994 | struct __sysctl_args tmp; | 3003 | struct __sysctl_args tmp; |
2995 | int error; | 3004 | int error; |
2996 | 3005 | ||
2997 | if (copy_from_user(&tmp, args, sizeof(tmp))) | 3006 | if (copy_from_user(&tmp, args, sizeof(tmp))) |
2998 | return -EFAULT; | 3007 | return -EFAULT; |
2999 | 3008 | ||
3000 | error = deprecated_sysctl_warning(&tmp); | 3009 | error = deprecated_sysctl_warning(&tmp); |
3001 | 3010 | ||
3002 | /* If no error reading the parameters then just -ENOSYS ... */ | 3011 | /* If no error reading the parameters then just -ENOSYS ... */ |
3003 | if (!error) | 3012 | if (!error) |
3004 | error = -ENOSYS; | 3013 | error = -ENOSYS; |
3005 | 3014 | ||
3006 | return error; | 3015 | return error; |
3007 | } | 3016 | } |
3008 | 3017 | ||
3009 | int sysctl_data(struct ctl_table *table, | 3018 | int sysctl_data(struct ctl_table *table, |
3010 | void __user *oldval, size_t __user *oldlenp, | 3019 | void __user *oldval, size_t __user *oldlenp, |
3011 | void __user *newval, size_t newlen) | 3020 | void __user *newval, size_t newlen) |
3012 | { | 3021 | { |
3013 | return -ENOSYS; | 3022 | return -ENOSYS; |
3014 | } | 3023 | } |
3015 | 3024 | ||
3016 | int sysctl_string(struct ctl_table *table, | 3025 | int sysctl_string(struct ctl_table *table, |
3017 | void __user *oldval, size_t __user *oldlenp, | 3026 | void __user *oldval, size_t __user *oldlenp, |
3018 | void __user *newval, size_t newlen) | 3027 | void __user *newval, size_t newlen) |
3019 | { | 3028 | { |
3020 | return -ENOSYS; | 3029 | return -ENOSYS; |
3021 | } | 3030 | } |
3022 | 3031 | ||
3023 | int sysctl_intvec(struct ctl_table *table, | 3032 | int sysctl_intvec(struct ctl_table *table, |
3024 | void __user *oldval, size_t __user *oldlenp, | 3033 | void __user *oldval, size_t __user *oldlenp, |
3025 | void __user *newval, size_t newlen) | 3034 | void __user *newval, size_t newlen) |
3026 | { | 3035 | { |
3027 | return -ENOSYS; | 3036 | return -ENOSYS; |
3028 | } | 3037 | } |
3029 | 3038 | ||
3030 | int sysctl_jiffies(struct ctl_table *table, | 3039 | int sysctl_jiffies(struct ctl_table *table, |
3031 | void __user *oldval, size_t __user *oldlenp, | 3040 | void __user *oldval, size_t __user *oldlenp, |
3032 | void __user *newval, size_t newlen) | 3041 | void __user *newval, size_t newlen) |
3033 | { | 3042 | { |
3034 | return -ENOSYS; | 3043 | return -ENOSYS; |
3035 | } | 3044 | } |
3036 | 3045 | ||
3037 | int sysctl_ms_jiffies(struct ctl_table *table, | 3046 | int sysctl_ms_jiffies(struct ctl_table *table, |
3038 | void __user *oldval, size_t __user *oldlenp, | 3047 | void __user *oldval, size_t __user *oldlenp, |
3039 | void __user *newval, size_t newlen) | 3048 | void __user *newval, size_t newlen) |
3040 | { | 3049 | { |
3041 | return -ENOSYS; | 3050 | return -ENOSYS; |
3042 | } | 3051 | } |
3043 | 3052 | ||
3044 | #endif /* CONFIG_SYSCTL_SYSCALL */ | 3053 | #endif /* CONFIG_SYSCTL_SYSCALL */ |
3045 | 3054 | ||
3046 | static int deprecated_sysctl_warning(struct __sysctl_args *args) | 3055 | static int deprecated_sysctl_warning(struct __sysctl_args *args) |
3047 | { | 3056 | { |
3048 | static int msg_count; | 3057 | static int msg_count; |
3049 | int name[CTL_MAXNAME]; | 3058 | int name[CTL_MAXNAME]; |
3050 | int i; | 3059 | int i; |
3051 | 3060 | ||
3052 | /* Check args->nlen. */ | 3061 | /* Check args->nlen. */ |
3053 | if (args->nlen < 0 || args->nlen > CTL_MAXNAME) | 3062 | if (args->nlen < 0 || args->nlen > CTL_MAXNAME) |
3054 | return -ENOTDIR; | 3063 | return -ENOTDIR; |
3055 | 3064 | ||
3056 | /* Read in the sysctl name for better debug message logging */ | 3065 | /* Read in the sysctl name for better debug message logging */ |
3057 | for (i = 0; i < args->nlen; i++) | 3066 | for (i = 0; i < args->nlen; i++) |
3058 | if (get_user(name[i], args->name + i)) | 3067 | if (get_user(name[i], args->name + i)) |
3059 | return -EFAULT; | 3068 | return -EFAULT; |
3060 | 3069 | ||
3061 | /* Ignore accesses to kernel.version */ | 3070 | /* Ignore accesses to kernel.version */ |
3062 | if ((args->nlen == 2) && (name[0] == CTL_KERN) && (name[1] == KERN_VERSION)) | 3071 | if ((args->nlen == 2) && (name[0] == CTL_KERN) && (name[1] == KERN_VERSION)) |
3063 | return 0; | 3072 | return 0; |
3064 | 3073 | ||
3065 | if (msg_count < 5) { | 3074 | if (msg_count < 5) { |
3066 | msg_count++; | 3075 | msg_count++; |
3067 | printk(KERN_INFO | 3076 | printk(KERN_INFO |
3068 | "warning: process `%s' used the deprecated sysctl " | 3077 | "warning: process `%s' used the deprecated sysctl " |
3069 | "system call with ", current->comm); | 3078 | "system call with ", current->comm); |
3070 | for (i = 0; i < args->nlen; i++) | 3079 | for (i = 0; i < args->nlen; i++) |
3071 | printk("%d.", name[i]); | 3080 | printk("%d.", name[i]); |
3072 | printk("\n"); | 3081 | printk("\n"); |
3073 | } | 3082 | } |
3074 | return 0; | 3083 | return 0; |
3075 | } | 3084 | } |
3076 | 3085 | ||
3077 | /* | 3086 | /* |
3078 | * No sense putting this after each symbol definition, twice, | 3087 | * No sense putting this after each symbol definition, twice, |
3079 | * exception granted :-) | 3088 | * exception granted :-) |
3080 | */ | 3089 | */ |
3081 | EXPORT_SYMBOL(proc_dointvec); | 3090 | EXPORT_SYMBOL(proc_dointvec); |
3082 | EXPORT_SYMBOL(proc_dointvec_jiffies); | 3091 | EXPORT_SYMBOL(proc_dointvec_jiffies); |
3083 | EXPORT_SYMBOL(proc_dointvec_minmax); | 3092 | EXPORT_SYMBOL(proc_dointvec_minmax); |
3084 | EXPORT_SYMBOL(proc_dointvec_userhz_jiffies); | 3093 | EXPORT_SYMBOL(proc_dointvec_userhz_jiffies); |
3085 | EXPORT_SYMBOL(proc_dointvec_ms_jiffies); | 3094 | EXPORT_SYMBOL(proc_dointvec_ms_jiffies); |
3086 | EXPORT_SYMBOL(proc_dostring); | 3095 | EXPORT_SYMBOL(proc_dostring); |
3087 | EXPORT_SYMBOL(proc_doulongvec_minmax); | 3096 | EXPORT_SYMBOL(proc_doulongvec_minmax); |
3088 | EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax); | 3097 | EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax); |
3089 | EXPORT_SYMBOL(register_sysctl_table); | 3098 | EXPORT_SYMBOL(register_sysctl_table); |
3090 | EXPORT_SYMBOL(register_sysctl_paths); | 3099 | EXPORT_SYMBOL(register_sysctl_paths); |
3091 | EXPORT_SYMBOL(sysctl_intvec); | 3100 | EXPORT_SYMBOL(sysctl_intvec); |
3092 | EXPORT_SYMBOL(sysctl_jiffies); | 3101 | EXPORT_SYMBOL(sysctl_jiffies); |
3093 | EXPORT_SYMBOL(sysctl_ms_jiffies); | 3102 | EXPORT_SYMBOL(sysctl_ms_jiffies); |
3094 | EXPORT_SYMBOL(sysctl_string); | 3103 | EXPORT_SYMBOL(sysctl_string); |
3095 | EXPORT_SYMBOL(sysctl_data); | 3104 | EXPORT_SYMBOL(sysctl_data); |
3096 | EXPORT_SYMBOL(unregister_sysctl_table); | 3105 | EXPORT_SYMBOL(unregister_sysctl_table); |
3097 | 3106 |