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