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