[klibc] i386 support for klibc The parts of klibc specific to the i386 architecture. Signed-off-by: H. Peter Anvin --- commit 1a2c580180c57f8471adc4a42c79482e78172034 tree 4c0e97cfc194c47763f08cea4467fc9219627c42 parent 911ca96bfc52d57bba5b27b33fc410f853389122 author H. Peter Anvin Sun, 02 Jul 2006 12:25:18 -0700 committer H. Peter Anvin Sun, 02 Jul 2006 12:25:18 -0700 usr/include/arch/i386/klibc/archconfig.h | 19 ++++ usr/include/arch/i386/klibc/archsetjmp.h | 19 ++++ usr/include/arch/i386/klibc/archsignal.h | 114 +++++++++++++++++++++++++++ usr/include/arch/i386/klibc/archstat.h | 38 +++++++++ usr/include/arch/i386/klibc/diverr.h | 15 ++++ usr/include/arch/i386/sys/io.h | 127 ++++++++++++++++++++++++++++++ usr/include/arch/i386/sys/vm86.h | 40 +++++++++ usr/klibc/arch/i386/MCONFIG | 33 ++++++++ usr/klibc/arch/i386/Makefile.inc | 30 +++++++ usr/klibc/arch/i386/crt0.S | 31 +++++++ usr/klibc/arch/i386/libgcc/__ashldi3.S | 29 +++++++ usr/klibc/arch/i386/libgcc/__ashrdi3.S | 29 +++++++ usr/klibc/arch/i386/libgcc/__lshrdi3.S | 29 +++++++ usr/klibc/arch/i386/libgcc/__muldi3.S | 34 ++++++++ usr/klibc/arch/i386/libgcc/__negdi2.S | 21 +++++ usr/klibc/arch/i386/open.S | 29 +++++++ usr/klibc/arch/i386/openat.S | 26 ++++++ usr/klibc/arch/i386/setjmp.S | 58 ++++++++++++++ usr/klibc/arch/i386/sigreturn.S | 15 ++++ usr/klibc/arch/i386/socketcall.S | 55 +++++++++++++ usr/klibc/arch/i386/syscall.S | 69 ++++++++++++++++ usr/klibc/arch/i386/sysstub.ph | 26 ++++++ usr/klibc/arch/i386/varsyscall.S | 36 +++++++++ usr/klibc/arch/i386/vfork.S | 26 ++++++ 24 files changed, 948 insertions(+), 0 deletions(-) diff --git a/usr/include/arch/i386/klibc/archconfig.h b/usr/include/arch/i386/klibc/archconfig.h new file mode 100644 index 0000000..4463d08 --- /dev/null +++ b/usr/include/arch/i386/klibc/archconfig.h @@ -0,0 +1,19 @@ +/* + * include/arch/i386/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +/* On i386, only half the signals are accessible using the legacy calls. */ +#define _KLIBC_USE_RT_SIG 1 + +/* The stock i386 kernel is fine, but a whole string of Fedora kernels + had a broken default restorer. It's easier to enable this here. */ +#define _KLIBC_NEEDS_SA_RESTORER 1 + +#endif /* _KLIBC_ARCHCONFIG_H */ diff --git a/usr/include/arch/i386/klibc/archsetjmp.h b/usr/include/arch/i386/klibc/archsetjmp.h new file mode 100644 index 0000000..ea1ba3d --- /dev/null +++ b/usr/include/arch/i386/klibc/archsetjmp.h @@ -0,0 +1,19 @@ +/* + * arch/i386/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned int __ebx; + unsigned int __esp; + unsigned int __ebp; + unsigned int __esi; + unsigned int __edi; + unsigned int __eip; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff --git a/usr/include/arch/i386/klibc/archsignal.h b/usr/include/arch/i386/klibc/archsignal.h new file mode 100644 index 0000000..6c942db --- /dev/null +++ b/usr/include/arch/i386/klibc/archsignal.h @@ -0,0 +1,114 @@ +/* + * arch/i386/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +/* The in-kernel headers for i386 still have libc5 + crap in them. Reconsider using + when/if it gets cleaned up; for now, duplicate + the definitions here. */ + +#define _NSIG 64 +#define _NSIG_BPW 32 +#define _NSIG_WORDS (_NSIG / _NSIG_BPW) + +typedef struct { + unsigned long sig[_NSIG_WORDS]; +} sigset_t; + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGIOT 6 +#define SIGBUS 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGUSR1 10 +#define SIGSEGV 11 +#define SIGUSR2 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGSTKFLT 16 +#define SIGCHLD 17 +#define SIGCONT 18 +#define SIGSTOP 19 +#define SIGTSTP 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGURG 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGIO 29 +#define SIGPOLL SIGIO +#define SIGPWR 30 +#define SIGSYS 31 +#define SIGUNUSED 31 + +#define SIGRTMIN 32 +#define SIGRTMAX (_NSIG-1) + +/* + * SA_FLAGS values: + * + * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the + * SA_RESTART flag to get restarting signals (which were the default long ago) + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. + * SA_RESETHAND clears the handler when the signal is delivered. + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. + * SA_NODEFER prevents the current signal from being masked in the handler. + * + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single + * Unix names RESETHAND and NODEFER respectively. + */ +#define SA_NOCLDSTOP 0x00000001u +#define SA_NOCLDWAIT 0x00000002u +#define SA_SIGINFO 0x00000004u +#define SA_ONSTACK 0x08000000u +#define SA_RESTART 0x10000000u +#define SA_NODEFER 0x40000000u +#define SA_RESETHAND 0x80000000u + +#define SA_NOMASK SA_NODEFER +#define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ + +#define SA_RESTORER 0x04000000 + +/* + * sigaltstack controls + */ +#define SS_ONSTACK 1 +#define SS_DISABLE 2 + +#define MINSIGSTKSZ 2048 +#define SIGSTKSZ 8192 + +#include + +/* This uses gcc anonymous union support... */ +struct siginfo; + +struct sigaction { + union { + __sighandler_t sa_handler; + void (*sa_sigaction)(int, struct siginfo *, void *); + }; + unsigned long sa_flags; + __sigrestore_t sa_restorer; + sigset_t sa_mask; +}; + +#endif diff --git a/usr/include/arch/i386/klibc/archstat.h b/usr/include/arch/i386/klibc/archstat.h new file mode 100644 index 0000000..c00f955 --- /dev/null +++ b/usr/include/arch/i386/klibc/archstat.h @@ -0,0 +1,38 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include + +#define _STATBUF_ST_NSEC + +/* This matches struct stat64 in glibc2.1, hence the absolutely + * insane amounts of padding around dev_t's. + */ +struct stat { + __stdev64 (st_dev); + unsigned char __pad0[4]; + + unsigned long __st_ino; + + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + __stdev64 (st_rdev); + unsigned char __pad3[4]; + + long long st_size; + unsigned long st_blksize; + + unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + + unsigned long long st_ino; +}; + +#endif diff --git a/usr/include/arch/i386/klibc/diverr.h b/usr/include/arch/i386/klibc/diverr.h new file mode 100644 index 0000000..fa238ac --- /dev/null +++ b/usr/include/arch/i386/klibc/diverr.h @@ -0,0 +1,15 @@ +/* + * arch/i386/include/klibc/diverr.h + */ + +#ifndef _KLIBC_DIVERR_H +#define _KLIBC_DIVERR_H + +#include + +static __inline__ void __divide_error(void) +{ + asm volatile ("int $0"); +} + +#endif /* _KLIBC_DIVERR_H */ diff --git a/usr/include/arch/i386/sys/io.h b/usr/include/arch/i386/sys/io.h new file mode 100644 index 0000000..cf31b97 --- /dev/null +++ b/usr/include/arch/i386/sys/io.h @@ -0,0 +1,127 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * sys/io.h for the i386 architecture + * + * Basic I/O macros + */ + +#ifndef _SYS_IO_H +#define _SYS_IO_H 1 + +/* I/O-related system calls */ + +int iopl(int); +int ioperm(unsigned long, unsigned long, int); + +/* Basic I/O macros */ + +static __inline__ void outb(unsigned char __v, unsigned short __p) +{ + asm volatile ("outb %0,%1" : : "a" (__v), "dN" (__p)); +} + +static __inline__ void outw(unsigned short __v, unsigned short __p) +{ + asm volatile ("outw %0,%1" : : "a" (__v), "dN" (__p)); +} + +static __inline__ void outl(unsigned int __v, unsigned short __p) +{ + asm volatile ("outl %0,%1" : : "a" (__v), "dN" (__p)); +} + +static __inline__ unsigned char inb(unsigned short __p) +{ + unsigned char __v; + asm volatile ("inb %1,%0" : "=a" (__v) : "dN" (__p)); + return __v; +} + +static __inline__ unsigned short inw(unsigned short __p) +{ + unsigned short __v; + asm volatile ("inw %1,%0" : "=a" (__v) : "dN" (__p)); + return __v; +} + +static __inline__ unsigned int inl(unsigned short __p) +{ + unsigned int __v; + asm volatile ("inl %1,%0" : "=a" (__v) : "dN" (__p)); + return __v; +} + +/* String I/O macros */ + +static __inline__ void +outsb(unsigned short __p, const void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; outsb" + : "+S" (__d), "+c" (__n) + : "d" (__p)); +} + +static __inline__ void +outsw(unsigned short __p, const void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; outsw" + : "+S" (__d), "+c" (__n) + : "d" (__p)); +} + +static __inline__ void +outsl(unsigned short __p, const void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; outsl" + : "+S" (__d), "+c"(__n) + : "d" (__p)); +} + +static __inline__ void insb(unsigned short __p, void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; insb" + : "+D" (__d), "+c" (__n) + : "d" (__p)); +} + +static __inline__ void insw(unsigned short __p, void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; insw" + : "+D" (__d), "+c" (__n) + : "d" (__p)); +} + +static __inline__ void insl(unsigned short __p, void *__d, unsigned long __n) +{ + asm volatile ("cld; rep; insl" + : "+D" (__d), "+c" (__n) + : "d" (__p)); +} + +#endif /* _SYS_IO_H */ diff --git a/usr/include/arch/i386/sys/vm86.h b/usr/include/arch/i386/sys/vm86.h new file mode 100644 index 0000000..c4651cd --- /dev/null +++ b/usr/include/arch/i386/sys/vm86.h @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2004 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * sys/vm86.h for i386 + */ + +#ifndef _SYS_VM86_H +#define _SYS_VM86_H 1 + +#include + +/* Actual system call */ +int vm86(struct vm86_struct *); + +#endif diff --git a/usr/klibc/arch/i386/MCONFIG b/usr/klibc/arch/i386/MCONFIG new file mode 100644 index 0000000..e173266 --- /dev/null +++ b/usr/klibc/arch/i386/MCONFIG @@ -0,0 +1,33 @@ +# -*- makefile -*- +# +# arch/i386/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +# Enable this to compile with register parameters; only safe for +# gcc >= 3 + +ifeq ($(CONFIG_REGPARM),y) +REGPARM_OPT := -mregparm=3 -D_REGPARM=3 +endif + +gcc_align_option := $(call cc-option, \ + -falign-functions=0 -falign-jumps=0 -falign-loops=0, \ + -malign-functions=0 -malign-jumps=0 -malign-loops=0) +gcc_m32_option := $(call cc-option, -m32, ) + +KLIBCOPTFLAGS = -march=i386 -Os -g -fomit-frame-pointer $(gcc_align_option) +KLIBCLDFLAGS = -m elf_i386 +KLIBCREQFLAGS += $(REGPARM_OPT) +KLIBCARCHREQFLAGS += $(gcc_m32_option) + +KLIBCBITSIZE = 32 + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# 96 MB - normal binaries start at 128 MB +KLIBCSHAREDFLAGS = -Ttext 0x06000200 diff --git a/usr/klibc/arch/i386/Makefile.inc b/usr/klibc/arch/i386/Makefile.inc new file mode 100644 index 0000000..d13a28f --- /dev/null +++ b/usr/klibc/arch/i386/Makefile.inc @@ -0,0 +1,30 @@ +# -*- makefile -*- +# +# arch/i386/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCARCHOBJS = \ + arch/$(KLIBCARCH)/socketcall.o \ + arch/$(KLIBCARCH)/setjmp.o \ + arch/$(KLIBCARCH)/syscall.o \ + arch/$(KLIBCARCH)/varsyscall.o \ + arch/$(KLIBCARCH)/open.o \ + arch/$(KLIBCARCH)/openat.o \ + arch/$(KLIBCARCH)/sigreturn.o \ + arch/$(KLIBCARCH)/vfork.o \ + arch/$(KLIBCARCH)/libgcc/__ashldi3.o \ + arch/$(KLIBCARCH)/libgcc/__ashrdi3.o \ + arch/$(KLIBCARCH)/libgcc/__lshrdi3.o \ + arch/$(KLIBCARCH)/libgcc/__muldi3.o \ + arch/$(KLIBCARCH)/libgcc/__negdi2.o \ + libgcc/__divdi3.o \ + libgcc/__moddi3.o \ + libgcc/__udivdi3.o \ + libgcc/__umoddi3.o \ + libgcc/__udivmoddi4.o + +archclean: diff --git a/usr/klibc/arch/i386/crt0.S b/usr/klibc/arch/i386/crt0.S new file mode 100644 index 0000000..8c6635e --- /dev/null +++ b/usr/klibc/arch/i386/crt0.S @@ -0,0 +1,31 @@ +# +# arch/i386/crt0.S +# +# Does arch-specific initialization and invokes __libc_init +# with the appropriate arguments. +# +# See __static_init.c or __shared_init.c for the expected +# arguments. +# + + .text + .align 4 + .type _start,@function + .globl _start +_start: + # Save the address of the ELF argument array + movl %esp,%eax # Address of ELF arguments + # Set up a faux stack frame for the benefit of gdb + xorl %ebp,%ebp + push %ebp # Keep gdb from getting confused + push %ebp # Keep gdb from getting confused + # Push the arguments and called __libc_init() +#ifndef _REGPARM + push %edx # atexit() function + push %eax # ELF array +#endif + call __libc_init + # If __libc_init returns, problem... + hlt + + .size _start, .-_start diff --git a/usr/klibc/arch/i386/libgcc/__ashldi3.S b/usr/klibc/arch/i386/libgcc/__ashldi3.S new file mode 100644 index 0000000..7344142 --- /dev/null +++ b/usr/klibc/arch/i386/libgcc/__ashldi3.S @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__ashldi3.S + * + * 64-bit shl + */ + .text + .align 4 + .globl __ashldi3 + .type __ashldi3,@function +__ashldi3: +#ifndef _REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx + movb 12(%esp),%cl +#endif + cmpb $32,%cl + jae 1f + + shldl %cl,%eax,%edx + shl %cl,%eax + ret + +1: + xorl %edx,%edx + shl %cl,%eax + xchgl %edx,%eax + ret + + .size __ashldi3,.-__ashldi3 diff --git a/usr/klibc/arch/i386/libgcc/__ashrdi3.S b/usr/klibc/arch/i386/libgcc/__ashrdi3.S new file mode 100644 index 0000000..7666eb2 --- /dev/null +++ b/usr/klibc/arch/i386/libgcc/__ashrdi3.S @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__ashrdi3.S + * + * 64-bit sar + */ + .text + .align 4 + .globl __ashrdi3 + .type __ashrdi3,@function +__ashrdi3: +#ifndef _REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx + movb 12(%esp),%cl +#endif + cmpb $32,%cl + jae 1f + + shrdl %cl,%edx,%eax + sarl %cl,%edx + ret + +1: + sarl %cl,%edx + movl %edx,%eax + cdq + ret + + .size __ashrdi3,.-__ashrdi3 diff --git a/usr/klibc/arch/i386/libgcc/__lshrdi3.S b/usr/klibc/arch/i386/libgcc/__lshrdi3.S new file mode 100644 index 0000000..6a63c52 --- /dev/null +++ b/usr/klibc/arch/i386/libgcc/__lshrdi3.S @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__lshrdi3.S + * + * 64-bit shr + */ + .text + .align 4 + .globl __lshrdi3 + .type __lshrdi3,@function +__lshrdi3: +#ifndef _REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx + movb 12(%esp),%cl +#endif + cmpb $32,%cl + jae 1f + + shrdl %cl,%edx,%eax + shrl %cl,%edx + ret + +1: + shrl %cl,%edx + xorl %eax,%eax + xchgl %edx,%eax + ret + + .size __lshrdi3,.-__lshrdi3 diff --git a/usr/klibc/arch/i386/libgcc/__muldi3.S b/usr/klibc/arch/i386/libgcc/__muldi3.S new file mode 100644 index 0000000..472c7cc --- /dev/null +++ b/usr/klibc/arch/i386/libgcc/__muldi3.S @@ -0,0 +1,34 @@ +/* + * arch/i386/libgcc/__muldi3.S + * + * 64*64 = 64 bit unsigned multiplication + */ + + .text + .align 4 + .globl __muldi3 + .type __muldi3,@function +__muldi3: + push %esi +#ifndef _REGPARM + movl 8(%esp),%eax + movl %eax,%esi + movl 16(%esp),%ecx + mull %ecx + imull 12(%esp),%ecx + imull 20(%esp),%esi + addl %ecx,%edx + addl %esi,%edx +#else + movl %eax,%esi + push %edx + mull %ecx + imull 8(%esp),%esi + addl %esi,%edx + pop %esi + imull %esi,%ecx + addl %ecx,%edx +#endif + pop %esi + ret + .size __muldi3,.-__muldi3 diff --git a/usr/klibc/arch/i386/libgcc/__negdi2.S b/usr/klibc/arch/i386/libgcc/__negdi2.S new file mode 100644 index 0000000..147ad94 --- /dev/null +++ b/usr/klibc/arch/i386/libgcc/__negdi2.S @@ -0,0 +1,21 @@ +/* + * arch/i386/libgcc/__negdi2.S + * + * 64-bit negation + */ + + .text + .align 4 + .globl __negdi2 + .type __negdi2,@function +__negdi2: +#ifndef _REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx +#endif + negl %edx + negl %eax + sbbl $0,%edx + ret + + .size __negdi2,.-__negdi2 diff --git a/usr/klibc/arch/i386/open.S b/usr/klibc/arch/i386/open.S new file mode 100644 index 0000000..7cd136c --- /dev/null +++ b/usr/klibc/arch/i386/open.S @@ -0,0 +1,29 @@ +/* + * arch/i386/open.S + * + * Handle the open() system call - oddball due to the varadic + * prototype, which forces the use of the cdecl calling convention, + * and the need for O_LARGEFILE. + */ + +#include + +/* , despite the name, isn't assembly-safe */ +#define O_LARGEFILE 0100000 + + .globl open + .type open,@function + +open: +#ifdef _REGPARM + movl 4(%esp),%eax + movl 8(%esp),%edx + movl 12(%esp),%ecx + orl $O_LARGEFILE,%edx +#else + orl $O_LARGEFILE,8(%esp) +#endif + pushl $__NR_open + jmp __syscall_common + + .size open,.-open diff --git a/usr/klibc/arch/i386/openat.S b/usr/klibc/arch/i386/openat.S new file mode 100644 index 0000000..2dfdfe2 --- /dev/null +++ b/usr/klibc/arch/i386/openat.S @@ -0,0 +1,26 @@ +/* + * arch/i386/openat.S + * + * Handle the openat() system call - oddball due to the varadic + * prototype, which forces the use of the cdecl calling convention, + * and the need for O_LARGEFILE. + */ + +#include + +/* , despite the name, isn't assembly-safe */ +#define O_LARGEFILE 0100000 + +#ifdef __NR_openat /* Don't build if kernel headers too old */ + + .globl openat + .type openat,@function + +openat: + orl $O_LARGEFILE,12(%esp) + pushl $__NR_openat + jmp __syscall_varadic + + .size openat,.-openat + +#endif diff --git a/usr/klibc/arch/i386/setjmp.S b/usr/klibc/arch/i386/setjmp.S new file mode 100644 index 0000000..b766792 --- /dev/null +++ b/usr/klibc/arch/i386/setjmp.S @@ -0,0 +1,58 @@ +# +# arch/i386/setjmp.S +# +# setjmp/longjmp for the i386 architecture +# + +# +# The jmp_buf is assumed to contain the following, in order: +# %ebx +# %esp +# %ebp +# %esi +# %edi +# +# + + .text + .align 4 + .globl setjmp + .type setjmp, @function +setjmp: +#ifdef _REGPARM + movl %eax,%edx +#else + movl 4(%esp),%edx +#endif + popl %ecx # Return address, and adjust the stack + xorl %eax,%eax # Return value + movl %ebx,(%edx) + movl %esp,4(%edx) # Post-return %esp! + pushl %ecx # Make the call/return stack happy + movl %ebp,8(%edx) + movl %esi,12(%edx) + movl %edi,16(%edx) + movl %ecx,20(%edx) # Return address + ret + + .size setjmp,.-setjmp + + .text + .align 4 + .globl longjmp + .type longjmp, @function +longjmp: +#ifdef _REGPARM + xchgl %eax,%edx +#else + movl 4(%esp),%edx # jmp_ptr address + movl 8(%esp),%eax # Return value +#endif + movl (%edx),%ebx + movl 4(%edx),%esp + movl 8(%edx),%ebp + movl 12(%edx),%esi + movl 16(%edx),%edi + jmp *20(%edx) + + .size longjmp,.-longjmp diff --git a/usr/klibc/arch/i386/sigreturn.S b/usr/klibc/arch/i386/sigreturn.S new file mode 100644 index 0000000..f2a3241 --- /dev/null +++ b/usr/klibc/arch/i386/sigreturn.S @@ -0,0 +1,15 @@ +# +# arch/i386/sigreturn.S +# + +#include + + .text + .align 4 + .globl __sigreturn + .type __sigreturn,@function +__sigreturn: + pop %eax # Have no idea why this is needed... + movl $__NR_sigreturn,%eax + int $0x80 + .size __sigreturn,.-__sigreturn diff --git a/usr/klibc/arch/i386/socketcall.S b/usr/klibc/arch/i386/socketcall.S new file mode 100644 index 0000000..816db34 --- /dev/null +++ b/usr/klibc/arch/i386/socketcall.S @@ -0,0 +1,55 @@ +# +# socketcall.S +# +# Socketcalls use the following convention: +# %eax = __NR_socketcall +# %ebx = socketcall number +# %ecx = pointer to arguments (up to 6) +# + +#include + +#ifdef __i386__ + + .text + .align 4 + .globl __socketcall_common + .type __socketcall_common, @function + +__socketcall_common: + xchgl %ebx,(%esp) # The stub passes the socketcall # on stack + +#ifdef _REGPARM + pushl 16(%esp) # Arg 6 + pushl 16(%esp) # Arg 5 + pushl 16(%esp) # Arg 4 + pushl %ecx + pushl %edx + pushl %eax + movl %esp,%ecx +#else + leal 8(%esp),%ecx # Arguments already contiguous on-stack +#endif + + movl $__NR_socketcall,%eax + int $0x80 + +#ifdef _REGPARM + addl $6*4, %esp +#endif + + cmpl $-4095,%eax # Error return? + + popl %ebx + + jb 1f + + negl %eax + movl %eax,errno + orl $-1,%eax # Return -1 +1: + ret + + .size __socketcall_common,.-__socketcall_common + +#endif diff --git a/usr/klibc/arch/i386/syscall.S b/usr/klibc/arch/i386/syscall.S new file mode 100644 index 0000000..d28717b --- /dev/null +++ b/usr/klibc/arch/i386/syscall.S @@ -0,0 +1,69 @@ +/* + * arch/i386/syscall.S + * + * Common tail-handling code for system calls. + * + * The arguments are on the stack; the system call number in %eax. + */ + +#define ARG(n) (4*n+20)(%esp) + + .text + .align 4 + .globl __syscall_common + .type __syscall_common,@function +__syscall_common: +#ifdef _REGPARM + xchgl %ebx,(%esp) +#else + popl %eax + pushl %ebx +#endif + pushl %esi + pushl %edi + pushl %ebp + +#ifdef _REGPARM + xchgl %eax,%ebx + xchgl %ecx,%edx + movl ARG(0),%esi + movl ARG(1),%edi + movl ARG(2),%ebp +#else + movl ARG(0),%ebx # Syscall arguments + movl ARG(1),%ecx + movl ARG(2),%edx + movl ARG(3),%esi + movl ARG(4),%edi + movl ARG(5),%ebp +#endif + .globl __syscall_common_tail +__syscall_common_tail: + int $0x80 + + cmpl $-4095,%eax + + popl %ebp + popl %edi + popl %esi + popl %ebx + + jb 1f + + # Error return, must set errno + negl %eax + movl %eax,errno + orl $-1,%eax # Return -1 + +1: + ret + + .size __syscall_common,.-__syscall_common + +#ifndef _REGPARM + + .globl __syscall_varadic + .type __syscall_varadic,@function +__syscall_varadic = __syscall_common + +#endif diff --git a/usr/klibc/arch/i386/sysstub.ph b/usr/klibc/arch/i386/sysstub.ph new file mode 100644 index 0000000..e73a3ff --- /dev/null +++ b/usr/klibc/arch/i386/sysstub.ph @@ -0,0 +1,26 @@ +# -*- perl -*- +# +# arch/i386/sysstub.ph +# +# Script to generate system call stubs +# + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.type ${fname},\@function\n"; + print OUT "\t.globl ${fname}\n"; + print OUT "${fname}:\n"; + + $stype = 'common' if ( $stype eq '' ); + + print OUT "\tpushl \$__NR_${sname}\n"; + print OUT "\tjmp __syscall_$stype\n"; + print OUT "\t.size ${fname},.-${fname}\n"; + close(OUT); +} + +1; diff --git a/usr/klibc/arch/i386/varsyscall.S b/usr/klibc/arch/i386/varsyscall.S new file mode 100644 index 0000000..24329ea --- /dev/null +++ b/usr/klibc/arch/i386/varsyscall.S @@ -0,0 +1,36 @@ +/* + * arch/i386/varsyscall.S + * + * Common tail-handling code for varadic system calls (which always + * use the cdecl convention.) + * + * The arguments are on the stack; the system call number in %eax. + */ + +#ifdef _REGPARM + +#define ARG(n) (4*n+20)(%esp) + + .text + .align 4 + .globl __syscall_varadic + .type __syscall_varadic,@function +__syscall_varadic: + popl %eax + pushl %ebx + pushl %esi + pushl %edi + pushl %ebp + + movl ARG(0),%ebx # Syscall arguments + movl ARG(1),%ecx + movl ARG(2),%edx + movl ARG(3),%esi + movl ARG(4),%edi + movl ARG(5),%ebp + + jmp __syscall_common_tail + + .size __syscall_varadic,.-__syscall_varadic + +#endif diff --git a/usr/klibc/arch/i386/vfork.S b/usr/klibc/arch/i386/vfork.S new file mode 100644 index 0000000..c98ba3a --- /dev/null +++ b/usr/klibc/arch/i386/vfork.S @@ -0,0 +1,26 @@ +# +# usr/klibc/arch/i386/vfork.S +# +# vfork is nasty - there must be nothing at all on the stack above +# the stack frame of the enclosing function. +# + +#include + + .text + .align 4 + .globl vfork + .type vfork, @function +vfork: + popl %edx /* Return address */ + movl $__NR_vfork, %eax + int $0x80 + pushl %edx + cmpl $-4095, %eax + jae 1f + ret +1: + negl %eax + movl %eax, errno + orl $-1, %eax + ret