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