kmod on 2.1.90 alpha

Steven N. Hirsch (shirsch@ibm.net)
Sun, 22 Mar 1998 11:48:50 -0500 (EST)


All,

After somewhat of a battle, I've convinced 2.1.90 to build on a UDB with
loadable modules configured. Unfortunately, it doesn't work. Not being
well-versed in low-level details of the Alpha, I'm stuck and would
appreciate input. Here's the picture:

It seems that kmod_thread needs to make two system calls: delete_module()
and fork(). On i386 linux, these eventually expand into small assembler
stubs invoking the corresponding kernel syscall handlers.

Alpha linux has been more aggressively glibc-ized. In
include/asm-alpha/unistd.h, all syscallX macros seem targeted for user
applications and assume use of the glibc syscall() entry.

So, I extracted what I believe to be the pertinent bits from the glibc
sources and mashed them into where logic would suggest they belonged.

The kernel goes through all the motions of booting, but when the first
module load request arrives, it scrolls many screens worth of traps before
complaining that kmod fork() failed and locking solid.

Can anyone suggest a different/better approach for compiling kernel
threads which require syscall services? At present, we have a rough
situation under alpha + glibc.

Steve

p.s. - At the very least, there was a typo in the macro definition for
syscall0 in asm-alph/unistd.h!

--- linux/kernel/kmod.c.orig Wed Mar 18 20:21:21 1998
+++ linux/kernel/kmod.c Sat Mar 21 16:11:15 1998
@@ -5,9 +5,17 @@

#define __KERNEL_SYSCALLS__

+#ifdef __alpha__
+# define __LIBRARY__
+#endif
+
#include <linux/sched.h>
#include <linux/types.h>
#include <linux/unistd.h>
+
+#ifdef __alpha__
+static inline _syscall0(int,fork)
+#endif

static inline _syscall1(int,delete_module,const char *,name_user)

--- linux/include/asm-alpha/unistd.h.orig Sat Mar 21 13:10:49 1998
+++ linux/include/asm-alpha/unistd.h Sat Mar 21 16:09:19 1998
@@ -313,7 +313,7 @@
type name(void) \
{ \
extern long syscall (int, ...); \
- return syscall(__NR_##name)); \
+ return syscall(__NR_##name); \
}

#define _syscall1(type,name,type1,arg1) \
--- linux/include/asm-alpha/sysdep.h.orig Sun Mar 22 10:30:35 1998
+++ linux/include/asm-alpha/sysdep.h Sun Mar 22 10:26:13 1998
@@ -0,0 +1,110 @@
+/* Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Brendan Kehoe (brendan@zen.org).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#ifdef ASSEMBLER
+
+#ifdef __linux__
+# include <alpha/regdef.h>
+#else
+# include <regdef.h>
+#endif
+
+#ifdef __STDC__
+#define __LABEL(x) x##:
+#else
+#define __LABEL(x) x/**/:
+#endif
+
+#define LEAF(name, framesize) \
+ .globl name; \
+ .align 3; \
+ .ent name, 0; \
+ __LABEL(name) \
+ .frame sp, framesize, ra
+
+#define ENTRY(name) \
+ .globl name; \
+ .align 3; \
+ .ent name, 0; \
+ __LABEL(name) \
+ .frame sp, 0, ra
+
+/* Mark the end of function SYM. */
+#undef END
+#define END(sym) .end sym
+
+/* Note that PSEUDO/PSEUDO_END use label number 1996---do not use a
+ label of that number between those two macros! */
+
+#ifdef PROF
+#define PSEUDO(name, syscall_name, args) \
+ .globl name; \
+ .align 3; \
+ .ent name,0; \
+__LABEL(name) \
+ .frame sp, 0, ra; \
+ ldgp gp,0(pv); \
+ .set noat; \
+ lda AT,_mcount; \
+ jsr AT,(AT),_mcount; \
+ .set at; \
+ .prologue 1; \
+ ldiq v0, SYS_ify(syscall_name); \
+ .set noat; \
+ call_pal PAL_callsys; \
+ .set at; \
+ bne a3, 1996f; \
+3:
+#else
+#define PSEUDO(name, syscall_name, args) \
+ .globl name; \
+ .align 3; \
+ .ent name,0; \
+__LABEL(name) \
+ .frame sp, 0, ra \
+ .prologue 0; \
+ ldiq v0, SYS_ify(syscall_name); \
+ .set noat; \
+ call_pal PAL_callsys; \
+ .set at; \
+ bne a3, 1996f; \
+3:
+#endif
+
+#undef PSEUDO_END
+#ifdef PROF
+#define PSEUDO_END(sym) \
+1996: \
+ jmp zero, __syscall_error; \
+ END(sym)
+#else
+#define PSEUDO_END(sym) \
+1996: \
+ br gp, 2f; \
+2: ldgp gp, 0(gp); \
+ jmp zero, __syscall_error; \
+ END(sym)
+#endif
+
+#define r0 v0
+#define r1 a4
+
+#define MOVE(x,y) mov x,y
+
+#endif
--- linux/arch/alpha/kernel/syscall.S.orig Sun Mar 22 10:30:57 1998
+++ linux/arch/alpha/kernel/syscall.S Sun Mar 22 11:40:36 1998
@@ -0,0 +1,88 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by David Mosberger <davidm@azstarnet.com>, 1996.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#define ASSEMBLER
+#include <asm/sysdep.h>
+#include <asm/system.h>
+/*
+ * This is for COMPATIBILITY with Linux/x86 only. Linux/Alpha system
+ * calls return an error indication in a3. This allows to return
+ * arbitrary 64bit values in v0 (because negative values are not
+ * mistaken as error numbers). However, C allows to return only one
+ * value so the interface below folds the error indication passed in
+ * a3 back into v0: it sets v0 to -errno if an error occurs. Thus,
+ * no negative 64bit numbers can be returned. To avoid this problem,
+ * use assembly stubs wherever possible/convenient.
+ *
+ * Usage:
+ *
+ * long syscall(syscall_number, arg1, arg2, arg3, arg4, arg5)
+ *
+ * syscall_number = the index of the system call we're invoking
+ * arg1-arg5 = up to 5 integer arguments to the system call
+ *
+ * We need to do some arg shifting: the kernel expects the
+ * syscall number in v0 and the first five args in a0-a4.
+ *
+ */
+
+
+LEAF(syscall, 0)
+#ifdef PROF
+ ldgp gp, 0(pv)
+ .set noat
+ lda AT, _mcount
+ jsr AT, (AT), _mcount
+ .set at
+ .prologue 1
+#else
+ .prologue 0
+#endif
+
+ mov a0, v0 /* Syscall number -> v0 */
+ mov a1, a0 /* arg1-arg5 -> a0-a4 */
+ mov a2, a1
+ mov a3, a2
+ mov a4, a3
+ mov a5, a4
+
+ call_pal PAL_callsys /* Invoke system call */
+ bne a3, $error
+ ret
+
+$error:
+#ifndef PROF
+ br gp, 2f
+2: ldgp gp, 0(gp)
+#endif
+ jmp zero, __syscall_error
+
+END(syscall)
+
+/* weak_alias(__syscall, syscall) */
+
+ENTRY(__syscall_error)
+ ldgp gp, 0(t12)
+ .prologue 1
+
+/* stl v0, errno */
+ lda v0, -1
+ ret
+
+END(__syscall_error)

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu