aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-12-15 14:33:22 -0500
committerIngo Molnar <mingo@elte.hu>2009-12-15 14:33:28 -0500
commitab1eebe77dd08b26585860d534e07810d1cd274d (patch)
tree92b1ff0952cbdeef34922c43ff7eaac2162e77c4 /arch/x86/kernel
parent186a25026c44d1bfa97671110ff14dcd0c99678e (diff)
parentdf59e7bf439918f523ac29e996ec1eebbed60440 (diff)
Merge branch 'x86/asm' into x86/urgent
Merge reason: it's stable so lets push it upstream. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/entry_32.S69
-rw-r--r--arch/x86/kernel/entry_64.S49
-rw-r--r--arch/x86/kernel/ioport.c28
-rw-r--r--arch/x86/kernel/process.c70
-rw-r--r--arch/x86/kernel/process_32.c73
-rw-r--r--arch/x86/kernel/process_64.c35
-rw-r--r--arch/x86/kernel/signal.c12
-rw-r--r--arch/x86/kernel/vm86_32.c11
-rw-r--r--arch/x86/kernel/x8664_ksyms_64.c2
9 files changed, 138 insertions, 211 deletions
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 50b9c220e12..44a8e0dc673 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -725,22 +725,61 @@ END(syscall_badsys)
725/* 725/*
726 * System calls that need a pt_regs pointer. 726 * System calls that need a pt_regs pointer.
727 */ 727 */
728#define PTREGSCALL(name) \ 728#define PTREGSCALL0(name) \
729 ALIGN; \ 729 ALIGN; \
730ptregs_##name: \ 730ptregs_##name: \
731 leal 4(%esp),%eax; \ 731 leal 4(%esp),%eax; \
732 jmp sys_##name; 732 jmp sys_##name;
733 733
734PTREGSCALL(iopl) 734#define PTREGSCALL1(name) \
735PTREGSCALL(fork) 735 ALIGN; \
736PTREGSCALL(clone) 736ptregs_##name: \
737PTREGSCALL(vfork) 737 leal 4(%esp),%edx; \
738PTREGSCALL(execve) 738 movl (PT_EBX+4)(%esp),%eax; \
739PTREGSCALL(sigaltstack) 739 jmp sys_##name;
740PTREGSCALL(sigreturn) 740
741PTREGSCALL(rt_sigreturn) 741#define PTREGSCALL2(name) \
742PTREGSCALL(vm86) 742 ALIGN; \
743PTREGSCALL(vm86old) 743ptregs_##name: \
744 leal 4(%esp),%ecx; \
745 movl (PT_ECX+4)(%esp),%edx; \
746 movl (PT_EBX+4)(%esp),%eax; \
747 jmp sys_##name;
748
749#define PTREGSCALL3(name) \
750 ALIGN; \
751ptregs_##name: \
752 leal 4(%esp),%eax; \
753 pushl %eax; \
754 movl PT_EDX(%eax),%ecx; \
755 movl PT_ECX(%eax),%edx; \
756 movl PT_EBX(%eax),%eax; \
757 call sys_##name; \
758 addl $4,%esp; \
759 ret
760
761PTREGSCALL1(iopl)
762PTREGSCALL0(fork)
763PTREGSCALL0(vfork)
764PTREGSCALL3(execve)
765PTREGSCALL2(sigaltstack)
766PTREGSCALL0(sigreturn)
767PTREGSCALL0(rt_sigreturn)
768PTREGSCALL2(vm86)
769PTREGSCALL1(vm86old)
770
771/* Clone is an oddball. The 4th arg is in %edi */
772 ALIGN;
773ptregs_clone:
774 leal 4(%esp),%eax
775 pushl %eax
776 pushl PT_EDI(%eax)
777 movl PT_EDX(%eax),%ecx
778 movl PT_ECX(%eax),%edx
779 movl PT_EBX(%eax),%eax
780 call sys_clone
781 addl $8,%esp
782 ret
744 783
745.macro FIXUP_ESPFIX_STACK 784.macro FIXUP_ESPFIX_STACK
746/* 785/*
@@ -1008,12 +1047,8 @@ END(spurious_interrupt_bug)
1008ENTRY(kernel_thread_helper) 1047ENTRY(kernel_thread_helper)
1009 pushl $0 # fake return address for unwinder 1048 pushl $0 # fake return address for unwinder
1010 CFI_STARTPROC 1049 CFI_STARTPROC
1011 movl %edx,%eax 1050 movl %edi,%eax
1012 push %edx 1051 call *%esi
1013 CFI_ADJUST_CFA_OFFSET 4
1014 call *%ebx
1015 push %eax
1016 CFI_ADJUST_CFA_OFFSET 4
1017 call do_exit 1052 call do_exit
1018 ud2 # padding for call trace 1053 ud2 # padding for call trace
1019 CFI_ENDPROC 1054 CFI_ENDPROC
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 63bca794c8f..73d9b2c0e21 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1166,63 +1166,20 @@ bad_gs:
1166 jmp 2b 1166 jmp 2b
1167 .previous 1167 .previous
1168 1168
1169/* 1169ENTRY(kernel_thread_helper)
1170 * Create a kernel thread.
1171 *
1172 * C extern interface:
1173 * extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
1174 *
1175 * asm input arguments:
1176 * rdi: fn, rsi: arg, rdx: flags
1177 */
1178ENTRY(kernel_thread)
1179 CFI_STARTPROC
1180 FAKE_STACK_FRAME $child_rip
1181 SAVE_ALL
1182
1183 # rdi: flags, rsi: usp, rdx: will be &pt_regs
1184 movq %rdx,%rdi
1185 orq kernel_thread_flags(%rip),%rdi
1186 movq $-1, %rsi
1187 movq %rsp, %rdx
1188
1189 xorl %r8d,%r8d
1190 xorl %r9d,%r9d
1191
1192 # clone now
1193 call do_fork
1194 movq %rax,RAX(%rsp)
1195 xorl %edi,%edi
1196
1197 /*
1198 * It isn't worth to check for reschedule here,
1199 * so internally to the x86_64 port you can rely on kernel_thread()
1200 * not to reschedule the child before returning, this avoids the need
1201 * of hacks for example to fork off the per-CPU idle tasks.
1202 * [Hopefully no generic code relies on the reschedule -AK]
1203 */
1204 RESTORE_ALL
1205 UNFAKE_STACK_FRAME
1206 ret
1207 CFI_ENDPROC
1208END(kernel_thread)
1209
1210ENTRY(child_rip)
1211 pushq $0 # fake return address 1170 pushq $0 # fake return address
1212 CFI_STARTPROC 1171 CFI_STARTPROC
1213 /* 1172 /*
1214 * Here we are in the child and the registers are set as they were 1173 * Here we are in the child and the registers are set as they were
1215 * at kernel_thread() invocation in the parent. 1174 * at kernel_thread() invocation in the parent.
1216 */ 1175 */
1217 movq %rdi, %rax 1176 call *%rsi
1218 movq %rsi, %rdi
1219 call *%rax
1220 # exit 1177 # exit
1221 mov %eax, %edi 1178 mov %eax, %edi
1222 call do_exit 1179 call do_exit
1223 ud2 # padding for call trace 1180 ud2 # padding for call trace
1224 CFI_ENDPROC 1181 CFI_ENDPROC
1225END(child_rip) 1182END(kernel_thread_helper)
1226 1183
1227/* 1184/*
1228 * execve(). This function needs to use IRET, not SYSRET, to set up all state properly. 1185 * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c
index 99c4d308f16..8eec0ec59af 100644
--- a/arch/x86/kernel/ioport.c
+++ b/arch/x86/kernel/ioport.c
@@ -103,9 +103,10 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
103 * on system-call entry - see also fork() and the signal handling 103 * on system-call entry - see also fork() and the signal handling
104 * code. 104 * code.
105 */ 105 */
106static int do_iopl(unsigned int level, struct pt_regs *regs) 106long sys_iopl(unsigned int level, struct pt_regs *regs)
107{ 107{
108 unsigned int old = (regs->flags >> 12) & 3; 108 unsigned int old = (regs->flags >> 12) & 3;
109 struct thread_struct *t = &current->thread;
109 110
110 if (level > 3) 111 if (level > 3)
111 return -EINVAL; 112 return -EINVAL;
@@ -115,29 +116,8 @@ static int do_iopl(unsigned int level, struct pt_regs *regs)
115 return -EPERM; 116 return -EPERM;
116 } 117 }
117 regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); 118 regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12);
118
119 return 0;
120}
121
122#ifdef CONFIG_X86_32
123long sys_iopl(struct pt_regs *regs)
124{
125 unsigned int level = regs->bx;
126 struct thread_struct *t = &current->thread;
127 int rc;
128
129 rc = do_iopl(level, regs);
130 if (rc < 0)
131 goto out;
132
133 t->iopl = level << 12; 119 t->iopl = level << 12;
134 set_iopl_mask(t->iopl); 120 set_iopl_mask(t->iopl);
135out: 121
136 return rc; 122 return 0;
137}
138#else
139asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs)
140{
141 return do_iopl(level, regs);
142} 123}
143#endif
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 7a7bd4e3ec4..98c2cdeb599 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -255,6 +255,76 @@ int sys_vfork(struct pt_regs *regs)
255 NULL, NULL); 255 NULL, NULL);
256} 256}
257 257
258long
259sys_clone(unsigned long clone_flags, unsigned long newsp,
260 void __user *parent_tid, void __user *child_tid, struct pt_regs *regs)
261{
262 if (!newsp)
263 newsp = regs->sp;
264 return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
265}
266
267/*
268 * This gets run with %si containing the
269 * function to call, and %di containing
270 * the "args".
271 */
272extern void kernel_thread_helper(void);
273
274/*
275 * Create a kernel thread
276 */
277int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
278{
279 struct pt_regs regs;
280
281 memset(&regs, 0, sizeof(regs));
282
283 regs.si = (unsigned long) fn;
284 regs.di = (unsigned long) arg;
285
286#ifdef CONFIG_X86_32
287 regs.ds = __USER_DS;
288 regs.es = __USER_DS;
289 regs.fs = __KERNEL_PERCPU;
290 regs.gs = __KERNEL_STACK_CANARY;
291#endif
292
293 regs.orig_ax = -1;
294 regs.ip = (unsigned long) kernel_thread_helper;
295 regs.cs = __KERNEL_CS | get_kernel_rpl();
296 regs.flags = X86_EFLAGS_IF | 0x2;
297
298 /* Ok, create the new process.. */
299 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
300}
301EXPORT_SYMBOL(kernel_thread);
302
303/*
304 * sys_execve() executes a new program.
305 */
306long sys_execve(char __user *name, char __user * __user *argv,
307 char __user * __user *envp, struct pt_regs *regs)
308{
309 long error;
310 char *filename;
311
312 filename = getname(name);
313 error = PTR_ERR(filename);
314 if (IS_ERR(filename))
315 return error;
316 error = do_execve(filename, argv, envp, regs);
317
318#ifdef CONFIG_X86_32
319 if (error == 0) {
320 /* Make sure we don't return using sysenter.. */
321 set_thread_flag(TIF_IRET);
322 }
323#endif
324
325 putname(filename);
326 return error;
327}
258 328
259/* 329/*
260 * Idle related variables and functions 330 * Idle related variables and functions
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 120b88797a7..9c517b5858f 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -180,39 +180,6 @@ void show_regs(struct pt_regs *regs)
180 show_trace(NULL, regs, &regs->sp, regs->bp); 180 show_trace(NULL, regs, &regs->sp, regs->bp);
181} 181}
182 182
183/*
184 * This gets run with %bx containing the
185 * function to call, and %dx containing
186 * the "args".
187 */
188extern void kernel_thread_helper(void);
189
190/*
191 * Create a kernel thread
192 */
193int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
194{
195 struct pt_regs regs;
196
197 memset(&regs, 0, sizeof(regs));
198
199 regs.bx = (unsigned long) fn;
200 regs.dx = (unsigned long) arg;
201
202 regs.ds = __USER_DS;
203 regs.es = __USER_DS;
204 regs.fs = __KERNEL_PERCPU;
205 regs.gs = __KERNEL_STACK_CANARY;
206 regs.orig_ax = -1;
207 regs.ip = (unsigned long) kernel_thread_helper;
208 regs.cs = __KERNEL_CS | get_kernel_rpl();
209 regs.flags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
210
211 /* Ok, create the new process.. */
212 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
213}
214EXPORT_SYMBOL(kernel_thread);
215
216void release_thread(struct task_struct *dead_task) 183void release_thread(struct task_struct *dead_task)
217{ 184{
218 BUG_ON(dead_task->mm); 185 BUG_ON(dead_task->mm);
@@ -424,46 +391,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
424 return prev_p; 391 return prev_p;
425} 392}
426 393
427int sys_clone(struct pt_regs *regs)
428{
429 unsigned long clone_flags;
430 unsigned long newsp;
431 int __user *parent_tidptr, *child_tidptr;
432
433 clone_flags = regs->bx;
434 newsp = regs->cx;
435 parent_tidptr = (int __user *)regs->dx;
436 child_tidptr = (int __user *)regs->di;
437 if (!newsp)
438 newsp = regs->sp;
439 return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
440}
441
442/*
443 * sys_execve() executes a new program.
444 */
445int sys_execve(struct pt_regs *regs)
446{
447 int error;
448 char *filename;
449
450 filename = getname((char __user *) regs->bx);
451 error = PTR_ERR(filename);
452 if (IS_ERR(filename))
453 goto out;
454 error = do_execve(filename,
455 (char __user * __user *) regs->cx,
456 (char __user * __user *) regs->dx,
457 regs);
458 if (error == 0) {
459 /* Make sure we don't return using sysenter.. */
460 set_thread_flag(TIF_IRET);
461 }
462 putname(filename);
463out:
464 return error;
465}
466
467#define top_esp (THREAD_SIZE - sizeof(unsigned long)) 394#define top_esp (THREAD_SIZE - sizeof(unsigned long))
468#define top_ebp (THREAD_SIZE - 2*sizeof(unsigned long)) 395#define top_ebp (THREAD_SIZE - 2*sizeof(unsigned long))
469 396
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index e5ab0cd0ef3..52fbd0c6019 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -57,8 +57,6 @@ asmlinkage extern void ret_from_fork(void);
57DEFINE_PER_CPU(unsigned long, old_rsp); 57DEFINE_PER_CPU(unsigned long, old_rsp);
58static DEFINE_PER_CPU(unsigned char, is_idle); 58static DEFINE_PER_CPU(unsigned char, is_idle);
59 59
60unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED;
61
62static ATOMIC_NOTIFIER_HEAD(idle_notifier); 60static ATOMIC_NOTIFIER_HEAD(idle_notifier);
63 61
64void idle_notifier_register(struct notifier_block *n) 62void idle_notifier_register(struct notifier_block *n)
@@ -273,8 +271,9 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
273 *childregs = *regs; 271 *childregs = *regs;
274 272
275 childregs->ax = 0; 273 childregs->ax = 0;
276 childregs->sp = sp; 274 if (user_mode(regs))
277 if (sp == ~0UL) 275 childregs->sp = sp;
276 else
278 childregs->sp = (unsigned long)childregs; 277 childregs->sp = (unsigned long)childregs;
279 278
280 p->thread.sp = (unsigned long) childregs; 279 p->thread.sp = (unsigned long) childregs;
@@ -508,25 +507,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
508 return prev_p; 507 return prev_p;
509} 508}
510 509
511/*
512 * sys_execve() executes a new program.
513 */
514asmlinkage
515long sys_execve(char __user *name, char __user * __user *argv,
516 char __user * __user *envp, struct pt_regs *regs)
517{
518 long error;
519 char *filename;
520
521 filename = getname(name);
522 error = PTR_ERR(filename);
523 if (IS_ERR(filename))
524 return error;
525 error = do_execve(filename, argv, envp, regs);
526 putname(filename);
527 return error;
528}
529
530void set_personality_64bit(void) 510void set_personality_64bit(void)
531{ 511{
532 /* inherit personality from parent */ 512 /* inherit personality from parent */
@@ -541,15 +521,6 @@ void set_personality_64bit(void)
541 current->personality &= ~READ_IMPLIES_EXEC; 521 current->personality &= ~READ_IMPLIES_EXEC;
542} 522}
543 523
544asmlinkage long
545sys_clone(unsigned long clone_flags, unsigned long newsp,
546 void __user *parent_tid, void __user *child_tid, struct pt_regs *regs)
547{
548 if (!newsp)
549 newsp = regs->sp;
550 return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
551}
552
553unsigned long get_wchan(struct task_struct *p) 524unsigned long get_wchan(struct task_struct *p)
554{ 525{
555 unsigned long stack; 526 unsigned long stack;
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 74fe6d86dc5..4fd173cd8e5 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -545,22 +545,12 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
545} 545}
546#endif /* CONFIG_X86_32 */ 546#endif /* CONFIG_X86_32 */
547 547
548#ifdef CONFIG_X86_32 548long
549int sys_sigaltstack(struct pt_regs *regs)
550{
551 const stack_t __user *uss = (const stack_t __user *)regs->bx;
552 stack_t __user *uoss = (stack_t __user *)regs->cx;
553
554 return do_sigaltstack(uss, uoss, regs->sp);
555}
556#else /* !CONFIG_X86_32 */
557asmlinkage long
558sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, 549sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
559 struct pt_regs *regs) 550 struct pt_regs *regs)
560{ 551{
561 return do_sigaltstack(uss, uoss, regs->sp); 552 return do_sigaltstack(uss, uoss, regs->sp);
562} 553}
563#endif /* CONFIG_X86_32 */
564 554
565/* 555/*
566 * Do a signal return; undo the signal stack. 556 * Do a signal return; undo the signal stack.
diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c
index 9c4e6253905..5ffb5622f79 100644
--- a/arch/x86/kernel/vm86_32.c
+++ b/arch/x86/kernel/vm86_32.c
@@ -197,9 +197,8 @@ out:
197static int do_vm86_irq_handling(int subfunction, int irqnumber); 197static int do_vm86_irq_handling(int subfunction, int irqnumber);
198static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk); 198static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk);
199 199
200int sys_vm86old(struct pt_regs *regs) 200int sys_vm86old(struct vm86_struct __user *v86, struct pt_regs *regs)
201{ 201{
202 struct vm86_struct __user *v86 = (struct vm86_struct __user *)regs->bx;
203 struct kernel_vm86_struct info; /* declare this _on top_, 202 struct kernel_vm86_struct info; /* declare this _on top_,
204 * this avoids wasting of stack space. 203 * this avoids wasting of stack space.
205 * This remains on the stack until we 204 * This remains on the stack until we
@@ -227,7 +226,7 @@ out:
227} 226}
228 227
229 228
230int sys_vm86(struct pt_regs *regs) 229int sys_vm86(unsigned long cmd, unsigned long arg, struct pt_regs *regs)
231{ 230{
232 struct kernel_vm86_struct info; /* declare this _on top_, 231 struct kernel_vm86_struct info; /* declare this _on top_,
233 * this avoids wasting of stack space. 232 * this avoids wasting of stack space.
@@ -239,12 +238,12 @@ int sys_vm86(struct pt_regs *regs)
239 struct vm86plus_struct __user *v86; 238 struct vm86plus_struct __user *v86;
240 239
241 tsk = current; 240 tsk = current;
242 switch (regs->bx) { 241 switch (cmd) {
243 case VM86_REQUEST_IRQ: 242 case VM86_REQUEST_IRQ:
244 case VM86_FREE_IRQ: 243 case VM86_FREE_IRQ:
245 case VM86_GET_IRQ_BITS: 244 case VM86_GET_IRQ_BITS:
246 case VM86_GET_AND_RESET_IRQ: 245 case VM86_GET_AND_RESET_IRQ:
247 ret = do_vm86_irq_handling(regs->bx, (int)regs->cx); 246 ret = do_vm86_irq_handling(cmd, (int)arg);
248 goto out; 247 goto out;
249 case VM86_PLUS_INSTALL_CHECK: 248 case VM86_PLUS_INSTALL_CHECK:
250 /* 249 /*
@@ -261,7 +260,7 @@ int sys_vm86(struct pt_regs *regs)
261 ret = -EPERM; 260 ret = -EPERM;
262 if (tsk->thread.saved_sp0) 261 if (tsk->thread.saved_sp0)
263 goto out; 262 goto out;
264 v86 = (struct vm86plus_struct __user *)regs->cx; 263 v86 = (struct vm86plus_struct __user *)arg;
265 tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs, 264 tmp = copy_vm86_regs_from_user(&info.regs, &v86->regs,
266 offsetof(struct kernel_vm86_struct, regs32) - 265 offsetof(struct kernel_vm86_struct, regs32) -
267 sizeof(info.regs)); 266 sizeof(info.regs));
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index a1029769b6f..9fafaf83b3b 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -17,8 +17,6 @@
17EXPORT_SYMBOL(mcount); 17EXPORT_SYMBOL(mcount);
18#endif 18#endif
19 19
20EXPORT_SYMBOL(kernel_thread);
21
22EXPORT_SYMBOL(__get_user_1); 20EXPORT_SYMBOL(__get_user_1);
23EXPORT_SYMBOL(__get_user_2); 21EXPORT_SYMBOL(__get_user_2);
24EXPORT_SYMBOL(__get_user_4); 22EXPORT_SYMBOL(__get_user_4);