From: Sven Oehme Date: Sun, 3 Apr 2005 20:32:38 +0000 (+0000) Subject: STABLE14-linux-ppc64-26-20050403 X-Git-Tag: openafs-devel-1_3_81~18 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=f43b69079ea24154f361f4f2ff3beee1eff820ca;p=packages%2Fo%2Fopenafs.git STABLE14-linux-ppc64-26-20050403 FIXES 18114 add support for ppc64 linux26 (cherry picked from commit face6451fda9809a28cf6bec42f50f211b51d07d) --- diff --git a/acinclude.m4 b/acinclude.m4 index 0a57fd9c9..5aac39851 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -455,7 +455,7 @@ else AFS_SYSNAME="ia64_linuxXX" ;; powerpc-*-linux*) - AFS_SYSNAME="ppc_linuxXX" + AFS_SYSNAME="`/bin/arch`_linuxXX" ;; powerpc64-*-linux*) AFS_SYSNAME="ppc64_linuxXX" diff --git a/src/afs/LINUX/osi_flush.s b/src/afs/LINUX/osi_flush.s new file mode 100644 index 000000000..925b874b2 --- /dev/null +++ b/src/afs/LINUX/osi_flush.s @@ -0,0 +1,41 @@ +/* Taken from linux-2.6/arch/ppc64/boot/string.S + * + * Copyright (C) Paul Mackerras 1997. + * + * Copyright 2000, International Business Machines Corporation and others. + * All Rights Reserved. + * + * This software has been released under the terms of the IBM Public + * License. For details, see the LICENSE file in the top-level source + * directory or online at http://www.openafs.org/dl/license10.html + * + * Flush the dcache and invalidate the icache for a range of addresses. + * + * flush_cache(addr, len) + */ + .section ".text" + .align 2 + .globl flush_cache + .section ".opd","aw" + .align 3 +flush_cache: + .quad .flush_cache,.TOC.@tocbase,0 + .previous + .size flush_cache,24 + .globl .flush_cache +.flush_cache: + addi 4,4,0x1f /* len = (len + 0x1f) / 0x20 */ + rlwinm. 4,4,27,5,31 + mtctr 4 + beqlr +1: dcbf 0,3 + icbi 0,3 + addi 3,3,0x20 + bdnz 1b + sync + isync + blr + .long 0 + .byte 0,12,0,0,0,0,0,0 + .type .flush_cache,@function + .size .flush_cache,.-.flush_cache diff --git a/src/afs/LINUX/osi_probe.c b/src/afs/LINUX/osi_probe.c index e94886604..3f3256fcf 100644 --- a/src/afs/LINUX/osi_probe.c +++ b/src/afs/LINUX/osi_probe.c @@ -65,6 +65,10 @@ #include #include +#if defined(AFS_PPC64_LINUX26_ENV) +#include +#endif + #ifdef AFS_AMD64_LINUX20_ENV #include #endif @@ -78,6 +82,8 @@ /* lower bound of valid kernel text pointers */ #ifdef AFS_IA64_LINUX20_ENV #define ktxt_lower_bound (((unsigned long)&kernel_thread ) & 0xfff00000L) +#elif defined(AFS_PPC64_LINUX20_ENV) +#define ktxt_lower_bound (KERNELBASE) #else #define ktxt_lower_bound (((unsigned long)&kernel_thread ) & ~0xfffffL) #endif @@ -188,6 +194,7 @@ extern SYSCALLTYPE ia32_sys_call_table[] __attribute__((weak)); extern SYSCALLTYPE sys_call_table32[] __attribute__((weak)); extern SYSCALLTYPE sys_call_table_emu[] __attribute__((weak)); +extern asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count) __attribute__((weak)); extern asmlinkage long sys_close(unsigned int) __attribute__((weak)); extern asmlinkage long sys_chdir(const char *) __attribute__((weak)); extern asmlinkage ssize_t sys_write(unsigned int, const char *, size_t) __attribute__((weak)); @@ -480,6 +487,10 @@ static probectl main_probe = { (unsigned long)(&tasklist_lock) - 0x30000, 0, 0x6000, +#elif defined(AFS_PPC64_LINUX26_ENV) + (unsigned long)(&do_signal), + 0xfff, + 0x400, #elif defined(AFS_PPC_LINUX20_ENV) || defined(AFS_PPC_LINUX20_ENV) (unsigned long)&init_mm, 0xffff, @@ -617,6 +628,10 @@ static probectl *probe_list[] = { /********** Probing Configuration: ppc64, sparc64 sys_call_table32 **********/ #elif defined(AFS_PPC64_LINUX20_ENV) || defined(AFS_SPARC64_LINUX20_ENV) +struct fptr { + void *ip; + unsigned long gp; +}; /* * syscall pairs/triplets to probe @@ -692,6 +707,10 @@ static probectl sct32_probe = { (unsigned long)(&sys_close), 0xfffff, 0x10000, +#elif defined(AFS_PPC64_LINUX26_ENV) + (unsigned long)(&do_signal), + 0xfff, + 0x400, #else (unsigned long)&init_mm, 0, @@ -859,7 +878,7 @@ static int check_table(probectl *P, PROBETYPE *ptr) return -1; } -static void *try(probectl *P, tryctl *T, PROBETYPE *ptr, +static void *try(probectl *P, tryctl *T, PROBETYPE *aptr, unsigned long datalen) { #ifdef OSI_PROBE_KALLSYMS @@ -870,8 +889,9 @@ static void *try(probectl *P, tryctl *T, PROBETYPE *ptr, #endif unsigned long offset, ip1, ip2, ip3; int ret; + PROBETYPE *ptr; -#ifdef AFS_IA64_LINUX20_ENV +#if defined(AFS_IA64_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV) ip1 = T->fn1 ? (unsigned long)((struct fptr *)T->fn1)->ip : 0; ip2 = T->fn2 ? (unsigned long)((struct fptr *)T->fn2)->ip : 0; ip3 = T->fn3 ? (unsigned long)((struct fptr *)T->fn3)->ip : 0; @@ -890,11 +910,19 @@ static void *try(probectl *P, tryctl *T, PROBETYPE *ptr, if (!ip1 || !ip2 || (T->NR3 >= 0 && !ip3)) return 0; - for (offset = 0; offset < datalen; offset++, ptr++) { + for (offset = 0; offset < datalen; offset++, aptr++) { +#if defined(AFS_PPC64_LINUX20_ENV) + ptr = (PROBETYPE*)(*aptr); + if ((unsigned long)ptr <= KERNELBASE) { + continue; + } +#else + ptr = aptr; +#endif ret = check_table(P, ptr); if (ret >= 0) { /* return value is number of entries to skip */ - ptr += ret; + aptr += ret; offset += ret; continue; } @@ -957,7 +985,7 @@ static int check_harder(probectl *P, PROBETYPE *p) } } -#ifdef AFS_IA64_LINUX20_ENV +#if defined(AFS_IA64_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV) ip1 = P->verify_fn ? (unsigned long)((struct fptr *)(P->verify_fn))->ip : 0; #else ip1 = (unsigned long)(P->verify_fn); diff --git a/src/afs/LINUX/osi_syscall.c b/src/afs/LINUX/osi_syscall.c index e10e9a6e2..6fad88427 100644 --- a/src/afs/LINUX/osi_syscall.c +++ b/src/afs/LINUX/osi_syscall.c @@ -36,6 +36,9 @@ RCSID #include #endif +#ifndef NR_syscalls +#define NR_syscalls 222 +#endif /* On SPARC64 and S390X, sys_call_table contains 32-bit entries * even though pointers are 64 bit quantities. @@ -96,12 +99,30 @@ asmlinkage long (*sys32_setgroups32p) (int gidsetsize, gid_t * grouplist); /***** PPC64 *****/ -#ifdef AFS_PPC64_LINUX20_ENV -extern SYSCALLTYPE *afs_sys_call_table32; +#ifdef AFS_PPC64_LINUX26_ENV +static SYSCALLTYPE *afs_sys_call_table32; static SYSCALLTYPE afs_ni_syscall32 = 0; +static SYSCALLTYPE old_sys_setgroupsp = 0; +static SYSCALLTYPE old_sys32_setgroupsp = 0; extern int afs32_xsetgroups(); asmlinkage long (*sys32_setgroupsp)(int gidsetsize, gid_t *grouplist); + +asmlinkage long sys_close(unsigned int fd); +static void sys_setgroups_stub() + __attribute__ ((pure,const,no_instrument_function)); +static void sys_setgroups_stub() +{ + printf("*** error! sys_setgroups_stub called\n"); +} + +static void sys32_setgroups_stub() + __attribute__ ((pure,const,no_instrument_function)); +static void sys32_setgroups_stub() +{ + printf("*** error! sys32_setgroups_stub called\n"); +} + #endif /* AFS_AMD64_LINUX20_ENV */ @@ -213,6 +234,127 @@ struct fptr { #endif /* AFS_IA64_LINUX20_ENV */ +/***** PPC64 ***** + * Spring 2005 + * sys_call_table hook for PPC64 + * by Soewono Effendi + * for IBM Deutschland + * Thanks go to SYSGO's team for their support: + * Horst Birthelmer + * Marius Groeger + */ +#if defined(AFS_PPC64_LINUX26_ENV) +extern void flush_cache(void *, unsigned long); +#define PPC_LO(v) ((v) & 0xffff) +#define PPC_HI(v) (((v) >> 16) & 0xffff) +#define PPC_HA(v) PPC_HI ((v) + 0x8000) +#define PPC_HLO(v) ((short)(((v) >> 32) & 0xffff)) +#define PPC_HHI(v) ((short)(((v) >> 48) & 0xffff)) + +struct ppc64_opd +{ + unsigned long funcaddr; + unsigned long r2; +}; + +struct ppc64_stub +{ + unsigned char jump[136]; + unsigned long r2; + unsigned long lr; + struct ppc64_opd opd; +} __attribute__ ((packed)); + +/* a stub to fix up r2 (TOC ptr) and to jump to our sys_call hook + function. We patch the new r2 value and function pointer into + the stub. */ +#define PPC64_STUB(stub) \ +static struct ppc64_stub stub = \ +{ .jump = { \ + 0xf8, 0x41, 0x00, 0x28, /* std r2,40(r1) */ \ + 0xfb, 0xc1, 0xff, 0xf0, /* std r30,-16(r1) */ \ + 0xfb, 0xa1, 0xff, 0xe8, /* std r29,-24(r1) */ \ + 0x7c, 0x5d, 0x13, 0x78, /* mr r29,r2 */ \ + 0x3c, 0x40, 0x12, 0x34, /*16: lis r2,4660 */ \ + 0x60, 0x42, 0x56, 0x78, /*20: ori r2,r2,22136 */ \ + 0x78, 0x42, 0x07, 0xc6, /* rldicr r2,r2,32,31 */ \ + 0x64, 0x42, 0x90, 0xab, /*28: oris r2,r2,37035 */ \ + 0x60, 0x42, 0xcd, 0xef, /*32: ori r2,r2,52719 */ \ + 0x3f, 0xc2, 0x00, 0x00, /*36: addis r30,r2,0 */ \ + 0x3b, 0xde, 0x00, 0x00, /*40: addi r30,r30,0 */ \ + 0xfb, 0xbe, 0x00, 0x88, /* std r29,136(r30) */ \ + 0x7f, 0xa8, 0x02, 0xa6, /* mflr r29 */ \ + 0xfb, 0xbe, 0x00, 0x90, /* std r29,144(r30) */ \ + 0xeb, 0xde, 0x00, 0x98, /* ld r30,152(r30) */ \ + 0x7f, 0xc8, 0x03, 0xa6, /* mtlr r30 */ \ + 0xeb, 0xa1, 0xff, 0xe8, /* ld r29,-24(r1) */ \ + 0xeb, 0xc1, 0xff, 0xf0, /* ld r30,-16(r1) */ \ + 0x4e, 0x80, 0x00, 0x21, /* blrl */ \ + 0x3c, 0x40, 0x12, 0x34, /*76: lis r2,4660 */ \ + 0x60, 0x42, 0x56, 0x78, /*80: ori r2,r2,22136 */ \ + 0x78, 0x42, 0x07, 0xc6, /* rldicr r2,r2,32,31 */ \ + 0x64, 0x42, 0x90, 0xab, /*88: oris r2,r2,37035 */ \ + 0x60, 0x42, 0xcd, 0xef, /*92: ori r2,r2,52719 */ \ + 0xfb, 0xc1, 0xff, 0xf0, /* std r30,-16(r1) */ \ + 0xfb, 0xa1, 0xff, 0xe8, /* std r29,-24(r1) */ \ + 0x3f, 0xc2, 0xab, 0xcd, /*104: addis r30,r2,-21555 */ \ + 0x3b, 0xde, 0x78, 0x90, /*108: addi r30,r30,30864 */ \ + 0xeb, 0xbe, 0x00, 0x90, /* ld r29,144(r30) */ \ + 0x7f, 0xa8, 0x03, 0xa6, /* mtlr r29 */ \ + 0xe8, 0x5e, 0x00, 0x88, /* ld r2,136(r30) */ \ + 0xeb, 0xa1, 0xff, 0xe8, /* ld r29,-24(r1) */ \ + 0xeb, 0xc1, 0xff, 0xf0, /* ld r30,-16(r1) */ \ + 0x4e, 0x80, 0x00, 0x20 /* blr */ \ +}} + +static void * create_stub(struct ppc64_stub *stub, + struct ppc64_opd *opd) +{ + unsigned short *p1, *p2, *p3, *p4; + unsigned long addr; + + stub->opd.funcaddr = opd->funcaddr; + stub->opd.r2 = opd->r2; + addr = (unsigned long) opd->r2; + p1 = (unsigned short*) &stub->jump[18]; + p2 = (unsigned short*) &stub->jump[22]; + p3 = (unsigned short*) &stub->jump[30]; + p4 = (unsigned short*) &stub->jump[34]; + + *p1 = PPC_HHI(addr); + *p2 = PPC_HLO(addr); + *p3 = PPC_HI(addr); + *p4 = PPC_LO(addr); + + addr = (unsigned long) stub - opd->r2; + p1 = (unsigned short*) &stub->jump[38]; + p2 = (unsigned short*) &stub->jump[42]; + *p1 = PPC_HA(addr); + *p2 = PPC_LO(addr); + p1 = (unsigned short*) &stub->jump[106]; + p2 = (unsigned short*) &stub->jump[110]; + *p1 = PPC_HA(addr); + *p2 = PPC_LO(addr); + + addr = (unsigned long) opd->r2; + p1 = (unsigned short*) &stub->jump[78]; + p2 = (unsigned short*) &stub->jump[82]; + p3 = (unsigned short*) &stub->jump[90]; + p4 = (unsigned short*) &stub->jump[94]; + + *p1 = PPC_HHI(addr); + *p2 = PPC_HLO(addr); + *p3 = PPC_HI(addr); + *p4 = PPC_LO(addr); + + flush_cache((void *)stub, sizeof(*stub)); + return ((void*)(stub)); +} + +PPC64_STUB(afs_sys_call_stub); +PPC64_STUB(afs_xsetgroups_stub); +PPC64_STUB(afs_xsetgroups32_stub); +#endif /* AFS_PPC64_LINUX26_ENV */ /**********************************************************************/ @@ -264,7 +406,51 @@ int osi_syscall_init(void) /* XXX no 32-bit syscalls on IA64? */ -/***** COMMON (except IA64) *****/ +#elif defined(AFS_PPC64_LINUX26_ENV) + + afs_sys_call_table = osi_find_syscall_table(0); + if (afs_sys_call_table) { + SYSCALLTYPE p; + struct ppc64_opd* opd = (struct ppc64_opd*) sys_close; + unsigned long r2 = opd->r2; + opd = (struct ppc64_opd*) afs_syscall; + afs_sys_call_table32 = (unsigned long)afs_sys_call_table - + NR_syscalls * sizeof(SYSCALLTYPE); + /* check we aren't already loaded */ + p = SYSCALL2POINTER afs_sys_call_table[_S(__NR_afs_syscall)]; + if ((unsigned long)p == opd->funcaddr) { + printf("AFS syscall entry point already in use!\n"); + return -EBUSY; + } + /* setup AFS entry point */ + p = create_stub(&afs_sys_call_stub, opd); + afs_ni_syscall = afs_sys_call_table[_S(__NR_afs_syscall)]; + afs_sys_call_table[_S(__NR_afs_syscall)] = POINTER2SYSCALL p; + + /* setup setgroups */ + opd = (struct ppc64_opd*) afs_xsetgroups; + p = create_stub(&afs_xsetgroups_stub, opd); + old_sys_setgroupsp = SYSCALL2POINTER afs_sys_call_table[_S(__NR_setgroups)]; + afs_sys_call_table[_S(__NR_setgroups)] = POINTER2SYSCALL p; + opd = (struct ppc64_opd*) sys_setgroups_stub; + opd->funcaddr = old_sys_setgroupsp; + opd->r2 = r2; + + /* setup setgroups32 */ + opd = (struct ppc64_opd*) afs32_xsetgroups; + p = create_stub(&afs_xsetgroups32_stub, opd); + old_sys32_setgroupsp = SYSCALL2POINTER afs_sys_call_table32[_S(__NR_setgroups)]; + afs_sys_call_table32[_S(__NR_setgroups)] = POINTER2SYSCALL p; + opd = (struct ppc64_opd*) sys32_setgroups_stub; + opd->funcaddr = old_sys32_setgroupsp; + opd->r2 = r2; + + flush_cache((void *)afs_sys_call_table, 2*NR_syscalls*sizeof(void*)); + + sys_setgroupsp = sys_setgroups_stub; + sys32_setgroupsp = sys32_setgroups_stub; + } +/***** COMMON (except IA64 or PPC64) *****/ #else /* !AFS_IA64_LINUX20_ENV */ afs_sys_call_table = osi_find_syscall_table(0); @@ -324,12 +510,6 @@ int osi_syscall_init(void) #endif /* AFS_AMD64_LINUX20_ENV */ -/***** PPC64 *****/ -#ifdef AFS_PPC64_LINUX20_ENV - /* XXX no 32-bit syscalls on PPC64? */ -#endif - - /***** SPARC64 *****/ #ifdef AFS_SPARC64_LINUX20_ENV afs_sys_call_table32 = osi_find_syscall_table(1); @@ -371,6 +551,12 @@ void osi_syscall_clean(void) #if defined(AFS_IA64_LINUX20_ENV) afs_sys_call_table[_S(__NR_setgroups)] = POINTER2SYSCALL((struct fptr *)sys_setgroupsp)->ip; +#elif defined(AFS_PPC64_LINUX26_ENV) + afs_sys_call_table[_S(__NR_setgroups)] = + POINTER2SYSCALL old_sys_setgroupsp; + /* put back setgroups32 for PPC64 */ + afs_sys_call_table32[__NR_setgroups] = + POINTER2SYSCALL old_sys32_setgroupsp; #else /* AFS_IA64_LINUX20_ENV */ afs_sys_call_table[_S(__NR_setgroups)] = POINTER2SYSCALL sys_setgroupsp; @@ -409,12 +595,6 @@ void osi_syscall_clean(void) #endif -/***** PPC64 *****/ -#ifdef AFS_PPC64_LINUX20_ENV - /* XXX no 32-bit syscalls on PPC64? */ -#endif - - /***** SPARC64 *****/ #ifdef AFS_SPARC64_LINUX20_ENV if (afs_sys_call_table32) { diff --git a/src/cf/linux-test3.m4 b/src/cf/linux-test3.m4 index f8c2151f5..f64c5ef98 100644 --- a/src/cf/linux-test3.m4 +++ b/src/cf/linux-test3.m4 @@ -116,7 +116,7 @@ CPPFLAGS="$save_CPPFLAGS"]) AC_DEFUN([LINUX_KERNEL_PAGE_FOLLOW_LINK],[ AC_MSG_CHECKING(for page_follow_link_light vs page_follow_link) save_CPPFLAGS="$CPPFLAGS" -CPPFLAGS="-I${LINUX_KERNEL_PATH}/include -Werror-implicit-function-declaration -D__KERNEL__ $CPPFLAGS" +CPPFLAGS="-I${LINUX_KERNEL_PATH}/include -I${LINUX_KERNEL_PATH}/include/asm/mach-default -Werror-implicit-function-declaration -D__KERNEL__ $CPPFLAGS" AC_CACHE_VAL(ac_cv_linux_kernel_page_follow_link, [ AC_TRY_COMPILE( diff --git a/src/cf/osconf.m4 b/src/cf/osconf.m4 index d1c930037..b8a94bd18 100644 --- a/src/cf/osconf.m4 +++ b/src/cf/osconf.m4 @@ -262,8 +262,9 @@ case $AFS_SYSNAME in MT_LIBS="-lpthread" PAM_CFLAGS="-g -O2 -Dlinux -DLINUX_PAM -fPIC" SHLIB_LDFLAGS="-shared -Xlinker -x" + SHLIB_CFLAGS="-fPIC" TXLIBS="-lncurses" - XCFLAGS="-g -O2 -D_LARGEFILE64_SOURCE" + XCFLAGS="-g -O2 -D_LARGEFILE64_SOURCE -fPIC" YACC="bison -y" SHLIB_LINKER="${MT_CC} -shared" ;; diff --git a/src/libafs/Makefile.common.in b/src/libafs/Makefile.common.in index 9ee7e74f3..c9e5dff15 100644 --- a/src/libafs/Makefile.common.in +++ b/src/libafs/Makefile.common.in @@ -393,6 +393,8 @@ osi_syscall.o: $(TOP_SRCDIR)/afs/$(MKAFS_OSTYPE)/osi_syscall.c $(CRULE_NOOPT) osi_sysctl.o: $(TOP_SRCDIR)/afs/$(MKAFS_OSTYPE)/osi_sysctl.c $(CRULE_NOOPT) +osi_flush.o: $(TOP_SRCDIR)/afs/$(MKAFS_OSTYPE)/osi_flush.s + $(CRULE_OPT) osi_alloc.o: $(TOP_SRCDIR)/afs/$(MKAFS_OSTYPE)/osi_alloc.c $(CRULE_NOOPT) osi_cred.o: $(TOP_SRCDIR)/afs/$(MKAFS_OSTYPE)/osi_cred.c diff --git a/src/libafs/MakefileProto.LINUX.in b/src/libafs/MakefileProto.LINUX.in index 9f54b631b..d23769c60 100644 --- a/src/libafs/MakefileProto.LINUX.in +++ b/src/libafs/MakefileProto.LINUX.in @@ -24,6 +24,9 @@ AFS_OS_OBJS = \ osi_sysctl.o \ osi_vfsops.o \ osi_vm.o \ + + osi_flush.o \ + osi_vnodeops.o AFS_OS_NFSOBJS = @@ -82,7 +85,7 @@ CCFLAGS = $(COMMON_KERN_CFLAGS) \ -mcpu=ultrasparc -m64 -mno-fpu -mcmodel=medlow -ffixed-g4 -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare DEFINES = $(COMMON_DEFINES) -DCPU=sparc64 - + CCFLAGS = $(COMMON_KERN_CFLAGS) -fsigned-char -msoft-float -fno-builtin -ffixed-r2 DEFINES = $(COMMON_DEFINES) -D__powerpc__ diff --git a/src/libafs/make_kbuild_makefile.pl b/src/libafs/make_kbuild_makefile.pl index 03584cc74..ce046e172 100755 --- a/src/libafs/make_kbuild_makefile.pl +++ b/src/libafs/make_kbuild_makefile.pl @@ -51,6 +51,9 @@ foreach $mf (@Makefiles) { elsif ($text =~ /^(\S+\.o):\s*(\S+\.c)/) { ## Dependency $deps{$1} = $2; } + elsif ($text =~ /^(\S+\.o):\s*(\S+\.s)/) { ## Dependency + $deps{$1} = $2; + } $text = ''; } $F->close(); @@ -74,8 +77,12 @@ if (! -d $KDIR) { foreach (@objects) { - ($src = $_) =~ s/\.o$/.c/; die "No source known for $_\n" unless exists $deps{$_}; + if($deps{$_} =~ /\.s$/) { + ($src = $_) =~ s/\.o$/.s/; + } else { + ($src = $_) =~ s/\.o$/.c/; + } if (-e "$KDIR/$src" || -l "$KDIR/$src") { unlink("$KDIR/$src") or die "$KDIR/$src: $!\n"; }