linux-2625-20080312
[openafs.git] / src / afs / LINUX / osi_syscall.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * Linux module support routines.
12  *
13  */
14 #include <afsconfig.h>
15 #include "afs/param.h"
16
17 RCSID
18     ("$Header$");
19
20 #ifdef AFS_LINUX24_ENV
21 #include <linux/module.h> /* early to avoid printf->printk mapping */
22 #endif
23 #include "afs/sysincludes.h"
24 #include "afsincludes.h"
25 #include "h/unistd.h"           /* For syscall numbers. */
26 #include "h/mm.h"
27
28 #ifdef AFS_AMD64_LINUX20_ENV
29 #include <asm/ia32_unistd.h>
30 #endif
31
32 #include <linux/proc_fs.h>
33 #include <linux/slab.h>
34 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
35 #include <linux/init.h>
36 #include <linux/sched.h>
37 #endif
38
39 #ifndef NR_syscalls
40 #define NR_syscalls 222
41 #endif
42
43 /* On SPARC64 and S390X, sys_call_table contains 32-bit entries
44  * even though pointers are 64 bit quantities.
45  * XXX unify this with osi_probe.c
46  */
47 #if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_S390X_LINUX24_ENV)
48 #define SYSCALLTYPE unsigned int
49 #define POINTER2SYSCALL (unsigned int)(unsigned long)
50 #define SYSCALL2POINTER (void *)(long)
51 #else
52 #define SYSCALLTYPE void *
53 #define POINTER2SYSCALL (void *)
54 #define SYSCALL2POINTER (void *)
55 #endif
56
57 #if defined(AFS_S390X_LINUX24_ENV) 
58 #define INSERT_SYSCALL(SLOT, TMPPAGE, FUNC) \
59         if (SYSCALL2POINTER FUNC > 0x7fffffff) { \
60             TMPPAGE = kmalloc ( PAGE_SIZE, GFP_DMA|GFP_KERNEL );        \
61             if (SYSCALL2POINTER TMPPAGE > 0x7fffffff) { \
62                 printf("Cannot allocate page for FUNC syscall jump vector\n"); \
63                 return EINVAL; \
64             } \
65             memcpy(TMPPAGE, syscall_jump_code, sizeof(syscall_jump_code)); \
66             *(void **)(TMPPAGE + 0x0c) = &FUNC; \
67             afs_sys_call_table[_S(SLOT)] = POINTER2SYSCALL TMPPAGE; \
68         } else \
69             afs_sys_call_table[_S(SLOT)] = POINTER2SYSCALL FUNC;
70 #else
71 #define INSERT_SYSCALL(SLOT, TMPPAGE, FUNC) \
72     afs_sys_call_table[_S(SLOT)] = POINTER2SYSCALL FUNC;
73 #endif 
74
75 #if defined(AFS_S390X_LINUX24_ENV) && !defined(AFS_LINUX26_ENV)
76 #define _S(x) ((x)<<1)
77 #elif defined(AFS_IA64_LINUX20_ENV)
78 #define _S(x) ((x)-1024)
79 #else
80 #define _S(x) x
81 #endif
82
83
84 /***** ALL PLATFORMS *****/
85 extern asmlinkage long
86 afs_syscall(long syscall, long parm1, long parm2, long parm3, long parm4);
87
88 static SYSCALLTYPE *afs_sys_call_table;
89 static SYSCALLTYPE afs_ni_syscall = 0;
90
91 #ifdef AFS_S390X_LINUX24_ENV
92 static void *afs_sys_setgroups_page = 0;
93 static void *afs_sys_setgroups32_page = 0;
94 static void *afs_syscall_page = 0;
95
96 /* Because of how the syscall table is handled, we need to ensure our 
97    syscalls are within the first 2gb of address space. This means we need
98    self-modifying code we can inject to call our handlers if the module 
99    is loaded high. If keyrings had advanced as fast as false protection
100    this would be unnecessary. */
101
102 uint32_t syscall_jump_code[] = {
103   0xe3d0f030, 0x00240dd0, 0xa7f40006, 0xffffffff, 0xffffffff, 0xe310d004, 
104   0x0004e3d0, 0xf0300004, 0x07f10000, 
105 };
106 #endif
107
108 extern long afs_xsetgroups();
109 asmlinkage long (*sys_setgroupsp) (int gidsetsize, gid_t * grouplist);
110
111 #ifdef AFS_LINUX24_ENV
112 extern int afs_xsetgroups32();
113 asmlinkage int (*sys_setgroups32p) (int gidsetsize,
114                                     __kernel_gid32_t * grouplist);
115 #endif
116
117 #if !defined(AFS_LINUX24_ENV)
118 asmlinkage int (*sys_settimeofdayp) (struct timeval * tv, struct timezone * tz);
119 #endif
120
121
122 /***** AMD64 *****/
123 #ifdef AFS_AMD64_LINUX20_ENV
124 static SYSCALLTYPE *afs_ia32_sys_call_table;
125 static SYSCALLTYPE ia32_ni_syscall = 0;
126
127 extern int afs32_xsetgroups();
128 asmlinkage long (*sys32_setgroupsp) (int gidsetsize, u16 * grouplist);
129 #ifdef AFS_LINUX24_ENV
130 extern int afs32_xsetgroups32();
131 asmlinkage long (*sys32_setgroups32p) (int gidsetsize, gid_t * grouplist);
132 #endif /* __NR_ia32_setgroups32 */
133 #endif /* AFS_AMD64_LINUX20_ENV */
134
135
136 /***** PPC64 *****/
137 #ifdef AFS_PPC64_LINUX26_ENV
138 static SYSCALLTYPE *afs_sys_call_table32;
139 static SYSCALLTYPE afs_ni_syscall32 = 0;
140 static SYSCALLTYPE old_sys_setgroupsp = 0;
141 static SYSCALLTYPE old_sys32_setgroupsp = 0;
142
143 extern int afs32_xsetgroups();
144 asmlinkage long (*sys32_setgroupsp)(int gidsetsize, gid_t *grouplist);
145
146 asmlinkage long sys_close(unsigned int fd);
147 static void sys_setgroups_stub() 
148         __attribute__ ((pure,const,no_instrument_function));
149 static void sys_setgroups_stub() 
150
151         printf("*** error! sys_setgroups_stub called\n");
152 }
153
154 static void sys32_setgroups_stub() 
155         __attribute__ ((pure,const,no_instrument_function));
156 static void sys32_setgroups_stub() 
157
158         printf("*** error! sys32_setgroups_stub called\n");
159 }
160
161 #endif /* AFS_AMD64_LINUX20_ENV */
162
163
164 /***** SPARC64 *****/
165 #ifdef AFS_SPARC64_LINUX20_ENV
166 #ifdef AFS_SPARC64_LINUX26_ENV
167 static SYSCALLTYPE *afs_sys_call_table32;
168 #else
169 extern SYSCALLTYPE *afs_sys_call_table32;
170 #endif
171 static SYSCALLTYPE afs_ni_syscall32 = 0;
172
173 extern int afs32_xsetgroups();
174 #ifdef AFS_SPARC64_LINUX26_ENV
175 asmlinkage int (*sys32_setgroupsp) (int gidsetsize,
176                                     __kernel_gid32_t * grouplist);
177 #else
178 asmlinkage int (*sys32_setgroupsp) (int gidsetsize,
179                                     __kernel_gid_t32 * grouplist);
180 #endif
181 #ifdef AFS_LINUX24_ENV
182 /* This number is not exported for some bizarre reason. */
183 #define __NR_setgroups32      82
184 extern int afs32_xsetgroups32();
185 #ifdef AFS_SPARC64_LINUX26_ENV
186 asmlinkage int (*sys32_setgroups32p) (int gidsetsize,
187                                       __kernel_gid32_t * grouplist);
188 #else
189 asmlinkage int (*sys32_setgroups32p) (int gidsetsize,
190                                       __kernel_gid_t32 * grouplist);
191 #endif
192 #endif
193
194 asmlinkage int
195 afs_syscall32(long syscall, long parm1, long parm2, long parm3, long parm4,
196               long parm5)
197 {
198     __asm__ __volatile__("srl %o4, 0, %o4\n\t"
199                          "mov %o7, %i7\n\t"
200                          "call afs_syscall\n\t"
201                          "srl %o5, 0, %o5\n\t"
202                          "ret\n\t"
203                          "nop");
204 }
205 #endif /* AFS_SPARC64_LINUX20_ENV */
206
207
208 /***** IA64 *****/
209 #ifdef AFS_IA64_LINUX20_ENV
210
211 asmlinkage long
212 afs_syscall_stub(int r0, int r1, long r2, long r3, long r4, long gp)
213 {
214     __asm__ __volatile__("alloc r42 = ar.pfs, 8, 3, 6, 0\n\t"
215                          "mov r41 = b0\n\t"     /* save rp */
216                          "mov out0 = in0\n\t"
217                          "mov out1 = in1\n\t"
218                          "mov out2 = in2\n\t"
219                          "mov out3 = in3\n\t"
220                          "mov out4 = in4\n\t"
221                          "mov out5 = gp\n\t"    /* save gp */
222                          ";;\n"
223                          ".L1:\n\t"
224                          "mov r3 = ip\n\t"
225                          ";;\n\t"
226                          "addl r15=.fptr_afs_syscall-.L1,r3\n\t"
227                          ";;\n\t"
228                          "ld8 r15=[r15]\n\t"
229                          ";;\n\t"
230                          "ld8 r16=[r15],8\n\t"
231                          ";;\n\t"
232                          "ld8 gp=[r15]\n\t"
233                          "mov b6=r16\n\t"
234                          "br.call.sptk.many b0 = b6\n\t"
235                          ";;\n\t"
236                          "mov ar.pfs = r42\n\t"
237                          "mov b0 = r41\n\t"
238                          "mov gp = r48\n\t"     /* restore gp */
239                          "br.ret.sptk.many b0\n"
240                          ".fptr_afs_syscall:\n\t"
241                          "data8 @fptr(afs_syscall)\n\t"
242                          ".skip 8");
243 }
244
245 asmlinkage long
246 afs_xsetgroups_stub(int r0, int r1, long r2, long r3, long r4, long gp)
247 {
248     __asm__ __volatile__("alloc r42 = ar.pfs, 8, 3, 6, 0\n\t"
249                          "mov r41 = b0\n\t"     /* save rp */
250                          "mov out0 = in0\n\t"
251                          "mov out1 = in1\n\t"
252                          "mov out2 = in2\n\t"
253                          "mov out3 = in3\n\t"
254                          "mov out4 = in4\n\t"
255                          "mov out5 = gp\n\t"    /* save gp */
256                          ";;\n"
257                          ".L2:\n\t"
258                          "mov r3 = ip\n\t"
259                          ";;\n\t"
260                          "addl r15=.fptr_afs_xsetgroups - .L2,r3\n\t"
261                          ";;\n\t"
262                          "ld8 r15=[r15]\n\t"
263                          ";;\n\t"
264                          "ld8 r16=[r15],8\n\t"
265                          ";;\n\t"
266                          "ld8 gp=[r15]\n\t"
267                          "mov b6=r16\n\t"
268                          "br.call.sptk.many b0 = b6\n\t"
269                          ";;\n\t"
270                          "mov ar.pfs = r42\n\t"
271                          "mov b0 = r41\n\t"
272                          "mov gp = r48\n\t"     /* restore gp */
273                          "br.ret.sptk.many b0\n"
274                          ".fptr_afs_xsetgroups:\n\t"
275                          "data8 @fptr(afs_xsetgroups)\n\t"
276                          ".skip 8");
277 }
278
279 struct fptr {
280     void *ip;
281     unsigned long gp;
282 };
283
284 #endif /* AFS_IA64_LINUX20_ENV */
285
286 /***** PPC64 ***** 
287  * Spring 2005
288  * sys_call_table hook for PPC64 
289  * by Soewono Effendi <Soewono.Effendi@sysgo.de>
290  * for IBM Deutschland
291  * Thanks go to SYSGO's team for their support:
292  * Horst Birthelmer <Horst.Birthelmer@sysgo.de>
293  * Marius Groeger <Marius.Groeger@sysgo.de>
294  */
295 #if defined(AFS_PPC64_LINUX26_ENV)
296 extern void flush_cache(void *, unsigned long);
297 #define PPC_LO(v) ((v) & 0xffff)
298 #define PPC_HI(v) (((v) >> 16) & 0xffff)
299 #define PPC_HA(v) PPC_HI ((v) + 0x8000)
300 #define PPC_HLO(v) ((short)(((v) >> 32) & 0xffff))
301 #define PPC_HHI(v) ((short)(((v) >> 48) & 0xffff))
302
303 struct ppc64_opd
304 {
305         unsigned long funcaddr;
306         unsigned long r2;
307 };
308
309 struct ppc64_stub
310 {
311         unsigned char jump[136];
312         unsigned long r2;
313         unsigned long lr;
314         struct ppc64_opd opd;
315 } __attribute__ ((packed));
316
317 /* a stub to fix up r2 (TOC ptr) and to jump to our sys_call hook
318    function.  We patch the new r2 value and function pointer into 
319    the stub. */
320 #define PPC64_STUB(stub) \
321 static struct ppc64_stub stub = \
322 { .jump = { \
323         0xf8, 0x41, 0x00, 0x28, /*     std     r2,40(r1) */ \
324         0xfb, 0xc1, 0xff, 0xf0, /*     std     r30,-16(r1) */ \
325         0xfb, 0xa1, 0xff, 0xe8, /*     std     r29,-24(r1) */ \
326         0x7c, 0x5d, 0x13, 0x78, /*     mr      r29,r2 */ \
327         0x3c, 0x40, 0x12, 0x34, /*16:  lis     r2,4660 */ \
328         0x60, 0x42, 0x56, 0x78, /*20:  ori     r2,r2,22136 */ \
329         0x78, 0x42, 0x07, 0xc6, /*     rldicr  r2,r2,32,31 */ \
330         0x64, 0x42, 0x90, 0xab, /*28:  oris    r2,r2,37035 */ \
331         0x60, 0x42, 0xcd, 0xef, /*32:  ori     r2,r2,52719 */ \
332         0x3f, 0xc2, 0x00, 0x00, /*36:  addis   r30,r2,0 */ \
333         0x3b, 0xde, 0x00, 0x00, /*40:  addi    r30,r30,0 */ \
334         0xfb, 0xbe, 0x00, 0x88, /*     std     r29,136(r30) */ \
335         0x7f, 0xa8, 0x02, 0xa6, /*     mflr    r29 */ \
336         0xfb, 0xbe, 0x00, 0x90, /*     std     r29,144(r30) */ \
337         0xeb, 0xde, 0x00, 0x98, /*     ld      r30,152(r30) */ \
338         0x7f, 0xc8, 0x03, 0xa6, /*     mtlr    r30 */ \
339         0xeb, 0xa1, 0xff, 0xe8, /*     ld      r29,-24(r1) */ \
340         0xeb, 0xc1, 0xff, 0xf0, /*     ld      r30,-16(r1) */ \
341         0x4e, 0x80, 0x00, 0x21, /*     blrl */ \
342         0x3c, 0x40, 0x12, 0x34, /*76:  lis     r2,4660 */ \
343         0x60, 0x42, 0x56, 0x78, /*80:  ori     r2,r2,22136 */ \
344         0x78, 0x42, 0x07, 0xc6, /*     rldicr  r2,r2,32,31 */ \
345         0x64, 0x42, 0x90, 0xab, /*88:  oris    r2,r2,37035 */ \
346         0x60, 0x42, 0xcd, 0xef, /*92:  ori     r2,r2,52719 */ \
347         0xfb, 0xc1, 0xff, 0xf0, /*     std     r30,-16(r1) */ \
348         0xfb, 0xa1, 0xff, 0xe8, /*     std     r29,-24(r1) */ \
349         0x3f, 0xc2, 0xab, 0xcd, /*104: addis   r30,r2,-21555 */ \
350         0x3b, 0xde, 0x78, 0x90, /*108: addi    r30,r30,30864 */ \
351         0xeb, 0xbe, 0x00, 0x90, /*     ld      r29,144(r30) */ \
352         0x7f, 0xa8, 0x03, 0xa6, /*     mtlr    r29 */ \
353         0xe8, 0x5e, 0x00, 0x88, /*     ld      r2,136(r30) */ \
354         0xeb, 0xa1, 0xff, 0xe8, /*     ld      r29,-24(r1) */ \
355         0xeb, 0xc1, 0xff, 0xf0, /*     ld      r30,-16(r1) */ \
356         0x4e, 0x80, 0x00, 0x20  /*     blr */ \
357 }} 
358
359 static void * create_stub(struct ppc64_stub *stub,
360                           struct ppc64_opd *opd)
361 {
362         unsigned short *p1, *p2, *p3, *p4;
363         unsigned long addr;
364
365         stub->opd.funcaddr = opd->funcaddr;
366         stub->opd.r2 = opd->r2;
367         addr = (unsigned long) opd->r2;
368         p1 = (unsigned short*) &stub->jump[18];
369         p2 = (unsigned short*) &stub->jump[22];
370         p3 = (unsigned short*) &stub->jump[30];
371         p4 = (unsigned short*) &stub->jump[34];
372
373         *p1 = PPC_HHI(addr);
374         *p2 = PPC_HLO(addr);
375         *p3 = PPC_HI(addr);
376         *p4 = PPC_LO(addr);
377
378         addr = (unsigned long) stub - opd->r2;
379         p1 = (unsigned short*) &stub->jump[38];
380         p2 = (unsigned short*) &stub->jump[42];
381         *p1 = PPC_HA(addr);
382         *p2 = PPC_LO(addr);
383         p1 = (unsigned short*) &stub->jump[106];
384         p2 = (unsigned short*) &stub->jump[110];
385         *p1 = PPC_HA(addr);
386         *p2 = PPC_LO(addr);
387
388         addr = (unsigned long) opd->r2;
389         p1 = (unsigned short*) &stub->jump[78];
390         p2 = (unsigned short*) &stub->jump[82];
391         p3 = (unsigned short*) &stub->jump[90];
392         p4 = (unsigned short*) &stub->jump[94];
393
394         *p1 = PPC_HHI(addr);
395         *p2 = PPC_HLO(addr);
396         *p3 = PPC_HI(addr);
397         *p4 = PPC_LO(addr);
398
399         flush_cache((void *)stub, sizeof(*stub));
400         return ((void*)(stub));
401 }
402
403 PPC64_STUB(afs_sys_call_stub);
404 PPC64_STUB(afs_xsetgroups_stub);
405 PPC64_STUB(afs_xsetgroups32_stub);
406 #endif /* AFS_PPC64_LINUX26_ENV */
407
408
409 /**********************************************************************/
410 /********************* System Call Initialization *********************/
411 /**********************************************************************/
412
413 int osi_syscall_init(void)
414 {
415 /***** IA64 *****/
416 #ifdef AFS_IA64_LINUX20_ENV
417     /* This needs to be first because we are declaring variables, and
418      * also because the handling of syscall pointers is bizarre enough
419      * that we want to special-case even the "common" part.
420      */
421     unsigned long kernel_gp = 0;
422     static struct fptr sys_setgroups;
423
424     afs_sys_call_table = osi_find_syscall_table(0);
425     if (afs_sys_call_table) {
426
427 #if !defined(AFS_LINUX24_ENV)
428         /* XXX no sys_settimeofday on IA64? */
429 #endif
430
431         /* check we aren't already loaded */
432         /* XXX this can't be right */
433         if (SYSCALL2POINTER afs_sys_call_table[_S(__NR_afs_syscall)]
434             == afs_syscall) {
435             printf("AFS syscall entry point already in use!\n");
436             return -EBUSY;
437         }
438
439         /* setup AFS entry point */
440         afs_ni_syscall = afs_sys_call_table[_S(__NR_afs_syscall)];
441         afs_sys_call_table[_S(__NR_afs_syscall)] =
442                 POINTER2SYSCALL((struct fptr *)afs_syscall_stub)->ip;
443
444         /* setup setgroups */
445         sys_setgroupsp = (void *)&sys_setgroups;
446
447         ((struct fptr *)sys_setgroupsp)->ip =
448             SYSCALL2POINTER afs_sys_call_table[_S(__NR_setgroups)];
449         ((struct fptr *)sys_setgroupsp)->gp = kernel_gp;
450
451         afs_sys_call_table[_S(__NR_setgroups)] =
452             POINTER2SYSCALL((struct fptr *)afs_xsetgroups_stub)->ip;
453     }
454
455     /* XXX no 32-bit syscalls on IA64? */
456
457
458 #elif defined(AFS_PPC64_LINUX26_ENV)
459
460     afs_sys_call_table = osi_find_syscall_table(0);
461     if (afs_sys_call_table) {
462         SYSCALLTYPE p;
463         struct ppc64_opd* opd = (struct ppc64_opd*) sys_close;
464         unsigned long r2 = opd->r2;
465         opd = (struct ppc64_opd*) afs_syscall;
466         afs_sys_call_table32 = (unsigned long)afs_sys_call_table - 
467                 NR_syscalls * sizeof(SYSCALLTYPE);
468         /* check we aren't already loaded */
469         p = SYSCALL2POINTER afs_sys_call_table[_S(__NR_afs_syscall)];
470         if ((unsigned long)p == opd->funcaddr) {
471             printf("AFS syscall entry point already in use!\n");
472             return -EBUSY;
473         }
474         /* setup AFS entry point */
475         p = create_stub(&afs_sys_call_stub, opd);
476         afs_ni_syscall = afs_sys_call_table[_S(__NR_afs_syscall)];
477         afs_sys_call_table[_S(__NR_afs_syscall)] = POINTER2SYSCALL p;
478
479         /* setup setgroups */
480         opd = (struct ppc64_opd*) afs_xsetgroups;
481         p = create_stub(&afs_xsetgroups_stub, opd);
482         old_sys_setgroupsp = SYSCALL2POINTER afs_sys_call_table[_S(__NR_setgroups)];
483         afs_sys_call_table[_S(__NR_setgroups)] = POINTER2SYSCALL p;
484         opd = (struct ppc64_opd*) sys_setgroups_stub;
485         opd->funcaddr = old_sys_setgroupsp;
486         opd->r2 = r2;
487
488         /* setup setgroups32 */
489         opd = (struct ppc64_opd*) afs32_xsetgroups;
490         p = create_stub(&afs_xsetgroups32_stub, opd);
491         old_sys32_setgroupsp = SYSCALL2POINTER afs_sys_call_table32[_S(__NR_setgroups)];
492         afs_sys_call_table32[_S(__NR_setgroups)] = POINTER2SYSCALL p;
493         opd = (struct ppc64_opd*) sys32_setgroups_stub;
494         opd->funcaddr = old_sys32_setgroupsp;
495         opd->r2 = r2;
496
497         flush_cache((void *)afs_sys_call_table, 2*NR_syscalls*sizeof(void*));
498
499         sys_setgroupsp = sys_setgroups_stub;
500         sys32_setgroupsp = sys32_setgroups_stub;
501     }
502 /***** COMMON (except IA64 or PPC64) *****/
503 #else /* !AFS_IA64_LINUX20_ENV */
504
505     afs_sys_call_table = osi_find_syscall_table(0);
506     if (afs_sys_call_table) {
507 #if !defined(AFS_LINUX24_ENV)
508         sys_settimeofdayp =
509             SYSCALL2POINTER afs_sys_call_table[_S(__NR_settimeofday)];
510 #endif /* AFS_LINUX24_ENV */
511
512         /* check we aren't already loaded */
513         if (SYSCALL2POINTER afs_sys_call_table[_S(__NR_afs_syscall)]
514             == afs_syscall) {
515             printf("AFS syscall entry point already in use!\n");
516             return -EBUSY;
517         }
518
519         /* setup AFS entry point */
520         afs_ni_syscall = afs_sys_call_table[_S(__NR_afs_syscall)];
521
522         INSERT_SYSCALL(__NR_afs_syscall, afs_syscall_page, afs_syscall)
523
524         /* setup setgroups */
525         sys_setgroupsp = SYSCALL2POINTER afs_sys_call_table[_S(__NR_setgroups)];
526         INSERT_SYSCALL(__NR_setgroups, afs_sys_setgroups_page, afs_xsetgroups)
527
528 #if defined(__NR_setgroups32)
529         /* setup setgroups32 */
530         sys_setgroups32p = SYSCALL2POINTER afs_sys_call_table[__NR_setgroups32];
531         INSERT_SYSCALL(__NR_setgroups32, afs_sys_setgroups32_page, afs_xsetgroups32)
532 #endif
533     }
534 #endif /* !AFS_IA64_LINUX20_ENV */
535
536
537 /***** AMD64 *****/
538 #ifdef AFS_AMD64_LINUX20_ENV
539     afs_ia32_sys_call_table = osi_find_syscall_table(1);
540     if (afs_ia32_sys_call_table) {
541         /* setup AFS entry point for IA32 */
542         ia32_ni_syscall = afs_ia32_sys_call_table[__NR_ia32_afs_syscall];
543         afs_ia32_sys_call_table[__NR_ia32_afs_syscall] =
544             POINTER2SYSCALL afs_syscall;
545
546         /* setup setgroups for IA32 */
547         sys32_setgroupsp =
548             SYSCALL2POINTER afs_ia32_sys_call_table[__NR_ia32_setgroups];
549         afs_ia32_sys_call_table[__NR_ia32_setgroups] =
550             POINTER2SYSCALL afs32_xsetgroups;
551
552 #if AFS_LINUX24_ENV
553         /* setup setgroups32 for IA32 */
554         sys32_setgroups32p =
555             SYSCALL2POINTER afs_ia32_sys_call_table[__NR_ia32_setgroups32];
556         afs_ia32_sys_call_table[__NR_ia32_setgroups32] =
557             POINTER2SYSCALL afs32_xsetgroups32;
558 #endif /* __NR_ia32_setgroups32 */
559     }
560 #endif /* AFS_AMD64_LINUX20_ENV */
561
562
563 /***** SPARC64 *****/
564 #ifdef AFS_SPARC64_LINUX20_ENV
565     afs_sys_call_table32 = osi_find_syscall_table(1);
566     if (afs_sys_call_table32) {
567         /* setup AFS entry point for 32-bit SPARC */
568         afs_ni_syscall32 = afs_sys_call_table32[__NR_afs_syscall];
569         afs_sys_call_table32[__NR_afs_syscall] = POINTER2SYSCALL afs_syscall32;
570
571         /* setup setgroups for 32-bit SPARC */
572         sys32_setgroupsp = SYSCALL2POINTER afs_sys_call_table32[__NR_setgroups];
573         afs_sys_call_table32[__NR_setgroups] = POINTER2SYSCALL afs32_xsetgroups;
574
575 #ifdef AFS_LINUX24_ENV
576         /* setup setgroups32 for 32-bit SPARC */
577         sys32_setgroups32p =
578             SYSCALL2POINTER afs_sys_call_table32[__NR_setgroups32];
579         afs_sys_call_table32[__NR_setgroups32] =
580             POINTER2SYSCALL afs32_xsetgroups32;
581 #endif
582     }
583 #endif /* AFS_SPARC64_LINUX20_ENV */
584     return 0;
585 }
586
587
588
589 /**********************************************************************/
590 /************************ System Call Cleanup *************************/
591 /**********************************************************************/
592
593 void osi_syscall_clean(void)
594 {
595 /***** COMMON *****/
596     if (afs_sys_call_table) {
597         /* put back the AFS entry point */
598         afs_sys_call_table[_S(__NR_afs_syscall)] = afs_ni_syscall;
599
600         /* put back setgroups */
601 #if defined(AFS_IA64_LINUX20_ENV)
602         afs_sys_call_table[_S(__NR_setgroups)] =
603             POINTER2SYSCALL((struct fptr *)sys_setgroupsp)->ip;
604 #elif defined(AFS_PPC64_LINUX26_ENV)
605         afs_sys_call_table[_S(__NR_setgroups)] =
606             POINTER2SYSCALL old_sys_setgroupsp;
607         /* put back setgroups32 for PPC64 */
608         afs_sys_call_table32[__NR_setgroups] =
609             POINTER2SYSCALL old_sys32_setgroupsp;
610 #else /* AFS_IA64_LINUX20_ENV */
611         afs_sys_call_table[_S(__NR_setgroups)] =
612             POINTER2SYSCALL sys_setgroupsp;
613 #endif
614
615 #if defined(__NR_setgroups32) && !defined(AFS_IA64_LINUX20_ENV)
616         /* put back setgroups32 */
617         afs_sys_call_table[__NR_setgroups32] = POINTER2SYSCALL sys_setgroups32p;
618 #endif
619 #if defined(AFS_S390X_LINUX24_ENV)
620 #if defined(__NR_setgroups32) && !defined(AFS_IA64_LINUX20_ENV)
621         if (afs_sys_setgroups32_page)
622             kfree(afs_sys_setgroups32_page);
623 #endif
624         if (afs_sys_setgroups_page)
625             kfree(afs_sys_setgroups_page);
626         if (afs_syscall_page)
627             kfree(afs_syscall_page);
628 #endif
629     }
630
631
632 /***** IA64 *****/
633 #ifdef AFS_IA64_LINUX20_ENV
634     /* XXX no 32-bit syscalls on IA64? */
635 #endif
636
637
638 /***** AMD64 *****/
639 #ifdef AFS_AMD64_LINUX20_ENV
640     if (afs_ia32_sys_call_table) {
641         /* put back AFS entry point for IA32 */
642         afs_ia32_sys_call_table[__NR_ia32_afs_syscall] =
643             POINTER2SYSCALL ia32_ni_syscall;
644
645         /* put back setgroups for IA32 */
646         afs_ia32_sys_call_table[__NR_ia32_setgroups] =
647             POINTER2SYSCALL sys32_setgroupsp;
648
649 #ifdef AFS_LINUX24_ENV
650         /* put back setgroups32 for IA32 */
651         afs_ia32_sys_call_table[__NR_ia32_setgroups32] =
652             POINTER2SYSCALL sys32_setgroups32p;
653 #endif
654     }
655 #endif
656
657
658 /***** SPARC64 *****/
659 #ifdef AFS_SPARC64_LINUX20_ENV
660     if (afs_sys_call_table32) {
661         /* put back AFS entry point for 32-bit SPARC */
662         afs_sys_call_table32[__NR_afs_syscall] = afs_ni_syscall32;
663
664         /* put back setgroups for IA32 */
665         afs_sys_call_table32[__NR_setgroups] =
666             POINTER2SYSCALL sys32_setgroupsp;
667
668 #ifdef AFS_LINUX24_ENV
669         /* put back setgroups32 for IA32 */
670         afs_sys_call_table32[__NR_setgroups32] =
671             POINTER2SYSCALL sys32_setgroups32p;
672 #endif
673     }
674 #endif
675 }