diff options
Diffstat (limited to 'arch')
65 files changed, 2987 insertions, 1672 deletions
diff --git a/arch/alpha/config.in b/arch/alpha/config.in index 9c74cc091..84402f1e0 100644 --- a/arch/alpha/config.in +++ b/arch/alpha/config.in @@ -134,6 +134,8 @@ if [ "$CONFIG_NET" = "y" ]; then endmenu fi +source drivers/net/hamradio/Config.in + mainmenu_option next_comment comment 'ISDN subsystem' @@ -152,6 +154,17 @@ if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then fi endmenu +# Conditionally compile in the Uniform CD-ROM driver +if [ "$CONFIG_BLK_DEV_IDECD" = "y" -o "$CONFIG_BLK_DEV_SR" = "y" -o "$CONFIG_SBPCD" = "y" -o "$CONFIG_MCD" = "y" -o "$CONFIG_CM206" = "y" -o "$CONFIG_CDU31A" = "y" ]; then + define_bool CONFIG_CDROM y +else + if [ "$CONFIG_BLK_DEV_IDECD" = "m" -o "$CONFIG_BLK_DEV_SR" = "m" -o "$CONFIG_SBPCD" = "m" -o "$CONFIG_MCD" = "m" -o "$CONFIG_CM206" = "m" -o "$CONFIG_CDU31A" = "m" ]; then + define_bool CONFIG_CDROM m + else + define_bool CONFIG_CDROM n + fi +fi + source fs/Config.in source fs/nls/Config.in diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index be75f566f..822513e4e 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c @@ -94,7 +94,7 @@ EXPORT_SYMBOL(csum_partial_copy); * The following are specially called from the uaccess assembly stubs. */ EXPORT_SYMBOL_NOVERS(__copy_user); -EXPORT_SYMBOL_NOVERS(__clear_user); +EXPORT_SYMBOL_NOVERS(__do_clear_user); EXPORT_SYMBOL(__strncpy_from_user); EXPORT_SYMBOL(__strlen_user); diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 75c0665a7..0eef8b539 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -10,7 +10,7 @@ #define rti .long PAL_rti #define SIGCHLD 20 -#define NR_SYSCALLS 352 +#define NR_SYSCALLS 360 #define osf_vfork sys_fork /* @@ -32,9 +32,8 @@ #define TASK_STATE 0 #define TASK_COUNTER 8 #define TASK_PRIORITY 16 -#define TASK_SIGNAL 24 -#define TASK_BLOCKED 32 -#define TASK_FLAGS 40 +#define TASK_FLAGS 24 +#define TASK_SIGPENDING 32 /* * task flags (must match include/linux/sched.h): @@ -509,7 +508,7 @@ entSys: lda $4,NR_SYSCALLS($31) stq $16,SP_OFF+24($30) lda $5,sys_call_table - lda $27,do_entSys + lda $27,alpha_ni_syscall cmpult $0,$4,$4 ldq $3,TASK_FLAGS($8) stq $17,SP_OFF+32($30) @@ -519,7 +518,7 @@ entSys: bne $3,strace beq $4,1f ldq $27,0($5) -1: jsr $26,($27),do_entSys +1: jsr $26,($27),alpha_ni_syscall ldgp $29,0($26) blt $0,syscall_error /* the call failed */ stq $0,0($30) @@ -544,11 +543,9 @@ ret_from_reschedule: lda $4,init_task_union bne $2,reschedule xor $4,$8,$4 + ldl $5,TASK_SIGPENDING($8) beq $4,restore_all - ldq $4,TASK_SIGNAL($8) - ldq $16,TASK_BLOCKED($8) - bic $4,$16,$4 - bne $4,signal_return + bne $5,signal_return restore_all: RESTORE_ALL rti @@ -574,12 +571,12 @@ strace: /* get the system call pointer.. */ lda $1,NR_SYSCALLS($31) lda $2,sys_call_table - lda $27,do_entSys + lda $27,alpha_ni_syscall cmpult $0,$1,$1 s8addq $0,$2,$2 beq $1,1f ldq $27,0($2) -1: jsr $26,($27),do_entSys +1: jsr $26,($27),alpha_ni_syscall ldgp $29,0($26) /* check return.. */ @@ -656,6 +653,7 @@ signal_return: bis $30,$30,$17 br $1,do_switch_stack bis $30,$30,$18 + bis $31,$31,$16 jsr $26,do_signal lda $30,SWITCH_STACK_SIZE($30) br $31,restore_all @@ -686,6 +684,17 @@ sys_sigreturn: .end sys_sigreturn .align 3 +.ent sys_rt_sigreturn +sys_rt_sigreturn: + bis $30,$30,$17 + lda $30,-SWITCH_STACK_SIZE($30) + bis $30,$30,$18 + jsr $26,do_rt_sigreturn + br $1,undo_switch_stack + br $31,ret_from_sys_call +.end sys_rt_sigreturn + +.align 3 .ent sys_sigsuspend sys_sigsuspend: bis $30,$30,$17 @@ -696,80 +705,383 @@ sys_sigsuspend: br $31,ret_from_sys_call .end sys_sigsuspend +.align 3 +.ent sys_rt_sigsuspend +sys_rt_sigsuspend: + bis $30,$30,$18 + br $1,do_switch_stack + bis $30,$30,$19 + jsr $26,do_rt_sigsuspend + lda $30,SWITCH_STACK_SIZE($30) + br $31,ret_from_sys_call +.end sys_rt_sigsuspend + + .data .align 3 .globl sys_call_table sys_call_table: -/*0*/ .quad do_entSys, sys_exit, sys_fork, sys_read, sys_write - .quad do_entSys, sys_close, sys_wait4, do_entSys, sys_link - .quad sys_unlink, do_entSys, sys_chdir, sys_fchdir, sys_mknod - .quad sys_chmod, sys_chown, osf_brk, do_entSys, sys_lseek - .quad sys_getxpid, osf_mount, osf_umount, sys_setuid, sys_getxuid - .quad do_entSys, sys_ptrace, do_entSys, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, sys_access, do_entSys - .quad do_entSys, sys_sync, sys_kill, do_entSys, sys_setpgid - .quad do_entSys, sys_dup, sys_pipe, osf_set_program_attributes, do_entSys - .quad sys_open, do_entSys, sys_getxgid, osf_sigprocmask, do_entSys -/*50*/ .quad do_entSys, sys_acct, sys_sigpending, do_entSys, sys_ioctl - .quad do_entSys, do_entSys, sys_symlink, sys_readlink, sys_execve - .quad sys_umask, sys_chroot, do_entSys, sys_getpgrp, sys_getpagesize - .quad do_entSys, osf_vfork, sys_newstat, sys_newlstat, do_entSys - .quad do_entSys, osf_mmap, do_entSys, sys_munmap, sys_mprotect - .quad sys_madvise, sys_vhangup, do_entSys, do_entSys, sys_getgroups + .quad alpha_ni_syscall /* 0 */ + .quad sys_exit + .quad sys_fork + .quad sys_read + .quad sys_write + .quad alpha_ni_syscall /* 5 */ + .quad sys_close + .quad osf_wait4 + .quad alpha_ni_syscall + .quad sys_link + .quad sys_unlink /* 10 */ + .quad alpha_ni_syscall + .quad sys_chdir + .quad sys_fchdir + .quad sys_mknod + .quad sys_chmod /* 15 */ + .quad sys_chown + .quad osf_brk + .quad alpha_ni_syscall + .quad sys_lseek + .quad sys_getxpid /* 20 */ + .quad osf_mount + .quad osf_umount + .quad sys_setuid + .quad sys_getxuid + .quad alpha_ni_syscall /* 25 */ + .quad sys_ptrace + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 30 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad sys_access + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 35 */ + .quad sys_sync + .quad sys_kill + .quad alpha_ni_syscall + .quad sys_setpgid + .quad alpha_ni_syscall /* 40 */ + .quad sys_dup + .quad sys_pipe + .quad osf_set_program_attributes + .quad alpha_ni_syscall + .quad sys_open /* 45 */ + .quad alpha_ni_syscall + .quad sys_getxgid + .quad osf_sigprocmask + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 50 */ + .quad sys_acct + .quad osf_sigpending + .quad alpha_ni_syscall + .quad sys_ioctl + .quad alpha_ni_syscall /* 55 */ + .quad alpha_ni_syscall + .quad sys_symlink + .quad sys_readlink + .quad sys_execve + .quad sys_umask /* 60 */ + .quad sys_chroot + .quad alpha_ni_syscall + .quad sys_getpgrp + .quad sys_getpagesize + .quad alpha_ni_syscall /* 65 */ + .quad osf_vfork + .quad sys_newstat + .quad sys_newlstat + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 70 */ + .quad osf_mmap + .quad alpha_ni_syscall + .quad sys_munmap + .quad sys_mprotect + .quad sys_madvise /* 75 */ + .quad sys_vhangup + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad sys_getgroups /* map BSD's setpgrp to sys_setpgid for binary compatibility: */ - .quad sys_setgroups, do_entSys, sys_setpgid, sys_setitimer, do_entSys - .quad do_entSys, sys_getitimer, sys_gethostname, sys_sethostname, sys_getdtablesize - .quad sys_dup2, sys_newfstat, sys_fcntl, sys_select, sys_poll - .quad sys_fsync, sys_setpriority, sys_socket, sys_connect, sys_accept -/*100*/ .quad osf_getpriority, sys_send, sys_recv, sys_sigreturn, sys_bind - .quad sys_setsockopt, sys_listen, do_entSys, do_entSys, do_entSys - .quad do_entSys, sys_sigsuspend, do_entSys, sys_recvmsg, sys_sendmsg - .quad do_entSys, sys_gettimeofday, sys_getrusage, sys_getsockopt, do_entSys - .quad sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod - .quad sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate - .quad sys_ftruncate, sys_flock, sys_setgid, sys_sendto, sys_shutdown - .quad sys_socketpair, sys_mkdir, sys_rmdir, sys_utimes, do_entSys - .quad do_entSys, sys_getpeername, do_entSys, do_entSys, sys_getrlimit - .quad sys_setrlimit, do_entSys, sys_setsid, sys_quotactl, do_entSys -/*150*/ .quad sys_getsockname, do_entSys, do_entSys, do_entSys, do_entSys - .quad do_entSys, sys_sigaction, do_entSys, do_entSys, osf_getdirentries - .quad osf_statfs, osf_fstatfs, do_entSys, do_entSys, do_entSys - .quad osf_getdomainname, sys_setdomainname, do_entSys, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, do_entSys, osf_swapon -/*200*/ .quad sys_msgctl, sys_msgget, sys_msgrcv, sys_msgsnd, sys_semctl - .quad sys_semget, sys_semop, osf_utsname, do_entSys, osf_shmat - .quad sys_shmctl, sys_shmdt, sys_shmget, do_entSys, do_entSys - .quad do_entSys, do_entSys, sys_msync, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, sys_getpgid, sys_getsid - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys - .quad do_entSys, osf_sysinfo, do_entSys, do_entSys, osf_proplist_syscall - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys -/*250*/ .quad do_entSys, osf_usleep_thread, do_entSys, do_entSys, sys_sysfs - .quad do_entSys, osf_getsysinfo, osf_setsysinfo, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys - .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys + .quad sys_setgroups /* 80 */ + .quad alpha_ni_syscall + .quad sys_setpgid + .quad osf_setitimer + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 85 */ + .quad osf_getitimer + .quad sys_gethostname + .quad sys_sethostname + .quad sys_getdtablesize + .quad sys_dup2 /* 90 */ + .quad sys_newfstat + .quad sys_fcntl + .quad osf_select + .quad sys_poll + .quad sys_fsync /* 95 */ + .quad sys_setpriority + .quad sys_socket + .quad sys_connect + .quad sys_accept + .quad osf_getpriority /* 100 */ + .quad sys_send + .quad sys_recv + .quad sys_sigreturn + .quad sys_bind + .quad sys_setsockopt /* 105 */ + .quad sys_listen + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 110 */ + .quad sys_sigsuspend + .quad alpha_ni_syscall + .quad sys_recvmsg + .quad sys_sendmsg + .quad alpha_ni_syscall /* 115 */ + .quad osf_gettimeofday + .quad osf_getrusage + .quad sys_getsockopt + .quad alpha_ni_syscall + .quad sys_readv /* 120 */ + .quad sys_writev + .quad osf_settimeofday + .quad sys_fchown + .quad sys_fchmod + .quad sys_recvfrom /* 125 */ + .quad sys_setreuid + .quad sys_setregid + .quad sys_rename + .quad sys_truncate + .quad sys_ftruncate /* 130 */ + .quad sys_flock + .quad sys_setgid + .quad sys_sendto + .quad sys_shutdown + .quad sys_socketpair /* 135 */ + .quad sys_mkdir + .quad sys_rmdir + .quad osf_utimes + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 140 */ + .quad sys_getpeername + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad sys_getrlimit + .quad sys_setrlimit /* 145 */ + .quad alpha_ni_syscall + .quad sys_setsid + .quad sys_quotactl + .quad alpha_ni_syscall + .quad sys_getsockname /* 150 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 155 */ + .quad osf_sigaction + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad osf_getdirentries + .quad osf_statfs /* 160 */ + .quad osf_fstatfs + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad osf_getdomainname /* 165 */ + .quad sys_setdomainname + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 170 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 175 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 180 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 185 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 190 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 195 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad osf_swapon + .quad sys_msgctl /* 200 */ + .quad sys_msgget + .quad sys_msgrcv + .quad sys_msgsnd + .quad sys_semctl + .quad sys_semget /* 205 */ + .quad sys_semop + .quad osf_utsname + .quad alpha_ni_syscall + .quad osf_shmat + .quad sys_shmctl /* 210 */ + .quad sys_shmdt + .quad sys_shmget + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 215 */ + .quad alpha_ni_syscall + .quad sys_msync + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 220 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 225 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 230 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad sys_getpgid + .quad sys_getsid + .quad alpha_ni_syscall /* 235 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 240 */ + .quad osf_sysinfo + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad osf_proplist_syscall + .quad alpha_ni_syscall /* 245 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 250 */ + .quad osf_usleep_thread + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad sys_sysfs + .quad alpha_ni_syscall /* 255 */ + .quad osf_getsysinfo + .quad osf_setsysinfo + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 260 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 265 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 270 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 275 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 280 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 285 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 290 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 295 */ + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* linux-specific system calls start at 300 */ -/*300*/ .quad sys_bdflush, sys_sethae, sys_mount, sys_adjtimex, sys_swapoff - .quad sys_getdents, alpha_create_module, sys_init_module, sys_delete_module, sys_get_kernel_syms - .quad sys_syslog, sys_reboot, sys_clone, sys_uselib, sys_mlock - .quad sys_munlock, sys_mlockall, sys_munlockall, sys_sysinfo, sys_sysctl - .quad sys_idle, sys_umount, sys_swapon, sys_times, sys_personality - .quad sys_setfsuid, sys_setfsgid, sys_ustat, sys_statfs, sys_fstatfs - .quad sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler, sys_sched_yield - .quad sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, do_entSys /* sys_afs_syscall */, sys_newuname - .quad sys_nanosleep, sys_mremap, sys_nfsservctl, sys_setresuid, sys_getresuid - .quad sys_pciconfig_read, sys_pciconfig_write, sys_query_module - .quad sys_prctl, sys_pread, sys_pwrite - .quad do_entSys, do_entSys + .quad sys_bdflush /* 300 */ + .quad sys_sethae + .quad sys_mount + .quad sys_adjtimex + .quad sys_swapoff + .quad sys_getdents /* 305 */ + .quad alpha_create_module + .quad sys_init_module + .quad sys_delete_module + .quad sys_get_kernel_syms + .quad sys_syslog /* 310 */ + .quad sys_reboot + .quad sys_clone + .quad sys_uselib + .quad sys_mlock + .quad sys_munlock /* 315 */ + .quad sys_mlockall + .quad sys_munlockall + .quad sys_sysinfo + .quad sys_sysctl + .quad sys_idle /* 320 */ + .quad sys_umount + .quad sys_swapon + .quad sys_times + .quad sys_personality + .quad sys_setfsuid /* 325 */ + .quad sys_setfsgid + .quad sys_ustat + .quad sys_statfs + .quad sys_fstatfs + .quad sys_sched_setparam /* 330 */ + .quad sys_sched_getparam + .quad sys_sched_setscheduler + .quad sys_sched_getscheduler + .quad sys_sched_yield + .quad sys_sched_get_priority_max /* 335 */ + .quad sys_sched_get_priority_min + .quad sys_sched_rr_get_interval + .quad alpha_ni_syscall /* sys_afs_syscall */ + .quad sys_newuname + .quad sys_nanosleep /* 340 */ + .quad sys_mremap + .quad sys_nfsservctl + .quad sys_setresuid + .quad sys_getresuid + .quad sys_pciconfig_read /* 345 */ + .quad sys_pciconfig_write + .quad sys_query_module + .quad sys_prctl + .quad sys_pread + .quad sys_pwrite /* 350 */ + .quad sys_rt_sigreturn + .quad sys_rt_sigaction + .quad sys_rt_sigprocmask + .quad sys_rt_sigpending + .quad sys_rt_sigtimedwait /* 355 */ + .quad sys_rt_sigqueueinfo + .quad sys_rt_sigsuspend + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall + .quad alpha_ni_syscall /* 360 */ diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index a736704a0..e64b6d5e1 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -28,6 +28,7 @@ #include <linux/stat.h> #include <linux/mman.h> #include <linux/shm.h> +#include <linux/poll.h> #include <asm/fpu.h> #include <asm/io.h> @@ -167,6 +168,9 @@ out: return error; } +#undef ROUND_UP +#undef NAME_OFFSET + /* * Alpha syscall convention has no problem returning negative * values: @@ -202,24 +206,24 @@ asmlinkage unsigned long sys_madvise(void) /* * No need to acquire the kernel lock, we're local.. */ -asmlinkage unsigned long sys_getxuid(int a0, int a1, int a2, int a3, int a4, int a5, - struct pt_regs regs) +asmlinkage unsigned long sys_getxuid(int a0, int a1, int a2, int a3, int a4, + int a5, struct pt_regs regs) { struct task_struct * tsk = current; (®s)->r20 = tsk->euid; return tsk->uid; } -asmlinkage unsigned long sys_getxgid(int a0, int a1, int a2, int a3, int a4, int a5, - struct pt_regs regs) +asmlinkage unsigned long sys_getxgid(int a0, int a1, int a2, int a3, int a4, + int a5, struct pt_regs regs) { struct task_struct * tsk = current; (®s)->r20 = tsk->egid; return tsk->gid; } -asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4, int a5, - struct pt_regs regs) +asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4, + int a5, struct pt_regs regs) { struct task_struct *tsk = current; @@ -524,47 +528,6 @@ asmlinkage int osf_umount(char *path, int flag) return ret; } -/* - * I don't know what the parameters are: the first one - * seems to be a timeval pointer, and I suspect the second - * one is the time remaining.. Ho humm.. No documentation. - */ -asmlinkage int osf_usleep_thread(struct timeval *sleep, struct timeval *remain) -{ - struct timeval tmp; - unsigned long ticks; - int retval; - - lock_kernel(); - retval = verify_area(VERIFY_READ, sleep, sizeof(*sleep)); - if (retval) - goto out; - if (remain && (retval = verify_area(VERIFY_WRITE, remain, sizeof(*remain)))) - goto out; - copy_from_user(&tmp, sleep, sizeof(*sleep)); - ticks = tmp.tv_usec; - ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ); - ticks += tmp.tv_sec * HZ; - current->timeout = ticks + jiffies; - current->state = TASK_INTERRUPTIBLE; - schedule(); - retval = 0; - if (!remain) - goto out; - ticks = jiffies; - if (ticks < current->timeout) - ticks = current->timeout - ticks; - else - ticks = 0; - current->timeout = 0; - tmp.tv_sec = ticks / HZ; - tmp.tv_usec = ticks % HZ; - copy_to_user(remain, &tmp, sizeof(*remain)); -out: - unlock_kernel(); - return retval; -} - asmlinkage int osf_utsname(char *name) { int error; @@ -956,3 +919,358 @@ asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer, return -EOPNOTSUPP; } + +/* Translations due to the fact that OSF's time_t is an int. Which + affects all sorts of things, like timeval and itimerval. */ + +extern struct timezone sys_tz; +extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz); +extern int do_getitimer(int which, struct itimerval *value); +extern int do_setitimer(int which, struct itimerval *, struct itimerval *); +asmlinkage int sys_utimes(char *, struct timeval *); +extern int sys_wait4(pid_t, int *, int, struct rusage *); + +struct timeval32 +{ + int tv_sec, tv_usec; +}; + +struct itimerval32 +{ + struct timeval32 it_interval; + struct timeval32 it_value; +}; + +static inline long get_tv32(struct timeval *o, struct timeval32 *i) +{ + return (!access_ok(VERIFY_READ, i, sizeof(*i)) || + (__get_user(o->tv_sec, &i->tv_sec) | + __get_user(o->tv_usec, &i->tv_usec))); +} + +static inline long put_tv32(struct timeval32 *o, struct timeval *i) +{ + return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || + (__put_user(i->tv_sec, &o->tv_sec) | + __put_user(i->tv_usec, &o->tv_usec))); +} + +static inline long get_it32(struct itimerval *o, struct itimerval32 *i) +{ + return (!access_ok(VERIFY_READ, i, sizeof(*i)) || + (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) | + __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) | + __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) | + __get_user(o->it_value.tv_usec, &i->it_value.tv_usec))); +} + +static inline long put_it32(struct itimerval32 *o, struct itimerval *i) +{ + return (!access_ok(VERIFY_WRITE, i, sizeof(*i)) || + (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) | + __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) | + __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) | + __put_user(i->it_value.tv_usec, &o->it_value.tv_usec))); +} + +asmlinkage int osf_gettimeofday(struct timeval32 *tv, struct timezone *tz) +{ + if (tv) { + struct timeval ktv; + do_gettimeofday(&ktv); + if (put_tv32(tv, &ktv)) + return -EFAULT; + } + if (tz) { + if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) + return -EFAULT; + } + return 0; +} + +asmlinkage int osf_settimeofday(struct timeval32 *tv, struct timezone *tz) +{ + struct timeval ktv; + struct timezone ktz; + + if (tv) { + if (get_tv32(&ktv, tv)) + return -EFAULT; + } + if (tz) { + if (copy_from_user(&ktz, tz, sizeof(*tz))) + return -EFAULT; + } + + return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL); +} + +asmlinkage int osf_getitimer(int which, struct itimerval32 *it) +{ + struct itimerval kit; + int error; + + error = do_getitimer(which, &kit); + if (!error && put_it32(it, &kit)) + error = -EFAULT; + + return error; +} + +asmlinkage int osf_setitimer(int which, struct itimerval32 *in, + struct itimerval32 *out) +{ + struct itimerval kin, kout; + int error; + + if (in) { + if (get_it32(&kin, in)) + return -EFAULT; + } else + memset(&kin, 0, sizeof(kin)); + + error = do_setitimer(which, &kin, out ? &kout : NULL); + if (error || !out) + return error; + + if (put_it32(out, &kout)) + return -EFAULT; + + return 0; + +} + +asmlinkage int osf_utimes(const char *filename, struct timeval32 *tvs) +{ + char *kfilename; + struct timeval ktvs[2]; + mm_segment_t old_fs; + int ret; + + kfilename = getname(filename); + if (IS_ERR(kfilename)) + return PTR_ERR(kfilename); + + if (tvs) { + if (get_tv32(&ktvs[0], &tvs[0]) || + get_tv32(&ktvs[1], &tvs[1])) + return -EFAULT; + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_utimes(kfilename, tvs ? ktvs : 0); + set_fs(old_fs); + + putname(kfilename); + + return ret; +} + +asmlinkage int +osf_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, + struct timeval32 *tvp) +{ + fd_set_buffer *fds; + unsigned long timeout; + int ret; + + timeout = ~0UL; + if (tvp) { + time_t sec, usec; + + if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp))) + || (ret = __get_user(sec, &tvp->tv_sec)) + || (ret = __get_user(usec, &tvp->tv_usec))) + goto out_nofds; + + timeout = (usec + 1000000/HZ - 1) / (1000000/HZ); + timeout += sec * HZ; + if (timeout) + timeout += jiffies + 1; + } + + ret = -ENOMEM; + fds = (fd_set_buffer *) __get_free_page(GFP_KERNEL); + if (!fds) + goto out_nofds; + ret = -EINVAL; + if (n < 0) + goto out; + if (n > KFDS_NR) + n = KFDS_NR; + if ((ret = get_fd_set(n, inp->fds_bits, fds->in)) || + (ret = get_fd_set(n, outp->fds_bits, fds->out)) || + (ret = get_fd_set(n, exp->fds_bits, fds->ex))) + goto out; + zero_fd_set(n, fds->res_in); + zero_fd_set(n, fds->res_out); + zero_fd_set(n, fds->res_ex); + + ret = do_select(n, fds, timeout); + + /* OSF does not copy back the remaining time. */ + + if (ret < 0) + goto out; + if (!ret) { + ret = -ERESTARTNOHAND; + if (signal_pending(current)) + goto out; + ret = 0; + } + + set_fd_set(n, inp->fds_bits, fds->res_in); + set_fd_set(n, outp->fds_bits, fds->res_out); + set_fd_set(n, exp->fds_bits, fds->res_ex); + +out: + free_page((unsigned long) fds); +out_nofds: + return ret; +} + +struct rusage32 { + struct timeval32 ru_utime; /* user time used */ + struct timeval32 ru_stime; /* system time used */ + long ru_maxrss; /* maximum resident set size */ + long ru_ixrss; /* integral shared memory size */ + long ru_idrss; /* integral unshared data size */ + long ru_isrss; /* integral unshared stack size */ + long ru_minflt; /* page reclaims */ + long ru_majflt; /* page faults */ + long ru_nswap; /* swaps */ + long ru_inblock; /* block input operations */ + long ru_oublock; /* block output operations */ + long ru_msgsnd; /* messages sent */ + long ru_msgrcv; /* messages received */ + long ru_nsignals; /* signals received */ + long ru_nvcsw; /* voluntary context switches */ + long ru_nivcsw; /* involuntary " */ +}; + +asmlinkage int osf_getrusage(int who, struct rusage32 *ru) +{ + struct rusage32 r; + + if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN) + return -EINVAL; + + memset(&r, 0, sizeof(r)); + switch (who) { + case RUSAGE_SELF: + r.ru_utime.tv_sec = CT_TO_SECS(current->times.tms_utime); + r.ru_utime.tv_usec = CT_TO_USECS(current->times.tms_utime); + r.ru_stime.tv_sec = CT_TO_SECS(current->times.tms_stime); + r.ru_stime.tv_usec = CT_TO_USECS(current->times.tms_stime); + r.ru_minflt = current->min_flt; + r.ru_majflt = current->maj_flt; + r.ru_nswap = current->nswap; + break; + case RUSAGE_CHILDREN: + r.ru_utime.tv_sec = CT_TO_SECS(current->times.tms_cutime); + r.ru_utime.tv_usec = CT_TO_USECS(current->times.tms_cutime); + r.ru_stime.tv_sec = CT_TO_SECS(current->times.tms_cstime); + r.ru_stime.tv_usec = CT_TO_USECS(current->times.tms_cstime); + r.ru_minflt = current->cmin_flt; + r.ru_majflt = current->cmaj_flt; + r.ru_nswap = current->cnswap; + break; + default: + r.ru_utime.tv_sec = CT_TO_SECS(current->times.tms_utime + + current->times.tms_cutime); + r.ru_utime.tv_usec = CT_TO_USECS(current->times.tms_utime + + current->times.tms_cutime); + r.ru_stime.tv_sec = CT_TO_SECS(current->times.tms_stime + + current->times.tms_cstime); + r.ru_stime.tv_usec = CT_TO_USECS(current->times.tms_stime + + current->times.tms_cstime); + r.ru_minflt = current->min_flt + current->cmin_flt; + r.ru_majflt = current->maj_flt + current->cmaj_flt; + r.ru_nswap = current->nswap + current->cnswap; + break; + } + + return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0; +} + +asmlinkage int osf_wait4(pid_t pid, int *ustatus, int options, + struct rusage32 *ur) +{ + if (!ur) { + return sys_wait4(pid, ustatus, options, NULL); + } else { + struct rusage r; + int ret, status; + mm_segment_t old_fs = get_fs(); + + set_fs (KERNEL_DS); + ret = sys_wait4(pid, &status, options, &r); + set_fs (old_fs); + + if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur))) + return -EFAULT; + __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec); + __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec); + __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec); + __put_user(r.ru_stime.tv_usec, &ur->ru_stime.tv_usec); + __put_user(r.ru_maxrss, &ur->ru_maxrss); + __put_user(r.ru_ixrss, &ur->ru_ixrss); + __put_user(r.ru_idrss, &ur->ru_idrss); + __put_user(r.ru_isrss, &ur->ru_isrss); + __put_user(r.ru_minflt, &ur->ru_minflt); + __put_user(r.ru_majflt, &ur->ru_majflt); + __put_user(r.ru_nswap, &ur->ru_nswap); + __put_user(r.ru_inblock, &ur->ru_inblock); + __put_user(r.ru_oublock, &ur->ru_oublock); + __put_user(r.ru_msgsnd, &ur->ru_msgsnd); + __put_user(r.ru_msgrcv, &ur->ru_msgrcv); + __put_user(r.ru_nsignals, &ur->ru_nsignals); + __put_user(r.ru_nvcsw, &ur->ru_nvcsw); + if (__put_user(r.ru_nivcsw, &ur->ru_nivcsw)) + return -EFAULT; + + if (ustatus && put_user(status, ustatus)) + return -EFAULT; + return ret; + } +} + +/* + * I don't know what the parameters are: the first one + * seems to be a timeval pointer, and I suspect the second + * one is the time remaining.. Ho humm.. No documentation. + */ +asmlinkage int osf_usleep_thread(struct timeval *sleep, struct timeval *remain) +{ + struct timeval tmp; + unsigned long ticks; + + if (get_tv32(&tmp, sleep)) + goto fault; + + ticks = tmp.tv_usec; + ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ); + ticks += tmp.tv_sec * HZ; + current->timeout = ticks + jiffies; + current->state = TASK_INTERRUPTIBLE; + + schedule(); + + if (remain) { + ticks = jiffies; + if (ticks < current->timeout) + ticks = current->timeout - ticks; + else + ticks = 0; + current->timeout = 0; + tmp.tv_sec = ticks / HZ; + tmp.tv_usec = ticks % HZ; + if (put_tv32(remain, &tmp)) + goto fault; + } + + return 0; +fault: + return -EFAULT; +} diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index 84cde1b4f..38cb5e05d 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c @@ -574,7 +574,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ ret = -EIO; - if ((unsigned long) data > NSIG) + if ((unsigned long) data > _NSIG) goto out; if (request == PTRACE_SYSCALL) child->flags |= PF_TRACESYS; @@ -606,7 +606,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, case PTRACE_SINGLESTEP: { /* execute single instruction. */ ret = -EIO; - if ((unsigned long) data > NSIG) + if ((unsigned long) data > _NSIG) goto out; child->debugreg[4] = -1; /* mark single-stepping */ child->flags &= ~PF_TRACESYS; @@ -619,7 +619,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, case PTRACE_DETACH: { /* detach a process that was attached. */ ret = -EIO; - if ((unsigned long) data > NSIG) + if ((unsigned long) data > _NSIG) goto out; child->flags &= ~(PF_PTRACED|PF_TRACESYS); wake_up_process(child); @@ -627,7 +627,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, REMOVE_LINKS(child); child->p_pptr = child->p_opptr; SET_LINKS(child); - /* make sure single-step breakpoint is gone. */ + /* make sure single-step breakpoint is gone. */ ptrace_cancel_bpt(child); ret = 0; goto out; @@ -644,22 +644,20 @@ out: asmlinkage void syscall_trace(void) { - lock_kernel(); if ((current->flags & (PF_PTRACED|PF_TRACESYS)) != (PF_PTRACED|PF_TRACESYS)) - goto out; + return; current->exit_code = SIGTRAP; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); /* - * this isn't the same as continuing with a signal, but it will do + * This isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the * stopping signal is not SIGTRAP. -brl */ - if (current->exit_code) - current->signal |= (1 << (current->exit_code - 1)); - current->exit_code = 0; -out: - unlock_kernel(); + if (current->exit_code) { + send_sig(current->exit_code, current, 1); + current->exit_code = 0; + } } diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 9f71e6146..1d4e8931d 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -2,6 +2,8 @@ * linux/arch/alpha/kernel/signal.c * * Copyright (C) 1995 Linus Torvalds + * + * 1997-11-02 Modified for POSIX.1b signals by Richard Henderson */ #include <linux/sched.h> @@ -14,21 +16,27 @@ #include <linux/mm.h> #include <linux/smp.h> #include <linux/smp_lock.h> +#include <linux/signal.h> +#include <linux/stddef.h> #include <asm/bitops.h> #include <asm/uaccess.h> +#include <asm/sigcontext.h> +#include <asm/ucontext.h> + +#define DEBUG_SIG 0 -#define _S(nr) (1<<((nr)-1)) -#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) asmlinkage int sys_wait4(int, int *, int, struct rusage *); asmlinkage void ret_from_sys_call(void); -asmlinkage int do_signal(unsigned long, struct pt_regs *, struct switch_stack *, - unsigned long, unsigned long); +asmlinkage int do_signal(sigset_t *, struct pt_regs *, + struct switch_stack *, unsigned long, unsigned long); extern int ptrace_set_bpt (struct task_struct *child); extern int ptrace_cancel_bpt (struct task_struct *child); + /* * The OSF/1 sigprocmask calling sequence is different from the * C sigprocmask() sequence.. @@ -44,51 +52,153 @@ extern int ptrace_cancel_bpt (struct task_struct *child); * Note that we don't need to acquire the kernel lock for SMP * operation, as all of this is local to this thread. */ -asmlinkage unsigned long osf_sigprocmask(int how, unsigned long newmask, - long a2, long a3, long a4, long a5, struct pt_regs regs) +asmlinkage unsigned long +osf_sigprocmask(int how, unsigned long newmask, long a2, long a3, + long a4, long a5, struct pt_regs regs) { - unsigned long ok, oldmask; - struct task_struct * tsk; - - ok = how-1; /* 0 .. 2 */ - tsk = current; - ok = ok <= 2; - oldmask = -EINVAL; - if (ok) { - long sign; /* -1 .. 1 */ + unsigned long oldmask = -EINVAL; + + if ((unsigned long)how-1 <= 2) { + long sign = how-2; /* -1 .. 1 */ unsigned long block, unblock; - oldmask = tsk->blocked; newmask &= _BLOCKABLE; - sign = how-2; + spin_lock_irq(¤t->sigmask_lock); + oldmask = current->blocked.sig[0]; + unblock = oldmask & ~newmask; block = oldmask | newmask; if (!sign) block = unblock; - regs.r0 = 0; /* special no error return */ if (sign <= 0) newmask = block; - tsk->blocked = newmask; + if (_NSIG_WORDS > 1 && sign > 0) + sigemptyset(¤t->blocked); + current->blocked.sig[0] = newmask; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + (®s)->r0 = 0; /* special no error return */ } return oldmask; } +asmlinkage int +osf_sigaction(int sig, const struct osf_sigaction *act, + struct osf_sigaction *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + old_sigset_t mask; + if (verify_area(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags)) + return -EFAULT; + __get_user(mask, &act->sa_mask); + siginitset(&new_ka.sa.sa_mask, mask); + new_ka.ka_restorer = NULL; + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_flags, &oact->sa_flags)) + return -EFAULT; + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + } + + return ret; +} + +asmlinkage int +sys_rt_sigaction(int sig, const struct sigaction *act, struct sigaction *oact, + void *restorer, size_t sigsetsize) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + + if (act) { + new_ka.ka_restorer = restorer; + if (copy_from_user(&new_ka.sa, act, sizeof(*act))) + return -EFAULT; + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (copy_to_user(oact, &old_ka.sa, sizeof(*oact))) + return -EFAULT; + } + + return ret; +} + +asmlinkage int +osf_sigpending(old_sigset_t *set) +{ + sigset_t pending; + + spin_lock_irq(¤t->sigmask_lock); + sigandsets(&pending, ¤t->blocked, ¤t->signal); + spin_unlock_irq(¤t->sigmask_lock); + + return copy_to_user(set, &pending, sizeof(*set)); +} + /* - * atomically swap in the new signal mask, and wait for a signal. + * Atomically swap in the new signal mask, and wait for a signal. */ -asmlinkage int do_sigsuspend(unsigned long mask, struct pt_regs * regs, struct switch_stack * sw) +asmlinkage int +do_sigsuspend(old_sigset_t mask, struct pt_regs *reg, struct switch_stack *sw) +{ + sigset_t oldset; + + mask &= _BLOCKABLE; + spin_lock_irq(¤t->sigmask_lock); + oldset = current->blocked; + siginitset(¤t->blocked, mask); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal(&oldset, reg, sw, 0, 0)) + return -EINTR; + } +} + +asmlinkage int +do_rt_sigsuspend(sigset_t *uset, size_t sigsetsize, + struct pt_regs *reg, struct switch_stack *sw) { - unsigned long oldmask; + sigset_t oldset, set; + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + if (copy_from_user(&set, uset, sizeof(set))) + return -EFAULT; + + sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sigmask_lock); - oldmask = current->blocked; - current->blocked = mask & _BLOCKABLE; + oldset = current->blocked; + current->blocked = set; + recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(oldmask, regs, sw, 0, 0)) + if (do_signal(&oldset, reg, sw, 0, 0)) return -EINTR; } } @@ -96,26 +206,35 @@ asmlinkage int do_sigsuspend(unsigned long mask, struct pt_regs * regs, struct s /* * Do a signal return; undo the signal stack. */ -asmlinkage void do_sigreturn(struct sigcontext * sc, - struct pt_regs * regs, struct switch_stack * sw) + +struct sigframe { - unsigned long mask, ps, usp; - int i; + struct sigcontext sc; + unsigned long extramask[_NSIG_WORDS-1]; + unsigned int retcode[3]; +}; - /* verify that it's a good sigcontext before using it */ - if (verify_area(VERIFY_READ, sc, sizeof(*sc))) - goto give_sigsegv; - if (__get_user(ps, &sc->sc_ps) || ps != 8) - goto give_sigsegv; - if (__get_user(mask, &sc->sc_mask) || (mask & ~_BLOCKABLE)) - goto give_sigsegv; +struct rt_sigframe +{ + struct siginfo info; + struct ucontext uc; + unsigned int retcode[3]; +}; + +#define INSN_MOV_R30_R16 0x47fe0410 +#define INSN_LDI_R0 0x201f0000 +#define INSN_CALLSYS 0x00000083 + + +static void +restore_sigcontext(struct sigcontext *sc, struct pt_regs *regs, + struct switch_stack *sw) +{ + unsigned long usp; + int i; - /* ok, looks fine, start restoring */ - __get_user(usp, sc->sc_regs+30); - wrusp(usp); __get_user(regs->pc, &sc->sc_pc); sw->r26 = (unsigned long) ret_from_sys_call; - current->blocked = mask; __get_user(regs->r0, sc->sc_regs+0); __get_user(regs->r1, sc->sc_regs+1); @@ -147,47 +266,98 @@ asmlinkage void do_sigreturn(struct sigcontext * sc, __get_user(regs->r27, sc->sc_regs+27); __get_user(regs->r28, sc->sc_regs+28); __get_user(regs->gp, sc->sc_regs+29); + __get_user(usp, sc->sc_regs+30); + wrusp(usp); + for (i = 0; i < 31; i++) __get_user(sw->fp[i], sc->sc_fpregs+i); + __get_user(sw->fp[31], &sc->sc_fpcr); +} - /* send SIGTRAP if we're single-stepping: */ - lock_kernel(); +asmlinkage void +do_sigreturn(struct sigframe *frame, struct pt_regs *regs, + struct switch_stack *sw) +{ + unsigned long ps; + sigset_t set; + + /* Verify that it's a good sigcontext before using it */ + if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + goto give_sigsegv; + if (__get_user(ps, &frame->sc.sc_ps) || ps != 8) + goto give_sigsegv; + if (__get_user(set.sig[0], &frame->sc.sc_mask) + || (_NSIG_WORDS > 1 + && __copy_from_user(&set.sig[1], &frame->extramask, + sizeof(frame->extramask)))) + goto give_sigsegv; + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + restore_sigcontext(&frame->sc, regs, sw); + + /* Send SIGTRAP if we're single-stepping: */ if (ptrace_cancel_bpt (current)) send_sig(SIGTRAP, current, 1); - unlock_kernel(); return; give_sigsegv: lock_kernel(); do_exit(SIGSEGV); - unlock_kernel(); } -/* - * Set up a signal frame... - */ -static void setup_frame(struct sigaction * sa, - struct pt_regs * regs, - struct switch_stack * sw, int signr, - unsigned long oldmask) +asmlinkage void +do_rt_sigreturn(struct rt_sigframe *frame, struct pt_regs *regs, + struct switch_stack *sw) { - int i; - unsigned long oldsp; - struct sigcontext * sc; + unsigned long ps; + sigset_t set; - oldsp = rdusp(); - sc = ((struct sigcontext *) oldsp) - 1; + /* Verify that it's a good sigcontext before using it */ + if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + goto give_sigsegv; + if (__get_user(ps, &frame->uc.uc_mcontext.sc_ps) || ps != 8) + goto give_sigsegv; + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) + goto give_sigsegv; - /* check here if we would need to switch stacks.. */ - if (verify_area(VERIFY_WRITE, sc, sizeof(*sc))) - do_exit(SIGSEGV); + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); - wrusp((unsigned long) sc); + restore_sigcontext(&frame->uc.uc_mcontext, regs, sw); - __put_user(oldmask, &sc->sc_mask); - __put_user(8, &sc->sc_ps); + /* Send SIGTRAP if we're single-stepping: */ + if (ptrace_cancel_bpt (current)) + send_sig(SIGTRAP, current, 1); + return; + +give_sigsegv: + lock_kernel(); + do_exit(SIGSEGV); +} + + +/* + * Set up a signal frame. + */ + +static void +setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, + struct switch_stack *sw, unsigned long mask, unsigned long sp) +{ + long i; + + __put_user(0, &sc->sc_onstack); + __put_user(mask, &sc->sc_mask); __put_user(regs->pc, &sc->sc_pc); - __put_user(oldsp, sc->sc_regs+30); + __put_user(8, &sc->sc_ps); __put_user(regs->r0 , sc->sc_regs+0); __put_user(regs->r1 , sc->sc_regs+1); @@ -219,63 +389,167 @@ static void setup_frame(struct sigaction * sa, __put_user(regs->r27, sc->sc_regs+27); __put_user(regs->r28, sc->sc_regs+28); __put_user(regs->gp , sc->sc_regs+29); + __put_user(sp, sc->sc_regs+30); + __put_user(0, sc->sc_regs+31); + for (i = 0; i < 31; i++) __put_user(sw->fp[i], sc->sc_fpregs+i); + __put_user(0, sc->sc_fpregs+31); + __put_user(sw->fp[31], &sc->sc_fpcr); + __put_user(regs->trap_a0, &sc->sc_traparg_a0); __put_user(regs->trap_a1, &sc->sc_traparg_a1); __put_user(regs->trap_a2, &sc->sc_traparg_a2); +} + +static void +setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, + struct pt_regs *regs, struct switch_stack * sw) +{ + unsigned long oldsp; + struct sigframe *frame; + + oldsp = rdusp(); + frame = (struct sigframe *)((oldsp - sizeof(*frame)) & -32); + + /* XXX: Check here if we would need to switch stacks.. */ + if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) + goto give_sigsegv; + + setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp); + if (_NSIG_WORDS > 1) { + __copy_to_user(frame->extramask, &set->sig[1], + sizeof(frame->extramask)); + } + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + if (ka->ka_restorer) { + regs->r26 = (unsigned long) ka->ka_restorer; + } else { + __put_user(INSN_MOV_R30_R16, frame->retcode+0); + __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1); + __put_user(INSN_CALLSYS, frame->retcode+2); + imb(); + regs->r26 = (unsigned long) frame->retcode; + } + + /* "Return" to the handler */ + regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler; + regs->r16 = sig; /* a0: signal number */ + regs->r17 = 0; /* a1: exception code */ + regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */ + wrusp((unsigned long) frame); + +#if DEBUG_SIG + printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", + current->comm, current->pid, frame, regs->pc, regs->r26); +#endif + + return; + +give_sigsegv: + lock_kernel(); + do_exit(SIGSEGV); +} + +static void +setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs, struct switch_stack * sw) +{ + unsigned long oldsp; + struct rt_sigframe *frame; + + oldsp = rdusp(); + frame = (struct rt_sigframe *)((oldsp - sizeof(*frame)) & -32); + + /* XXX: Check here if we would need to switch stacks.. */ + if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) + goto give_sigsegv; + + __copy_to_user(&frame->info, info, sizeof(siginfo_t)); + + /* Zero all bits of the ucontext besides the sigcontext. */ + __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); + + /* Copy in the bits we actually use. */ + __put_user(set->sig[0], &frame->uc.uc_osf_sigmask); + setup_sigcontext(&frame->uc.uc_mcontext, regs, sw, set->sig[0], oldsp); + __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + if (ka->ka_restorer) { + regs->r26 = (unsigned long) ka->ka_restorer; + } else { + __put_user(INSN_MOV_R30_R16, frame->retcode+0); + __put_user(INSN_LDI_R0+__NR_rt_sigreturn, frame->retcode+1); + __put_user(INSN_CALLSYS, frame->retcode+2); + imb(); + regs->r26 = (unsigned long) frame->retcode; + } - /* - * The following is: - * - * bis $30,$30,$16 - * addq $31,0x67,$0 - * call_pal callsys - * - * ie, "sigreturn(stack-pointer)" - */ - __put_user(0x43ecf40047de0410, sc->sc_retcode+0); - __put_user(0x0000000000000083, sc->sc_retcode+1); - imb(); - - /* "return" to the handler */ - regs->r27 = regs->pc = (unsigned long) sa->sa_handler; - regs->r26 = (unsigned long) sc->sc_retcode; - regs->r16 = signr; /* a0: signal number */ - regs->r17 = 0; /* a1: exception code; see gentrap.h */ - regs->r18 = (unsigned long) sc; /* a2: sigcontext pointer */ + /* "Return" to the handler */ + regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler; + regs->r16 = sig; /* a0: signal number */ + regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */ + regs->r18 = (unsigned long) &frame->uc; /* a2: ucontext pointer */ + wrusp((unsigned long) frame); + +#if DEBUG_SIG + printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", + current->comm, current->pid, frame, regs->pc, regs->r26); +#endif + + return; + +give_sigsegv: + lock_kernel(); + do_exit(SIGSEGV); } + /* - * OK, we're invoking a handler + * OK, we're invoking a handler. */ -static inline void handle_signal(unsigned long signr, struct sigaction *sa, - unsigned long oldmask, struct pt_regs * regs, struct switch_stack *sw) +static inline void +handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *oldset, struct pt_regs * regs, struct switch_stack *sw) { - setup_frame(sa,regs,sw,signr,oldmask); - - if (sa->sa_flags & SA_ONESHOT) - sa->sa_handler = NULL; - if (!(sa->sa_flags & SA_NOMASK)) - current->blocked |= (sa->sa_mask | _S(signr)) & _BLOCKABLE; + if (ka->sa.sa_flags & SA_SIGINFO) + setup_rt_frame(sig, ka, info, oldset, regs, sw); + else + setup_frame(sig, ka, oldset, regs, sw); + + if (ka->sa.sa_flags & SA_RESETHAND) + ka->sa.sa_handler = SIG_DFL; + + if (!(ka->sa.sa_flags & SA_NODEFER)) { + spin_lock_irq(¤t->sigmask_lock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked,sig); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + } } -static inline void syscall_restart(unsigned long r0, unsigned long r19, - struct pt_regs * regs, struct sigaction * sa) +static inline void +syscall_restart(unsigned long r0, unsigned long r19, + struct pt_regs *regs, struct k_sigaction *ka) { switch (regs->r0) { + case ERESTARTSYS: + if (!(ka->sa.sa_flags & SA_RESTART)) { case ERESTARTNOHAND: - no_system_call_restart: regs->r0 = EINTR; break; - case ERESTARTSYS: - if (!(sa->sa_flags & SA_RESTART)) - goto no_system_call_restart; + } /* fallthrough */ - case ERESTARTNOINTR: - regs->r0 = r0; /* reset v0 and a3 and replay syscall */ - regs->r19 = r19; - regs->pc -= 4; + case ERESTARTNOINTR: + regs->r0 = r0; /* reset v0 and a3 and replay syscall */ + regs->r19 = r19; + regs->pc -= 4; + break; } } @@ -293,53 +567,77 @@ static inline void syscall_restart(unsigned long r0, unsigned long r19, * restart. "r0" is also used as an indicator whether we can restart at * all (if we get here from anything but a syscall return, it will be 0) */ -asmlinkage int do_signal(unsigned long oldmask, - struct pt_regs * regs, - struct switch_stack * sw, - unsigned long r0, unsigned long r19) +asmlinkage int +do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw, + unsigned long r0, unsigned long r19) { - unsigned long mask; - unsigned long signr, single_stepping; - struct sigaction * sa; - int ret; + unsigned long single_stepping = ptrace_cancel_bpt(current); + + if (!oldset) + oldset = ¤t->blocked; + + while (1) { + unsigned long signr; + struct k_sigaction *ka; + siginfo_t info; + + spin_lock_irq(¤t->sigmask_lock); + signr = dequeue_signal(¤t->blocked, &info); + spin_unlock_irq(¤t->sigmask_lock); + + if (!signr) + break; - lock_kernel(); - mask = ~current->blocked; - single_stepping = ptrace_cancel_bpt(current); - - while ((signr = current->signal & mask) != 0) { - signr = ffz(~signr); - clear_bit(signr, ¤t->signal); - sa = current->sig->action + signr; - signr++; if ((current->flags & PF_PTRACED) && signr != SIGKILL) { + /* Let the debugger run. */ current->exit_code = signr; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); single_stepping |= ptrace_cancel_bpt(current); + + /* We're back. Did the debugger cancel the sig? */ if (!(signr = current->exit_code)) continue; current->exit_code = 0; + + /* The debugger continued. Ignore SIGSTOP. */ if (signr == SIGSTOP) continue; - if (_S(signr) & current->blocked) { - current->signal |= _S(signr); + + /* Update the siginfo structure. Is this good? */ + if (signr != info.si_signo) { + info.si_signo = signr; + info.si_errno = 0; + info.si_code = SI_USER; + info.si_pid = current->p_pptr->pid; + info.si_uid = current->p_pptr->uid; + } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(¤t->blocked, signr)) { + send_sig_info(signr, &info, current); continue; } - sa = current->sig->action + signr - 1; } - if (sa->sa_handler == SIG_IGN) { + + ka = ¤t->sig->action[signr-1]; + if (ka->sa.sa_handler == SIG_IGN) { if (signr != SIGCHLD) continue; - /* check for SIGCHLD: it's special */ + /* Check for SIGCHLD: it's special. */ while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) /* nothing */; continue; } - if (sa->sa_handler == SIG_DFL) { + + if (ka->sa.sa_handler == SIG_DFL) { + int exit_code = signr & 0x7f; + + /* Init gets no signals it doesn't want. */ if (current->pid == 1) continue; + switch (signr) { case SIGCONT: case SIGCHLD: case SIGWINCH: continue; @@ -347,13 +645,13 @@ asmlinkage int do_signal(unsigned long oldmask, case SIGTSTP: case SIGTTIN: case SIGTTOU: if (is_orphaned_pgrp(current->pgrp)) continue; + /* FALLTHRU */ + case SIGSTOP: - if (current->flags & PF_PTRACED) - continue; current->state = TASK_STOPPED; current->exit_code = signr; - if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & - SA_NOCLDSTOP)) + if (!(current->p_pptr->sig->action[SIGCHLD-1] + .sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); single_stepping |= ptrace_cancel_bpt(current); @@ -361,26 +659,32 @@ asmlinkage int do_signal(unsigned long oldmask, case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: - if (current->binfmt && current->binfmt->core_dump) { - if (current->binfmt->core_dump(signr, regs)) - signr |= 0x80; - } - /* fall through */ + lock_kernel(); + if (current->binfmt + && current->binfmt->core_dump + && current->binfmt->core_dump(signr, regs)) + exit_code |= 0x80; + unlock_kernel(); + /* FALLTHRU */ + default: - current->signal |= _S(signr & 0x7f); + lock_kernel(); + sigaddset(¤t->signal, signr); current->flags |= PF_SIGNALED; - do_exit(signr); + do_exit(exit_code); + /* NOTREACHED */ } + continue; } - if (r0) - syscall_restart(r0, r19, regs, sa); - handle_signal(signr, sa, oldmask, regs, sw); - if (single_stepping) { - ptrace_set_bpt(current); /* re-set breakpoint */ - } - ret = 1; - goto out; + + /* Whee! Actually deliver the signal. */ + if (r0) syscall_restart(r0, r19, regs, ka); + handle_signal(signr, ka, &info, oldset, regs, sw); + if (single_stepping) + ptrace_set_bpt(current); /* re-set bpt */ + return 1; } + if (r0 && (regs->r0 == ERESTARTNOHAND || regs->r0 == ERESTARTSYS || @@ -389,11 +693,8 @@ asmlinkage int do_signal(unsigned long oldmask, regs->r19 = r19; regs->pc -= 4; } - if (single_stepping) { + if (single_stepping) ptrace_set_bpt(current); /* re-set breakpoint */ - } - ret = 0; -out: - unlock_kernel(); - return ret; + + return 0; } diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index 2b0870c3b..9d8b56dc3 100644 --- a/arch/alpha/kernel/time.c +++ b/arch/alpha/kernel/time.c @@ -17,17 +17,18 @@ * (round system clock to nearest tick instead of truncating) * fixed algorithm in time_init for getting time from CMOS clock */ +#include <linux/config.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/param.h> #include <linux/string.h> #include <linux/mm.h> +#include <linux/delay.h> #include <asm/uaccess.h> #include <asm/io.h> #include <asm/hwrpb.h> -#include <asm/delay.h> #include <linux/mc146818rtc.h> #include <linux/timex.h> @@ -52,16 +53,18 @@ static int set_rtc_mmss(unsigned long); /* lump static variables together for more efficient access: */ static struct { - __u32 last_time; /* cycle counter last time it got invoked */ - unsigned long scaled_ticks_per_cycle; /* ticks/cycle * 2^48 */ - long last_rtc_update; /* last time the cmos clock got updated */ + /* cycle counter last time it got invoked */ + __u32 last_time; + /* ticks/cycle * 2^48 */ + unsigned long scaled_ticks_per_cycle; + /* last time the cmos clock got updated */ + time_t last_rtc_update; } state; static inline __u32 rpcc(void) { __u32 result; - asm volatile ("rpcc %0" : "r="(result)); return result; } @@ -73,37 +76,46 @@ static inline __u32 rpcc(void) */ void timer_interrupt(int irq, void *dev, struct pt_regs * regs) { - __u32 delta, now; - int i, nticks; + const unsigned long half = 1UL << (FIX_SHIFT - 1); + const unsigned long mask = (1UL << (FIX_SHIFT + 1)) - 1; + unsigned long delta; + __u32 now; + long nticks; + /* + * Estimate how many ticks have passed since the last update. + * Round the result, .5 to even. When we loose ticks due to + * say using IDE, the clock has been seen to run up to 15% slow + * if we truncate. + */ now = rpcc(); delta = now - state.last_time; state.last_time = now; - if(hwrpb->cycle_freq) { - nticks = (delta * state.scaled_ticks_per_cycle) >> (FIX_SHIFT-1); - nticks = (nticks+1) >> 1; - } - else nticks=1; /* No way to estimate lost ticks if we don't know - the cycle frequency. */ - for (i = 0; i < nticks; ++i) { + delta = delta * state.scaled_ticks_per_cycle; + if ((delta & mask) != half) + delta += half; + nticks = delta >> FIX_SHIFT; + + do { do_timer(regs); - } + } while (--nticks > 0); /* * If we have an externally synchronized Linux clock, then update * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be * called as close as possible to 500 ms before the new second starts. */ - if (time_state != TIME_BAD && xtime.tv_sec > state.last_rtc_update + 660 && - xtime.tv_usec > 500000 - (tick >> 1) && - xtime.tv_usec < 500000 + (tick >> 1)) - if (set_rtc_mmss(xtime.tv_sec) == 0) - state.last_rtc_update = xtime.tv_sec; - else - state.last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + if (time_state != TIME_BAD + && xtime.tv_sec > state.last_rtc_update + 660 + && xtime.tv_usec >= 500000 - (tick >> 1) + && xtime.tv_usec <= 500000 + (tick >> 1)) { + int tmp = set_rtc_mmss(xtime.tv_sec); + state.last_rtc_update = xtime.tv_sec - (tmp ? 600 : 0); + } } -/* Converts Gregorian date to seconds since 1970-01-01 00:00:00. +/* + * Converts Gregorian date to seconds since 1970-01-01 00:00:00. * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. * @@ -140,25 +152,40 @@ void time_init(void) unsigned char save_control; #endif void (*irq_handler)(int, void *, struct pt_regs *); - unsigned int year, mon, day, hour, min, sec; + unsigned int year, mon, day, hour, min, sec, cc1, cc2; - /* The Linux interpretation of the CMOS clock register contents: + /* + * The Linux interpretation of the CMOS clock register contents: * When the Update-In-Progress (UIP) flag goes from 1 to 0, the * RTC registers show the second which has precisely just started. * Let's hope other operating systems interpret the RTC the same way. */ - /* read RTC exactly on falling edge of update flag */ - /* Wait for rise.... (may take up to 1 second) */ - - do {} while(!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)); - -/* Jay Estabook <jestabro@amt.tay1.dec.com>: - * Wait for the Update Done Interrupt bit (0x10) in reg C (12) to be set, - * which (hopefully) indicates that the update is really done. - */ - - do {} while(!CMOS_READ(RTC_REG_C) & RTC_UIP); - + do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)); + do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); + + /* Read cycle counter exactly on falling edge of update flag */ + cc1 = rpcc(); + + /* If our cycle frequency isn't valid, go another round and give + a guess at what it should be. */ + if (hwrpb->cycle_freq == 0) { + printk("HWPRB cycle frequency bogus. Estimating... "); + + do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)); + do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); + cc2 = rpcc(); + hwrpb->cycle_freq = cc2 - cc1; + cc1 = cc2; + + printk("%lu Hz\n", hwrpb->cycle_freq); + } + + /* From John Bowman <bowman@math.ualberta.ca>: allow the values + to settle, as the Update-In-Progress bit going low isn't good + enough on some hardware. 2ms is our guess; we havn't found + bogomips yet, but this is close on a 500Mhz box. */ + __delay(1000000); + sec = CMOS_READ(RTC_SECONDS); min = CMOS_READ(RTC_MINUTES); hour = CMOS_READ(RTC_HOURS); @@ -167,14 +194,14 @@ void time_init(void) year = CMOS_READ(RTC_YEAR); if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - } + { + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + } #ifdef ALPHA_PRE_V1_2_SRM_CONSOLE /* * The meaning of life, the universe, and everything. Plus @@ -192,9 +219,10 @@ void time_init(void) extern void __you_loose (void); __you_loose(); } - state.last_time = rpcc(); - if(hwrpb->cycle_freq) - state.scaled_ticks_per_cycle = ((unsigned long) HZ << FIX_SHIFT) / hwrpb->cycle_freq; + + state.last_time = cc1; + state.scaled_ticks_per_cycle + = ((unsigned long) HZ << FIX_SHIFT) / hwrpb->cycle_freq; state.last_rtc_update = 0; #ifdef CONFIG_RTC @@ -210,22 +238,52 @@ void time_init(void) /* setup timer */ irq_handler = timer_interrupt; if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL)) - panic("Could not allocate timer IRQ!"); + panic("Could not allocate timer IRQ!"); } /* - * We could get better timer accuracy by using the alpha - * time counters or something. Now this is limited to - * the HZ clock frequency. + * Use the cycle counter to estimate an displacement from the last time + * tick. Unfortunately the Alpha designers made only the low 32-bits of + * the cycle counter active, so we overflow on 8.2 seconds on a 500MHz + * part. So we can't do the "find absolute time in terms of cycles" thing + * that the other ports do. */ void do_gettimeofday(struct timeval *tv) { - unsigned long flags; + unsigned long flags, now, delta_cycles, delta_usec; + unsigned long sec, usec; - save_flags(flags); - cli(); - *tv = xtime; + now = rpcc(); + save_and_cli(flags); + sec = xtime.tv_sec; + usec = xtime.tv_usec; + delta_cycles = now - state.last_time; restore_flags(flags); + + /* + * usec = cycles * ticks_per_cycle * 2**48 * 1e6 / (2**48 * ticks) + * = cycles * (s_t_p_c) * 1e6 / (2**48 * ticks) + * = cycles * (s_t_p_c) * 15625 / (2**42 * ticks) + * + * which, given a 600MHz cycle and a 1024Hz tick, has a + * dynamic range of about 1.7e17, which is less than the + * 1.8e19 in an unsigned long, so we are safe from overflow. + * + * Round, but with .5 up always, since .5 to even is harder + * with no clear gain. + */ + + delta_usec = delta_cycles * state.scaled_ticks_per_cycle * 15625; + delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6)) * HZ)) + 1) / 2; + + usec += delta_usec; + if (usec >= 1000000) { + sec += 1; + usec -= 1000000; + } + + tv->tv_sec = sec; + tv->tv_usec = usec; } void do_settimeofday(struct timeval *tv) @@ -252,10 +310,12 @@ static int set_rtc_mmss(unsigned long nowtime) int real_seconds, real_minutes, cmos_minutes; unsigned char save_control, save_freq_select; - save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ + /* Tell the clock it's being set */ + save_control = CMOS_READ(RTC_CONTROL); CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ + /* Stop and reset prescaler */ + save_freq_select = CMOS_READ(RTC_FREQ_SELECT); CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); cmos_minutes = CMOS_READ(RTC_MINUTES); @@ -270,8 +330,10 @@ static int set_rtc_mmss(unsigned long nowtime) */ real_seconds = nowtime % 60; real_minutes = nowtime / 60; - if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ + if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) { + /* correct for half hour time zone */ + real_minutes += 30; + } real_minutes %= 60; if (abs(real_minutes - cmos_minutes) < 30) { diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index 12bee3fbc..14a8e2010 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -12,6 +12,7 @@ #include <linux/mm.h> #include <linux/sched.h> #include <linux/tty.h> +#include <linux/delay.h> #include <asm/gentrap.h> #include <asm/uaccess.h> @@ -20,45 +21,41 @@ #include <asm/smp_lock.h> -void die_if_kernel(char * str, struct pt_regs * regs, long err, - unsigned long *r9_15) +static void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15) { - long i; - unsigned long ra; - unsigned int * pc; - unsigned long * sp; - - if (regs->ps & 8) - return; - printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err); - sp = (unsigned long *) (regs+1); - __get_user(ra, (unsigned long *)sp); - printk("pc = [<%016lx>] ps = %04lx\n", regs->pc, regs->ps); - printk("rp = [<%016lx>] ra = [<%016lx>]\n", regs->r26, ra); - printk("r0 = %016lx r1 = %016lx\n", regs->r0, regs->r1); - printk("r2 = %016lx r3 = %016lx\n", regs->r2, regs->r3); - printk("r4 = %016lx r5 = %016lx\n", regs->r4, regs->r5); - printk("r6 = %016lx r7 = %016lx\n", regs->r6, regs->r7); + printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx\n", + regs->pc, regs->r26, regs->ps); + printk("r0 = %016lx r1 = %016lx r2 = %016lx\n", + regs->r0, regs->r1, regs->r2); + printk("r3 = %016lx r4 = %016lx r5 = %016lx\n", + regs->r3, regs->r4, regs->r5); + printk("r6 = %016lx r7 = %016lx r8 = %016lx\n", + regs->r6, regs->r7, regs->r8); if (r9_15) { - printk("r8 = %016lx r9 = %016lx\n", regs->r8, r9_15[9]); - printk("r10= %016lx r11= %016lx\n", r9_15[10], r9_15[11]); - printk("r12= %016lx r13= %016lx\n", r9_15[12], r9_15[13]); - printk("r14= %016lx r15= %016lx\n", r9_15[14], r9_15[15]); - } else { - printk("r8 = %016lx\n", regs->r8); + printk("r9 = %016lx r10= %016lx r11= %016lx\n", + r9_15[9], r9_15[10], r9_15[11]); + printk("r12= %016lx r13= %016lx r14= %016lx\n", + r9_15[12], r9_15[13], r9_15[14]); + printk("r15= %016lx\n", r9_15[15]); } - printk("r16= %016lx r17= %016lx\n", regs->r16, regs->r17); - printk("r18= %016lx r19= %016lx\n", regs->r18, regs->r19); - printk("r20= %016lx r21= %016lx\n", regs->r20, regs->r21); - printk("r22= %016lx r23= %016lx\n", regs->r22, regs->r23); - printk("r24= %016lx r25= %016lx\n", regs->r24, regs->r25); - printk("r27= %016lx r28= %016lx\n", regs->r27, regs->r28); - printk("gp = %016lx sp = %p\n", regs->gp, sp); + printk("r16= %016lx r17= %016lx r18= %016lx\n", + regs->r16, regs->r17, regs->r18); + printk("r19= %016lx r20= %016lx r21= %016lx\n", + regs->r19, regs->r20, regs->r21); + printk("r22= %016lx r23= %016lx r24= %016lx\n", + regs->r22, regs->r23, regs->r24); + printk("r25= %016lx r27= %016lx r28= %016lx\n", + regs->r25, regs->r27, regs->r28); + printk("gp = %016lx sp = %p\n", regs->gp, regs+1); +} + +static void dik_show_code(unsigned int *pc) +{ + long i; printk("Code:"); - pc = (unsigned int *) regs->pc; for (i = -3; i < 6; i++) { unsigned int insn; if (__get_user(insn, pc+i)) @@ -66,6 +63,11 @@ void die_if_kernel(char * str, struct pt_regs * regs, long err, printk("%c%08x%c",i?' ':'<',insn,i?' ':'>'); } printk("\n"); +} + +static void dik_show_trace(unsigned long *sp) +{ + long i = 0; printk("Trace:"); while (0x1ff8 & (unsigned long) sp) { extern unsigned long _stext, _etext; @@ -76,9 +78,30 @@ void die_if_kernel(char * str, struct pt_regs * regs, long err, if (tmp >= (unsigned long) &_etext) continue; printk(" [<%lx>]", tmp); + if (++i > 40) { + printk(" ..."); + break; + } } printk("\n"); - +} + +void die_if_kernel(char * str, struct pt_regs *regs, long err, + unsigned long *r9_15) +{ + if (regs->ps & 8) + return; + printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err); + dik_show_regs(regs, r9_15); + dik_show_code((unsigned int *)regs->pc); + dik_show_trace((unsigned long *)(regs+1)); + + if (current->tss.flags & (1UL << 63)) { + printk("die_if_kernel recursion detected.\n"); + sti(); + while (1); + } + current->tss.flags |= (1UL << 63); do_exit(SIGSEGV); } @@ -397,8 +420,6 @@ asmlinkage void do_entUna(void * va, unsigned long opcode, unsigned long reg, printk("Bad unaligned kernel access at %016lx: %p %lx %ld\n", pc, va, opcode, reg); do_exit(SIGSEGV); - unlock_kernel(); - return; got_exception: /* Ok, we caught the exception, but we don't want it. Is there @@ -416,13 +437,48 @@ got_exception: return; } - /* Yikes! No one to forward the exception to. */ + /* + * Yikes! No one to forward the exception to. + * Since the registers are in a weird format, dump them ourselves. + */ lock_kernel(); - printk("%s: unhandled unaligned exception at pc=%lx ra=%lx" - " (bad address = %p)\n", current->comm, - pc, una_reg(26), va); + + printk("%s(%d): unhandled unaligned exception\n", + current->comm, current->pid); + + printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx\n", + pc, una_reg(26), regs.ps); + printk("r0 = %016lx r1 = %016lx r2 = %016lx\n", + una_reg(0), una_reg(1), una_reg(2)); + printk("r3 = %016lx r4 = %016lx r5 = %016lx\n", + una_reg(3), una_reg(4), una_reg(5)); + printk("r6 = %016lx r7 = %016lx r8 = %016lx\n", + una_reg(6), una_reg(7), una_reg(8)); + printk("r9 = %016lx r10= %016lx r11= %016lx\n", + una_reg(9), una_reg(10), una_reg(11)); + printk("r12= %016lx r13= %016lx r14= %016lx\n", + una_reg(12), una_reg(13), una_reg(14)); + printk("r15= %016lx\n", una_reg(15)); + printk("r16= %016lx r17= %016lx r18= %016lx\n", + una_reg(16), una_reg(17), una_reg(18)); + printk("r19= %016lx r20= %016lx r21= %016lx\n", + una_reg(19), una_reg(20), una_reg(21)); + printk("r22= %016lx r23= %016lx r24= %016lx\n", + una_reg(22), una_reg(23), una_reg(24)); + printk("r25= %016lx r27= %016lx r28= %016lx\n", + una_reg(25), una_reg(27), una_reg(28)); + printk("gp = %016lx sp = %p\n", regs.gp, ®s+1); + + dik_show_code((unsigned int *)pc); + dik_show_trace((unsigned long *)(®s+1)); + + if (current->tss.flags & (1UL << 63)) { + printk("die_if_kernel recursion detected.\n"); + sti(); + while (1); + } + current->tss.flags |= (1UL << 63); do_exit(SIGSEGV); - unlock_kernel(); } /* @@ -800,26 +856,17 @@ give_sigbus: } /* - * DEC means people to use the "retsys" instruction for return from - * a system call, but they are clearly misguided about this. We use - * "rti" in all cases, and fill in the stack with the return values. - * That should make signal handling etc much cleaner. - * - * Even more horribly, DEC doesn't allow system calls from kernel mode. - * "Security" features letting the user do something the kernel can't - * are a thinko. DEC palcode is strange. The PAL-code designers probably - * got terminally tainted by VMS at some point. + * Unimplemented system calls. */ -asmlinkage long do_entSys(unsigned long a0, unsigned long a1, unsigned long a2, - unsigned long a3, unsigned long a4, unsigned long a5, - struct pt_regs regs) +asmlinkage long alpha_ni_syscall(unsigned long a0, unsigned long a1, + unsigned long a2, unsigned long a3, + unsigned long a4, unsigned long a5, + struct pt_regs regs) { - lock_kernel(); /* Only report OSF system calls. */ if (regs.r0 != 112 && regs.r0 < 300) printk("<sc %ld(%lx,%lx,%lx)>", regs.r0, a0, a1, a2); - unlock_kernel(); - return -1; + return -ENOSYS; } extern asmlinkage void entMM(void); diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile index a4e0fea9f..28dc3d451 100644 --- a/arch/alpha/lib/Makefile +++ b/arch/alpha/lib/Makefile @@ -19,9 +19,6 @@ endif lib.a: $(OBJS) $(AR) rcs lib.a $(OBJS) -memset.o: memset.S - $(CC) -c -o memset.o memset.S - __divqu.o: divide.S $(CC) -DDIV -c -o __divqu.o divide.S diff --git a/arch/alpha/lib/clear_user.S b/arch/alpha/lib/clear_user.S index db179adfd..65d7e2f28 100644 --- a/arch/alpha/lib/clear_user.S +++ b/arch/alpha/lib/clear_user.S @@ -37,8 +37,8 @@ .set noreorder .align 4 - .globl __clear_user - .ent __clear_user + .globl __do_clear_user + .ent __do_clear_user .frame $30, 0, $28 .prologue 0 @@ -79,7 +79,7 @@ $tail: EX( stq_u $5, 0($6) ) # e0 : ret $31, ($28), 1 # .. e1 : -__clear_user: +__do_clear_user: and $6, 7, $4 # e0 : find dest misalignment beq $0, $zerolength # .. e1 : addq $0, $4, $1 # e0 : bias counter @@ -110,4 +110,4 @@ $zerolength: $exception: ret $31, ($28), 1 # .. e1 : - .end __clear_user + .end __do_clear_user diff --git a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c index 475c84e7d..24a45e7aa 100644 --- a/arch/alpha/lib/csum_partial_copy.c +++ b/arch/alpha/lib/csum_partial_copy.c @@ -8,7 +8,7 @@ */ #include <linux/types.h> -#include <asm/string.h> +#include <linux/string.h> #include <asm/uaccess.h> diff --git a/arch/i386/boot/compressed/head.S b/arch/i386/boot/compressed/head.S index 6f68a92d4..30384a3a3 100644 --- a/arch/i386/boot/compressed/head.S +++ b/arch/i386/boot/compressed/head.S @@ -37,7 +37,7 @@ startup_32: cld cli - movl $(KERNEL_DS),%eax + movl $(__KERNEL_DS),%eax mov %ax,%ds mov %ax,%es mov %ax,%fs @@ -56,7 +56,7 @@ startup_32: movl %eax,%esp pushl 0 # Clear NT popfl - ljmp $(KERNEL_CS), $0x100000 # Into C and sanity + ljmp $(__KERNEL_CS), $0x100000 # Into C and sanity 2: #endif @@ -92,7 +92,7 @@ startup_32: orl %eax,%eax jnz 3f xorl %ebx,%ebx - ljmp $(KERNEL_CS), $0x100000 + ljmp $(__KERNEL_CS), $0x100000 /* * We come here, if we were loaded high. @@ -116,7 +116,7 @@ startup_32: popl %eax # hcount movl $0x100000,%edi cli # make sure we don't get interrupted - ljmp $(KERNEL_CS), $0x1000 # and jump to the move routine + ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine /* * Routine (template) for moving the decompressed kernel in place, @@ -136,5 +136,5 @@ move_routine_start: * so we set esp here. */ mov $0x90000,%esp - ljmp $(KERNEL_CS), $0x100000 + ljmp $(__KERNEL_CS), $0x100000 move_routine_end: diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c index 9a556baf4..e4a6ede9a 100644 --- a/arch/i386/boot/compressed/misc.c +++ b/arch/i386/boot/compressed/misc.c @@ -285,7 +285,7 @@ long user_stack [STACK_SIZE]; struct { long * a; short b; - } stack_start = { & user_stack [STACK_SIZE] , KERNEL_DS }; + } stack_start = { & user_stack [STACK_SIZE] , __KERNEL_DS }; void setup_normal_output_buffer() { diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S index edc0fe0ff..11310bd49 100644 --- a/arch/i386/boot/setup.S +++ b/arch/i386/boot/setup.S @@ -594,7 +594,7 @@ flush_instr: xor bx,bx ! Flag to indicate a boot ! NOTE: For high loaded big kernels we need a -! jmpi 0x100000,KERNEL_CS +! jmpi 0x100000,__KERNEL_CS ! ! but we yet haven't reloaded the CS register, so the default size ! of the target offset still is 16 bit. @@ -603,7 +603,7 @@ flush_instr: ! Manual, Mixing 16-bit and 32-bit code, page 16-6) db 0x66,0xea ! prefix + jmpi-opcode code32: dd 0x1000 ! will be set to 0x100000 for big kernels - dw KERNEL_CS + dw __KERNEL_CS kernel_version: .ascii UTS_RELEASE diff --git a/arch/i386/config.in b/arch/i386/config.in index f7042fa33..7595ab5fe 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -84,6 +84,8 @@ if [ "$CONFIG_NET" = "y" ]; then endmenu fi +source drivers/net/hamradio/Config.in + mainmenu_option next_comment comment 'ISDN subsystem' @@ -102,6 +104,17 @@ if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then fi endmenu +# Conditionally compile in the Uniform CD-ROM driver +if [ "$CONFIG_BLK_DEV_IDECD" = "y" -o "$CONFIG_BLK_DEV_SR" = "y" -o "$CONFIG_SBPCD" = "y" -o "$CONFIG_MCD" = "y" -o "$CONFIG_CM206" = "y" -o "$CONFIG_CDU31A" = "y" ]; then + define_bool CONFIG_CDROM y +else + if [ "$CONFIG_BLK_DEV_IDECD" = "m" -o "$CONFIG_BLK_DEV_SR" = "m" -o "$CONFIG_SBPCD" = "m" -o "$CONFIG_MCD" = "m" -o "$CONFIG_CM206" = "m" -o "$CONFIG_CDU31A" = "m" ]; then + define_bool CONFIG_CDROM m + else + define_bool CONFIG_CDROM n + fi +fi + source fs/Config.in source fs/nls/Config.in diff --git a/arch/i386/defconfig b/arch/i386/defconfig index bd100e08d..222b10939 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -58,7 +58,7 @@ CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_CMD640=y # CONFIG_BLK_DEV_CMD640_ENHANCED is not set CONFIG_BLK_DEV_RZ1000=y -CONFIG_BLK_DEV_TRITON=y +CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDE_CHIPSETS is not set # @@ -74,22 +74,27 @@ CONFIG_BLK_DEV_TRITON=y # # Networking options # +CONFIG_PACKET=y # CONFIG_NETLINK is not set # CONFIG_FIREWALL is not set # CONFIG_NET_ALIAS is not set +CONFIG_UNIX=y CONFIG_INET=y # CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set # CONFIG_IP_ACCT is not set +# CONFIG_IP_MASQUERADE is not set # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_ALIAS is not set # CONFIG_SYN_COOKIES is not set # # (it is safe to leave these untouched) # -# CONFIG_INET_PCTCP is not set # CONFIG_INET_RARP is not set -CONFIG_PATH_MTU_DISCOVERY=y CONFIG_IP_NOSR=y CONFIG_SKB_LARGE=y @@ -98,7 +103,6 @@ CONFIG_SKB_LARGE=y # # CONFIG_IPX is not set # CONFIG_ATALK is not set -# CONFIG_AX25 is not set # # SCSI support @@ -179,14 +183,20 @@ CONFIG_EEXPRESS_PRO100=y # CONFIG_FDDI is not set # CONFIG_DLCI is not set # CONFIG_PPP is not set -# CONFIG_NET_RADIO is not set # CONFIG_SLIP is not set +# CONFIG_STRIP is not set +# CONFIG_WAVELAN is not set # CONFIG_TR is not set # CONFIG_WAN_DRIVERS is not set # CONFIG_LAPBETHER is not set # CONFIG_X25_ASY is not set # +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# # ISDN subsystem # # CONFIG_ISDN is not set @@ -195,6 +205,7 @@ CONFIG_EEXPRESS_PRO100=y # CD-ROM drivers (not for SCSI or IDE/ATAPI drives) # # CONFIG_CD_NO_IDESCSI is not set +CONFIG_CDROM=y # # Filesystems @@ -214,6 +225,7 @@ CONFIG_NFS_FS=y CONFIG_NFSD=y CONFIG_SUNRPC=y CONFIG_LOCKD=y +# CONFIG_CODA_FS is not set # CONFIG_SMB_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_SYSV_FS is not set @@ -234,6 +246,7 @@ CONFIG_AUTOFS_FS=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_SERIAL=y +# CONFIG_SERIAL_CONSOLE is not set # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set CONFIG_MOUSE=y diff --git a/arch/i386/kernel/bios32.c b/arch/i386/kernel/bios32.c index e98819258..8e41188c3 100644 --- a/arch/i386/kernel/bios32.c +++ b/arch/i386/kernel/bios32.c @@ -1,7 +1,7 @@ /* * bios32.c - BIOS32, PCI BIOS functions. * - * $Id: bios32.c,v 1.14 1997/08/02 22:20:57 mj Exp $ + * $Id: bios32.c,v 1.5 1997/12/02 01:48:00 ralf Exp $ * * Sponsored by * iX Multiuser Multitasking Magazine @@ -528,7 +528,7 @@ static unsigned long bios32_entry = 0; static struct { unsigned long address; unsigned short segment; -} bios32_indirect = { 0, KERNEL_CS }; +} bios32_indirect = { 0, __KERNEL_CS }; /* * Returns the entry point for the given service, NULL on error @@ -570,7 +570,7 @@ static long pcibios_entry = 0; static struct { unsigned long address; unsigned short segment; -} pci_indirect = { 0, KERNEL_CS }; +} pci_indirect = { 0, __KERNEL_CS }; __initfunc(static int check_pcibios(void)) { diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index dffc13795..cf99d6e2e 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -73,15 +73,15 @@ VM_MASK = 0x00020000 state = 0 counter = 4 priority = 8 -signal = 12 -blocked = 16 -flags = 20 -dbgreg6 = 52 -dbgreg7 = 56 -exec_domain = 60 +flags = 12 +sigpending = 16 +dbgreg6 = 44 +dbgreg7 = 48 +exec_domain = 52 ENOSYS = 38 + #define SAVE_ALL \ cld; \ push %es; \ @@ -93,7 +93,7 @@ ENOSYS = 38 pushl %edx; \ pushl %ecx; \ pushl %ebx; \ - movl $(KERNEL_DS),%edx; \ + movl $(__KERNEL_DS),%edx; \ mov %dx,%ds; \ mov %dx,%es; @@ -170,10 +170,7 @@ ret_from_sys_call: ret_with_reschedule: cmpl $0,SYMBOL_NAME(need_resched) jne reschedule - movl blocked(%ebx),%eax - movl %eax,%esi # save blocked in %esi for signal handling - notl %eax - andl signal(%ebx),%eax + cmpl $0,sigpending(%ebx) jne signal_return RESTORE_ALL ALIGN @@ -181,7 +178,7 @@ signal_return: testl $(VM_MASK),EFLAGS(%esp) pushl %esp jne v86_signal_return - pushl %esi + pushl $0 call SYMBOL_NAME(do_signal) addl $8,%esp RESTORE_ALL @@ -190,7 +187,7 @@ v86_signal_return: call SYMBOL_NAME(save_v86_state) movl %eax,%esp pushl %eax - pushl %esi + pushl $0 call SYMBOL_NAME(do_signal) addl $8,%esp RESTORE_ALL @@ -255,7 +252,7 @@ error_code: xchgl %ecx, ES(%esp) # get the address and save es. pushl %eax # push the error code pushl %edx - movl $(KERNEL_DS),%edx + movl $(__KERNEL_DS),%edx mov %dx,%ds mov %dx,%es GET_CURRENT(%ebx) @@ -529,6 +526,16 @@ ENTRY(sys_call_table) .long SYMBOL_NAME(sys_setresgid) /* 170 */ .long SYMBOL_NAME(sys_getresgid) .long SYMBOL_NAME(sys_prctl) - .rept NR_syscalls-172 + .long SYMBOL_NAME(sys_rt_sigreturn) + .long SYMBOL_NAME(sys_rt_sigaction) + .long SYMBOL_NAME(sys_rt_sigprocmask) /* 175 */ + .long SYMBOL_NAME(sys_rt_sigpending) + .long SYMBOL_NAME(sys_rt_sigtimedwait) + .long SYMBOL_NAME(sys_rt_sigqueueinfo) + .long SYMBOL_NAME(sys_rt_sigsuspend) + .long SYMBOL_NAME(sys_pread) /* 180 */ + .long SYMBOL_NAME(sys_pwrite) + + .rept NR_syscalls-181 .long SYMBOL_NAME(sys_ni_syscall) .endr diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index 00a8e122e..a21ac6791 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -29,7 +29,7 @@ startup_32: * Set segments to known values */ cld - movl $(KERNEL_DS),%eax + movl $(__KERNEL_DS),%eax mov %ax,%ds mov %ax,%es mov %ax,%fs @@ -227,14 +227,14 @@ is386: pushl %ecx # restore original EFLAGS #endif lgdt gdt_descr lidt idt_descr - ljmp $(KERNEL_CS),$1f -1: movl $(KERNEL_DS),%eax # reload all the segment registers + ljmp $(__KERNEL_CS),$1f +1: movl $(__KERNEL_DS),%eax# reload all the segment registers mov %ax,%ds # after changing gdt. mov %ax,%es mov %ax,%fs mov %ax,%gs #ifdef __SMP__ - movl $(KERNEL_DS), %eax + movl $(__KERNEL_DS), %eax mov %ax,%ss # Reload the stack pointer (segment only) #else lss stack_start,%esp # Load processor stack @@ -285,7 +285,7 @@ check_x87: */ setup_idt: lea ignore_int,%edx - movl $(KERNEL_CS << 16),%eax + movl $(__KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ @@ -301,7 +301,7 @@ rp_sidt: ENTRY(stack_start) .long SYMBOL_NAME(init_task_union)+8192 - .long KERNEL_DS + .long __KERNEL_DS /* This is the default interrupt "handler" :-) */ int_msg: @@ -314,7 +314,7 @@ ignore_int: pushl %edx push %es push %ds - movl $(KERNEL_DS),%eax + movl $(__KERNEL_DS),%eax mov %ax,%ds mov %ax,%es pushl $int_msg diff --git a/arch/i386/kernel/init_task.c b/arch/i386/kernel/init_task.c index cc0a19231..acc206942 100644 --- a/arch/i386/kernel/init_task.c +++ b/arch/i386/kernel/init_task.c @@ -1,6 +1,7 @@ #include <linux/mm.h> #include <linux/sched.h> +#include <asm/uaccess.h> #include <asm/pgtable.h> static struct vm_area_struct init_mmap = INIT_MMAP; diff --git a/arch/i386/kernel/irq.h b/arch/i386/kernel/irq.h index 7d70264ba..db70872f1 100644 --- a/arch/i386/kernel/irq.h +++ b/arch/i386/kernel/irq.h @@ -44,7 +44,7 @@ static inline void irq_exit(int cpu, int irq) "pushl %edx\n\t" \ "pushl %ecx\n\t" \ "pushl %ebx\n\t" \ - "movl $" STR(KERNEL_DS) ",%edx\n\t" \ + "movl $" STR(__KERNEL_DS) ",%edx\n\t" \ "mov %dx,%ds\n\t" \ "mov %dx,%es\n\t" diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index a8fe0315b..5a13e0179 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -281,22 +281,19 @@ void machine_restart(char * __unused) { if(!reboot_thru_bios) { -#if 0 - sti(); -#endif /* rebooting needs to touch the page at absolute addr 0 */ *((unsigned short *)__va(0x472)) = reboot_mode; for (;;) { int i; for (i=0; i<100; i++) { - int j; kb_wait(); - for(j = 0; j < 100000 ; j++) - /* nothing */; + udelay(10); outb(0xfe,0x64); /* pulse reset low */ udelay(10); } - __asm__ __volatile__("\tlidt %0": "=m" (no_idt)); + /* That didn't work - force a triple fault.. */ + __asm__ __volatile__("lidt %0": :"m" (no_idt)); + __asm__ __volatile__("int3"); } } @@ -480,13 +477,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, p->tss.tr = _TSS(nr); p->tss.ldt = _LDT(nr); - p->tss.es = KERNEL_DS; - p->tss.cs = KERNEL_CS; - p->tss.ss = KERNEL_DS; - p->tss.ds = KERNEL_DS; - p->tss.fs = USER_DS; - p->tss.gs = USER_DS; - p->tss.ss0 = KERNEL_DS; + p->tss.es = __KERNEL_DS; + p->tss.cs = __KERNEL_CS; + p->tss.ss = __KERNEL_DS; + p->tss.ds = __KERNEL_DS; + p->tss.fs = __USER_DS; + p->tss.gs = __USER_DS; + p->tss.ss0 = __KERNEL_DS; p->tss.esp0 = 2*PAGE_SIZE + (unsigned long) p; childregs = ((struct pt_regs *) (p->tss.esp0)) - 1; p->tss.esp = (unsigned long) childregs; diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index c8a7f986e..246a6c29b 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -492,7 +492,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) long tmp; ret = -EIO; - if ((unsigned long) data > NSIG) + if ((unsigned long) data > _NSIG) goto out; if (request == PTRACE_SYSCALL) child->flags |= PF_TRACESYS; @@ -530,7 +530,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) long tmp; ret = -EIO; - if ((unsigned long) data > NSIG) + if ((unsigned long) data > _NSIG) goto out; child->flags &= ~PF_TRACESYS; tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG; @@ -546,7 +546,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) long tmp; ret = -EIO; - if ((unsigned long) data > NSIG) + if ((unsigned long) data > _NSIG) goto out; child->flags &= ~(PF_PTRACED|PF_TRACESYS); wake_up_process(child); @@ -585,9 +585,7 @@ asmlinkage void syscall_trace(void) * stopping signal is not SIGTRAP. -brl */ if (current->exit_code) { - spin_lock_irq(¤t->sigmask_lock); - current->signal |= (1 << (current->exit_code - 1)); - spin_unlock_irq(¤t->sigmask_lock); + send_sig(current->exit_code, current, 1); + current->exit_code = 0; } - current->exit_code = 0; } diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index f5af47201..7d5cf3a95 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c @@ -2,6 +2,8 @@ * linux/arch/i386/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds + * + * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson */ #include <linux/config.h> @@ -16,40 +18,132 @@ #include <linux/wait.h> #include <linux/ptrace.h> #include <linux/unistd.h> - +#include <linux/stddef.h> +#include <asm/ucontext.h> #include <asm/uaccess.h> -#define _S(nr) (1<<((nr)-1)) +#define DEBUG_SIG 0 -#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, int options, unsigned long *ru); - -asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs); +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); /* - * atomically swap in the new signal mask, and wait for a signal. + * Atomically swap in the new signal mask, and wait for a signal. */ -asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set) +asmlinkage int +sys_sigsuspend(int history0, int history1, old_sigset_t mask) { - struct pt_regs * regs = (struct pt_regs *) &restart; - unsigned long mask; + struct pt_regs * regs = (struct pt_regs *) &history0; + sigset_t saveset; + mask &= _BLOCKABLE; spin_lock_irq(¤t->sigmask_lock); - mask = current->blocked; - current->blocked = set & _BLOCKABLE; + saveset = current->blocked; + siginitset(¤t->blocked, mask); + recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); regs->eax = -EINTR; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(mask, regs)) + if (do_signal(&saveset, regs)) return -EINTR; } } +asmlinkage int +sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize) +{ + struct pt_regs * regs = (struct pt_regs *) &unewset; + sigset_t saveset, newset; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + + if (copy_from_user(&newset, unewset, sizeof(newset))) + return -EFAULT; + sigdelsetmask(&newset, ~_BLOCKABLE); + + spin_lock_irq(¤t->sigmask_lock); + saveset = current->blocked; + current->blocked = newset; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + regs->eax = -EINTR; + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal(&saveset, regs)) + return -EINTR; + } +} + +asmlinkage int +sys_sigaction(int sig, const struct old_sigaction *act, + struct old_sigaction *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + old_sigset_t mask; + if (verify_area(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + return -EFAULT; + __get_user(new_ka.sa.sa_flags, &act->sa_flags); + __get_user(mask, &act->sa_mask); + siginitset(&new_ka.sa.sa_mask, mask); + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + return -EFAULT; + __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + } + + return ret; +} + + +/* + * Do a signal return; undo the signal stack. + */ + +struct sigframe +{ + char *pretcode; + int sig; + struct sigcontext sc; + struct _fpstate fpstate; + unsigned long extramask[_NSIG_WORDS-1]; + char retcode[8]; +}; + +struct rt_sigframe +{ + char *pretcode; + int sig; + struct siginfo *pinfo; + void *puc; + struct siginfo info; + struct ucontext uc; + struct _fpstate fpstate; + char retcode[8]; +}; + + static inline void restore_i387_hard(struct _fpstate *buf) { #ifdef __SMP__ @@ -64,94 +158,150 @@ static inline void restore_i387_hard(struct _fpstate *buf) #endif current->used_math = 1; current->flags &= ~PF_USEDFPU; - copy_from_user(¤t->tss.i387.hard, buf, sizeof(*buf)); + __copy_from_user(¤t->tss.i387.hard, buf, sizeof(*buf)); } -static void restore_i387(struct _fpstate *buf) +static inline void restore_i387(struct _fpstate *buf) { #ifndef CONFIG_MATH_EMULATION restore_i387_hard(buf); #else - if (hard_math) { + if (hard_math) restore_i387_hard(buf); - return; - } - restore_i387_soft(buf); -#endif + else + restore_i387_soft(buf); +#endif } - -/* - * This sets regs->esp even though we don't actually use sigstacks yet.. - */ -asmlinkage int sys_sigreturn(unsigned long __unused) +static int +restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) { -#define COPY(x) regs->x = context->x -#define COPY_SEG(seg) \ -{ unsigned int tmp = context->seg; \ -if ( (tmp & 0xfffc) /* not a NULL selectors */ \ - && (tmp & 0x4) != 0x4 /* not a LDT selector */ \ - && (tmp & 3) != 3 /* not a RPL3 GDT selector */ \ - ) goto badframe; \ -regs->x##seg = tmp; } -#define COPY_SEG_STRICT(seg) \ -{ unsigned int tmp = context->seg; \ -if ((tmp & 0xfffc) && (tmp & 3) != 3) goto badframe; \ -regs->x##seg = tmp; } -#define GET_SEG(seg) \ -{ unsigned int tmp = context->seg; \ -if ( (tmp & 0xfffc) /* not a NULL selectors */ \ - && (tmp & 0x4) != 0x4 /* not a LDT selector */ \ - && (tmp & 3) != 3 /* not a RPL3 GDT selector */ \ - ) goto badframe; \ -__asm__("mov %w0,%%" #seg: :"r" (tmp)); } - struct sigcontext * context; - struct pt_regs * regs; - - regs = (struct pt_regs *) &__unused; - context = (struct sigcontext *) regs->esp; - if (verify_area(VERIFY_READ, context, sizeof(*context))) - goto badframe; - current->blocked = context->oldmask & _BLOCKABLE; - COPY_SEG(ds); - COPY_SEG(es); - GET_SEG(fs); + unsigned int tmp; + +#define COPY(x) __get_user(regs->x, &sc->x) + +#define COPY_SEG(seg) \ + { __get_user(tmp, &sc->seg); \ + if ((tmp & 0xfffc) /* not a NULL selectors */ \ + && (tmp & 0x4) != 0x4 /* not a LDT selector */ \ + && (tmp & 3) != 3) /* not a RPL3 GDT selector */ \ + goto badframe; \ + regs->x##seg = tmp; } + +#define COPY_SEG_STRICT(seg) \ + { __get_user(tmp, &sc->seg); \ + if ((tmp & 0xfffc) && (tmp & 3) != 3) goto badframe; \ + regs->x##seg = tmp; } + +#define GET_SEG(seg) \ + { __get_user(tmp, &sc->seg); \ + if ((tmp & 0xfffc) /* not a NULL selectors */ \ + && (tmp & 0x4) != 0x4 /* not a LDT selector */ \ + && (tmp & 3) != 3) /* not a RPL3 GDT selector */ \ + goto badframe; \ + __asm__ __volatile__("mov %w0,%%" #seg : : "r"(tmp)); } + GET_SEG(gs); - COPY_SEG_STRICT(ss); - COPY_SEG_STRICT(cs); - COPY(eip); - COPY(ecx); COPY(edx); + GET_SEG(fs); + COPY_SEG(es); + COPY_SEG(ds); + COPY(edi); + COPY(esi); + COPY(ebp); + COPY(esp); COPY(ebx); - COPY(esp); COPY(ebp); - COPY(edi); COPY(esi); - regs->eflags &= ~0x40DD5; - regs->eflags |= context->eflags & 0x40DD5; + COPY(edx); + COPY(ecx); + COPY(eip); + COPY_SEG_STRICT(cs); + COPY_SEG_STRICT(ss); + + __get_user(tmp, &sc->eflags); + regs->eflags = (regs->eflags & ~0x40DD5) | (tmp & 0x40DD5); regs->orig_eax = -1; /* disable syscall checks */ - if (context->fpstate) { - struct _fpstate * buf = context->fpstate; + + __get_user(tmp, (unsigned long *)&sc->fpstate); + if (tmp) { + struct _fpstate * buf = (struct _fpstate *) tmp; if (verify_area(VERIFY_READ, buf, sizeof(*buf))) goto badframe; restore_i387(buf); } - return context->eax; + + __get_user(tmp, &sc->eax); + return tmp; badframe: lock_kernel(); do_exit(SIGSEGV); - unlock_kernel(); } +asmlinkage int sys_sigreturn(unsigned long __unused) +{ + struct pt_regs *regs = (struct pt_regs *) &__unused; + struct sigframe *frame = (struct sigframe *)(regs->esp - 8); + sigset_t set; + + if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + if (__get_user(set.sig[0], &frame->sc.oldmask) + || (_NSIG_WORDS > 1 + && __copy_from_user(&set.sig[1], &frame->extramask, + sizeof(frame->extramask)))) + goto badframe; + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + return restore_sigcontext(regs, &frame->sc); + +badframe: + lock_kernel(); + do_exit(SIGSEGV); +} + +asmlinkage int sys_rt_sigreturn(unsigned long __unused) +{ + struct pt_regs *regs = (struct pt_regs *) &__unused; + struct rt_sigframe *frame = (struct rt_sigframe *)(regs->esp - 4); + sigset_t set; + + if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) + goto badframe; + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + return restore_sigcontext(regs, &frame->uc.uc_mcontext); + +badframe: + lock_kernel(); + do_exit(SIGSEGV); +} + +/* + * Set up a signal frame. + */ + static inline struct _fpstate * save_i387_hard(struct _fpstate * buf) { #ifdef __SMP__ if (current->flags & PF_USEDFPU) { - __asm__ __volatile__("fnsave %0":"=m" (current->tss.i387.hard)); + __asm__ __volatile__("fnsave %0":"=m"(current->tss.i387.hard)); stts(); current->flags &= ~PF_USEDFPU; } #else if (current == last_task_used_math) { - __asm__ __volatile__("fnsave %0":"=m" (current->tss.i387.hard)); + __asm__ __volatile__("fnsave %0":"=m"(current->tss.i387.hard)); last_task_used_math = NULL; __asm__ __volatile__("fwait"); /* not needed on 486+ */ stts(); @@ -163,7 +313,7 @@ static inline struct _fpstate * save_i387_hard(struct _fpstate * buf) return buf; } -static struct _fpstate * save_i387(struct _fpstate * buf) +static struct _fpstate * save_i387(struct _fpstate *buf) { if (!current->used_math) return NULL; @@ -171,107 +321,197 @@ static struct _fpstate * save_i387(struct _fpstate * buf) #ifndef CONFIG_MATH_EMULATION return save_i387_hard(buf); #else - if (hard_math) - return save_i387_hard(buf); - return save_i387_soft(buf); + return hard_math ? save_i387_hard(buf) : save_i387_soft(buf); #endif } -/* - * Set up a signal frame... Make the stack look the way iBCS2 expects - * it to look. - */ -static void setup_frame(struct sigaction * sa, - struct pt_regs * regs, int signr, - unsigned long oldmask) +static void +setup_sigcontext(struct sigcontext *sc, struct _fpstate *fpstate, + struct pt_regs *regs, unsigned long mask) { - unsigned long * frame; + unsigned int tmp; + + tmp = 0; + __asm__("mov %%gs,%w0" : "=r"(tmp): "0"(tmp)); + __put_user(tmp, (unsigned int *)&sc->gs); + __asm__("mov %%fs,%w0" : "=r"(tmp): "0"(tmp)); + __put_user(tmp, (unsigned int *)&sc->fs); + + __put_user(regs->xes, (unsigned int *)&sc->es); + __put_user(regs->xds, (unsigned int *)&sc->ds); + __put_user(regs->edi, &sc->edi); + __put_user(regs->esi, &sc->esi); + __put_user(regs->ebp, &sc->ebp); + __put_user(regs->esp, &sc->esp); + __put_user(regs->ebx, &sc->ebx); + __put_user(regs->edx, &sc->edx); + __put_user(regs->ecx, &sc->ecx); + __put_user(regs->eax, &sc->eax); + __put_user(current->tss.trap_no, &sc->trapno); + __put_user(current->tss.error_code, &sc->err); + __put_user(regs->eip, &sc->eip); + __put_user(regs->xcs, (unsigned int *)&sc->cs); + __put_user(regs->eflags, &sc->eflags); + __put_user(regs->esp, &sc->esp_at_signal); + __put_user(regs->xss, (unsigned int *)&sc->ss); + + __put_user(save_i387(fpstate), &sc->fpstate); + + /* non-iBCS2 extensions.. */ + __put_user(mask, &sc->oldmask); + __put_user(current->tss.cr2, &sc->cr2); +} + +static void setup_frame(int sig, struct k_sigaction *ka, + sigset_t *set, struct pt_regs * regs) +{ + struct sigframe *frame; - frame = (unsigned long *) regs->esp; - if ((regs->xss & 0xffff) != USER_DS && sa->sa_restorer) - frame = (unsigned long *) sa->sa_restorer; - frame -= 64; - if (!access_ok(VERIFY_WRITE,frame,64*4)) - goto segv_and_exit; + frame = (struct sigframe *)((regs->esp - sizeof(*frame)) & -8); -/* set up the "normal" stack seen by the signal handler (iBCS2) */ -#define __CODE ((unsigned long)(frame+24)) -#define CODE(x) ((unsigned long *) ((x)+__CODE)) - - /* XXX Can possible miss a SIGSEGV when frame crosses a page border - and a thread unmaps it while we are accessing it. - So either check all put_user() calls or don't do it at all. - We use __put_user() here because the access_ok() call was already - done earlier. */ - if (__put_user(__CODE,frame)) + /* XXX: Check here if we need to switch stacks.. */ + + /* This is legacy signal stack switching. */ + if ((regs->xss & 0xffff) != __USER_DS + && !(ka->sa.sa_flags & SA_RESTORER) && ka->sa.sa_restorer) + frame = (struct sigframe *) ka->sa.sa_restorer; + + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto segv_and_exit; - if (current->exec_domain && current->exec_domain->signal_invmap) - __put_user(current->exec_domain->signal_invmap[signr], frame+1); - else - __put_user(signr, frame+1); + + __put_user((current->exec_domain + && current->exec_domain->signal_invmap + && sig < 32 + ? current->exec_domain->signal_invmap[sig] + : sig), + &frame->sig); + + setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]); + + if (_NSIG_WORDS > 1) { + __copy_to_user(frame->extramask, &set->sig[1], + sizeof(frame->extramask)); + } + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + if (ka->sa.sa_flags & SA_RESTORER) { + __put_user(ka->sa.sa_restorer, &frame->pretcode); + } else { + __put_user(frame->retcode, &frame->pretcode); + /* This is popl %eax ; movl $,%eax ; int $0x80 */ + __put_user(0xb858, (short *)(frame->retcode+0)); + __put_user(__NR_sigreturn, (int *)(frame->retcode+2)); + __put_user(0x80cd, (short *)(frame->retcode+6)); + } + + /* Set up registers for signal handler */ + regs->esp = (unsigned long) frame; + regs->eip = (unsigned long) ka->sa.sa_handler; { - unsigned int tmp = 0; -#define PUT_SEG(seg, mem) \ -__asm__("mov %%" #seg",%w0":"=r" (tmp):"0" (tmp)); __put_user(tmp,mem); - PUT_SEG(gs, frame+2); - PUT_SEG(fs, frame+3); + unsigned long seg = __USER_DS; + __asm__("mov %w0,%%fs ; mov %w0,%%gs": "=r"(seg) : "0"(seg)); + set_fs(MAKE_MM_SEG(seg)); + regs->xds = seg; + regs->xes = seg; + regs->xss = seg; + regs->xcs = __USER_CS; + } + regs->eflags &= ~TF_MASK; + +#if DEBUG_SIG + printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", + current->comm, current->pid, frame, regs->eip, frame->pretcode); +#endif + + return; + +segv_and_exit: + lock_kernel(); + do_exit(SIGSEGV); +} + +static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs * regs) +{ + struct rt_sigframe *frame; + + frame = (struct rt_sigframe *)((regs->esp - sizeof(*frame)) & -8); + + /* XXX: Check here if we need to switch stacks.. */ + + /* This is legacy signal stack switching. */ + if ((regs->xss & 0xffff) != __USER_DS + && !(ka->sa.sa_flags & SA_RESTORER) && ka->sa.sa_restorer) + frame = (struct rt_sigframe *) ka->sa.sa_restorer; + + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + goto segv_and_exit; + + __put_user((current->exec_domain + && current->exec_domain->signal_invmap + && sig < 32 + ? current->exec_domain->signal_invmap[sig] + : sig), + &frame->sig); + __put_user(&frame->info, &frame->pinfo); + __put_user(&frame->uc, &frame->puc); + __copy_to_user(&frame->info, info, sizeof(*info)); + + /* Clear all the bits of the ucontext we don't use. */ + __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); + + setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, + regs, set->sig[0]); + __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + if (ka->sa.sa_flags & SA_RESTORER) { + __put_user(ka->sa.sa_restorer, &frame->pretcode); + } else { + __put_user(frame->retcode, &frame->pretcode); + /* This is movl $,%eax ; int $0x80 */ + __put_user(0xb8, (char *)(frame->retcode+0)); + __put_user(__NR_rt_sigreturn, (int *)(frame->retcode+1)); + __put_user(0x80cd, (short *)(frame->retcode+5)); } - __put_user(regs->xes, frame+4); - __put_user(regs->xds, frame+5); - __put_user(regs->edi, frame+6); - __put_user(regs->esi, frame+7); - __put_user(regs->ebp, frame+8); - __put_user(regs->esp, frame+9); - __put_user(regs->ebx, frame+10); - __put_user(regs->edx, frame+11); - __put_user(regs->ecx, frame+12); - __put_user(regs->eax, frame+13); - __put_user(current->tss.trap_no, frame+14); - __put_user(current->tss.error_code, frame+15); - __put_user(regs->eip, frame+16); - __put_user(regs->xcs, frame+17); - __put_user(regs->eflags, frame+18); - __put_user(regs->esp, frame+19); - __put_user(regs->xss, frame+20); - __put_user((unsigned long) save_i387((struct _fpstate *)(frame+32)),frame+21); -/* non-iBCS2 extensions.. */ - __put_user(oldmask, frame+22); - __put_user(current->tss.cr2, frame+23); -/* set up the return code... */ - __put_user(0x0000b858, CODE(0)); /* popl %eax ; movl $,%eax */ - __put_user(0x80cd0000, CODE(4)); /* int $0x80 */ - __put_user(__NR_sigreturn, CODE(2)); -#undef __CODE -#undef CODE /* Set up registers for signal handler */ regs->esp = (unsigned long) frame; - regs->eip = (unsigned long) sa->sa_handler; + regs->eip = (unsigned long) ka->sa.sa_handler; { - unsigned long seg = USER_DS; - __asm__("mov %w0,%%fs ; mov %w0,%%gs":"=r" (seg) :"0" (seg)); - set_fs(seg); + unsigned long seg = __USER_DS; + __asm__("mov %w0,%%fs ; mov %w0,%%gs": "=r"(seg) : "0"(seg)); + set_fs(MAKE_MM_SEG(seg)); regs->xds = seg; regs->xes = seg; regs->xss = seg; - regs->xcs = USER_CS; + regs->xcs = __USER_CS; } regs->eflags &= ~TF_MASK; + +#if DEBUG_SIG + printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", + current->comm, current->pid, frame, regs->eip, frame->pretcode); +#endif + return; segv_and_exit: lock_kernel(); do_exit(SIGSEGV); - unlock_kernel(); } /* * OK, we're invoking a handler */ -static void handle_signal(unsigned long signr, struct sigaction *sa, - unsigned long oldmask, struct pt_regs * regs) + +static void +handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) { - /* are we from a system call? */ + /* Are we from a system call? */ if (regs->orig_eax >= 0) { /* If so, check system call restarting.. */ switch (regs->eax) { @@ -280,7 +520,7 @@ static void handle_signal(unsigned long signr, struct sigaction *sa, break; case -ERESTARTSYS: - if (!(sa->sa_flags & SA_RESTART)) { + if (!(ka->sa.sa_flags & SA_RESTART)) { regs->eax = -EINTR; break; } @@ -291,14 +531,20 @@ static void handle_signal(unsigned long signr, struct sigaction *sa, } } - /* set up the stack frame */ - setup_frame(sa, regs, signr, oldmask); + /* Set up the stack frame */ + if (ka->sa.sa_flags & SA_SIGINFO) + setup_rt_frame(sig, ka, info, oldset, regs); + else + setup_frame(sig, ka, oldset, regs); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; - if (sa->sa_flags & SA_ONESHOT) - sa->sa_handler = NULL; - if (!(sa->sa_flags & SA_NOMASK)) { + if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sigmask_lock); - current->blocked |= (sa->sa_mask | _S(signr)) & _BLOCKABLE; + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked,sig); + recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); } } @@ -312,66 +558,82 @@ static void handle_signal(unsigned long signr, struct sigaction *sa, * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ -asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) { - unsigned long mask; - unsigned long signr; - struct sigaction * sa; + siginfo_t info; + struct k_sigaction *ka; /* - * We want the common case to go fast, which + * We want the common case to go fast, which * is why we may in certain cases get here from * kernel mode. Just return without doing anything * if so. */ if ((regs->xcs & 3) != 3) return 1; - mask = ~current->blocked; - while ((signr = current->signal & mask)) { - /* - * This stops gcc flipping out. Otherwise the assembler - * including volatiles for the inline function to get - * current combined with this gets it confused. - */ - struct task_struct *t=current; - __asm__("bsf %3,%1\n\t" -#ifdef __SMP__ - "lock ; " -#endif - "btrl %1,%0" - :"=m" (t->signal),"=r" (signr) - :"0" (t->signal), "1" (signr)); - sa = current->sig->action + signr; - signr++; + + if (!oldset) + oldset = ¤t->blocked; + + for (;;) { + unsigned long signr; + + spin_lock_irq(¤t->sigmask_lock); + signr = dequeue_signal(¤t->blocked, &info); + spin_unlock_irq(¤t->sigmask_lock); + + if (!signr) + break; + if ((current->flags & PF_PTRACED) && signr != SIGKILL) { + /* Let the debugger run. */ current->exit_code = signr; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); + + /* We're back. Did the debugger cancel the sig? */ if (!(signr = current->exit_code)) continue; current->exit_code = 0; + + /* The debugger continued. Ignore SIGSTOP. */ if (signr == SIGSTOP) continue; - if (_S(signr) & current->blocked) { - spin_lock_irq(¤t->sigmask_lock); - current->signal |= _S(signr); - spin_unlock_irq(¤t->sigmask_lock); + + /* Update the siginfo structure. Is this good? */ + if (signr != info.si_signo) { + info.si_signo = signr; + info.si_errno = 0; + info.si_code = SI_USER; + info.si_pid = current->p_pptr->pid; + info.si_uid = current->p_pptr->uid; + } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(¤t->blocked, signr)) { + send_sig_info(signr, &info, current); continue; } - sa = current->sig->action + signr - 1; } - if (sa->sa_handler == SIG_IGN) { + + ka = ¤t->sig->action[signr-1]; + if (ka->sa.sa_handler == SIG_IGN) { if (signr != SIGCHLD) continue; - /* check for SIGCHLD: it's special */ - while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0) + /* Check for SIGCHLD: it's special. */ + while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) /* nothing */; continue; } - if (sa->sa_handler == SIG_DFL) { + + if (ka->sa.sa_handler == SIG_DFL) { + int exit_code = signr; + + /* Init gets no signals it doesn't want. */ if (current->pid == 1) continue; + switch (signr) { case SIGCONT: case SIGCHLD: case SIGWINCH: continue; @@ -379,13 +641,12 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) case SIGTSTP: case SIGTTIN: case SIGTTOU: if (is_orphaned_pgrp(current->pgrp)) continue; + /* FALLTHRU */ + case SIGSTOP: - if (current->flags & PF_PTRACED) - continue; current->state = TASK_STOPPED; current->exit_code = signr; - if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & - SA_NOCLDSTOP)) + if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); continue; @@ -393,25 +654,24 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: lock_kernel(); - if (current->binfmt && current->binfmt->core_dump) { - if (current->binfmt->core_dump(signr, regs)) - signr |= 0x80; - } + if (current->binfmt + && current->binfmt->core_dump + && current->binfmt->core_dump(signr, regs)) + exit_code |= 0x80; unlock_kernel(); - /* fall through */ - default: - spin_lock_irq(¤t->sigmask_lock); - current->signal |= _S(signr & 0x7f); - spin_unlock_irq(¤t->sigmask_lock); + /* FALLTHRU */ + default: + lock_kernel(); + sigaddset(¤t->signal, signr); current->flags |= PF_SIGNALED; - - lock_kernel(); /* 8-( */ - do_exit(signr); - unlock_kernel(); + do_exit(exit_code); + /* NOTREACHED */ } } - handle_signal(signr, sa, oldmask, regs); + + /* Whee! Actually deliver the signal. */ + handle_signal(signr, ka, &info, oldset, regs); return 1; } diff --git a/arch/i386/kernel/sys_i386.c b/arch/i386/kernel/sys_i386.c index f43dfe726..80ef4be47 100644 --- a/arch/i386/kernel/sys_i386.c +++ b/arch/i386/kernel/sys_i386.c @@ -180,7 +180,7 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, } case 1: /* iBCS2 emulator entry point */ ret = -EINVAL; - if (get_fs() != get_ds()) + if (!segment_eq(get_fs(), get_ds())) goto out; ret = sys_shmat (first, (char *) ptr, second, (ulong *) third); goto out; @@ -225,15 +225,16 @@ asmlinkage int sys_olduname(struct oldold_utsname * name) return -EFAULT; error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); - error -= __put_user(0,name->sysname+__OLD_UTS_LEN); - error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); - error -= __put_user(0,name->nodename+__OLD_UTS_LEN); - error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); - error -= __put_user(0,name->release+__OLD_UTS_LEN); - error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); - error -= __put_user(0,name->version+__OLD_UTS_LEN); - error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); - error = __put_user(0,name->machine+__OLD_UTS_LEN); + error |= __put_user(0,name->sysname+__OLD_UTS_LEN); + error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); + error |= __put_user(0,name->nodename+__OLD_UTS_LEN); + error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); + error |= __put_user(0,name->release+__OLD_UTS_LEN); + error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); + error |= __put_user(0,name->version+__OLD_UTS_LEN); + error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); + error |= __put_user(0,name->machine+__OLD_UTS_LEN); + error = error ? -EFAULT : 0; return error; diff --git a/arch/i386/kernel/trampoline.S b/arch/i386/kernel/trampoline.S index f44b9abde..9cee704f1 100644 --- a/arch/i386/kernel/trampoline.S +++ b/arch/i386/kernel/trampoline.S @@ -53,7 +53,7 @@ r_base = . lmsw %ax # into protected mode jmp flush_instr flush_instr: - ljmp $KERNEL_CS, $0x00100000 + ljmp $__KERNEL_CS, $0x00100000 # jump to startup_32 idt_48: diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index f08b7de6b..bd125a041 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -127,7 +127,7 @@ static void show_registers(struct pt_regs *regs) extern char _stext, _etext; esp = (unsigned long) ®s->esp; - ss = KERNEL_DS; + ss = __KERNEL_DS; if (regs->xcs & 3) { esp = regs->esp; ss = regs->xss & 0xffff; @@ -184,7 +184,7 @@ static void show_registers(struct pt_regs *regs) spinlock_t die_lock; -/*static*/ void die_if_kernel(const char * str, struct pt_regs * regs, long err) +void die_if_kernel(const char * str, struct pt_regs * regs, long err) { if ((regs->eflags & VM_MASK) || (3 & regs->xcs) == 3) return; diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c index a09fa6419..0628e2d68 100644 --- a/arch/i386/kernel/vm86.c +++ b/arch/i386/kernel/vm86.c @@ -438,8 +438,13 @@ int handle_vm86_trap(struct kernel_vm86_regs * regs, long error_code, int trapno } if (trapno !=1) return 1; /* we let this handle by the calling routine */ - if (current->flags & PF_PTRACED) - current->blocked &= ~(1 << (SIGTRAP-1)); + if (current->flags & PF_PTRACED) { + unsigned long flags; + spin_lock_irqsave(¤t->sigmask_lock, flags); + sigdelset(¤t->blocked, SIGTRAP); + recalc_sigpending(current); + spin_unlock_irqrestore(¤t->sigmask_lock, flags); + } send_sig(SIGTRAP, current, 1); current->tss.trap_no = trapno; current->tss.error_code = error_code; diff --git a/arch/i386/lib/delay.c b/arch/i386/lib/delay.c index c3c29a7d9..4afc206e5 100644 --- a/arch/i386/lib/delay.c +++ b/arch/i386/lib/delay.c @@ -9,7 +9,7 @@ */ #include <linux/sched.h> -#include <asm/delay.h> +#include <linux/delay.h> #ifdef __SMP__ #include <asm/smp.h> diff --git a/arch/i386/math-emu/errors.c b/arch/i386/math-emu/errors.c index f76020d1f..38a72e572 100644 --- a/arch/i386/math-emu/errors.c +++ b/arch/i386/math-emu/errors.c @@ -42,7 +42,7 @@ void Un_impl(void) RE_ENTRANT_CHECK_OFF; /* No need to verify_area(), we have previously fetched these bytes. */ printk("Unimplemented FPU Opcode at eip=%p : ", (void *) address); - if ( FPU_CS == USER_CS ) + if ( FPU_CS == __USER_CS ) { while ( 1 ) { @@ -93,7 +93,7 @@ void emu_printall(void) RE_ENTRANT_CHECK_OFF; /* No need to verify_area(), we have previously fetched these bytes. */ printk("At %p:", (void *) address); - if ( FPU_CS == USER_CS ) + if ( FPU_CS == __USER_CS ) { #define MAX_PRINTED_BYTES 20 for ( i = 0; i < MAX_PRINTED_BYTES; i++ ) diff --git a/arch/i386/math-emu/fpu_entry.c b/arch/i386/math-emu/fpu_entry.c index 07c32db9a..943daf3b9 100644 --- a/arch/i386/math-emu/fpu_entry.c +++ b/arch/i386/math-emu/fpu_entry.c @@ -179,11 +179,11 @@ asmlinkage void math_emulate(long arg) FPU_EIP += code_base = FPU_CS << 4; code_limit = code_base + 0xffff; /* Assumes code_base <= 0xffff0000 */ } - else if ( FPU_CS == USER_CS && FPU_DS == USER_DS ) + else if ( FPU_CS == __USER_CS && FPU_DS == __USER_DS ) { addr_modes.default_mode = 0; } - else if ( FPU_CS == KERNEL_CS ) + else if ( FPU_CS == __KERNEL_CS ) { printk("math_emulate: %04x:%08lx\n",FPU_CS,FPU_EIP); panic("Math emulation needed in kernel"); diff --git a/arch/m68k/config.in b/arch/m68k/config.in index 569da18ce..ab460947b 100644 --- a/arch/m68k/config.in +++ b/arch/m68k/config.in @@ -207,6 +207,17 @@ endmenu fi +# Conditionally compile in the Uniform CD-ROM driver +if [ "$CONFIG_BLK_DEV_IDECD" = "y" -o "$CONFIG_BLK_DEV_SR" = "y" ]; then + define_bool CONFIG_CDROM y +else + if [ "$CONFIG_BLK_DEV_IDECD" = "m" -o "$CONFIG_BLK_DEV_SR" = "m" ]; then + define_bool CONFIG_CDROM m + else + define_bool CONFIG_CDROM n + fi +fi + source fs/Config.in source fs/nls/Config.in diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 10b1581ea..5d38e46ca 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S @@ -569,6 +569,8 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_poll) .long SYMBOL_NAME(sys_nfsservctl) .long SYMBOL_NAME(sys_prctl) + .long SYMBOL_NAME(sys_pread) + .long SYMBOL_NAME(sys_pwrite) .rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4 .long SYMBOL_NAME(sys_ni_syscall) .endr diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 2624d2d0c..174de5799 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -13,7 +13,7 @@ # Copyright (C) 1994, 1995, 1996 by Ralf Baechle # DECStation modifications by Paul M. Antoine, 1996 # -# $Id: Makefile,v 1.9 1997/09/19 08:34:54 ralf Exp $ +# $Id: Makefile,v 1.9 1997/12/02 01:48:01 ralf Exp $ # # @@ -100,22 +100,6 @@ CORE_FILES += arch/mips/algor/algor.o SUBDIRS += arch/mips/algor #LOADADDR += 0x80000000 endif -ifdef CONFIG_DECSTATION -CORE_FILES += arch/mips/dec/dec.o -SUBDIRS += arch/mips/dec -LINKSCRIPT += arch/mips/dec/ld.script -LOADADDR += 0x80000000 -endif -ifdef CONFIG_DESKSTATION_RPC44 -CORE_FILES += arch/mips/deskstation/deskstation.o -SUBDIRS += arch/mips/deskstation -LOADADDR += 0x80100000 -endif -ifdef CONFIG_DESKSTATION_TYNE -CORE_FILES += arch/mips/deskstation/deskstation.o -SUBDIRS += arch/mips/deskstation -LOADADDR += 0x80000000 -endif # # Acer PICA 61, Mips Magnum 4000 and Olivetti M700. # @@ -124,9 +108,6 @@ CORE_FILES += arch/mips/jazz/jazz.o SUBDIRS += arch/mips/jazz LOADADDR += 0x80000000 endif -ifdef CONFIG_MIPS_MAGNUM_3000 -LOADADDR += 0x80000000 -endif ifdef CONFIG_SNI_RM200_PCI CORE_FILES += arch/mips/sni/sni.o SUBDIRS += arch/mips/sni diff --git a/arch/mips/config.in b/arch/mips/config.in index 44c78e270..1913421be 100644 --- a/arch/mips/config.in +++ b/arch/mips/config.in @@ -14,20 +14,10 @@ comment 'Machine selection' bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool 'Support for Algorithmics P4032' CONFIG_ALGOR_P4032 - bool 'Support for DECstation' CONFIG_DECSTATION - bool 'Support for Deskstation RPC44' CONFIG_DESKSTATION_RPC44 - bool 'Support for Deskstation Tyne' CONFIG_DESKSTATION_TYNE - bool 'Support for Mips Magnum 3000' CONFIG_MIPS_MAGNUM_3000 fi bool 'Support for Mips Magnum 4000' CONFIG_MIPS_MAGNUM_4000 bool 'Support for Olivetti M700-10' CONFIG_OLIVETTI_M700 -if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool 'Support for SGI workstations' CONFIG_SGI - if [ "$CONFIG_SGI" = "y" ]; then - bool 'Support for SGI graphic devices' CONFIG_SGI_GRAPHICS - define_bool CONFIG_UMISC y - fi -fi +bool 'Support for SGI workstations' CONFIG_SGI bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI # @@ -44,10 +34,6 @@ if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \ "$CONFIG_OLIVETTI_M700" = "y" ]; then define_bool CONFIG_VIDEO_G364 y fi -if [ "$CONFIG_DESKSTATION_RPC44" = "y" -o \ - "$CONFIG_DESKSTATION_TYNE" = "y" ]; then - define_bool CONFIG_MIPS_ARC y -fi if [ "$CONFIG_ACER_PICA_61" = "y" -o \ "$CONFIG_OLIVETTI_M700" = "y" -o \ "$CONFIG_MIPS_MAGNUM_4000" = "y" ]; then @@ -174,6 +160,8 @@ if [ "$CONFIG_NET" = "y" ]; then fi if [ "$CONFIG_SGI" != "y" ]; then + source drivers/net/hamradio/Config.in + mainmenu_option next_comment comment 'ISDN subsystem' @@ -193,32 +181,34 @@ if [ "$CONFIG_SGI" != "y" ]; then endmenu fi +# Conditionally compile in the Uniform CD-ROM driver +if [ "$CONFIG_BLK_DEV_IDECD" = "y" -o "$CONFIG_BLK_DEV_SR" = "y" -o "$CONFIG_SBPCD" = "y" -o "$CONFIG_MCD" = "y" -o "$CONFIG_CM206" = "y" -o "$CONFIG_CDU31A" = "y" ]; then + define_bool CONFIG_CDROM y +else + if [ "$CONFIG_BLK_DEV_IDECD" = "m" -o "$CONFIG_BLK_DEV_SR" = "m" -o "$CONFIG_SBPCD" = "m" -o "$CONFIG_MCD" = "m" -o "$CONFIG_CM206" = "m" -o "$CONFIG_CDU31A" = "m" ]; then + define_bool CONFIG_CDROM m + else + define_bool CONFIG_CDROM n + fi +fi + source fs/Config.in source fs/nls/Config.in -if [ "$CONFIG_SGI" != "y" ]; then - source drivers/char/Config.in +source drivers/char/Config.in - mainmenu_option next_comment - comment 'Sound' +mainmenu_option next_comment +comment 'Sound' - tristate 'Sound card support' CONFIG_SOUND - if [ "$CONFIG_SOUND" != "n" ]; then - source drivers/sound/Config.in - fi - endmenu -else - comment 'SGI Character Devices' - bool 'Virtual terminal' CONFIG_VT - if [ "$CONFIG_VT" = "y" ]; then - bool 'Console on virtual terminal' CONFIG_VT_CONSOLE - fi - tristate 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE - bool 'SGI Zilog85C30 serial support' CONFIG_SGI_SERIAL - if [ "$CONFIG_SGI_SERIAL" != "n" ]; then - define_bool CONFIG_SERIAL y - fi +tristate 'Sound card support' CONFIG_SOUND +if [ "$CONFIG_SOUND" != "n" ]; then + source drivers/sound/Config.in +fi +endmenu + +if [ "$CONFIG_SGI" = "y" ]; then + source drivers/sgi/char/Config.in fi mainmenu_option next_comment diff --git a/arch/mips/defconfig b/arch/mips/defconfig index 147145db6..3120b4b28 100644 --- a/arch/mips/defconfig +++ b/arch/mips/defconfig @@ -13,6 +13,7 @@ CONFIG_ACER_PICA_61=y # CONFIG_MIPS_MAGNUM_4000 is not set # CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI is not set CONFIG_SNI_RM200_PCI=y CONFIG_MIPS_JAZZ=y CONFIG_PCI=y @@ -64,7 +65,7 @@ CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_RZ1000 is not set -# CONFIG_BLK_DEV_TRITON is not set +# CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDE_CHIPSETS is not set # @@ -80,22 +81,27 @@ CONFIG_BLK_DEV_IDECD=y # # Networking options # +# CONFIG_PACKET is not set # CONFIG_NETLINK is not set # CONFIG_FIREWALL is not set # CONFIG_NET_ALIAS is not set +CONFIG_UNIX=y CONFIG_INET=y # CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set # CONFIG_IP_ACCT is not set +# CONFIG_IP_MASQUERADE is not set # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_ALIAS is not set # CONFIG_SYN_COOKIES is not set # # (it is safe to leave these untouched) # -# CONFIG_INET_PCTCP is not set # CONFIG_INET_RARP is not set -CONFIG_PATH_MTU_DISCOVERY=y CONFIG_IP_NOSR=y # CONFIG_SKB_LARGE is not set @@ -104,7 +110,6 @@ CONFIG_IP_NOSR=y # # CONFIG_IPX is not set # CONFIG_ATALK is not set -# CONFIG_AX25 is not set # # SCSI support @@ -138,14 +143,20 @@ CONFIG_PCNET32=y # CONFIG_FDDI is not set # CONFIG_DLCI is not set # CONFIG_PPP is not set -# CONFIG_NET_RADIO is not set # CONFIG_SLIP is not set +# CONFIG_STRIP is not set +# CONFIG_WAVELAN is not set # CONFIG_TR is not set # CONFIG_WAN_DRIVERS is not set # CONFIG_LAPBETHER is not set # CONFIG_X25_ASY is not set # +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# # ISDN subsystem # # CONFIG_ISDN is not set @@ -154,6 +165,7 @@ CONFIG_PCNET32=y # CD-ROM drivers (not for SCSI or IDE/ATAPI drives) # # CONFIG_CD_NO_IDESCSI is not set +CONFIG_CDROM=y # # Filesystems @@ -169,12 +181,10 @@ CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_PROC_FS=y CONFIG_NFS_FS=y -CONFIG_ROOT_NFS=y -CONFIG_RNFS_BOOTP=y -# CONFIG_RNFS_RARP is not set CONFIG_NFSD=y CONFIG_SUNRPC=y CONFIG_LOCKD=y +# CONFIG_CODA_FS is not set # CONFIG_SMB_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_SYSV_FS is not set @@ -221,6 +231,7 @@ CONFIG_NLS_ISO8859_1=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_SERIAL=y +# CONFIG_SERIAL_CONSOLE is not set # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_MOUSE is not set @@ -228,6 +239,9 @@ CONFIG_SERIAL=y # CONFIG_APM is not set # CONFIG_WATCHDOG is not set # CONFIG_RTC is not set +# CONFIG_VIDEO_DEV is not set +# CONFIG_VIDEO_BT848 is not set +# CONFIG_VIDEO_PMS is not set # CONFIG_NVRAM is not set # CONFIG_JOYSTICK is not set # CONFIG_MISC_RADIO is not set diff --git a/arch/mips/jazz/g364.c b/arch/mips/jazz/g364.c index dc0c7fac0..92522dcd1 100644 --- a/arch/mips/jazz/g364.c +++ b/arch/mips/jazz/g364.c @@ -432,3 +432,11 @@ void set_vesa_blanking(const unsigned long arg) { } + +/* + * FIXME: how can we probe for the video board? + */ +__initfunc(int con_is_present()) +{ + return; +} diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index 2e286da80..e0e98d9b5 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S @@ -7,7 +7,7 @@ * * Copyright (C) 1994, 1995 by Ralf Baechle * - * $Id: entry.S,v 1.4 1997/09/20 19:20:13 root Exp $ + * $Id: entry.S,v 1.4 1997/12/01 17:57:25 ralf Exp $ */ /* @@ -57,24 +57,17 @@ EXPORT(ret_from_irq) bnez t0,handle_bottom_half 9: lw t0,PT_STATUS(sp) # returning to kernel mode? - andi t1,t0, 0x10 - beqz t1,return # -> yes - lw t1,need_resched - bnez t1,reschedule + andi t1, t0, 0x10 + beqz t1, return # -> yes + lw t1, need_resched + bnez t1, reschedule GET_CURRENT(s0) - lw t0,task - lw a0,TASK_BLOCKED(s0) - - beq s0,t0,return # task[0] cannot have signals - lw t0,TASK_SIGNAL(s0) - - nor t1,zero,a0 - and t1,t0,t1 - beqz t1,return + lw v0, TASK_SIGPENDING(s0) + move a0, zero + beqz v0, return nop - jal do_signal - move a1,sp + move a1, sp EXPORT(return) .set noat RESTORE_ALL diff --git a/arch/mips/kernel/ipc.c b/arch/mips/kernel/ipc.c index 2e91b6755..2e764a607 100644 --- a/arch/mips/kernel/ipc.c +++ b/arch/mips/kernel/ipc.c @@ -101,7 +101,7 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, } case 1: /* iBCS2 emulator entry point */ ret = -EINVAL; - if (get_fs() != get_ds()) + if (!segment_eq(get_fs(), get_ds())) goto out; ret = sys_shmat (first, (char *) ptr, second, (ulong *) third); goto out; diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c index a64ebd1f6..b29bc0563 100644 --- a/arch/mips/kernel/irixelf.c +++ b/arch/mips/kernel/irixelf.c @@ -447,7 +447,8 @@ static inline int look_for_irix_interpreter(char **name, struct elf_phdr *epp, struct linux_binprm *bprm, int pnum) { - int i, old_fs; + mm_segment_t old_fs; + int i; int retval = -EINVAL; struct dentry *dentry = NULL; @@ -551,7 +552,7 @@ static inline void map_executable(struct file *fp, struct elf_phdr *epp, int pnu static inline int map_interpreter(struct elf_phdr *epp, struct elfhdr *ihp, struct dentry *identry, unsigned int *iladdr, - int pnum, int old_fs, + int pnum, mm_segment_t old_fs, unsigned int *eentry) { int i; @@ -616,8 +617,9 @@ static inline int do_load_irix_binary(struct linux_binprm * bprm, unsigned int load_addr, elf_bss, elf_brk; unsigned int elf_entry, interp_load_addr = 0; unsigned int start_code, end_code, end_data, elf_stack; - int old_fs, elf_exec_fileno, retval, has_interp, has_ephdr, i; + int elf_exec_fileno, retval, has_interp, has_ephdr, i; char *elf_interpreter; + mm_segment_t old_fs; load_addr = 0; has_interp = has_ephdr = 0; @@ -1124,7 +1126,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs) struct file file; struct dentry *dentry; struct inode *inode; - unsigned short fs; + mm_segment_t fs; char corefile[6+sizeof(current->comm)]; int segs; int i; diff --git a/arch/mips/kernel/irixioctl.c b/arch/mips/kernel/irixioctl.c index 1483da812..4dea62d59 100644 --- a/arch/mips/kernel/irixioctl.c +++ b/arch/mips/kernel/irixioctl.c @@ -1,4 +1,4 @@ -/* $Id: irixioctl.c,v 1.1.1.1 1997/06/01 03:16:43 ralf Exp $ +/* $Id: irixioctl.c,v 1.3 1997/12/15 10:37:27 ralf Exp $ * irixioctl.c: A fucking mess... * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -55,8 +55,8 @@ static struct tty_struct *get_real_tty(struct tty_struct *tp) asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg) { struct tty_struct *tp, *rtp; + mm_segment_t old_fs; int error = 0; - int old_fs; lock_kernel(); #ifdef DEBUG_IOCTLS diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index 76c5abf71..b2f9d592b 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -1,4 +1,4 @@ -/* $Id: irixsig.c,v 1.5 1997/12/01 17:57:27 ralf Exp $ +/* $Id: irixsig.c,v 1.8 1997/12/15 17:38:34 ralf Exp $ * irixsig.c: WHEEE, IRIX signals! YOW, am I compatable or what?!?! * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -15,12 +15,19 @@ #include <asm/ptrace.h> #include <asm/uaccess.h> +asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, + int options, unsigned long *ru); + #undef DEBUG_SIG #define _S(nr) (1<<((nr)-1)) #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) +typedef struct { + unsigned long sig[4]; +} irix_sigset_t; + struct sigctx_irix5 { u32 rmask, cp0_status; u64 pc; @@ -29,7 +36,7 @@ struct sigctx_irix5 { u32 usedfp, fpcsr, fpeir, sstk_flags; u64 hi, lo; u64 cp0_cause, cp0_badvaddr, _unused0; - u32 sigset[4]; + irix_sigset_t sigset; u64 weird_fpu_thing; u64 _unused1[31]; }; @@ -63,14 +70,15 @@ static inline void dump_irix5_sigctx(struct sigctx_irix5 *c) (unsigned long) c->hi, (unsigned long) c->lo, (unsigned long) c->cp0_cause, (unsigned long) c->cp0_badvaddr); printk("misc: sigset<0>[%08lx] sigset<1>[%08lx] sigset<2>[%08lx] " - "sigset<3>[%08lx]\n", (unsigned long) c->sigset[0], - (unsigned long) c->sigset[1], (unsigned long) c->sigset[2], - (unsigned long) c->sigset[3]); + "sigset<3>[%08lx]\n", (unsigned long) c->sigset.sig[0], + (unsigned long) c->sigset.sig[1], + (unsigned long) c->sigset.sig[2], + (unsigned long) c->sigset.sig[3]); } #endif -static void setup_irix_frame(struct sigaction * sa, struct pt_regs *regs, - int signr, unsigned long oldmask) +static void setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs, + int signr, sigset_t *oldmask) { unsigned long sp; struct sigctx_irix5 *ctx; @@ -98,10 +106,7 @@ static void setup_irix_frame(struct sigaction * sa, struct pt_regs *regs, __put_user(0, &ctx->sstk_flags); /* XXX sigstack unimp... todo... */ - __put_user(0, &ctx->sigset[1]); - __put_user(0, &ctx->sigset[2]); - __put_user(0, &ctx->sigset[3]); - __put_user(oldmask, &ctx->sigset[0]); + __copy_to_user(&ctx->sigset, oldmask, sizeof(irix_sigset_t)); #ifdef DEBUG_SIG dump_irix5_sigctx(ctx); @@ -110,7 +115,7 @@ static void setup_irix_frame(struct sigaction * sa, struct pt_regs *regs, regs->regs[5] = 0; /* XXX sigcode XXX */ regs->regs[4] = (unsigned long) signr; regs->regs[6] = regs->regs[29] = sp; - regs->regs[7] = (unsigned long) sa->sa_handler; + regs->regs[7] = (unsigned long) ka->sa.sa_handler; regs->regs[25] = regs->cp0_epc = current->tss.irix_trampoline; return; @@ -120,52 +125,126 @@ segv_and_exit: unlock_kernel(); } -asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, - int options, unsigned long *ru); +static void inline +setup_irix_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, + int signr, sigset_t *oldmask, siginfo_t *info) +{ + lock_kernel(); + printk("Aiee: setup_tr_frame wants to be written"); + do_exit(SIGSEGV); + unlock_kernel(); +} + +static inline void handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) +{ + if (ka->sa.sa_flags & SA_SIGINFO) + setup_irix_rt_frame(ka, regs, sig, oldset, info); + else + setup_irix_frame(ka, regs, sig, oldset); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + if (!(ka->sa.sa_flags & SA_NODEFER)) { + spin_lock_irq(¤t->sigmask_lock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked,sig); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + } +} + +static inline void syscall_restart(unsigned long r0, unsigned long or2, + unsigned long or7, struct pt_regs *regs, + struct sigaction *sa) +{ + switch(r0) { + case ERESTARTNOHAND: + no_system_call_restart: + regs->regs[0] = regs->regs[2] = EINTR; + break; + case ERESTARTSYS: + if(!(sa->sa_flags & SA_RESTART)) + goto no_system_call_restart; + /* fallthrough */ + case ERESTARTNOINTR: + regs->regs[0] = regs->regs[2] = or2; + regs->regs[7] = or7; + regs->cp0_epc -= 8; + } +} -asmlinkage int do_irix_signal(unsigned long oldmask, struct pt_regs * regs) +asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs) { - unsigned long mask = ~current->blocked; - unsigned long handler_signal = 0; + unsigned long r0 = regs->regs[0]; + unsigned long r7 = regs->orig_reg7; + struct k_sigaction *ka; unsigned long signr; - struct sigaction * sa; + sigset_t _oldset; + siginfo_t info; + + if (!oldset) + oldset = ¤t->blocked; + + for (;;) { + unsigned long signr; + + spin_lock_irq(¤t->sigmask_lock); + signr = dequeue_signal(¤t->blocked, &info); + spin_unlock_irq(¤t->sigmask_lock); + + if (!signr) + break; -#ifdef DEBUG_SIG - printk("[%s:%d] Delivering IRIX signal oldmask=%08lx\n", - current->comm, current->pid, oldmask); -#endif - while ((signr = current->signal & mask)) { - signr = ffz(~signr); - clear_bit(signr, ¤t->signal); - sa = current->sig->action + signr; - signr++; if ((current->flags & PF_PTRACED) && signr != SIGKILL) { + /* Let the debugger run. */ current->exit_code = signr; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); + + /* We're back. Did the debugger cancel the sig? */ if (!(signr = current->exit_code)) continue; current->exit_code = 0; + + /* The debugger continued. Ignore SIGSTOP. */ if (signr == SIGSTOP) continue; - if (_S(signr) & current->blocked) { - current->signal |= _S(signr); + + /* Update the siginfo structure. Is this good? */ + if (signr != info.si_signo) { + info.si_signo = signr; + info.si_errno = 0; + info.si_code = SI_USER; + info.si_pid = current->p_pptr->pid; + info.si_uid = current->p_pptr->uid; + } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(¤t->blocked, signr)) { + send_sig_info(signr, &info, current); continue; } - sa = current->sig->action + signr - 1; } - if (sa->sa_handler == SIG_IGN) { + + ka = ¤t->sig->action[signr-1]; + if (ka->sa.sa_handler == SIG_IGN) { if (signr != SIGCHLD) continue; - /* check for SIGCHLD: it's special */ - while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0) + /* Check for SIGCHLD: it's special. */ + while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) /* nothing */; continue; } - if (sa->sa_handler == SIG_DFL) { + + if (ka->sa.sa_handler == SIG_DFL) { + int exit_code = signr; + + /* Init gets no signals it doesn't want. */ if (current->pid == 1) continue; + switch (signr) { case SIGCONT: case SIGCHLD: case SIGWINCH: continue; @@ -173,78 +252,56 @@ asmlinkage int do_irix_signal(unsigned long oldmask, struct pt_regs * regs) case SIGTSTP: case SIGTTIN: case SIGTTOU: if (is_orphaned_pgrp(current->pgrp)) continue; + /* FALLTHRU */ + case SIGSTOP: - if (current->flags & PF_PTRACED) - continue; current->state = TASK_STOPPED; current->exit_code = signr; - if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & - SA_NOCLDSTOP)) + if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); continue; case SIGQUIT: case SIGILL: case SIGTRAP: - case SIGIOT: case SIGFPE: case SIGSEGV: case SIGBUS: + case SIGABRT: case SIGFPE: case SIGSEGV: lock_kernel(); - if (current->binfmt && current->binfmt->core_dump) { - if (current->binfmt->core_dump(signr, regs)) - signr |= 0x80; - } + if (current->binfmt + && current->binfmt->core_dump + && current->binfmt->core_dump(signr, regs)) + exit_code |= 0x80; unlock_kernel(); - /* fall through */ + /* FALLTHRU */ + default: - current->signal |= _S(signr & 0x7f); + lock_kernel(); + sigaddset(¤t->signal, signr); current->flags |= PF_SIGNALED; - lock_kernel(); /* 8-( */ - do_exit(signr); - unlock_kernel(); - } - } - /* - * OK, we're invoking a handler - */ - if (regs->orig_reg2 >= 0) { - if (regs->regs[2] == ERESTARTNOHAND) { - regs->regs[2] = EINTR; - } else if((regs->regs[2] == ERESTARTSYS && - !(sa->sa_flags & SA_RESTART))) { - regs->regs[2] = regs->orig_reg2; - regs->cp0_epc -= 8; + do_exit(exit_code); + /* NOTREACHED */ } } - handler_signal |= 1 << (signr-1); - mask &= ~sa->sa_mask; + + if (r0) + syscall_restart(r0, regs->orig_reg2, r7, regs, &ka->sa); + /* Whee! Actually deliver the signal. */ + handle_signal(signr, ka, &info, oldset, regs); + return 1; } + /* * Who's code doesn't conform to the restartable syscall convention * dies here!!! The li instruction, a single machine instruction, * must directly be followed by the syscall instruction. */ - if (regs->orig_reg2 >= 0 && + if (r0 && (regs->regs[2] == ERESTARTNOHAND || regs->regs[2] == ERESTARTSYS || regs->regs[2] == ERESTARTNOINTR)) { - regs->regs[2] = regs->orig_reg2; + regs->regs[0] = regs->regs[2] = regs->orig_reg2; + regs->regs[7] = r7; regs->cp0_epc -= 8; } - if (!handler_signal) /* no handler will be called - return 0 */ - return 0; - signr = 1; - sa = current->sig->action; - for (mask = 1 ; mask ; sa++,signr++,mask += mask) { - if (mask > handler_signal) - break; - if (!(mask & handler_signal)) - continue; - setup_irix_frame(sa, regs, signr, oldmask); - if (sa->sa_flags & SA_ONESHOT) - sa->sa_handler = NULL; - current->blocked |= sa->sa_mask; - oldmask |= sa->sa_mask; - } - - return 1; + return 0; } asmlinkage unsigned long irix_sigreturn(struct pt_regs *regs) @@ -253,6 +310,7 @@ asmlinkage unsigned long irix_sigreturn(struct pt_regs *regs) unsigned long umask, mask; u64 *fregs, res; int sig, i, base = 0; + sigset_t blocked; if(regs->regs[2] == 1000) base = 1; @@ -291,10 +349,18 @@ asmlinkage unsigned long irix_sigreturn(struct pt_regs *regs) /* XXX do sigstack crapola here... XXX */ + if (__copy_from_user(&blocked, &context->sigset, sizeof(blocked))) + goto badframe; + + sigdelsetmask(&blocked, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = blocked; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + regs->orig_reg2 = -1; - __get_user(current->blocked, &context->sigset[0]); - current->blocked &= _BLOCKABLE; __get_user(res, &context->regs[2]); + return res; badframe: @@ -321,27 +387,12 @@ static inline void dump_sigact_irix5(struct sigact_irix5 *p) } #endif -static inline void check_pending(int signum) +asmlinkage int +irix_sigaction(int sig, const struct sigaction *act, + struct sigaction *oact, unsigned long trampoline) { - struct sigaction *p; - - p = signum - 1 + current->sig->action; - spin_lock(¤t->sigmask_lock); - if (p->sa_handler == SIG_IGN) { - current->signal &= ~_S(signum); - } else if (p->sa_handler == SIG_DFL) { - if (signum != SIGCONT && signum != SIGCHLD && signum != SIGWINCH) - return; - current->signal &= ~_S(signum); - } - spin_unlock(¤t->sigmask_lock); -} - -asmlinkage int irix_sigaction(int sig, struct sigact_irix5 *new, - struct sigact_irix5 *old, unsigned long trampoline) -{ - struct sigaction new_sa, *p; - int res; + struct k_sigaction new_ka, old_ka; + int ret; #ifdef DEBUG_SIG printk(" (%d,%s,%s,%08lx) ", sig, (!new ? "0" : "NEW"), @@ -350,110 +401,103 @@ asmlinkage int irix_sigaction(int sig, struct sigact_irix5 *new, dump_sigact_irix5(new); printk(" "); } #endif - if(sig < 1 || sig > 32) { - return -EINVAL; - } - p = sig - 1 + current->sig->action; + if (act) { + sigset_t mask; + if (verify_area(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags)) + return -EFAULT; - if(new) { - res = verify_area(VERIFY_READ, new, sizeof(*new)); - if(res) - return res; - if(sig == SIGKILL || sig == SIGSTOP) { - return -EINVAL; - } - __get_user(new_sa.sa_flags, &new->flags); - __get_user(new_sa.sa_handler, &(__sighandler_t) new->handler); - __get_user(new_sa.sa_mask, &new->sigset[0]); - - if(new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) { - res = verify_area(VERIFY_READ, new_sa.sa_handler, 1); - if(res) - return res; - } + __copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t)); + new_ka.ka_restorer = NULL; } - /* Hmmm... methinks IRIX libc always passes a valid trampoline + + /* + * Hmmm... methinks IRIX libc always passes a valid trampoline * value for all invocations of sigaction. Will have to * investigate. POSIX POSIX, die die die... */ current->tss.irix_trampoline = trampoline; - if(old) { - int res = verify_area(VERIFY_WRITE, old, sizeof(*old)); - if(res) - return res; - __put_user(p->sa_flags, &old->flags); - __put_user(p->sa_handler, &old->handler); - __put_user(p->sa_mask, &old->sigset[0]); - __put_user(0, &old->sigset[1]); - __put_user(0, &old->sigset[2]); - __put_user(0, &old->sigset[3]); - __put_user(0, &old->_unused0[0]); - __put_user(0, &old->_unused0[1]); - } - if(new) { - spin_lock_irq(¤t->sig->siglock); - *p = new_sa; - check_pending(sig); - spin_unlock_irq(¤t->sig->siglock); + +/* XXX Implement SIG_SETMASK32 for IRIX compatibility */ + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_flags, &oact->sa_flags)) + return -EFAULT; + __copy_to_user(&old_ka.sa.sa_mask, &oact->sa_mask, + sizeof(sigset_t)); } - return 0; + return ret; } -asmlinkage int irix_sigpending(unsigned long *set) +asmlinkage int irix_sigpending(irix_sigset_t *set) { - int res; - lock_kernel(); - res = verify_area(VERIFY_WRITE, set, (sizeof(unsigned long) * 4)); - if(!res) { - /* fill in "set" with signals pending but blocked. */ - spin_lock_irq(¤t->sigmask_lock); - __put_user(0, &set[1]); - __put_user(0, &set[2]); - __put_user(0, &set[3]); - __put_user((current->blocked & current->signal), &set[0]); - spin_unlock_irq(¤t->sigmask_lock); - } - return res; + if (verify_area(VERIFY_WRITE, set, sizeof(*set)) < 0) + return -EFAULT; + + /* fill in "set" with signals pending but blocked. */ + spin_lock_irq(¤t->sigmask_lock); + __put_user(current->blocked.sig[0] & current->signal.sig[0], + &set->sig[0]); + __put_user(current->blocked.sig[1] & current->signal.sig[1], + &set->sig[1]); + __put_user(current->blocked.sig[2] & current->signal.sig[2], + &set->sig[2]); + __put_user(current->blocked.sig[3] & current->signal.sig[3], + &set->sig[3]); + spin_unlock_irq(¤t->sigmask_lock); + + return 0; } -asmlinkage int irix_sigprocmask(int how, unsigned long *new, unsigned long *old) +asmlinkage int irix_sigprocmask(int how, irix_sigset_t *new, irix_sigset_t *old) { - unsigned long bits, oldbits = current->blocked; + sigset_t oldbits, newbits; int error; + if(new) { - error = verify_area(VERIFY_READ, new, (sizeof(unsigned long) * 4)); + error = verify_area(VERIFY_READ, new, sizeof(*new)); if(error) return error; - bits = new[0] & _BLOCKABLE; + __copy_from_user(&newbits, new, sizeof(unsigned long)*4); + sigdelsetmask(&newbits, ~_BLOCKABLE); + + spin_lock_irq(¤t->sigmask_lock); + oldbits = current->blocked; + switch(how) { case 1: - current->blocked |= bits; + sigorsets(&newbits, &oldbits, &newbits); break; case 2: - current->blocked &= ~bits; + sigandsets(&newbits, &oldbits, &newbits); break; case 3: + break; + case 256: - current->blocked = bits; + siginitset(&newbits, newbits.sig[0]); break; default: return -EINVAL; } + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); } if(old) { - error = verify_area(VERIFY_WRITE, old, (sizeof(unsigned long) * 4)); + error = verify_area(VERIFY_WRITE, old, sizeof(*old)); if(error) return error; - __put_user(0, &old[1]); - __put_user(0, &old[2]); - __put_user(0, &old[3]); - __put_user(oldbits, &old[0]); + __copy_to_user(old, ¤t->blocked, sizeof(unsigned long)*4); } return 0; @@ -461,26 +505,25 @@ asmlinkage int irix_sigprocmask(int how, unsigned long *new, unsigned long *old) asmlinkage int irix_sigsuspend(struct pt_regs *regs) { - unsigned int mask; - unsigned long *uset; - int base = 0, error; + sigset_t *uset, saveset, newset; - if(regs->regs[2] == 1000) - base = 1; - - uset = (unsigned long *) regs->regs[base + 4]; - if(verify_area(VERIFY_READ, uset, (sizeof(unsigned long) * 4))) + uset = (sigset_t *) regs->regs[4]; + if (copy_from_user(&newset, uset, sizeof(sigset_t))) return -EFAULT; - mask = current->blocked; + sigdelsetmask(&newset, ~_BLOCKABLE); - current->blocked = uset[0] & _BLOCKABLE; - while(1) { + spin_lock_irq(¤t->sigmask_lock); + saveset = current->blocked; + current->blocked = newset; + spin_unlock_irq(¤t->sigmask_lock); + + regs->regs[2] = -EINTR; + while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if(do_irix_signal(mask, regs)) + if (do_irix_signal(&saveset, regs)) return -EINTR; } - return error; } /* hate hate hate... */ @@ -524,8 +567,9 @@ static inline unsigned long timespectojiffies(struct timespec *value) asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info, struct timespec *tp) { - unsigned long mask, kset, expire = 0; - int sig, error, timeo = 0; + unsigned long expire = 0; + sigset_t kset; + int i, sig, error, timeo = 0; lock_kernel(); #ifdef DEBUG_SIG @@ -537,11 +581,15 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info, if(!set) return -EINVAL; - error = get_user(kset, &set[0]); - if(error) + error = verify_area(VERIFY_READ, set, sizeof(kset)); + if (error) + goto out; + + __copy_from_user(&kset, set, sizeof(set)); + if (error) goto out; - if(info && clear_user(info, sizeof(*info))) { + if (info && clear_user(info, sizeof(*info))) { error = -EFAULT; goto out; } @@ -559,21 +607,32 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info, } while(1) { + long tmp = 0; + current->state = TASK_INTERRUPTIBLE; schedule(); - if(current->signal & kset) break; - if(tp && expire <= jiffies) { + + for (i=0; i<=4; i++) + tmp |= (current->signal.sig[i] & kset.sig[i]); + + if (tmp) + break; + if (tp && expire <= jiffies) { timeo = 1; break; } - if(signal_pending(current)) return -EINTR; + if (signal_pending(current)) + return -EINTR; } + if (timeo) + return -EAGAIN; - if(timeo) return -EAGAIN; - for(sig = 1, mask = 2; mask; mask <<= 1, sig++) { - if(!(mask & kset)) continue; - if(mask & current->signal) { + for(sig = 1; i <= 65 /* IRIX_NSIG */; sig++) { + if (sigismember (&kset, sig)) + continue; + if (sigismember (¤t->signal, sig)) { /* XXX need more than this... */ - if(info) info->sig = sig; + if (info) + info->sig = sig; error = 0; goto out; } @@ -724,6 +783,7 @@ asmlinkage int irix_getcontext(struct pt_regs *regs) { int error, i, base = 0; struct irix5_context *ctx; + unsigned long flags; lock_kernel(); if(regs->regs[2] == 1000) @@ -738,28 +798,32 @@ asmlinkage int irix_getcontext(struct pt_regs *regs) error = verify_area(VERIFY_WRITE, ctx, sizeof(*ctx)); if(error) goto out; - ctx->flags = 0x0f; - ctx->link = current->tss.irix_oldctx; - ctx->sigmask[1] = ctx->sigmask[2] = ctx->sigmask[4] = 0; - ctx->sigmask[0] = current->blocked; + __put_user(current->tss.irix_oldctx, &ctx->link); + + __copy_to_user(&ctx->sigmask, ¤t->blocked, sizeof(irix_sigset_t)); /* XXX Do sigstack stuff someday... */ - ctx->stack.sp = ctx->stack.size = ctx->stack.flags = 0; + __put_user(0, &ctx->stack.sp); + __put_user(0, &ctx->stack.size); + __put_user(0, &ctx->stack.flags); - ctx->weird_graphics_thing = 0; - ctx->regs[0] = 0; + __put_user(0, &ctx->weird_graphics_thing); + __put_user(0, &ctx->regs[0]); for(i = 1; i < 32; i++) - ctx->regs[i] = regs->regs[i]; - ctx->regs[32] = regs->lo; - ctx->regs[33] = regs->hi; - ctx->regs[34] = regs->cp0_cause; - ctx->regs[35] = regs->cp0_epc; + __put_user(regs->regs[i], &ctx->regs[i]); + __put_user(regs->lo, &ctx->regs[32]); + __put_user(regs->hi, &ctx->regs[33]); + __put_user(regs->cp0_cause, &ctx->regs[34]); + __put_user(regs->cp0_epc, &ctx->regs[35]); + + flags = 0x0f; if(!current->used_math) { - ctx->flags &= ~(0x08); + flags &= ~(0x08); } else { /* XXX wheee... */ printk("Wheee, no code for saving IRIX FPU context yet.\n"); } + __put_user(flags, &ctx->flags); error = 0; out: diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 6d28d6e98..941abec8f 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -36,7 +36,7 @@ #include <asm/sgialib.h> #endif -int active_ds = USER_DS; +mm_segment_t active_ds = USER_DS; asmlinkage void ret_from_sys_call(void); diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index b5a5a4428..ebd657d4c 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -435,7 +435,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ - if ((unsigned long) data > NSIG) { + if ((unsigned long) data > _NSIG) { res = -EIO; goto out; } @@ -464,7 +464,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) } case PTRACE_DETACH: { /* detach a process that was attached. */ - if ((unsigned long) data > NSIG) { + if ((unsigned long) data > _NSIG) { res = -EIO; goto out; } @@ -502,9 +502,7 @@ asmlinkage void syscall_trace(void) * stopping signal is not SIGTRAP. -brl */ if (current->exit_code) { - spin_lock_irq(¤t->sigmask_lock); - current->signal |= (1 << (current->exit_code - 1)); - spin_unlock_irq(¤t->sigmask_lock); + send_sig(current->exit_code, current, 1); + current->exit_code = 0; } - current->exit_code = 0; } diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 474437ef5..98f99f9f5 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -5,7 +5,7 @@ * Copyright (C) 1995, 1996 Ralf Baechle * Copyright (C) 1996 Stoned Elipot * - * $Id: setup.c,v 1.4 1997/12/01 17:57:31 ralf Exp $ + * $Id: setup.c,v 1.5 1997/12/02 23:44:02 ralf Exp $ */ #include <linux/config.h> #include <linux/errno.h> @@ -175,20 +175,6 @@ __initfunc(void setup_arch(char **cmdline_p, switch(mips_machgroup) { -#ifdef CONFIG_MIPS_DECSTATION - case MACH_GROUP_DEC: - decstation_setup(); - break; -#endif -#if defined(CONFIG_MIPS_ARC) - /* - * Perhaps arch/mips/deskstation should be renamed to arch/mips/arc. - * For now CONFIG_MIPS_ARC means DeskStation. -Stoned. - */ - case MACH_GROUP_ARC: - deskstation_setup(); - break; -#endif #ifdef CONFIG_MIPS_JAZZ case MACH_GROUP_JAZZ: jazz_setup(); diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 481a34147..2095d63fb 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c @@ -4,7 +4,7 @@ * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1994, 1995, 1996 Ralf Baechle * - * $Id: signal.c,v 1.8 1997/12/01 16:26:34 ralf Exp $ + * $Id: signal.c,v 1.7 1997/12/01 17:57:31 ralf Exp $ */ #include <linux/config.h> #include <linux/sched.h> @@ -23,58 +23,94 @@ #include <asm/pgtable.h> #include <asm/uaccess.h> -#define _S(nr) (1<<((nr)-1)) +#define DEBUG_SIG 0 -#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, int options, unsigned long *ru); -asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs); +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); extern asmlinkage void (*save_fp_context)(struct sigcontext *sc); extern asmlinkage void (*restore_fp_context)(struct sigcontext *sc); /* * Atomically swap in the new signal mask, and wait for a signal. - * Unlike on Intel we pass a sigset_t *, not sigset_t. */ -asmlinkage int sys_sigsuspend(struct pt_regs *regs) +asmlinkage inline int +sys_sigsuspend(struct pt_regs *regs) { - unsigned long mask; - sigset_t *uset, set; + sigset_t *uset, saveset, newset; uset = (sigset_t *) regs->regs[4]; - if (get_user(set, uset)) + if (copy_from_user(&newset, uset, sizeof(sigset_t))) return -EFAULT; + sigdelsetmask(&newset, ~_BLOCKABLE); spin_lock_irq(¤t->sigmask_lock); - mask = current->blocked; - current->blocked = set & _BLOCKABLE; + saveset = current->blocked; + current->blocked = newset; spin_unlock_irq(¤t->sigmask_lock); regs->regs[2] = -EINTR; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(mask, regs)) + if (do_signal(&saveset, regs)) return -EINTR; } - return -EINTR; } -asmlinkage int sys_sigreturn(struct pt_regs *regs) +asmlinkage int +sys_rt_sigsuspend(struct pt_regs *regs) +{ + if (regs->regs[5] != sizeof(sigset_t)) + return -EINVAL; + return sys_sigsuspend(regs); +} + +asmlinkage int +sys_sigaction(int sig, const struct sigaction *act, + struct sigaction *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + sigset_t mask; + if (verify_area(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags)) + return -EFAULT; + + __copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t)); + new_ka.ka_restorer = NULL; + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_flags, &oact->sa_flags)) + return -EFAULT; + __copy_to_user(&old_ka.sa.sa_mask, &oact->sa_mask, + sizeof(sigset_t)); + } + + return ret; +} + +/* + * To do: this entire function should be accessed over a function pointer + * such that we can handle stack frames for different ABIs. + */ + +asmlinkage void +restore_sigcontext(struct pt_regs *regs, struct sigcontext *context) { - struct sigcontext *context; - unsigned long blocked; long long reg; int i; - context = (struct sigcontext *)(long) regs->regs[29]; - if (!access_ok(VERIFY_READ, context, sizeof(struct sigcontext)) || - (regs->regs[29] & (SZREG - 1))) - goto badframe; - - __get_user(blocked, &context->sc_sigset); - current->blocked = blocked & _BLOCKABLE; __get_user(regs->cp0_epc, &context->sc_pc); /* @@ -89,11 +125,66 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs) __get_user(reg, &context->sc_mdlo); regs->lo = (int) reg; +#define restore_gp_reg(i) __get_user(reg, &context->sc_regs[i]); \ + regs->regs[i] = (int) reg; + restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3); + restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6); + restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9); + restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12); + restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15); + restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18); + restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21); + restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24); + restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27); + restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30); + restore_gp_reg(31); +#undef restore_gp_reg + /* * FP depends on what FPU in what mode we have. Best done in * Assembler ... */ restore_fp_context(context); +} + +/* + * The structure sc describes the stackframe on the userstack. The frames + * are identical for normal and realtime signal stackframes with the + * exception of the additional struct ucontext for rt frames. + */ +struct sigframe { + unsigned long ass[4]; /* argument save space for o32 */ + unsigned int code[4]; /* signal trampoline */ + struct sigcontext scc; +}; + +struct rt_sigframe { + unsigned long ass[4]; + unsigned int code[4]; + struct sigcontext scc; + // struct ucontext uc; +}; + +asmlinkage int sys_sigreturn(struct pt_regs *regs) +{ + struct sigcontext *context; + sigset_t blocked; + + context = (struct sigcontext *)(long) regs->regs[29]; + if (!access_ok(VERIFY_READ, context, sizeof(struct sigcontext)) || + (regs->regs[29] & (SZREG - 1))) + goto badframe; + + if (__copy_from_user(&blocked, &context->sc_sigset, sizeof(blocked))) + goto badframe; + + sigdelsetmask(&blocked, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = blocked; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + restore_sigcontext(regs, context); /* * Disable syscall checks @@ -116,103 +207,95 @@ badframe: unlock_kernel(); } +/* same as sys_sigreturn for now */ +asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) +{ + return -ENOSYS; +} + +#define scc_offset ((size_t)&((struct sigframe *)0)->scc) + /* - * Set up a signal frame... - * - * This routine is somewhat complicated by the fact that if the kernel may be - * entered by an exception other than a system call; e.g. a bus error or other - * "bad" exception. If this is the case, then *all* the context on the kernel - * stack frame must be saved. - * - * For a large number of exceptions, the stack frame format is the same - * as that which will be created when the process traps back to the kernel - * when finished executing the signal handler. In this case, nothing - * must be done. This information is saved on the user stack and restored - * when the signal handler is returned. - * - * The signal handler will be called with ra pointing to code1 (see below) and - * one parameters in a0 (signum). + * Set up the return code ... * - * usp -> [unused] ; first free word on stack - * arg save space ; 16/32 bytes arg. save space - * code1 (addiu sp,#1-offset) ; pop stackframe - * code2 (li v0,__NR_sigreturn) ; syscall number - * code3 (syscall) ; do sigreturn(2) - * #1| $0, at, v0, v1, a0, a1, a2, a3 ; All integer registers - * | t0, t1, t2, t3, t4, t5, t6, t7 ; $0, k0 and k1 are placeholders - * | s0, s1, s2, s3, s4, s5, s6, s7 - * | k0, k1, t8, t9, gp, sp, fp, ra; - * | epc ; old program counter - * | cause ; CP0 cause register - * | oldmask + * .set noreorder + * addiu sp,0x20 + * li v0,__NR_sigreturn + * syscall + * .set reorder */ +static void inline +setup_trampoline(unsigned int *code) +{ + __put_user(0x27bd0000 + scc_offset , code + 0); + __put_user(0x24020000 + __NR_sigreturn, code + 1); + __put_user(0x0000000c , code + 2); -struct sc { - unsigned long ass[4]; - unsigned int code[4]; - struct sigcontext scc; -}; -#define scc_offset ((size_t)&((struct sc *)0)->scc) + /* + * Flush caches so that the instructions will be correctly executed. + */ + flush_cache_sigtramp((unsigned long) code); +} + +static void inline +setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc, sigset_t *set) +{ + __put_user(regs->cp0_epc, &sc->sc_pc); + __put_user(regs->cp0_status, &sc->sc_status); /* Status register */ + +#define save_gp_reg(i) __put_user(regs->regs[(i)], &sc->sc_regs[(i)]) + __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2); + save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6); + save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10); + save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14); + save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18); + save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22); + save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26); + save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30); + save_gp_reg(31); +#undef save_gp_reg + + save_fp_context(sc); /* cpu dependand */ + __put_user(regs->hi, &sc->sc_mdhi); + __put_user(regs->lo, &sc->sc_mdlo); + __put_user(regs->cp0_cause, &sc->sc_cause); + __put_user((regs->cp0_status & ST0_CU1) != 0, &sc->sc_ownedfp); + + __copy_to_user(sc->sc_sigset, set, sizeof(*set)); +} -static void setup_frame(struct sigaction * sa, struct pt_regs *regs, - int signr, unsigned long oldmask) +static void inline +setup_frame(struct k_sigaction * ka, struct pt_regs *regs, + int signr, sigset_t *oldmask) { - struct sc *frame; + struct sigframe *frame; struct sigcontext *sc; - int i; /* Align the stackframe to an adequate boundary for the architecture. */ - frame = (struct sc *) (long) regs->regs[29]; + frame = (struct sigframe *) (long) regs->regs[29]; frame--; - frame = (struct sc *)((unsigned long)frame & ALMASK); + frame = (struct sigframe *)((unsigned long)frame & ALMASK); if (verify_area(VERIFY_WRITE, frame, sizeof (*frame))) goto segv_and_exit; sc = &frame->scc; - /* - * Set up the return code ... - * - * .set noreorder - * addiu sp,0x20 - * li v0,__NR_sigreturn - * syscall - * .set reorder - */ - __put_user(0x27bd0000 + scc_offset, &frame->code[0]); - __put_user(0x24020000 + __NR_sigreturn, &frame->code[1]); - __put_user(0x0000000c, &frame->code[2]); + setup_trampoline(frame->code); + setup_sigcontext(regs, &frame->scc, oldmask); - /* - * Flush caches so that the instructions will be correctly executed. - */ - flush_cache_sigtramp((unsigned long) frame->code); + regs->regs[4] = signr; /* arguments */ + regs->regs[5] = 0; /* should be cause */ + regs->regs[6] = (long) frame; /* ptr to sigcontext */ + regs->regs[29] = (unsigned long) frame; /* Stack pointer */ + regs->regs[31] = (unsigned long) frame->code; /* Return address */ + regs->cp0_epc = (unsigned long) ka->sa.sa_handler; /* handler address */ + regs->regs[25] = regs->cp0_epc; /* PIC shit... */ - /* - * Set up the "normal" sigcontext - */ - __put_user(regs->cp0_epc, &sc->sc_pc); - __put_user(regs->cp0_status, &sc->sc_status); /* Status register */ - for(i = 31;i >= 0;i--) - __put_user(regs->regs[i], &sc->sc_regs[i]); - save_fp_context(sc); - __put_user(regs->hi, &sc->sc_mdhi); - __put_user(regs->lo, &sc->sc_mdlo); - __put_user(regs->cp0_cause, &sc->sc_cause); - __put_user((regs->cp0_status & ST0_CU1) != 0, &sc->sc_ownedfp); - __put_user(oldmask, &sc->sc_sigset); - __put_user(0, &sc->__pad0[0]); - __put_user(0, &sc->__pad0[1]); - __put_user(0, &sc->__pad0[2]); - - regs->regs[4] = signr; /* Arguments for handler */ - regs->regs[5] = 0; /* For now. */ - regs->regs[6] = (long) frame; /* Pointer to sigcontext */ - regs->regs[29] = (unsigned long) frame; /* Stack pointer */ - regs->regs[31] = (unsigned long) frame->code; /* Return address */ - regs->cp0_epc = (unsigned long) sa->sa_handler; /* "return" to the first handler */ - regs->regs[25] = regs->cp0_epc; /* PIC shit... */ - return; +#if DEBUG_SIG + printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n", + current->comm, current->pid, frame, regs->cp0_epc, frame->code); +#endif + return; segv_and_exit: lock_kernel(); @@ -220,16 +303,30 @@ segv_and_exit: unlock_kernel(); } -static inline void handle_signal(unsigned long signr, struct sigaction *sa, - unsigned long oldmask, struct pt_regs * regs) +static void inline +setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, + int signr, sigset_t *oldmask, siginfo_t *info) { - setup_frame(sa, regs, signr, oldmask); + printk("Aiee: setup_tr_frame wants to be written"); +} - if (sa->sa_flags & SA_ONESHOT) - sa->sa_handler = NULL; - if (!(sa->sa_flags & SA_NOMASK)) { +/* ------------------------------------------------------------------------- */ + +static inline void handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) +{ + if (ka->sa.sa_flags & SA_SIGINFO) + setup_rt_frame(ka, regs, sig, oldset, info); + else + setup_frame(ka, regs, sig, oldset); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sigmask_lock); - current->blocked |= (sa->sa_mask | _S(signr)) & _BLOCKABLE; + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked,sig); + recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); } } @@ -254,62 +351,82 @@ static inline void syscall_restart(unsigned long r0, unsigned long or2, } } -extern int do_irix_signal(unsigned long oldmask, struct pt_regs *regs); +extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs); -/* - * Note that 'init' is a special process: it doesn't get signals it doesn't - * want to handle. Thus you cannot kill init even with a SIGKILL even by - * mistake. - * - * Note that we go through the signals twice: once to check the signals that - * the kernel can handle, and then we build all the user-level signal handling - * stack-frames in one go after that. - */ -asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) { - unsigned long mask = ~current->blocked; - unsigned long signr, r0 = regs->regs[0]; + unsigned long r0 = regs->regs[0]; unsigned long r7 = regs->orig_reg7; - struct sigaction * sa; + struct k_sigaction *ka; + siginfo_t info; #ifdef CONFIG_BINFMT_IRIX - if(current->personality != PER_LINUX) - return do_irix_signal(oldmask, regs); + if (current->personality != PER_LINUX) /* XXX */ + return do_irix_signal(oldset, regs); #endif - while ((signr = current->signal & mask)) { - signr = ffz(~signr); - clear_bit(signr, ¤t->signal); - sa = current->sig->action + signr; - signr++; + + if (!oldset) + oldset = ¤t->blocked; + + for (;;) { + unsigned long signr; + + spin_lock_irq(¤t->sigmask_lock); + signr = dequeue_signal(¤t->blocked, &info); + spin_unlock_irq(¤t->sigmask_lock); + + if (!signr) + break; + if ((current->flags & PF_PTRACED) && signr != SIGKILL) { + /* Let the debugger run. */ current->exit_code = signr; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); + + /* We're back. Did the debugger cancel the sig? */ if (!(signr = current->exit_code)) continue; current->exit_code = 0; + + /* The debugger continued. Ignore SIGSTOP. */ if (signr == SIGSTOP) continue; - if (_S(signr) & current->blocked) { - spin_lock_irq(¤t->sigmask_lock); - current->signal |= _S(signr); - spin_unlock_irq(¤t->sigmask_lock); + + /* Update the siginfo structure. Is this good? */ + if (signr != info.si_signo) { + info.si_signo = signr; + info.si_errno = 0; + info.si_code = SI_USER; + info.si_pid = current->p_pptr->pid; + info.si_uid = current->p_pptr->uid; + } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(¤t->blocked, signr)) { + send_sig_info(signr, &info, current); continue; } - sa = current->sig->action + signr - 1; } - if (sa->sa_handler == SIG_IGN) { + + ka = ¤t->sig->action[signr-1]; + if (ka->sa.sa_handler == SIG_IGN) { if (signr != SIGCHLD) continue; - /* check for SIGCHLD: it's special */ - while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0) + /* Check for SIGCHLD: it's special. */ + while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) /* nothing */; continue; } - if (sa->sa_handler == SIG_DFL) { + + if (ka->sa.sa_handler == SIG_DFL) { + int exit_code = signr; + + /* Init gets no signals it doesn't want. */ if (current->pid == 1) continue; + switch (signr) { case SIGCONT: case SIGCHLD: case SIGWINCH: continue; @@ -317,48 +434,42 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) case SIGTSTP: case SIGTTIN: case SIGTTOU: if (is_orphaned_pgrp(current->pgrp)) continue; + /* FALLTHRU */ + case SIGSTOP: - if (current->flags & PF_PTRACED) - continue; current->state = TASK_STOPPED; current->exit_code = signr; - if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & - SA_NOCLDSTOP)) + if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); continue; case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: - case SIGBUS: lock_kernel(); - if (current->binfmt && current->binfmt->core_dump) { - if (current->binfmt->core_dump(signr, regs)) - signr |= 0x80; - } + if (current->binfmt + && current->binfmt->core_dump + && current->binfmt->core_dump(signr, regs)) + exit_code |= 0x80; unlock_kernel(); - /* fall through */ - default: - spin_lock_irq(¤t->sigmask_lock); - current->signal |= _S(signr & 0x7f); - spin_unlock_irq(¤t->sigmask_lock); + /* FALLTHRU */ + default: + lock_kernel(); + sigaddset(¤t->signal, signr); current->flags |= PF_SIGNALED; - - lock_kernel(); /* 8-( */ - do_exit(signr); - unlock_kernel(); + do_exit(exit_code); + /* NOTREACHED */ } } - /* - * OK, we're invoking a handler - */ - if(r0) - syscall_restart(r0, regs->orig_reg2, - r7, regs, sa); - handle_signal(signr, sa, oldmask, regs); + + if (r0) + syscall_restart(r0, regs->orig_reg2, r7, regs, &ka->sa); + /* Whee! Actually deliver the signal. */ + handle_signal(signr, ka, &info, oldset, regs); return 1; } + /* * Who's code doesn't conform to the restartable syscall convention * dies here!!! The li instruction, a single machine instruction, @@ -376,16 +487,6 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) } /* - * The signal(2) syscall is no longer available in the kernel - * because GNU libc doesn't use it. Maybe I'll add it back to the - * kernel for the binary compatibility stuff. - */ -asmlinkage unsigned long sys_signal(int signum, __sighandler_t handler) -{ - return -ENOSYS; -} - -/* * Compatibility syscall. Can be replaced in libc. */ asmlinkage int sys_pause(void) diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index ffcf176e4..91cc6a3ae 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -11,7 +11,7 @@ * Don't waste that much memory for empty entries in the syscall * table. * - * $Id: syscall.c,v 1.4 1997/09/18 07:57:30 root Exp $ + * $Id: syscall.c,v 1.4 1997/12/01 17:57:31 ralf Exp $ */ #undef CONF_PRINT_SYSCALLS #undef CONF_DEBUG_IRIX @@ -365,7 +365,7 @@ void do_sys(struct pt_regs *regs) if ((current->flags & PF_TRACESYS) == 0) { errno = do_syscalls(regs, syscall, narg); - if ((errno < 0 && errno > (-ENOIOCTLCMD - 1)) || current->errno) { + if (errno < 0 && errno > (-ENOIOCTLCMD - 1)) { goto bad_syscall; } regs->regs[2] = errno; @@ -376,7 +376,7 @@ void do_sys(struct pt_regs *regs) syscall_trace(); errno = do_syscalls(regs, syscall, narg); - if (errno < 0 || current->errno) + if (errno < 0) { regs->regs[2] = -errno; regs->regs[7] = 1; diff --git a/arch/mips/kernel/syscalls.h b/arch/mips/kernel/syscalls.h index 6b0e2d3c6..f0614b69f 100644 --- a/arch/mips/kernel/syscalls.h +++ b/arch/mips/kernel/syscalls.h @@ -7,7 +7,7 @@ * * Copyright (C) 1995, 1996 by Ralf Baechle * - * $Id: syscalls.h,v 1.8 1997/12/01 17:57:32 ralf Exp $ + * $Id: syscalls.h,v 1.9 1997/12/06 23:52:06 ralf Exp $ */ /* @@ -66,7 +66,7 @@ SYS(sys_ni_syscall, 0) SYS(sys_brk, 1) /* 4045 */ SYS(sys_setgid, 1) SYS(sys_getgid, 0) -SYS(sys_signal, 2) +SYS(sys_ni_syscall, 0) /* was signal(2) */ SYS(sys_geteuid, 0) SYS(sys_getegid, 0) /* 4050 */ SYS(sys_acct, 0) @@ -211,3 +211,12 @@ SYS(sys_nfsservctl, 3) SYS(sys_setresgid, 3) /* 4190 */ SYS(sys_getresgid, 3) SYS(sys_prctl, 5) +SYS(sys_rt_sigreturn, 0) +SYS(sys_rt_sigaction, 4) +SYS(sys_rt_sigprocmask, 4) /* 4195 */ +SYS(sys_rt_sigpending, 2) +SYS(sys_rt_sigtimedwait, 4) +SYS(sys_rt_sigqueueinfo, 3) +SYS(sys_rt_sigsuspend, 2) +SYS(sys_pread, 4) /* 4200 */ +SYS(sys_pwrite, 4) diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c index 711a52791..64941c67c 100644 --- a/arch/mips/kernel/sysirix.c +++ b/arch/mips/kernel/sysirix.c @@ -1,8 +1,10 @@ -/* $Id: sysirix.c,v 1.7 1997/09/13 23:49:30 shaver Exp $ +/* * sysirix.c: IRIX system call emulation. * * Copyright (C) 1996 David S. Miller * Copyright (C) 1997 Miguel de Icaza + * + * $Id: sysirix.c,v 1.8 1997/09/21 22:58:44 miguel Exp $ */ #include <linux/kernel.h> @@ -56,7 +58,7 @@ asmlinkage int irix_sysmp(struct pt_regs *regs) error = NR_CPUS; break; default: - printk("SYSMP[%s:%d]: Unsupported opcode %d\n", + printk("SYSMP[%s:%ld]: Unsupported opcode %d\n", current->comm, current->pid, (int)cmd); error = -EINVAL; break; @@ -95,7 +97,7 @@ asmlinkage int irix_prctl(struct pt_regs *regs) cmd = regs->regs[base + 4]; switch(cmd) { case PR_MAXPROCS: - printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n", + printk("irix_prctl[%s:%ld]: Wants PR_MAXPROCS\n", current->comm, current->pid); error = NR_TASKS; break; @@ -103,7 +105,7 @@ asmlinkage int irix_prctl(struct pt_regs *regs) case PR_ISBLOCKED: { struct task_struct *task; - printk("irix_prctl[%s:%d]: Wants PR_ISBLOCKED\n", + printk("irix_prctl[%s:%ld]: Wants PR_ISBLOCKED\n", current->comm, current->pid); task = find_task_by_pid(regs->regs[base + 5]); if(!task) { @@ -118,7 +120,7 @@ asmlinkage int irix_prctl(struct pt_regs *regs) case PR_SETSTACKSIZE: { long value = regs->regs[base + 5]; - printk("irix_prctl[%s:%d]: Wants PR_SETSTACKSIZE<%08lx>\n", + printk("irix_prctl[%s:%ld]: Wants PR_SETSTACKSIZE<%08lx>\n", current->comm, current->pid, (unsigned long) value); if(value > RLIM_INFINITY) value = RLIM_INFINITY; @@ -138,25 +140,25 @@ asmlinkage int irix_prctl(struct pt_regs *regs) } case PR_GETSTACKSIZE: - printk("irix_prctl[%s:%d]: Wants PR_GETSTACKSIZE\n", + printk("irix_prctl[%s:%ld]: Wants PR_GETSTACKSIZE\n", current->comm, current->pid); error = current->rlim[RLIMIT_STACK].rlim_cur; break; case PR_MAXPPROCS: - printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n", + printk("irix_prctl[%s:%ld]: Wants PR_MAXPROCS\n", current->comm, current->pid); error = 1; break; case PR_UNBLKONEXEC: - printk("irix_prctl[%s:%d]: Wants PR_UNBLKONEXEC\n", + printk("irix_prctl[%s:%ld]: Wants PR_UNBLKONEXEC\n", current->comm, current->pid); error = -EINVAL; break; case PR_SETEXITSIG: - printk("irix_prctl[%s:%d]: Wants PR_SETEXITSIG\n", + printk("irix_prctl[%s:%ld]: Wants PR_SETEXITSIG\n", current->comm, current->pid); /* We can probably play some game where we set the task @@ -167,31 +169,31 @@ asmlinkage int irix_prctl(struct pt_regs *regs) break; case PR_RESIDENT: - printk("irix_prctl[%s:%d]: Wants PR_RESIDENT\n", + printk("irix_prctl[%s:%ld]: Wants PR_RESIDENT\n", current->comm, current->pid); error = 0; /* Compatability indeed. */ break; case PR_ATTACHADDR: - printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDR\n", + printk("irix_prctl[%s:%ld]: Wants PR_ATTACHADDR\n", current->comm, current->pid); error = -EINVAL; break; case PR_DETACHADDR: - printk("irix_prctl[%s:%d]: Wants PR_DETACHADDR\n", + printk("irix_prctl[%s:%ld]: Wants PR_DETACHADDR\n", current->comm, current->pid); error = -EINVAL; break; case PR_TERMCHILD: - printk("irix_prctl[%s:%d]: Wants PR_TERMCHILD\n", + printk("irix_prctl[%s:%ld]: Wants PR_TERMCHILD\n", current->comm, current->pid); error = -EINVAL; break; case PR_GETSHMASK: - printk("irix_prctl[%s:%d]: Wants PR_GETSHMASK\n", + printk("irix_prctl[%s:%ld]: Wants PR_GETSHMASK\n", current->comm, current->pid); error = -EINVAL; /* Until I have the sproc() stuff in. */ break; @@ -201,24 +203,24 @@ asmlinkage int irix_prctl(struct pt_regs *regs) break; case PR_COREPID: - printk("irix_prctl[%s:%d]: Wants PR_COREPID\n", + printk("irix_prctl[%s:%ld]: Wants PR_COREPID\n", current->comm, current->pid); error = -EINVAL; break; case PR_ATTACHADDRPERM: - printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDRPERM\n", + printk("irix_prctl[%s:%ld]: Wants PR_ATTACHADDRPERM\n", current->comm, current->pid); error = -EINVAL; break; case PR_PTHREADEXIT: - printk("irix_prctl[%s:%d]: Wants PR_PTHREADEXIT\n", + printk("irix_prctl[%s:%ld]: Wants PR_PTHREADEXIT\n", current->comm, current->pid); do_exit(regs->regs[base + 5]); default: - printk("irix_prctl[%s:%d]: Non-existant opcode %d\n", + printk("irix_prctl[%s:%ld]: Non-existant opcode %d\n", current->comm, current->pid, (int)cmd); error = -EINVAL; break; @@ -339,7 +341,7 @@ asmlinkage int irix_syssgi(struct pt_regs *regs) case SGI_SETPGID: { #ifdef DEBUG_PROCGRPS - printk("[%s:%d] setpgid(%d, %d) ", + printk("[%s:%ld] setpgid(%d, %d) ", current->comm, current->pid, (int) regs->regs[base + 5], (int)regs->regs[base + 6]); #endif @@ -436,7 +438,7 @@ asmlinkage int irix_syssgi(struct pt_regs *regs) case SGI_GETSID: #ifdef DEBUG_PROCGRPS - printk("[%s:%d] getsid(%d) ", current->comm, current->pid, + printk("[%s:%ld] getsid(%d) ", current->comm, current->pid, (int) regs->regs[base + 5]); #endif retval = sys_getsid(regs->regs[base + 5]); @@ -636,7 +638,8 @@ out: return ret; } -extern int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue); +extern int do_setitimer(int which, struct itimerval *value, + struct itimerval *ovalue); static inline void jiffiestotv(unsigned long jiffies, struct timeval *value) { @@ -677,7 +680,7 @@ asmlinkage unsigned int irix_alarm(unsigned int seconds) it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0; it_new.it_value.tv_sec = seconds; it_new.it_value.tv_usec = 0; - _setitimer(ITIMER_REAL, &it_new, &it_old); + do_setitimer(ITIMER_REAL, &it_new, &it_old); } oldalarm = it_old.it_value.tv_sec; /* ehhh.. We can't return 0 if we have an alarm pending.. */ @@ -707,7 +710,7 @@ asmlinkage int irix_mount(char *dev_name, char *dir_name, unsigned long flags, int ret; lock_kernel(); - printk("[%s:%d] irix_mount(%p,%p,%08lx,%p,%p,%d)\n", + printk("[%s:%ld] irix_mount(%p,%p,%08lx,%p,%p,%d)\n", current->comm, current->pid, dev_name, dir_name, flags, type, data, datalen); ret = sys_mount(dev_name, dir_name, type, flags, data); @@ -727,8 +730,9 @@ asmlinkage int irix_statfs(const char *path, struct irix_statfs *buf, { struct dentry *dentry; struct inode *inode; + mm_segment_t old_fs; struct statfs kbuf; - int error, old_fs, i; + int error, i; /* We don't support this feature yet. */ if(fs_type) { @@ -776,8 +780,9 @@ asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf) struct dentry *dentry; struct inode *inode; struct statfs kbuf; + mm_segment_t old_fs; struct file *file; - int error, old_fs, i; + int error, i; lock_kernel(); error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs)); @@ -839,7 +844,7 @@ asmlinkage int irix_setpgrp(int flags) lock_kernel(); #ifdef DEBUG_PROCGRPS - printk("[%s:%d] setpgrp(%d) ", current->comm, current->pid, flags); + printk("[%s:%ld] setpgrp(%d) ", current->comm, current->pid, flags); #endif if(!flags) error = current->pgrp; @@ -919,7 +924,7 @@ out: asmlinkage unsigned long irix_gethostid(void) { lock_kernel(); - printk("[%s:%d]: irix_gethostid() called...\n", + printk("[%s:%ld]: irix_gethostid() called...\n", current->comm, current->pid); unlock_kernel(); return -EINVAL; @@ -928,7 +933,7 @@ asmlinkage unsigned long irix_gethostid(void) asmlinkage unsigned long irix_sethostid(unsigned long val) { lock_kernel(); - printk("[%s:%d]: irix_sethostid(%08lx) called...\n", + printk("[%s:%ld]: irix_sethostid(%08lx) called...\n", current->comm, current->pid, val); unlock_kernel(); return -EINVAL; @@ -1057,8 +1062,9 @@ extern asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high, asmlinkage int irix_lseek64(int fd, int _unused, int offhi, int offlow, int base) { + mm_segment_t old_fs; loff_t junk; - int old_fs, error; + int error; lock_kernel(); old_fs = get_fs(); set_fs(get_ds()); @@ -1139,7 +1145,7 @@ out: asmlinkage int irix_madvise(unsigned long addr, int len, int behavior) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_madvise(%08lx,%d,%d)\n", + printk("[%s:%ld] Wheee.. irix_madvise(%08lx,%d,%d)\n", current->comm, current->pid, addr, len, behavior); unlock_kernel(); return -EINVAL; @@ -1148,7 +1154,7 @@ asmlinkage int irix_madvise(unsigned long addr, int len, int behavior) asmlinkage int irix_pagelock(char *addr, int len, int op) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_pagelock(%p,%d,%d)\n", + printk("[%s:%ld] Wheee.. irix_pagelock(%p,%d,%d)\n", current->comm, current->pid, addr, len, op); unlock_kernel(); return -EINVAL; @@ -1157,7 +1163,7 @@ asmlinkage int irix_pagelock(char *addr, int len, int op) asmlinkage int irix_quotactl(struct pt_regs *regs) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_quotactl()\n", + printk("[%s:%ld] Wheee.. irix_quotactl()\n", current->comm, current->pid); unlock_kernel(); return -EINVAL; @@ -1169,7 +1175,7 @@ asmlinkage int irix_BSDsetpgrp(int pid, int pgrp) lock_kernel(); #ifdef DEBUG_PROCGRPS - printk("[%s:%d] BSDsetpgrp(%d, %d) ", current->comm, current->pid, + printk("[%s:%ld] BSDsetpgrp(%d, %d) ", current->comm, current->pid, pid, pgrp); #endif if(!pid) @@ -1192,7 +1198,7 @@ asmlinkage int irix_BSDsetpgrp(int pid, int pgrp) asmlinkage int irix_systeminfo(int cmd, char *buf, int cnt) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_systeminfo(%d,%p,%d)\n", + printk("[%s:%ld] Wheee.. irix_systeminfo(%d,%p,%d)\n", current->comm, current->pid, cmd, buf, cnt); unlock_kernel(); return -EINVAL; @@ -1320,13 +1326,13 @@ asmlinkage int irix_xstat(int version, char *filename, struct stat *statbuf) lock_kernel(); #ifdef DEBUG_XSTAT - printk("[%s:%d] Wheee.. irix_xstat(%d,%s,%p) ", + printk("[%s:%ld] Wheee.. irix_xstat(%d,%s,%p) ", current->comm, current->pid, version, filename, statbuf); #endif switch(version) { case 2: { struct stat kb; - int old_fs; + mm_segment_t old_fs; old_fs = get_fs(); set_fs(get_ds()); retval = sys_newstat(filename, &kb); @@ -1371,13 +1377,13 @@ asmlinkage int irix_lxstat(int version, char *filename, struct stat *statbuf) lock_kernel(); #ifdef DEBUG_XSTAT - printk("[%s:%d] Wheee.. irix_lxstat(%d,%s,%p) ", + printk("[%s:%ld] Wheee.. irix_lxstat(%d,%s,%p) ", current->comm, current->pid, version, filename, statbuf); #endif switch(version) { case 2: { struct stat kb; - int old_fs; + mm_segment_t old_fs; old_fs = get_fs(); set_fs(get_ds()); error = sys_newlstat(filename, &kb); @@ -1422,13 +1428,13 @@ asmlinkage int irix_fxstat(int version, int fd, struct stat *statbuf) lock_kernel(); #ifdef DEBUG_XSTAT - printk("[%s:%d] Wheee.. irix_fxstat(%d,%d,%p) ", + printk("[%s:%ld] Wheee.. irix_fxstat(%d,%d,%p) ", current->comm, current->pid, version, fd, statbuf); #endif switch(version) { case 2: { struct stat kb; - int old_fs; + mm_segment_t old_fs; old_fs = get_fs(); set_fs(get_ds()); error = sys_newfstat(fd, &kb); @@ -1472,7 +1478,7 @@ asmlinkage int irix_xmknod(int ver, char *filename, int mode, dev_t dev) int retval; lock_kernel(); - printk("[%s:%d] Wheee.. irix_xmknod(%d,%s,%x,%x)\n", + printk("[%s:%ld] Wheee.. irix_xmknod(%d,%s,%x,%x)\n", current->comm, current->pid, ver, filename, mode, (int) dev); switch(ver) { case 2: @@ -1492,7 +1498,7 @@ out: asmlinkage int irix_swapctl(int cmd, char *arg) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_swapctl(%d,%p)\n", + printk("[%s:%ld] Wheee.. irix_swapctl(%d,%p)\n", current->comm, current->pid, cmd, arg); unlock_kernel(); return -EINVAL; @@ -1510,11 +1516,12 @@ asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf) { struct dentry *dentry; struct inode *inode; + mm_segment_t old_fs; struct statfs kbuf; - int error, old_fs, i; + int error, i; lock_kernel(); - printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n", + printk("[%s:%ld] Wheee.. irix_statvfs(%s,%p)\n", current->comm, current->pid, fname, buf); error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); if(error) @@ -1569,12 +1576,13 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf) { struct dentry *dentry; struct inode *inode; + mm_segment_t old_fs; struct statfs kbuf; struct file *file; - int error, old_fs, i; + int error, i; lock_kernel(); - printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n", + printk("[%s:%ld] Wheee.. irix_fstatvfs(%d,%p)\n", current->comm, current->pid, fd, buf); error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); @@ -1725,7 +1733,7 @@ asmlinkage int irix_lchown(const char *filename, int uid, int gid) asmlinkage int irix_priocntl(struct pt_regs *regs) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_priocntl()\n", + printk("[%s:%ld] Wheee.. irix_priocntl()\n", current->comm, current->pid); unlock_kernel(); return -EINVAL; @@ -1734,7 +1742,7 @@ asmlinkage int irix_priocntl(struct pt_regs *regs) asmlinkage int irix_sigqueue(int pid, int sig, int code, int val) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_sigqueue(%d,%d,%d,%d)\n", + printk("[%s:%ld] Wheee.. irix_sigqueue(%d,%d,%d,%d)\n", current->comm, current->pid, pid, sig, code, val); unlock_kernel(); return -EINVAL; @@ -1842,7 +1850,7 @@ out: asmlinkage int irix_dmi(struct pt_regs *regs) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_dmi()\n", + printk("[%s:%ld] Wheee.. irix_dmi()\n", current->comm, current->pid); unlock_kernel(); return -EINVAL; @@ -1852,7 +1860,7 @@ asmlinkage int irix_pread(int fd, char *buf, int cnt, int off64, int off1, int off2) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n", + printk("[%s:%ld] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n", current->comm, current->pid, fd, buf, cnt, off64, off1, off2); unlock_kernel(); return -EINVAL; @@ -1862,7 +1870,7 @@ asmlinkage int irix_pwrite(int fd, char *buf, int cnt, int off64, int off1, int off2) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n", + printk("[%s:%ld] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n", current->comm, current->pid, fd, buf, cnt, off64, off1, off2); unlock_kernel(); return -EINVAL; @@ -1873,7 +1881,7 @@ asmlinkage int irix_sgifastpath(int cmd, unsigned long arg0, unsigned long arg1, unsigned long arg4, unsigned long arg5) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_fastpath(%d,%08lx,%08lx,%08lx,%08lx," + printk("[%s:%ld] Wheee.. irix_fastpath(%d,%08lx,%08lx,%08lx,%08lx," "%08lx,%08lx)\n", current->comm, current->pid, cmd, arg0, arg1, arg2, arg3, arg4, arg5); @@ -1896,10 +1904,11 @@ asmlinkage int irix_statvfs64(char *fname, struct irix_statvfs64 *buf) { struct dentry *dentry; struct inode *inode; + mm_segment_t old_fs; struct statfs kbuf; - int error, old_fs, i; + int error, i; - printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n", + printk("[%s:%ld] Wheee.. irix_statvfs(%s,%p)\n", current->comm, current->pid, fname, buf); error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); if(error) @@ -1953,12 +1962,13 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf) { struct dentry *dentry; struct inode *inode; + mm_segment_t old_fs; struct statfs kbuf; struct file *file; - int error, old_fs, i; + int error, i; lock_kernel(); - printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n", + printk("[%s:%ld] Wheee.. irix_fstatvfs(%d,%p)\n", current->comm, current->pid, fd, buf); error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); @@ -2021,7 +2031,7 @@ asmlinkage int irix_getmountid(char *fname, unsigned long *midbuf) int error; lock_kernel(); - printk("[%s:%d] irix_getmountid(%s, %p)\n", + printk("[%s:%ld] irix_getmountid(%s, %p)\n", current->comm, current->pid, fname, midbuf); error = verify_area(VERIFY_WRITE, midbuf, (sizeof(unsigned long) * 4)); if(error) @@ -2048,7 +2058,7 @@ asmlinkage int irix_nsproc(unsigned long entry, unsigned long mask, unsigned long arg, unsigned long sp, int slen) { lock_kernel(); - printk("[%s:%d] Wheee.. irix_nsproc(%08lx,%08lx,%08lx,%08lx,%d)\n", + printk("[%s:%ld] Wheee.. irix_nsproc(%08lx,%08lx,%08lx,%08lx,%d)\n", current->comm, current->pid, entry, mask, arg, sp, slen); unlock_kernel(); return -EINVAL; @@ -2121,7 +2131,7 @@ asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count lock_kernel(); #ifdef DEBUG_GETDENTS - printk("[%s:%d] ngetdents(%d, %p, %d, %p) ", current->comm, + printk("[%s:%ld] ngetdents(%d, %p, %d, %p) ", current->comm, current->pid, fd, dirent, count, eob); #endif error = -EBADF; @@ -2353,41 +2363,41 @@ asmlinkage int irix_uadmin(unsigned long op, unsigned long func, unsigned long a switch(op) { case 1: /* Reboot */ - printk("[%s:%d] irix_uadmin: Wants to reboot...\n", + printk("[%s:%ld] irix_uadmin: Wants to reboot...\n", current->comm, current->pid); retval = -EINVAL; goto out; case 2: /* Shutdown */ - printk("[%s:%d] irix_uadmin: Wants to shutdown...\n", + printk("[%s:%ld] irix_uadmin: Wants to shutdown...\n", current->comm, current->pid); retval = -EINVAL; goto out; case 4: /* Remount-root */ - printk("[%s:%d] irix_uadmin: Wants to remount root...\n", + printk("[%s:%ld] irix_uadmin: Wants to remount root...\n", current->comm, current->pid); retval = -EINVAL; goto out; case 8: /* Kill all tasks. */ - printk("[%s:%d] irix_uadmin: Wants to kill all tasks...\n", + printk("[%s:%ld] irix_uadmin: Wants to kill all tasks...\n", current->comm, current->pid); retval = -EINVAL; goto out; case 256: /* Set magic mushrooms... */ - printk("[%s:%d] irix_uadmin: Wants to set magic mushroom[%d]...\n", + printk("[%s:%ld] irix_uadmin: Wants to set magic mushroom[%d]...\n", current->comm, current->pid, (int) func); retval = -EINVAL; goto out; default: - printk("[%s:%d] irix_uadmin: Unknown operation [%d]...\n", + printk("[%s:%ld] irix_uadmin: Unknown operation [%d]...\n", current->comm, current->pid, (int) op); retval = -EINVAL; goto out; @@ -2411,20 +2421,20 @@ asmlinkage int irix_utssys(char *inbuf, int arg, int type, char *outbuf) case 2: /* ustat() */ - printk("[%s:%d] irix_utssys: Wants to do ustat()\n", + printk("[%s:%ld] irix_utssys: Wants to do ustat()\n", current->comm, current->pid); retval = -EINVAL; goto out; case 3: /* fusers() */ - printk("[%s:%d] irix_utssys: Wants to do fusers()\n", + printk("[%s:%ld] irix_utssys: Wants to do fusers()\n", current->comm, current->pid); retval = -EINVAL; goto out; default: - printk("[%s:%d] irix_utssys: Wants to do unknown type[%d]\n", + printk("[%s:%ld] irix_utssys: Wants to do unknown type[%d]\n", current->comm, current->pid, (int) type); retval = -EINVAL; goto out; @@ -2448,7 +2458,7 @@ asmlinkage int irix_fcntl(int fd, int cmd, int arg) lock_kernel(); #ifdef DEBUG_FCNTL - printk("[%s:%d] irix_fcntl(%d, %d, %d) ", current->comm, + printk("[%s:%ld] irix_fcntl(%d, %d, %d) ", current->comm, current->pid, fd, cmd, arg); #endif if (cmd == IRIX_F_ALLOCSP){ @@ -2469,26 +2479,26 @@ asmlinkage int irix_ulimit(int cmd, int arg) lock_kernel(); switch(cmd) { case 1: - printk("[%s:%d] irix_ulimit: Wants to get file size limit.\n", + printk("[%s:%ld] irix_ulimit: Wants to get file size limit.\n", current->comm, current->pid); retval = -EINVAL; goto out; case 2: - printk("[%s:%d] irix_ulimit: Wants to set file size limit.\n", + printk("[%s:%ld] irix_ulimit: Wants to set file size limit.\n", current->comm, current->pid); retval = -EINVAL; goto out; case 3: - printk("[%s:%d] irix_ulimit: Wants to get brk limit.\n", + printk("[%s:%ld] irix_ulimit: Wants to get brk limit.\n", current->comm, current->pid); retval = -EINVAL; goto out; case 4: #if 0 - printk("[%s:%d] irix_ulimit: Wants to get fd limit.\n", + printk("[%s:%ld] irix_ulimit: Wants to get fd limit.\n", current->comm, current->pid); retval = -EINVAL; goto out; @@ -2497,13 +2507,13 @@ asmlinkage int irix_ulimit(int cmd, int arg) goto out; case 5: - printk("[%s:%d] irix_ulimit: Wants to get txt offset.\n", + printk("[%s:%ld] irix_ulimit: Wants to get txt offset.\n", current->comm, current->pid); retval = -EINVAL; goto out; default: - printk("[%s:%d] irix_ulimit: Unknown command [%d].\n", + printk("[%s:%ld] irix_ulimit: Unknown command [%d].\n", current->comm, current->pid, cmd); retval = -EINVAL; goto out; @@ -2516,7 +2526,7 @@ out: asmlinkage int irix_unimp(struct pt_regs *regs) { lock_kernel(); - printk("irix_unimp [%s:%d] v0=%d v1=%d a0=%08lx a1=%08lx a2=%08lx " + printk("irix_unimp [%s:%ld] v0=%d v1=%d a0=%08lx a1=%08lx a2=%08lx " "a3=%08lx\n", current->comm, current->pid, (int) regs->regs[2], (int) regs->regs[3], regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index fc0dd091c..b80dc6dc8 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -8,7 +8,7 @@ * Copyright 1994, 1995, 1996, 1997 by Ralf Baechle * Modified for R3000 by Paul M. Antoine, 1995, 1996 * - * $Id: traps.c,v 1.7 1997/12/01 16:33:28 ralf Exp $ + * $Id: traps.c,v 1.5 1997/12/01 17:57:33 ralf Exp $ */ #include <linux/config.h> #include <linux/init.h> @@ -105,7 +105,7 @@ void show_registers(char * str, struct pt_regs * regs, long err) /* * Dump the stack */ - printk("Process %s (pid: %d, stackpage=%08lx)\nStack: ", + printk("Process %s (pid: %ld, stackpage=%08lx)\nStack: ", current->comm, current->pid, (unsigned long)current); for(i=0;i<5;i++) printk("%08x ", *sp++); @@ -337,7 +337,7 @@ void do_ri(struct pt_regs *regs) #ifdef CONF_DEBUG_EXCEPTIONS show_regs(regs); #endif - printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n", + printk("[%s:%ld] Illegal instruction at %08lx ra=%08lx\n", current->comm, current->pid, regs->cp0_epc, regs->regs[31]); if (compute_return_epc(regs)) goto out; @@ -489,7 +489,6 @@ __initfunc(void trap_init(void)) unsigned long i; if(mips_machtype == MACH_MIPS_MAGNUM_4000 || - mips_machtype == MACH_DESKSTATION_RPC44 || mips_machtype == MACH_SNI_RM200_PCI) EISA_bus = 1; diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index fd706165c..7da90c6d0 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -17,10 +17,9 @@ L_TARGET = lib.a L_OBJS = beep.o checksum.o copy_user.o csum.o dump_tlb.o memset.o memcpy.o \ strlen_user.o strncpy_user.o tags.o watch.o -ifdef CONFIG_DECSTATION -L_OBJS += pmaxcon.o pmaxio.o -else +# +# Debug console, works without other support from the kernel +# L_OBJS += tinycon.o -endif include $(TOPDIR)/Rules.make diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c index 0c7f81877..6205719f5 100644 --- a/arch/mips/lib/dump_tlb.c +++ b/arch/mips/lib/dump_tlb.c @@ -20,17 +20,6 @@ static char *region_map [] = { "u", "s", "k", "!" }; -static char *cache_map [] = { - "c/nc/wt/nwa,", - "c/nc/wt/wa, ", - "uncached, ", - "c/nc/wb, " - "unknown, ", - "unknown, ", - "unknown, ", - "unknown, " -}; - void dump_tlb(int first, int last) { @@ -69,9 +58,9 @@ dump_tlb(int first, int last) c0 = (entrylo0 >> 3) & 7; c1 = (entrylo1 >> 3) & 7; - printk("%s vpn2=%08x " - "[pfn=%06x c=%d d=%d v=%d g=%d]" - "[pfn=%06x c=%d d=%d v=%d g=%d]", + printk("%s vpn2=%08Lx " + "[pfn=%06Lx c=%d d=%d v=%d g=%Ld]" + "[pfn=%06Lx c=%d d=%d v=%d g=%Ld]", region_map [r], (entryhi >> 13) & 0xffffffff, (entrylo0 >> 6) & 0xffffff, c0, (entrylo0 & 4) ? 1 : 0, diff --git a/arch/mips/lib/pmaxcon.c b/arch/mips/lib/pmaxcon.c index 3b2cb1216..e69de29bb 100644 --- a/arch/mips/lib/pmaxcon.c +++ b/arch/mips/lib/pmaxcon.c @@ -1,150 +0,0 @@ -/* ---------------------------------------------------------------------- - * console.c - * - * Copyright (C) 1994 by Waldorf Electronic, - * written by Ralf Baechle and Andreas Busse - * Copyright (C) 1995 Paul M. Antoine (PMAX) - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * ---------------------------------------------------------------------- */ -/* - * FIXME: This file is hacked to be hardwired for the Personal DECStation - * Only thought of as a debugging console output - */ - -#include <linux/tty.h> -#include <asm/bootinfo.h> - -static unsigned int size_x; -static unsigned int size_y; -static unsigned short cursor_x; -static unsigned short cursor_y; -static volatile unsigned short *vram_addr; -static int console_needs_init = 1; - -extern struct bootinfo boot_info; -extern struct screen_info screen_info; - -/* - * Here is the base address of the prom calls - */ -unsigned long pmax_rex_base = 0; - -/* ---------------------------------------------------------------------- - * init_console() - * ---------------------------------------------------------------------- */ - -void init_console(void) -{ - size_x = 80; - size_y = 50; - cursor_x = 0; - cursor_y = 0; - - vram_addr = (unsigned short *)0xe10b8000; - - console_needs_init = 0; -} - -void -set_size_x(unsigned int x) -{ - size_x = x; -} - -void -set_size_y(unsigned int y) -{ - size_y = y; -} - -void -set_vram(unsigned short *vram) -{ - vram_addr = vram; -} - -/* - * FIXME: Temporary hack - changed its name to avoid conflict in - * drivers/char/vga.c that shouldn't be there <sigh> PMA - */ -void -set_pmax_cursor(unsigned int x, unsigned int y) -{ - cursor_x = x; - cursor_y = y; -} - -void -print_char(unsigned int x, unsigned int y, unsigned char c) -{ - volatile unsigned short *caddr; - -/* caddr = vram_addr + (y * size_x) + x; - *caddr = (*caddr & 0xff00) | 0x0f00 | (unsigned short) c; -*/ - pmax_putch(c); -} - -static void -scroll(void) -{ - volatile unsigned short *caddr; - register int i; -/* - caddr = vram_addr; - for(i=0; i<size_x * (size_y-1); i++) - *(caddr++) = *(caddr + size_x); - - blank last line - - caddr = vram_addr + (size_x * (size_y-1)); - for(i=0; i<size_x; i++) - *(caddr++) = (*caddr & 0xff00) | (unsigned short) ' '; -*/ - pmax_putch('\n'); -} - -void print_string(const unsigned char *str) -{ - unsigned char c; - - if (console_needs_init) - init_console(); -/* - while((c = *str++)) - switch(c) - { - case '\n': - cursor_x = 0; - cursor_y++; - if(cursor_y == size_y) - { - scroll(); - cursor_y = size_y - 1; - } - break; - - default: - print_char(cursor_x, cursor_y, c); - cursor_x++; - if(cursor_x == size_x) - { - cursor_x = 0; - cursor_y++; - if(cursor_y == size_y) - { - scroll(); - cursor_y = size_y - 1; - } - } - break; - } -*/ - pmax_printf(str); - -} - -/* end of file */ diff --git a/arch/mips/lib/pmaxio.S b/arch/mips/lib/pmaxio.S index 66e216a55..e69de29bb 100644 --- a/arch/mips/lib/pmaxio.S +++ b/arch/mips/lib/pmaxio.S @@ -1,40 +0,0 @@ -#include <asm/regdef.h> -#include <asm/decstation.h> - - .text - .set reorder -/* - * pmax_printf - call the PROM printf() function - */ - .globl pmax_printf -pmax_printf: - lw v0,pmax_rex_base - lw v0,REX_PRINTF(v0) - j v0 - -/* - * pmax_getchar - call the PROM getchar() function - */ - .globl pmax_getch -pmax_getch: - lw v0,pmax_rex_base - lw v0,REX_GETCHAR(v0) - j v0 - -/* - * pmax_putchar - call the PROM putchar() function - */ - .globl pmax_putch -pmax_putch: - lw v0,pmax_rex_base - lw v0,REX_PUTCHAR(v0) - j v0 - -/* - * pmax_halt - call the PROM halt() function - */ - .globl pmax_halt -pmax_halt: - lw v0,pmax_rex_base - lw v0,REX_HALT(v0) - j v0 diff --git a/arch/mips/mips/Makefile b/arch/mips/mips/Makefile index b252e2fe4..e69de29bb 100644 --- a/arch/mips/mips/Makefile +++ b/arch/mips/mips/Makefile @@ -1,39 +0,0 @@ -# -# PROM Entries for the big endian firmware used in the Mips Computer -# System, Inc. machines. Beware: some of the machines seem to be -# different. -# -# Copyright (C) 1997 Ralf Baechle -# -prom-entries= reset exec restart reinit reboot autoboot open read write ioctl \ - close getchar putchar showchar gets puts printf initproto protoenable \ - protodisable getpkt putpkt orw_rmw orh_rmw orb_rmw andw_rmw andh_rmw \ - andb_rmw flushcache clearcache setjmp longjmp bevutlb getenv setenv \ - atob strcmp strlen strcpy strcat parser range argvize help dumpcmd \ - setenvcmd unsetenvcmd printenvcmd bevexcept enablecmd disablecmd \ - clearnofault notimplement nv_get nv_set -asm-files=$(addsuffix .S,$(prom-entries)) -object-files=$(addsuffix .o,$(prom-entries)) - -CC=mipsel-linux-gcc -AR=mipsel-linux-ar -CFLAGS=-O2 -mno-abicalls -fno-pic -G0 -Wall - -all: libprom.a - -libprom.a: $(asm-files) - set -e;for i in $(prom-entries); do \ - $(CC) $(CFLAGS) -c -o $$i.o $$i.S; \ - $(AR) rcv libprom.a $$i.o; \ - done - -$(asm-files): mkprom - set -e;for i in $(prom-entries); do \ - mkprom $$i; \ - done - -clean: - rm -f $(object-files) - -distclean: - rm -rf $(asm-files) libprom.a diff --git a/arch/mips/mips/mkprom b/arch/mips/mips/mkprom index 9e4cdf465..e69de29bb 100755 --- a/arch/mips/mips/mkprom +++ b/arch/mips/mips/mkprom @@ -1,25 +0,0 @@ -# -# Generate PROM library stubs for the firmware used in the -# Mips Computer System, Inc. machines. Beware: some of the -# machines seem to be different. -# -# Copyright (C) 1997 Ralf Baechle -# -fname=$1 -ucase=`echo $fname | tr 'a-z' 'A-Z'` -cat << EOF | sed -e "s/@1@/$fname/" -e "s/@2@/$ucase/" >$fname.S -/* - * WARNING: This file has been generated automatically. Do not edit! - * - * Stub for the Mips firmware @1@() function. - */ -#include <asm/asm.h> -#include <asm/regdef.h> -#include <asm/mipsprom.h> - -LEAF(mips_prom_@1@) - lw t0,__mips_prom_entry_offset - addu t0,PROM_@2@ - jr t0 - END(mips_prom_@1@) -EOF diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index 72e13336b..8385eb22f 100644 --- a/arch/mips/mm/fault.c +++ b/arch/mips/mm/fault.c @@ -85,7 +85,7 @@ bad_area: if (user_mode(regs)) { tsk->tss.cp0_badvaddr = address; tsk->tss.error_code = writeaccess; -#if 1 +#if 0 printk("do_page_fault() #2: sending SIGSEGV to %s for illegal %s\n" "%08lx (epc == %08lx, ra == %08lx)\n", tsk->comm, diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index b62e571d6..9cb47cefa 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -229,27 +229,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem) for(tmp = MAP_NR(start_mem);tmp < max_mapnr;tmp++) clear_bit(PG_reserved, &mem_map[tmp].flags); - /* - * For rPC44 and RM200 we've reserved some memory too much. Free - * the memory from PAGE_SIZE to PAGE_OFFSET + 0xa0000 again. We - * don't free the lowest page where the exception handlers will - * reside. - */ - if (mips_machgroup == MACH_GROUP_ARC && - mips_machtype == MACH_DESKSTATION_RPC44) - for(tmp = MAP_NR(PAGE_OFFSET + PAGE_SIZE); - tmp < MAP_NR(PAGE_OFFSET + 0xa000); tmp++) - clear_bit(PG_reserved, &mem_map[tmp].flags); - #ifdef CONFIG_SGI prom_fixup_mem_map(start_mem, (unsigned long)high_memory); #endif -#ifdef CONFIG_DESKSTATION_TYNE - deskstation_tyne_dma_init(); -#endif - for (tmp = PAGE_OFFSET; tmp < end_mem; tmp += PAGE_SIZE) { /* * This is only for PC-style DMA. The onboard DMA diff --git a/arch/mips/mm/r4xx0.c b/arch/mips/mm/r4xx0.c index a0786131f..4c7ebd6f0 100644 --- a/arch/mips/mm/r4xx0.c +++ b/arch/mips/mm/r4xx0.c @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r4xx0.c,v 1.9 1997/12/01 17:57:36 ralf Exp $ + * $Id: r4xx0.c,v 1.10 1997/12/02 14:49:20 ralf Exp $ * * To do: * @@ -2424,6 +2424,38 @@ static void probe_dcache(unsigned long config) (int)(dcache_size >> 10), (int)dc_lsize); } +/* + * Activate the chipset controlled R4600 and R5000 caches of the Indy + */ +static inline void enable_indy_scache(void) +{ + unsigned long addr, tmp1, tmp2; + + /* This is really cool... */ + printk("Enabling R4600 SCACHE\n"); + __asm__ __volatile__(" + .set noreorder + .set mips3 + mfc0 %2, $12 + nop; nop; nop; nop; + li %1, 0x80 + mtc0 %1, $12 + nop; nop; nop; nop; + li %0, 0x1 + dsll %0, 31 + lui %1, 0x9000 + dsll32 %1, 0 + or %0, %1, %0 + sb $0, 0(%0) + mtc0 $0, $12 + nop; nop; nop; nop; + mtc0 %2, $12 + nop; nop; nop; nop; + .set mips0 + .set reorder" + : "=r" (tmp1), "=r" (tmp2), "=r" (addr)); +} + static int probe_scache_eeprom(unsigned long config) { #ifdef CONFIG_SGI @@ -2487,7 +2519,7 @@ static int probe_scache_eeprom(unsigned long config) printk("linesize %d bytes\n", sc_lsize); scache_size = data; if(data) { - unsigned long addr, tmp1, tmp2; + unsigned long addr; /* Enable r4600/r5000 cache. But flush it first. */ for(addr = KSEG0; addr < (KSEG0 + dcache_size); @@ -2500,42 +2532,26 @@ static int probe_scache_eeprom(unsigned long config) addr += sc_lsize) flush_scache_line_indexed(addr); - /* R5000 scache enable is in CP0 config, on R4600 variants + /* + * R5000 scache enable is in CP0 config, on R4600 variants * the scache is enable by the memory mapped cache controller. */ + if (mips_cputype == CPU_R4600 || + mips_cputype == CPU_R5000) { + enable_indy_scache(); + return 1; + } +#if 0 if(mips_cputype == CPU_R5000) { unsigned long config; config = read_32bit_cp0_register(CP0_CONFIG); config |= 0x1000; write_32bit_cp0_register(CP0_CONFIG, config); - } else { - /* This is really cool... */ - printk("Enabling R4600 SCACHE\n"); - __asm__ __volatile__(" - .set noreorder - .set mips3 - mfc0 %2, $12 - nop; nop; nop; nop; - li %1, 0x80 - mtc0 %1, $12 - nop; nop; nop; nop; - li %0, 0x1 - dsll %0, 31 - lui %1, 0x9000 - dsll32 %1, 0 - or %0, %1, %0 - sb $0, 0(%0) - mtc0 $0, $12 - nop; nop; nop; nop; - mtc0 %2, $12 - nop; nop; nop; nop; - .set mips0 - .set reorder - " : "=r" (tmp1), "=r" (tmp2), "=r" (addr)); } - +#endif return 1; + } else { if(mips_cputype == CPU_R5000) return -1; @@ -2831,7 +2847,8 @@ void ld_mmu_r4xx0(void) } else { /* Lacks true secondary cache. */ setup_noscache_funcs(); - if((mips_cputype != CPU_R5000)) { /* XXX */ + if (mips_cputype == CPU_R4600 || + mips_cputype == CPU_R5000) { flush_cache_page = r4k_flush_cache_page_d32i32_r4600; flush_page_to_ram = diff --git a/arch/mips/sgi/kernel/reset.c b/arch/mips/sgi/kernel/reset.c index 6bb8616fa..578a20574 100644 --- a/arch/mips/sgi/kernel/reset.c +++ b/arch/mips/sgi/kernel/reset.c @@ -6,6 +6,7 @@ #include <asm/io.h> #include <asm/system.h> #include <asm/reboot.h> +#include <asm/sgialib.h> /* XXX How to pass the reboot command to the firmware??? */ void sgi_machine_restart(char *command) diff --git a/arch/mips/tools/offset.c b/arch/mips/tools/offset.c index cc6b7b7d3..88926ebfd 100644 --- a/arch/mips/tools/offset.c +++ b/arch/mips/tools/offset.c @@ -4,7 +4,7 @@ * Copyright (C) 1996 David S. Miller * Made portable by Ralf Baechle * - * $Id: offset.c,v 1.3 1997/07/29 18:57:11 ralf Exp $ + * $Id: offset.c,v 1.3 1997/12/01 17:57:41 ralf Exp $ */ #include <linux/types.h> @@ -81,9 +81,8 @@ void output_task_defines(void) offset("#define TASK_STATE ", struct task_struct, state); offset("#define TASK_COUNTER ", struct task_struct, counter); offset("#define TASK_PRIORITY ", struct task_struct, priority); - offset("#define TASK_SIGNAL ", struct task_struct, signal); - offset("#define TASK_BLOCKED ", struct task_struct, blocked); offset("#define TASK_FLAGS ", struct task_struct, flags); + offset("#define TASK_SIGPENDING ", struct task_struct, sigpending); offset("#define TASK_MM ", struct task_struct, mm); linefeed; } diff --git a/arch/ppc/config.in b/arch/ppc/config.in index cdd5c4a03..7ce44ea4c 100644 --- a/arch/ppc/config.in +++ b/arch/ppc/config.in @@ -89,6 +89,7 @@ if [ "$CONFIG_NET" = "y" ]; then endmenu fi +source drivers/net/hamradio/Config.in mainmenu_option next_comment comment 'ISDN subsystem' @@ -106,6 +107,17 @@ if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then fi endmenu +# Conditionally compile in the Uniform CD-ROM driver +if [ "$CONFIG_BLK_DEV_SR" = "y" -o "$CONFIG_SBPCD" = "y" -o "$CONFIG_MCD" = "y" -o "$CONFIG_CM206" = "y" -o "$CONFIG_CDU31A" = "y" ]; then + define_bool CONFIG_CDROM y +else + if [ "$CONFIG_BLK_DEV_SR" = "m" -o "$CONFIG_SBPCD" = "m" -o "$CONFIG_MCD" = "m" -o "$CONFIG_CM206" = "m" -o "$CONFIG_CDU31A" = "m" ]; then + define_bool CONFIG_CDROM m + else + define_bool CONFIG_CDROM n + fi +fi + source fs/Config.in source fs/nls/Config.in diff --git a/arch/sparc/config.in b/arch/sparc/config.in index ae8568b25..ef4bb3777 100644 --- a/arch/sparc/config.in +++ b/arch/sparc/config.in @@ -144,6 +144,17 @@ if [ "$CONFIG_NET" = "y" ]; then endmenu fi +# Conditionally compile in the Uniform CD-ROM driver +if [ "$CONFIG_BLK_DEV_SR" = "y" ]; then + define_bool CONFIG_CDROM y +else + if [ "$CONFIG_BLK_DEV_SR" = "m" ]; then + define_bool CONFIG_CDROM m + else + define_bool CONFIG_CDROM n + fi +fi + source fs/Config.in source fs/nls/Config.in diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in index 13f056050..14d545e39 100644 --- a/arch/sparc64/config.in +++ b/arch/sparc64/config.in @@ -181,6 +181,17 @@ if [ "$CONFIG_NET" = "y" ]; then endmenu fi +# Conditionally compile in the Uniform CD-ROM driver +if [ "$CONFIG_BLK_DEV_IDECD" = "y" -o "$CONFIG_BLK_DEV_SR" = "y" ]; then + define_bool CONFIG_CDROM y +else + if [ "$CONFIG_BLK_DEV_IDECD" = "m" -o "$CONFIG_BLK_DEV_SR" = "m" ]; then + define_bool CONFIG_CDROM m + else + define_bool CONFIG_CDROM n + fi +fi + source fs/Config.in source fs/nls/Config.in diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index e2c199f60..81640c8e6 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -38,9 +38,9 @@ #include <linux/nfsd/xdr.h> #include <linux/nfsd/syscall.h> #include <linux/module.h> +#include <linux/poll.h> #include <asm/types.h> -#include <asm/poll.h> #include <asm/ipc.h> #include <asm/uaccess.h> #include <asm/fpumacro.h> @@ -1075,104 +1075,139 @@ out: /* end of readdir & getdents */ -extern asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, - fd_set *exp, struct timeval *tvp); +/* + * Ooo, nasty. We need here to frob 32-bit unsigned longs to + * 64-bit unsigned longs. + */ -asmlinkage int sys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp) +static inline int +get_fd_set32(unsigned long n, unsigned long *fdset, u32 ufdset_x) { - struct timeval kern_tv, *ktvp; - unsigned long old_fs; - char *p; - u32 *q, *Inp, *Outp, *Exp; - int i, ret = -EINVAL, nn; - - if (n < 0 || n > PAGE_SIZE*2) - return -EINVAL; - - lock_kernel (); - p = (char *)__get_free_page (GFP_KERNEL); - if (!p) - goto out_nofree; + u32 *ufdset = (u32 *)A(ufdset_x); - q = (u32 *)p; - Inp = (u32 *)A(inp); - Outp = (u32 *)A(outp); - Exp = (u32 *)A(exp); + if (ufdset) { + unsigned long odd; - ret = -EFAULT; + if (verify_area(VERIFY_WRITE, ufdset, nn*sizeof(u32))) + return -EFAULT; - nn = (n + (8 * sizeof(long)) - 1) / (8 * sizeof(long)); - if (inp && verify_area(VERIFY_WRITE, Inp, nn*sizeof(long))) - goto out; - if (outp && verify_area(VERIFY_WRITE, Outp, nn*sizeof(long))) - goto out; - if (exp && verify_area(VERIFY_WRITE, Exp, nn*sizeof(long))) - goto out; - for (i = 0; i < nn; i++, Inp += 2, Outp += 2, Exp += 2, q += 2) { - if(inp && (__get_user (q[1], Inp) || __get_user (q[0], Inp+1))) - goto out; - if(outp && (__get_user (q[1+(PAGE_SIZE/4/sizeof(u32))], Outp) || - __get_user (q[(PAGE_SIZE/4/sizeof(u32))], Outp+1))) - goto out; - if(exp && (__get_user (q[1+(PAGE_SIZE/2/sizeof(u32))], Exp) || - __get_user (q[(PAGE_SIZE/2/sizeof(u32))], Exp+1))) - goto out; + odd = n & 1UL; + n &= ~1UL; + while (n) { + unsigned long h, l; + __get_user(l, ufdset); + __get_user(h, ufdset+1); + ufdset += 2; + *fdset++ = h << 32 | l; + n -= 2; + } + if (odd) + __get_user(*fdset, ufdset); + } else { + /* Tricky, must clear full unsigned long in the kernel + fdset at the end, this makes sure that actually + happens. */ + memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32)); } - ktvp = NULL; - if(tvp) { - if (get_tv32(&kern_tv, (struct timeval32 *)A(tvp))) - goto out; - ktvp = &kern_tv; - } + return 0; +} - old_fs = get_fs (); - set_fs (KERNEL_DS); - q = (u32 *) p; - ret = sys_select(n, - inp ? (fd_set *)&q[0] : (fd_set *)0, - outp ? (fd_set *)&q[PAGE_SIZE/4/sizeof(u32)] : (fd_set *)0, - exp ? (fd_set *)&q[PAGE_SIZE/2/sizeof(u32)] : (fd_set *)0, - ktvp); - set_fs (old_fs); +static inline void +set_fd_set32(unsigned long n, u32 ufdset_x, unsigned long *fdset) +{ + unsigned long odd; + u32 *ufdset = (u32 *)A(ufdset_x); - if(tvp && !(current->personality & STICKY_TIMEOUTS)) { - if (put_tv32((struct timeval32 *)A(tvp), &kern_tv)) { - ret = -EFAULT; - goto out; - } + if (!ufdset) + return; + + odd = n & 1UL; + n &= ~1UL; + while (n) { + unsigned long h, l; + l = *fdset++; + h = l >> 32; + __put_user(l, ufdset); + __put_user(h, ufdset+1); + ufdset += 2; + n -= 2; } + if (odd) + __put_user(*fdset, ufdset); +} + +asmlinkage int sys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp_x) +{ + fd_set_buffer *fds; + struct timeval32 *tvp = (struct timeval32 *)A(tvp_x); + unsigned long timeout, nn; + int ret; - q = (u32 *)p; - Inp = (u32 *)A(inp); - Outp = (u32 *)A(outp); - Exp = (u32 *)A(exp); + timeout = ~0UL; + if (tvp) { + time_t sec, usec; - if(ret < 0) - goto out; + if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp))) + || (ret = __get_user(sec, &tvp->tv_sec)) + || (ret = __get_user(usec, &tvp->tv_usec))) + goto out_nofds; - for (i = 0; - i < nn; - i++, Inp += 2, Outp += 2, Exp += 2, q += 2) { - if(inp && (__put_user (q[1], Inp) || __put_user (q[0], Inp+1))) { - ret = -EFAULT; - goto out; - } - if(outp && (__put_user (q[1+(PAGE_SIZE/4/sizeof(u32))], Outp) || - __put_user (q[(PAGE_SIZE/4/sizeof(u32))], Outp+1))) { - ret = -EFAULT; - goto out; + timeout = (usec + 1000000/HZ - 1) / (1000000/HZ); + timeout += sec * HZ; + if (timeout) + timeout += jiffies + 1; + } + + ret = -ENOMEM; + fds = (fd_set_buffer *) __get_free_page(GFP_KERNEL); + if (!fds) + goto out_nofds; + ret = -EINVAL; + if (n < 0) + goto out; + if (n > KFDS_NR) + n = KFDS_NR; + + nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32)); + if ((ret = get_fd_set32(nn, fds->in, inp)) || + (ret = get_fd_set32(nn, fds->out, outp)) || + (ret = get_fd_set32(nn, fds->ex, exp))) + goto out; + zero_fd_set(n, fds->res_in); + zero_fd_set(n, fds->res_out); + zero_fd_set(n, fds->res_ex); + + ret = do_select(n, fds, timeout); + + if (tvp && !(current->personality & STICKY_TIMEOUTS)) { + unsigned long timeout = current->timeout - jiffies - 1; + time_t sec = 0, usec = 0; + if ((long) timeout > 0) { + sec = timeout / HZ; + usec = timeout % HZ; + usec *= (1000000/HZ); } - if(exp && (__put_user (q[1+(PAGE_SIZE/2/sizeof(u32))], Exp) || - __put_user (q[(PAGE_SIZE/2/sizeof(u32))], Exp+1))) { - ret = -EFAULT; + put_user(sec, &tvp->tv_sec); + put_user(usec, &tvp->tv_usec); + } + + if (ret < 0) + goto out; + if (!ret) { + ret = -ERESTARTNOHAND; + if (current->signal & ~current->blocked) goto out; - } + ret = 0; } + + set_fd_set32(nn, inp, fds->res_in); + set_fd_set32(nn, outp, fds->res_out); + set_fd_set32(nn, exp, fds->res_ex); + out: - free_page ((unsigned long)p); -out_nofree: - unlock_kernel(); + free_page ((unsigned long)fds); +out_nofds: return ret; } |