Commit 3f43be64 authored by David S. Miller's avatar David S. Miller

Merge

parents 9c75ad3b 21872250
...@@ -251,6 +251,10 @@ CONFIG_ALPHA_PRIMO ...@@ -251,6 +251,10 @@ CONFIG_ALPHA_PRIMO
CONFIG_ALPHA_GAMMA CONFIG_ALPHA_GAMMA
Say Y if you have an AS 2000 5/xxx or an AS 2100 5/xxx. Say Y if you have an AS 2000 5/xxx or an AS 2100 5/xxx.
CONFIG_ALPHA_EV67
Is this a machine based on the EV67 core? If in doubt, select N here
and the machine will be treated as an EV6.
CONFIG_ALPHA_SRM CONFIG_ALPHA_SRM
There are two different types of booting firmware on Alphas: SRM, There are two different types of booting firmware on Alphas: SRM,
which is command line driven, and ARC, which uses menus and arrow which is command line driven, and ARC, which uses menus and arrow
...@@ -610,3 +614,14 @@ CONFIG_DEBUG_SPINLOCK ...@@ -610,3 +614,14 @@ CONFIG_DEBUG_SPINLOCK
best used in conjunction with the NMI watchdog so that spinlock best used in conjunction with the NMI watchdog so that spinlock
deadlocks are also debuggable. deadlocks are also debuggable.
CONFIG_DEBUG_RWLOCK
If you say Y here then read-write lock processing will count how many
times it has tried to get the lock and issue an error message after
too many attempts. If you suspect a rwlock problem or a kernel
hacker asks for this option then say Y. Otherwise say N.
CONFIG_DEBUG_SEMAPHORE
If you say Y here then semaphore processing will issue lots of
verbose debugging messages. If you suspect a semaphore problem or a
kernel hacker asks for this option then say Y. Otherwise say N.
...@@ -99,30 +99,32 @@ export libs-y ...@@ -99,30 +99,32 @@ export libs-y
MAKEBOOT = $(MAKE) -C arch/alpha/boot MAKEBOOT = $(MAKE) -C arch/alpha/boot
rawboot: rawboot: vmlinux
@$(MAKEBOOT) rawboot @$(MAKEBOOT) rawboot
boot: vmlinux
@$(MAKEBOOT)
# #
# My boot writes directly to a specific disk partition, I doubt most # My boot writes directly to a specific disk partition, I doubt most
# people will want to do that without changes.. # people will want to do that without changes..
# #
msb my-special-boot: msb my-special-boot: vmlinux
@$(MAKEBOOT) msb @$(MAKEBOOT) msb
bootimage: bootimage: vmlinux
@$(MAKEBOOT) bootimage @$(MAKEBOOT) bootimage
srmboot: srmboot: vmlinux
@$(MAKEBOOT) srmboot @$(MAKEBOOT) srmboot
archclean: archclean:
@$(MAKE) -C arch/alpha/kernel clean
@$(MAKEBOOT) clean @$(MAKEBOOT) clean
archmrproper: archmrproper:
rm -f include/asm-alpha/asm_offsets.h rm -f include/asm-alpha/asm_offsets.h
bootpfile: bootpfile: vmlinux
@$(MAKEBOOT) bootpfile @$(MAKEBOOT) bootpfile
......
...@@ -8,7 +8,9 @@ ...@@ -8,7 +8,9 @@
# Copyright (C) 1994 by Linus Torvalds # Copyright (C) 1994 by Linus Torvalds
# #
LINKFLAGS = -static -T bootloader.lds #-N -relax LINKFLAGS = -static -T bootloader.lds -uvsprintf #-N -relax
CFLAGS := $(CFLAGS) -I$(TOPDIR)/include
.S.s: .S.s:
$(CPP) $(AFLAGS) -traditional -o $*.o $< $(CPP) $(AFLAGS) -traditional -o $*.o $<
......
...@@ -8,8 +8,9 @@ EXTRA_AFLAGS := $(CFLAGS) ...@@ -8,8 +8,9 @@ EXTRA_AFLAGS := $(CFLAGS)
export-objs := alpha_ksyms.o export-objs := alpha_ksyms.o
obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o irq_alpha.o \ obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
signal.o setup.o ptrace.o time.o semaphore.o alpha_ksyms.o irq_alpha.o signal.o setup.o ptrace.o time.o semaphore.o \
alpha_ksyms.o systbls.o
# #
# FIXME! # FIXME!
......
...@@ -161,7 +161,6 @@ EXPORT_SYMBOL(sys_read); ...@@ -161,7 +161,6 @@ EXPORT_SYMBOL(sys_read);
EXPORT_SYMBOL(sys_lseek); EXPORT_SYMBOL(sys_lseek);
EXPORT_SYMBOL(__kernel_execve); EXPORT_SYMBOL(__kernel_execve);
EXPORT_SYMBOL(sys_setsid); EXPORT_SYMBOL(sys_setsid);
EXPORT_SYMBOL(sys_sync);
EXPORT_SYMBOL(sys_wait4); EXPORT_SYMBOL(sys_wait4);
/* Networking helper routines. */ /* Networking helper routines. */
......
...@@ -9,8 +9,7 @@ ...@@ -9,8 +9,7 @@
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/asm_offsets.h> #include <asm/asm_offsets.h>
#include <asm/thread_info.h> #include <asm/thread_info.h>
#include <asm/unistd.h>
#define NR_SYSCALLS 381
/* /*
* stack offsets * stack offsets
...@@ -677,6 +676,7 @@ ret_success: ...@@ -677,6 +676,7 @@ ret_success:
.end entSys .end entSys
.align 3 .align 3
.globl sys_sigreturn
.ent sys_sigreturn .ent sys_sigreturn
sys_sigreturn: sys_sigreturn:
mov $30,$17 mov $30,$17
...@@ -688,6 +688,7 @@ sys_sigreturn: ...@@ -688,6 +688,7 @@ sys_sigreturn:
.end sys_sigreturn .end sys_sigreturn
.align 3 .align 3
.globl sys_rt_sigreturn
.ent sys_rt_sigreturn .ent sys_rt_sigreturn
sys_rt_sigreturn: sys_rt_sigreturn:
mov $30,$17 mov $30,$17
...@@ -699,6 +700,7 @@ sys_rt_sigreturn: ...@@ -699,6 +700,7 @@ sys_rt_sigreturn:
.end sys_rt_sigreturn .end sys_rt_sigreturn
.align 3 .align 3
.globl sys_sigsuspend
.ent sys_sigsuspend .ent sys_sigsuspend
sys_sigsuspend: sys_sigsuspend:
mov $30,$17 mov $30,$17
...@@ -713,6 +715,7 @@ sys_sigsuspend: ...@@ -713,6 +715,7 @@ sys_sigsuspend:
.end sys_sigsuspend .end sys_sigsuspend
.align 3 .align 3
.globl sys_rt_sigsuspend
.ent sys_rt_sigsuspend .ent sys_rt_sigsuspend
sys_rt_sigsuspend: sys_rt_sigsuspend:
mov $30,$18 mov $30,$18
...@@ -725,421 +728,3 @@ sys_rt_sigsuspend: ...@@ -725,421 +728,3 @@ sys_rt_sigsuspend:
lda $30,SWITCH_STACK_SIZE+16($30) lda $30,SWITCH_STACK_SIZE+16($30)
ret $31,($26),1 ret $31,($26),1
.end sys_rt_sigsuspend .end sys_rt_sigsuspend
.data
.align 3
.globl sys_call_table
sys_call_table:
.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 sys_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 sys_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 sys_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 /* 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 osf_sigstack
.quad sys_recvmsg
.quad sys_sendmsg
.quad alpha_ni_syscall /* 115 */
.quad osf_gettimeofday
.quad osf_getrusage
.quad sys_getsockopt
.quad alpha_ni_syscall
#ifdef CONFIG_OSF4_COMPAT
.quad osf_readv /* 120 */
.quad osf_writev
#else
.quad sys_readv /* 120 */
.quad sys_writev
#endif
.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 sys_lchown
.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 sys_sigaltstack /* 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 */
.quad sys_bdflush /* 300 */
.quad sys_sethae
.quad sys_mount
.quad sys_old_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_ni_syscall /* 320 */
.quad sys_oldumount
.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 sys_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_pread64
.quad sys_pwrite64 /* 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 sys_select
.quad sys_gettimeofday
.quad sys_settimeofday /* 360 */
.quad sys_getitimer
.quad sys_setitimer
.quad sys_utimes
.quad sys_getrusage
.quad sys_wait4 /* 365 */
.quad sys_adjtimex
.quad sys_getcwd
.quad sys_capget
.quad sys_capset
.quad sys_sendfile /* 370 */
.quad sys_setresgid
.quad sys_getresgid
.quad sys_ni_syscall /* sys_dipc */
.quad sys_pivot_root
.quad sys_mincore /* 375 */
.quad sys_pciconfig_iobase
.quad sys_getdents64
.quad sys_gettid
.quad sys_readahead
.quad sys_ni_syscall /* 380, sys_security */
.quad sys_tkill
.quad sys_setxattr
.quad sys_lsetxattr
.quad sys_fsetxattr
.quad sys_getxattr
.quad sys_lgetxattr
.quad sys_fgetxattr
.quad sys_listxattr
.quad sys_llistxattr
.quad sys_flistxattr /* 390 */
.quad sys_removexattr
.quad sys_lremovexattr
.quad sys_fremovexattr
.quad sys_futex
.quad sys_sched_setaffinity
.quad sys_sched_getaffinity
.quad sys_ni_syscall /* 397, tux */
.quad sys_io_setup
.quad sys_io_destroy
.quad sys_io_getevents /* 400 */
.quad sys_io_submit
.quad sys_io_cancel
.quad sys_ni_syscall /* 403, sys_alloc_hugepages */
.quad sys_ni_syscall /* 404, sys_free_hugepages */
.quad sys_exit_group
...@@ -44,8 +44,9 @@ ...@@ -44,8 +44,9 @@
#include <asm/processor.h> #include <asm/processor.h>
extern int do_pipe(int *); extern int do_pipe(int *);
extern asmlinkage unsigned long sys_brk(unsigned long); extern asmlinkage unsigned long sys_brk(unsigned long);
extern int sys_getpriority(int, int);
extern asmlinkage unsigned long sys_create_module(char *, unsigned long);
/* /*
* Brk needs to return an error. Still support Linux's brk(0) query idiom, * Brk needs to return an error. Still support Linux's brk(0) query idiom,
...@@ -53,7 +54,8 @@ extern asmlinkage unsigned long sys_brk(unsigned long); ...@@ -53,7 +54,8 @@ extern asmlinkage unsigned long sys_brk(unsigned long);
* identical to OSF as we don't return 0 on success, but doing otherwise * identical to OSF as we don't return 0 on success, but doing otherwise
* would require changes to libc. Hopefully this is good enough. * would require changes to libc. Hopefully this is good enough.
*/ */
asmlinkage unsigned long osf_brk(unsigned long brk) asmlinkage unsigned long
osf_brk(unsigned long brk)
{ {
unsigned long retval = sys_brk(brk); unsigned long retval = sys_brk(brk);
if (brk && brk != retval) if (brk && brk != retval)
...@@ -64,9 +66,9 @@ asmlinkage unsigned long osf_brk(unsigned long brk) ...@@ -64,9 +66,9 @@ asmlinkage unsigned long osf_brk(unsigned long brk)
/* /*
* This is pure guess-work.. * This is pure guess-work..
*/ */
asmlinkage int osf_set_program_attributes( asmlinkage int
unsigned long text_start, unsigned long text_len, osf_set_program_attributes(unsigned long text_start, unsigned long text_len,
unsigned long bss_start, unsigned long bss_len) unsigned long bss_start, unsigned long bss_len)
{ {
struct mm_struct *mm; struct mm_struct *mm;
...@@ -106,8 +108,9 @@ struct osf_dirent_callback { ...@@ -106,8 +108,9 @@ struct osf_dirent_callback {
int error; int error;
}; };
static int osf_filldir(void *__buf, const char *name, int namlen, loff_t offset, static int
ino_t ino, unsigned int d_type) osf_filldir(void *__buf, const char *name, int namlen, loff_t offset,
ino_t ino, unsigned int d_type)
{ {
struct osf_dirent *dirent; struct osf_dirent *dirent;
struct osf_dirent_callback *buf = (struct osf_dirent_callback *) __buf; struct osf_dirent_callback *buf = (struct osf_dirent_callback *) __buf;
...@@ -134,8 +137,9 @@ static int osf_filldir(void *__buf, const char *name, int namlen, loff_t offset, ...@@ -134,8 +137,9 @@ static int osf_filldir(void *__buf, const char *name, int namlen, loff_t offset,
return 0; return 0;
} }
asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent *dirent, asmlinkage int
unsigned int count, long *basep) osf_getdirentries(unsigned int fd, struct osf_dirent *dirent,
unsigned int count, long *basep)
{ {
int error; int error;
struct file *file; struct file *file;
...@@ -159,9 +163,9 @@ asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent *dirent, ...@@ -159,9 +163,9 @@ asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent *dirent,
if (count != buf.count) if (count != buf.count)
error = count - buf.count; error = count - buf.count;
out_putf: out_putf:
fput(file); fput(file);
out: out:
return error; return error;
} }
...@@ -172,8 +176,9 @@ asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent *dirent, ...@@ -172,8 +176,9 @@ asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent *dirent,
* Alpha syscall convention has no problem returning negative * Alpha syscall convention has no problem returning negative
* values: * values:
*/ */
asmlinkage int osf_getpriority(int which, int who, int a2, int a3, int a4, asmlinkage int
int a5, struct pt_regs regs) osf_getpriority(int which, int who,
int a2, int a3, int a4, int a5, struct pt_regs regs)
{ {
extern int sys_getpriority(int, int); extern int sys_getpriority(int, int);
int prio; int prio;
...@@ -194,24 +199,24 @@ asmlinkage int osf_getpriority(int which, int who, int a2, int a3, int a4, ...@@ -194,24 +199,24 @@ asmlinkage int osf_getpriority(int which, int who, int a2, int a3, int a4,
/* /*
* No need to acquire the kernel lock, we're local.. * 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, asmlinkage unsigned long
int a5, struct pt_regs regs) sys_getxuid(int a0, int a1, int a2, int a3, int a4, int a5, struct pt_regs regs)
{ {
struct task_struct * tsk = current; struct task_struct * tsk = current;
(&regs)->r20 = tsk->euid; (&regs)->r20 = tsk->euid;
return tsk->uid; return tsk->uid;
} }
asmlinkage unsigned long sys_getxgid(int a0, int a1, int a2, int a3, int a4, asmlinkage unsigned long
int a5, struct pt_regs regs) sys_getxgid(int a0, int a1, int a2, int a3, int a4, int a5, struct pt_regs regs)
{ {
struct task_struct * tsk = current; struct task_struct * tsk = current;
(&regs)->r20 = tsk->egid; (&regs)->r20 = tsk->egid;
return tsk->gid; return tsk->gid;
} }
asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4, asmlinkage unsigned long
int a5, struct pt_regs regs) sys_getxpid(int a0, int a1, int a2, int a3, int a4, int a5, struct pt_regs regs)
{ {
struct task_struct *tsk = current; struct task_struct *tsk = current;
...@@ -226,9 +231,9 @@ asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4, ...@@ -226,9 +231,9 @@ asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4,
return tsk->tgid; return tsk->tgid;
} }
asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len, asmlinkage unsigned long
unsigned long prot, unsigned long flags, unsigned long fd, osf_mmap(unsigned long addr, unsigned long len, unsigned long prot,
unsigned long off) unsigned long flags, unsigned long fd, unsigned long off)
{ {
struct file *file = NULL; struct file *file = NULL;
unsigned long ret = -EBADF; unsigned long ret = -EBADF;
...@@ -249,7 +254,7 @@ asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len, ...@@ -249,7 +254,7 @@ asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len,
up_write(&current->mm->mmap_sem); up_write(&current->mm->mmap_sem);
if (file) if (file)
fput(file); fput(file);
out: out:
return ret; return ret;
} }
...@@ -271,7 +276,9 @@ struct osf_statfs { ...@@ -271,7 +276,9 @@ struct osf_statfs {
__kernel_fsid_t f_fsid; __kernel_fsid_t f_fsid;
} *osf_stat; } *osf_stat;
static int linux_to_osf_statfs(struct statfs *linux_stat, struct osf_statfs *osf_stat, unsigned long bufsiz) static int
linux_to_osf_statfs(struct statfs *linux_stat, struct osf_statfs *osf_stat,
unsigned long bufsiz)
{ {
struct osf_statfs tmp_stat; struct osf_statfs tmp_stat;
...@@ -291,7 +298,9 @@ static int linux_to_osf_statfs(struct statfs *linux_stat, struct osf_statfs *osf ...@@ -291,7 +298,9 @@ static int linux_to_osf_statfs(struct statfs *linux_stat, struct osf_statfs *osf
return copy_to_user(osf_stat, &tmp_stat, bufsiz) ? -EFAULT : 0; return copy_to_user(osf_stat, &tmp_stat, bufsiz) ? -EFAULT : 0;
} }
static int do_osf_statfs(struct dentry * dentry, struct osf_statfs *buffer, unsigned long bufsiz) static int
do_osf_statfs(struct dentry * dentry, struct osf_statfs *buffer,
unsigned long bufsiz)
{ {
struct statfs linux_stat; struct statfs linux_stat;
int error = vfs_statfs(dentry->d_inode->i_sb, &linux_stat); int error = vfs_statfs(dentry->d_inode->i_sb, &linux_stat);
...@@ -300,7 +309,8 @@ static int do_osf_statfs(struct dentry * dentry, struct osf_statfs *buffer, unsi ...@@ -300,7 +309,8 @@ static int do_osf_statfs(struct dentry * dentry, struct osf_statfs *buffer, unsi
return error; return error;
} }
asmlinkage int osf_statfs(char *path, struct osf_statfs *buffer, unsigned long bufsiz) asmlinkage int
osf_statfs(char *path, struct osf_statfs *buffer, unsigned long bufsiz)
{ {
struct nameidata nd; struct nameidata nd;
int retval; int retval;
...@@ -313,7 +323,8 @@ asmlinkage int osf_statfs(char *path, struct osf_statfs *buffer, unsigned long b ...@@ -313,7 +323,8 @@ asmlinkage int osf_statfs(char *path, struct osf_statfs *buffer, unsigned long b
return retval; return retval;
} }
asmlinkage int osf_fstatfs(unsigned long fd, struct osf_statfs *buffer, unsigned long bufsiz) asmlinkage int
osf_fstatfs(unsigned long fd, struct osf_statfs *buffer, unsigned long bufsiz)
{ {
struct file *file; struct file *file;
int retval; int retval;
...@@ -342,10 +353,9 @@ struct cdfs_args { ...@@ -342,10 +353,9 @@ struct cdfs_args {
char *devname; char *devname;
int flags; int flags;
uid_t exroot; uid_t exroot;
/*
* This has lots more here, which Linux handles with the option block /* This has lots more here, which Linux handles with the option block
* but I'm too lazy to do the translation into ASCII. but I'm too lazy to do the translation into ASCII. */
*/
}; };
struct procfs_args { struct procfs_args {
...@@ -362,7 +372,8 @@ struct procfs_args { ...@@ -362,7 +372,8 @@ struct procfs_args {
* Just how long ago was it written? OTOH our UFS driver may be still * Just how long ago was it written? OTOH our UFS driver may be still
* unhappy with OSF UFS. [CHECKME] * unhappy with OSF UFS. [CHECKME]
*/ */
static int osf_ufs_mount(char *dirname, struct ufs_args *args, int flags) static int
osf_ufs_mount(char *dirname, struct ufs_args *args, int flags)
{ {
int retval; int retval;
struct cdfs_args tmp; struct cdfs_args tmp;
...@@ -377,11 +388,12 @@ static int osf_ufs_mount(char *dirname, struct ufs_args *args, int flags) ...@@ -377,11 +388,12 @@ static int osf_ufs_mount(char *dirname, struct ufs_args *args, int flags)
goto out; goto out;
retval = do_mount(devname, dirname, "ext2", flags, NULL); retval = do_mount(devname, dirname, "ext2", flags, NULL);
putname(devname); putname(devname);
out: out:
return retval; return retval;
} }
static int osf_cdfs_mount(char *dirname, struct cdfs_args *args, int flags) static int
osf_cdfs_mount(char *dirname, struct cdfs_args *args, int flags)
{ {
int retval; int retval;
struct cdfs_args tmp; struct cdfs_args tmp;
...@@ -396,11 +408,12 @@ static int osf_cdfs_mount(char *dirname, struct cdfs_args *args, int flags) ...@@ -396,11 +408,12 @@ static int osf_cdfs_mount(char *dirname, struct cdfs_args *args, int flags)
goto out; goto out;
retval = do_mount(devname, dirname, "iso9660", flags, NULL); retval = do_mount(devname, dirname, "iso9660", flags, NULL);
putname(devname); putname(devname);
out: out:
return retval; return retval;
} }
static int osf_procfs_mount(char *dirname, struct procfs_args *args, int flags) static int
osf_procfs_mount(char *dirname, struct procfs_args *args, int flags)
{ {
struct procfs_args tmp; struct procfs_args tmp;
...@@ -410,7 +423,8 @@ static int osf_procfs_mount(char *dirname, struct procfs_args *args, int flags) ...@@ -410,7 +423,8 @@ static int osf_procfs_mount(char *dirname, struct procfs_args *args, int flags)
return do_mount("", dirname, "proc", flags, NULL); return do_mount("", dirname, "proc", flags, NULL);
} }
asmlinkage int osf_mount(unsigned long typenr, char *path, int flag, void *data) asmlinkage int
osf_mount(unsigned long typenr, char *path, int flag, void *data)
{ {
int retval = -EINVAL; int retval = -EINVAL;
char *name; char *name;
...@@ -435,12 +449,13 @@ asmlinkage int osf_mount(unsigned long typenr, char *path, int flag, void *data) ...@@ -435,12 +449,13 @@ asmlinkage int osf_mount(unsigned long typenr, char *path, int flag, void *data)
printk("osf_mount(%ld, %x)\n", typenr, flag); printk("osf_mount(%ld, %x)\n", typenr, flag);
} }
putname(name); putname(name);
out: out:
unlock_kernel(); unlock_kernel();
return retval; return retval;
} }
asmlinkage int osf_utsname(char *name) asmlinkage int
osf_utsname(char *name)
{ {
int error; int error;
...@@ -458,12 +473,13 @@ asmlinkage int osf_utsname(char *name) ...@@ -458,12 +473,13 @@ asmlinkage int osf_utsname(char *name)
goto out; goto out;
error = 0; error = 0;
out: out:
up_read(&uts_sem); up_read(&uts_sem);
return error; return error;
} }
asmlinkage int osf_swapon(const char *path, int flags, int lowat, int hiwat) asmlinkage int
osf_swapon(const char *path, int flags, int lowat, int hiwat)
{ {
int ret; int ret;
...@@ -474,35 +490,36 @@ asmlinkage int osf_swapon(const char *path, int flags, int lowat, int hiwat) ...@@ -474,35 +490,36 @@ asmlinkage int osf_swapon(const char *path, int flags, int lowat, int hiwat)
return ret; return ret;
} }
asmlinkage unsigned long sys_getpagesize(void) asmlinkage unsigned long
sys_getpagesize(void)
{ {
return PAGE_SIZE; return PAGE_SIZE;
} }
asmlinkage unsigned long sys_getdtablesize(void) asmlinkage unsigned long
sys_getdtablesize(void)
{ {
return NR_OPEN; return NR_OPEN;
} }
asmlinkage int sys_pipe(int a0, int a1, int a2, int a3, int a4, int a5, asmlinkage int
struct pt_regs regs) sys_pipe(int a0, int a1, int a2, int a3, int a4, int a5, struct pt_regs regs)
{ {
int fd[2]; int fd[2], error;
int error;
error = do_pipe(fd); error = do_pipe(fd);
if (error) if (!error) {
goto out; regs.r20 = fd[1];
(&regs)->r20 = fd[1]; error = fd[0];
error = fd[0]; }
out:
return error; return error;
} }
/* /*
* For compatibility with OSF/1 only. Use utsname(2) instead. * For compatibility with OSF/1 only. Use utsname(2) instead.
*/ */
asmlinkage int osf_getdomainname(char *name, int namelen) asmlinkage int
osf_getdomainname(char *name, int namelen)
{ {
unsigned len; unsigned len;
int i, error; int i, error;
...@@ -522,12 +539,12 @@ asmlinkage int osf_getdomainname(char *name, int namelen) ...@@ -522,12 +539,12 @@ asmlinkage int osf_getdomainname(char *name, int namelen)
break; break;
} }
up_read(&uts_sem); up_read(&uts_sem);
out: out:
return error; return error;
} }
asmlinkage long
asmlinkage long osf_shmat(int shmid, void *shmaddr, int shmflg) osf_shmat(int shmid, void *shmaddr, int shmflg)
{ {
unsigned long raddr; unsigned long raddr;
long err; long err;
...@@ -541,7 +558,7 @@ asmlinkage long osf_shmat(int shmid, void *shmaddr, int shmflg) ...@@ -541,7 +558,7 @@ asmlinkage long osf_shmat(int shmid, void *shmaddr, int shmflg)
* non-negative longs! * non-negative longs!
*/ */
err = raddr; err = raddr;
out: out:
unlock_kernel(); unlock_kernel();
return err; return err;
} }
...@@ -612,7 +629,8 @@ enum pl_code { ...@@ -612,7 +629,8 @@ enum pl_code {
PL_DEL = 5, PL_FDEL = 6 PL_DEL = 5, PL_FDEL = 6
}; };
asmlinkage long osf_proplist_syscall(enum pl_code code, union pl_args *args) asmlinkage long
osf_proplist_syscall(enum pl_code code, union pl_args *args)
{ {
long error; long error;
int *min_buf_size_ptr; int *min_buf_size_ptr;
...@@ -655,7 +673,8 @@ asmlinkage long osf_proplist_syscall(enum pl_code code, union pl_args *args) ...@@ -655,7 +673,8 @@ asmlinkage long osf_proplist_syscall(enum pl_code code, union pl_args *args)
return error; return error;
} }
asmlinkage int osf_sigstack(struct sigstack *uss, struct sigstack *uoss) asmlinkage int
osf_sigstack(struct sigstack *uss, struct sigstack *uoss)
{ {
unsigned long usp = rdusp(); unsigned long usp = rdusp();
unsigned long oss_sp = current->sas_ss_sp + current->sas_ss_size; unsigned long oss_sp = current->sas_ss_sp + current->sas_ss_size;
...@@ -691,7 +710,7 @@ asmlinkage int osf_sigstack(struct sigstack *uss, struct sigstack *uoss) ...@@ -691,7 +710,7 @@ asmlinkage int osf_sigstack(struct sigstack *uss, struct sigstack *uoss)
} }
error = 0; error = 0;
out: out:
return error; return error;
} }
...@@ -702,32 +721,28 @@ asmlinkage int osf_sigstack(struct sigstack *uss, struct sigstack *uoss) ...@@ -702,32 +721,28 @@ asmlinkage int osf_sigstack(struct sigstack *uss, struct sigstack *uoss)
* create_module() because it's one of the few system calls * create_module() because it's one of the few system calls
* that return kernel addresses (which are negative). * that return kernel addresses (which are negative).
*/ */
asmlinkage unsigned long alpha_create_module(char *module_name, unsigned long size,
int a3, int a4, int a5, int a6, asmlinkage unsigned long
struct pt_regs regs) alpha_create_module(char *module_name, unsigned long size,
int a3, int a4, int a5, int a6, struct pt_regs regs)
{ {
asmlinkage unsigned long sys_create_module(char *, unsigned long);
long retval; long retval;
lock_kernel(); lock_kernel();
retval = sys_create_module(module_name, size); retval = sys_create_module(module_name, size);
/*
* we get either a module address or an error number,
* and we know the error number is a small negative
* number, while the address is always negative but
* much larger.
*/
if (retval + 1000 > 0)
goto out;
/* tell entry.S:syscall_error that this is NOT an error: */ /* We get either a module address or an error number, and we know
regs.r0 = 0; the error number is a small negative number, while the address
out: is always negative but much larger. */
unlock_kernel(); if (retval + 1000 < 0)
regs.r0 = 0;
unlock_kernel();
return retval; return retval;
} }
asmlinkage long osf_sysinfo(int command, char *buf, long count) asmlinkage long
osf_sysinfo(int command, char *buf, long count)
{ {
static char * sysinfo_table[] = { static char * sysinfo_table[] = {
system_utsname.sysname, system_utsname.sysname,
...@@ -761,13 +776,13 @@ asmlinkage long osf_sysinfo(int command, char *buf, long count) ...@@ -761,13 +776,13 @@ asmlinkage long osf_sysinfo(int command, char *buf, long count)
else else
err = 0; err = 0;
up_read(&uts_sem); up_read(&uts_sem);
out: out:
return err; return err;
} }
asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer, asmlinkage unsigned long
unsigned long nbytes, osf_getsysinfo(unsigned long op, void *buffer, unsigned long nbytes,
int *start, void *arg) int *start, void *arg)
{ {
unsigned long w; unsigned long w;
struct percpu_struct *cpu; struct percpu_struct *cpu;
...@@ -823,9 +838,9 @@ asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer, ...@@ -823,9 +838,9 @@ asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer, asmlinkage unsigned long
unsigned long nbytes, osf_setsysinfo(unsigned long op, void *buffer, unsigned long nbytes,
int *start, void *arg) int *start, void *arg)
{ {
switch (op) { switch (op) {
case SSI_IEEE_FP_CONTROL: { case SSI_IEEE_FP_CONTROL: {
...@@ -925,21 +940,24 @@ struct itimerval32 ...@@ -925,21 +940,24 @@ struct itimerval32
struct timeval32 it_value; struct timeval32 it_value;
}; };
static inline long get_tv32(struct timeval *o, struct timeval32 *i) static inline long
get_tv32(struct timeval *o, struct timeval32 *i)
{ {
return (!access_ok(VERIFY_READ, i, sizeof(*i)) || return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
(__get_user(o->tv_sec, &i->tv_sec) | (__get_user(o->tv_sec, &i->tv_sec) |
__get_user(o->tv_usec, &i->tv_usec))); __get_user(o->tv_usec, &i->tv_usec)));
} }
static inline long put_tv32(struct timeval32 *o, struct timeval *i) static inline long
put_tv32(struct timeval32 *o, struct timeval *i)
{ {
return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
(__put_user(i->tv_sec, &o->tv_sec) | (__put_user(i->tv_sec, &o->tv_sec) |
__put_user(i->tv_usec, &o->tv_usec))); __put_user(i->tv_usec, &o->tv_usec)));
} }
static inline long get_it32(struct itimerval *o, struct itimerval32 *i) static inline long
get_it32(struct itimerval *o, struct itimerval32 *i)
{ {
return (!access_ok(VERIFY_READ, i, sizeof(*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_sec, &i->it_interval.tv_sec) |
...@@ -948,7 +966,8 @@ static inline long get_it32(struct itimerval *o, struct itimerval32 *i) ...@@ -948,7 +966,8 @@ static inline long get_it32(struct itimerval *o, struct itimerval32 *i)
__get_user(o->it_value.tv_usec, &i->it_value.tv_usec))); __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
} }
static inline long put_it32(struct itimerval32 *o, struct itimerval *i) static inline long
put_it32(struct itimerval32 *o, struct itimerval *i)
{ {
return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
(__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) | (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
...@@ -964,7 +983,8 @@ jiffies_to_timeval32(unsigned long jiffies, struct timeval32 *value) ...@@ -964,7 +983,8 @@ jiffies_to_timeval32(unsigned long jiffies, struct timeval32 *value)
value->tv_sec = jiffies / HZ; value->tv_sec = jiffies / HZ;
} }
asmlinkage int osf_gettimeofday(struct timeval32 *tv, struct timezone *tz) asmlinkage int
osf_gettimeofday(struct timeval32 *tv, struct timezone *tz)
{ {
if (tv) { if (tv) {
struct timeval ktv; struct timeval ktv;
...@@ -979,7 +999,8 @@ asmlinkage int osf_gettimeofday(struct timeval32 *tv, struct timezone *tz) ...@@ -979,7 +999,8 @@ asmlinkage int osf_gettimeofday(struct timeval32 *tv, struct timezone *tz)
return 0; return 0;
} }
asmlinkage int osf_settimeofday(struct timeval32 *tv, struct timezone *tz) asmlinkage int
osf_settimeofday(struct timeval32 *tv, struct timezone *tz)
{ {
struct timeval ktv; struct timeval ktv;
struct timezone ktz; struct timezone ktz;
...@@ -996,7 +1017,8 @@ asmlinkage int osf_settimeofday(struct timeval32 *tv, struct timezone *tz) ...@@ -996,7 +1017,8 @@ asmlinkage int osf_settimeofday(struct timeval32 *tv, struct timezone *tz)
return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL); return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
} }
asmlinkage int osf_getitimer(int which, struct itimerval32 *it) asmlinkage int
osf_getitimer(int which, struct itimerval32 *it)
{ {
struct itimerval kit; struct itimerval kit;
int error; int error;
...@@ -1008,8 +1030,8 @@ asmlinkage int osf_getitimer(int which, struct itimerval32 *it) ...@@ -1008,8 +1030,8 @@ asmlinkage int osf_getitimer(int which, struct itimerval32 *it)
return error; return error;
} }
asmlinkage int osf_setitimer(int which, struct itimerval32 *in, asmlinkage int
struct itimerval32 *out) osf_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out)
{ {
struct itimerval kin, kout; struct itimerval kin, kout;
int error; int error;
...@@ -1031,7 +1053,8 @@ asmlinkage int osf_setitimer(int which, struct itimerval32 *in, ...@@ -1031,7 +1053,8 @@ asmlinkage int osf_setitimer(int which, struct itimerval32 *in,
} }
asmlinkage int osf_utimes(const char *filename, struct timeval32 *tvs) asmlinkage int
osf_utimes(const char *filename, struct timeval32 *tvs)
{ {
char *kfilename; char *kfilename;
struct timeval ktvs[2]; struct timeval ktvs[2];
...@@ -1136,9 +1159,9 @@ osf_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, ...@@ -1136,9 +1159,9 @@ osf_select(int n, fd_set *inp, fd_set *outp, fd_set *exp,
set_fd_set(n, outp->fds_bits, fds.res_out); set_fd_set(n, outp->fds_bits, fds.res_out);
set_fd_set(n, exp->fds_bits, fds.res_ex); set_fd_set(n, exp->fds_bits, fds.res_ex);
out: out:
kfree(bits); kfree(bits);
out_nofds: out_nofds:
return ret; return ret;
} }
...@@ -1161,7 +1184,8 @@ struct rusage32 { ...@@ -1161,7 +1184,8 @@ struct rusage32 {
long ru_nivcsw; /* involuntary " */ long ru_nivcsw; /* involuntary " */
}; };
asmlinkage int osf_getrusage(int who, struct rusage32 *ru) asmlinkage int
osf_getrusage(int who, struct rusage32 *ru)
{ {
struct rusage32 r; struct rusage32 r;
...@@ -1198,8 +1222,8 @@ asmlinkage int osf_getrusage(int who, struct rusage32 *ru) ...@@ -1198,8 +1222,8 @@ asmlinkage int osf_getrusage(int who, struct rusage32 *ru)
return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0; return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
} }
asmlinkage int osf_wait4(pid_t pid, int *ustatus, int options, asmlinkage int
struct rusage32 *ur) osf_wait4(pid_t pid, int *ustatus, int options, struct rusage32 *ur)
{ {
if (!ur) { if (!ur) {
return sys_wait4(pid, ustatus, options, NULL); return sys_wait4(pid, ustatus, options, NULL);
...@@ -1245,7 +1269,8 @@ asmlinkage int osf_wait4(pid_t pid, int *ustatus, int options, ...@@ -1245,7 +1269,8 @@ asmlinkage int osf_wait4(pid_t pid, int *ustatus, int options,
* seems to be a timeval pointer, and I suspect the second * seems to be a timeval pointer, and I suspect the second
* one is the time remaining.. Ho humm.. No documentation. * one is the time remaining.. Ho humm.. No documentation.
*/ */
asmlinkage int osf_usleep_thread(struct timeval32 *sleep, struct timeval32 *remain) asmlinkage int
osf_usleep_thread(struct timeval32 *sleep, struct timeval32 *remain)
{ {
struct timeval tmp; struct timeval tmp;
unsigned long ticks; unsigned long ticks;
...@@ -1268,7 +1293,7 @@ asmlinkage int osf_usleep_thread(struct timeval32 *sleep, struct timeval32 *rema ...@@ -1268,7 +1293,7 @@ asmlinkage int osf_usleep_thread(struct timeval32 *sleep, struct timeval32 *rema
} }
return 0; return 0;
fault: fault:
return -EFAULT; return -EFAULT;
} }
...@@ -1302,7 +1327,8 @@ struct timex32 { ...@@ -1302,7 +1327,8 @@ struct timex32 {
int :32; int :32; int :32; int :32; int :32; int :32; int :32; int :32;
}; };
asmlinkage int sys_old_adjtimex(struct timex32 *txc_p) asmlinkage int
sys_old_adjtimex(struct timex32 *txc_p)
{ {
struct timex txc; struct timex txc;
int ret; int ret;
......
...@@ -191,26 +191,13 @@ machine_power_off(void) ...@@ -191,26 +191,13 @@ machine_power_off(void)
common_shutdown(LINUX_REBOOT_CMD_POWER_OFF, NULL); common_shutdown(LINUX_REBOOT_CMD_POWER_OFF, NULL);
} }
/* Used by sysrq-p, among others. I don't believe r9-r15 are ever
saved in the context it's used. */
void void
show_regs(struct pt_regs * regs) show_regs(struct pt_regs *regs)
{ {
printk("\n"); dik_show_regs(regs, 0);
printk("Pid: %d, comm: %20s\n", current->pid, current->comm);
printk("ps: %04lx pc: [<%016lx>] CPU %d %s\n",
regs->ps, regs->pc, smp_processor_id(), print_tainted());
printk("rp: [<%016lx>] sp: %p\n", regs->r26, regs+1);
printk(" r0: %016lx r1: %016lx r2: %016lx r3: %016lx\n",
regs->r0, regs->r1, regs->r2, regs->r3);
printk(" r4: %016lx r5: %016lx r6: %016lx r7: %016lx\n",
regs->r4, regs->r5, regs->r6, regs->r7);
printk(" r8: %016lx r16: %016lx r17: %016lx r18: %016lx\n",
regs->r8, regs->r16, regs->r17, regs->r18);
printk("r19: %016lx r20: %016lx r21: %016lx r22: %016lx\n",
regs->r19, regs->r20, regs->r21, regs->r22);
printk("r23: %016lx r24: %016lx r25: %016lx r26: %016lx\n",
regs->r23, regs->r24, regs->r25, regs->r26);
printk("r27: %016lx r28: %016lx r29: %016lx hae: %016lx\n",
regs->r27, regs->r28, regs->gp, regs->hae);
} }
/* /*
......
...@@ -37,6 +37,11 @@ ...@@ -37,6 +37,11 @@
#include <linux/blk.h> #include <linux/blk.h>
#endif #endif
#ifdef CONFIG_MAGIC_SYSRQ
#include <linux/sysrq.h>
#include <linux/reboot.h>
#endif
#include <linux/notifier.h> #include <linux/notifier.h>
extern struct notifier_block *panic_notifier_list; extern struct notifier_block *panic_notifier_list;
static int alpha_panic_event(struct notifier_block *, unsigned long, void *); static int alpha_panic_event(struct notifier_block *, unsigned long, void *);
...@@ -539,6 +544,15 @@ setup_arch(char **cmdline_p) ...@@ -539,6 +544,15 @@ setup_arch(char **cmdline_p)
register_srm_console(); register_srm_console();
} }
#ifdef CONFIG_MAGIC_SYSRQ
/* If we're using SRM, make sysrq-b halt back to the prom,
not auto-reboot. */
if (alpha_using_srm) {
struct sysrq_key_op *op = __sysrq_get_key_op('b');
op->handler = (void *) machine_halt;
}
#endif
/* /*
* Indentify and reconfigure for the current system. * Indentify and reconfigure for the current system.
*/ */
......
/*
* arch/alpha/kernel/systbls.S
*
* The system call table.
*/
#include <asm/unistd.h>
.data
.align 3
.globl sys_call_table
sys_call_table:
.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 sys_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 sys_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 sys_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 /* 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 osf_sigstack
.quad sys_recvmsg
.quad sys_sendmsg
.quad alpha_ni_syscall /* 115 */
.quad osf_gettimeofday
.quad osf_getrusage
.quad sys_getsockopt
.quad alpha_ni_syscall
#ifdef CONFIG_OSF4_COMPAT
.quad osf_readv /* 120 */
.quad osf_writev
#else
.quad sys_readv /* 120 */
.quad sys_writev
#endif
.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 sys_lchown
.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 sys_sigaltstack /* 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 */
.quad sys_bdflush /* 300 */
.quad sys_sethae
.quad sys_mount
.quad sys_old_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_ni_syscall /* 320 */
.quad sys_oldumount
.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 sys_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_pread64
.quad sys_pwrite64 /* 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 sys_select
.quad sys_gettimeofday
.quad sys_settimeofday /* 360 */
.quad sys_getitimer
.quad sys_setitimer
.quad sys_utimes
.quad sys_getrusage
.quad sys_wait4 /* 365 */
.quad sys_adjtimex
.quad sys_getcwd
.quad sys_capget
.quad sys_capset
.quad sys_sendfile /* 370 */
.quad sys_setresgid
.quad sys_getresgid
.quad sys_ni_syscall /* sys_dipc */
.quad sys_pivot_root
.quad sys_mincore /* 375 */
.quad sys_pciconfig_iobase
.quad sys_getdents64
.quad sys_gettid
.quad sys_readahead
.quad sys_ni_syscall /* 380, sys_security */
.quad sys_tkill
.quad sys_setxattr
.quad sys_lsetxattr
.quad sys_fsetxattr
.quad sys_getxattr /* 385 */
.quad sys_lgetxattr
.quad sys_fgetxattr
.quad sys_listxattr
.quad sys_llistxattr
.quad sys_flistxattr /* 390 */
.quad sys_removexattr
.quad sys_lremovexattr
.quad sys_fremovexattr
.quad sys_futex
.quad sys_sched_setaffinity /* 395 */
.quad sys_sched_getaffinity
.quad sys_ni_syscall /* 397, tux */
.quad sys_io_setup
.quad sys_io_destroy
.quad sys_io_getevents /* 400 */
.quad sys_io_submit
.quad sys_io_cancel
.quad sys_ni_syscall /* 403, sys_alloc_hugepages */
.quad sys_ni_syscall /* 404, sys_free_hugepages */
.quad sys_exit_group
.size sys_call_table, . - sys_call_table
.type sys_call_table, @object
/* Remember to update everything, kids. */
.ifne (. - sys_call_table) - (NR_SYSCALLS * 8)
.err
.endif
...@@ -51,14 +51,16 @@ obj-$(CONFIG_SMP) += dec_and_lock.o ...@@ -51,14 +51,16 @@ obj-$(CONFIG_SMP) += dec_and_lock.o
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
__divqu.o: $(ev6)divide.S $(obj)/__divqu.o: $(obj)/$(ev6)divide.S
$(CC) $(AFLAGS) -DDIV -c -o __divqu.o $(ev6)divide.S $(CC) $(AFLAGS) -DDIV -c -o $(obj)/__divqu.o $(obj)/$(ev6)divide.S
__remqu.o: $(ev6)divide.S $(obj)/__remqu.o: $(obj)/$(ev6)divide.S
$(CC) $(AFLAGS) -DREM -c -o __remqu.o $(ev6)divide.S $(CC) $(AFLAGS) -DREM -c -o $(obj)/__remqu.o $(obj)/$(ev6)divide.S
__divlu.o: $(ev6)divide.S $(obj)/__divlu.o: $(obj)/$(ev6)divide.S
$(CC) $(AFLAGS) -DDIV -DINTSIZE -c -o __divlu.o $(ev6)divide.S $(CC) $(AFLAGS) -DDIV -DINTSIZE \
-c -o $(obj)/__divlu.o $(obj)/$(ev6)divide.S
__remlu.o: $(ev6)divide.S $(obj)/__remlu.o: $(obj)/$(ev6)divide.S
$(CC) $(AFLAGS) -DREM -DINTSIZE -c -o __remlu.o $(ev6)divide.S $(CC) $(AFLAGS) -DREM -DINTSIZE \
-c -o $(obj)/__remlu.o $(obj)/$(ev6)divide.S
...@@ -278,7 +278,7 @@ $u_eoc: ...@@ -278,7 +278,7 @@ $u_eoc:
extqh t2, a1, t0 # e0 : extract low bits for last word extqh t2, a1, t0 # e0 : extract low bits for last word
or t1, t0, t1 # e1 : or t1, t0, t1 # e1 :
1: cmpbge zero, t1, t7 1: cmpbge zero, t1, t8
mov t1, t0 mov t1, t0
$u_eocfin: # end-of-count, final word $u_eocfin: # end-of-count, final word
......
...@@ -125,11 +125,10 @@ do_page_fault(unsigned long address, unsigned long mmcsr, ...@@ -125,11 +125,10 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
goto bad_area; goto bad_area;
if (expand_stack(vma, address)) if (expand_stack(vma, address))
goto bad_area; goto bad_area;
/*
* Ok, we have a good vm_area for this memory access, so /* Ok, we have a good vm_area for this memory access, so
* we can handle it.. we can handle it. */
*/ good_area:
good_area:
if (cause < 0) { if (cause < 0) {
if (!(vma->vm_flags & VM_EXEC)) if (!(vma->vm_flags & VM_EXEC))
goto bad_area; goto bad_area;
...@@ -143,11 +142,9 @@ do_page_fault(unsigned long address, unsigned long mmcsr, ...@@ -143,11 +142,9 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
} }
survive: survive:
/* /* If for any reason at all we couldn't handle the fault,
* If for any reason at all we couldn't handle the fault, make sure we exit gracefully rather than endlessly redo
* make sure we exit gracefully rather than endlessly redo the fault. */
* the fault.
*/
fault = handle_mm_fault(mm, vma, address, cause > 0); fault = handle_mm_fault(mm, vma, address, cause > 0);
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
...@@ -155,14 +152,11 @@ do_page_fault(unsigned long address, unsigned long mmcsr, ...@@ -155,14 +152,11 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
goto out_of_memory; goto out_of_memory;
if (fault == 0) if (fault == 0)
goto do_sigbus; goto do_sigbus;
return; return;
/* /* Something tried to access memory that isn't in our memory map.
* Something tried to access memory that isn't in our memory map.. Fix it, but check if it's kernel or user first. */
* Fix it, but check if it's kernel or user first.. bad_area:
*/
bad_area:
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
if (user_mode(regs)) { if (user_mode(regs)) {
...@@ -170,7 +164,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr, ...@@ -170,7 +164,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
return; return;
} }
no_context: no_context:
/* Are we prepared to handle this fault as an exception? */ /* Are we prepared to handle this fault as an exception? */
if ((fixup = search_exception_table(regs->pc, regs->gp)) != 0) { if ((fixup = search_exception_table(regs->pc, regs->gp)) != 0) {
unsigned long newpc; unsigned long newpc;
...@@ -183,20 +177,16 @@ do_page_fault(unsigned long address, unsigned long mmcsr, ...@@ -183,20 +177,16 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
return; return;
} }
/* /* Oops. The kernel tried to access some bad page. We'll have to
* Oops. The kernel tried to access some bad page. We'll have to terminate things with extreme prejudice. */
* terminate things with extreme prejudice.
*/
printk(KERN_ALERT "Unable to handle kernel paging request at " printk(KERN_ALERT "Unable to handle kernel paging request at "
"virtual address %016lx\n", address); "virtual address %016lx\n", address);
die_if_kernel("Oops", regs, cause, (unsigned long*)regs - 16); die_if_kernel("Oops", regs, cause, (unsigned long*)regs - 16);
do_exit(SIGKILL); do_exit(SIGKILL);
/* /* We ran out of memory, or some other thing happened to us that
* We ran out of memory, or some other thing happened to us that made made us unable to handle the page fault gracefully. */
* us unable to handle the page fault gracefully. out_of_memory:
*/
out_of_memory:
if (current->pid == 1) { if (current->pid == 1) {
yield(); yield();
down_read(&mm->mmap_sem); down_read(&mm->mmap_sem);
...@@ -208,18 +198,16 @@ do_page_fault(unsigned long address, unsigned long mmcsr, ...@@ -208,18 +198,16 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
goto no_context; goto no_context;
do_exit(SIGKILL); do_exit(SIGKILL);
do_sigbus: do_sigbus:
/* /* Send a sigbus, regardless of whether we were in kernel
* Send a sigbus, regardless of whether we were in kernel or user mode. */
* or user mode.
*/
force_sig(SIGBUS, current); force_sig(SIGBUS, current);
if (!user_mode(regs)) if (!user_mode(regs))
goto no_context; goto no_context;
return; return;
#ifdef CONFIG_ALPHA_LARGE_VMALLOC #ifdef CONFIG_ALPHA_LARGE_VMALLOC
vmalloc_fault: vmalloc_fault:
if (user_mode(regs)) { if (user_mode(regs)) {
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
return; return;
......
...@@ -58,10 +58,11 @@ SECTIONS ...@@ -58,10 +58,11 @@ SECTIONS
__initcall_end = .; __initcall_end = .;
} }
. = ALIGN(64); .data.percpu ALIGN(64): {
__per_cpu_start = .; __per_cpu_start = .;
.data.percpu : { *(.data.percpu) } *(.data.percpu)
__per_cpu_end = .; __per_cpu_end = .;
}
/* The initial task and kernel stack */ /* The initial task and kernel stack */
.data.init_thread ALIGN(2*8192) : { .data.init_thread ALIGN(2*8192) : {
......
...@@ -65,6 +65,14 @@ CONFIG_X86_NUMAQ ...@@ -65,6 +65,14 @@ CONFIG_X86_NUMAQ
You will need a new lynxer.elf file to flash your firmware with - send You will need a new lynxer.elf file to flash your firmware with - send
email to Martin.Bligh@us.ibm.com email to Martin.Bligh@us.ibm.com
CONFIG_X86_CYCLONE
This patch used the Cyclone performance counter on IBM x440, x360,
and other Summit based systems for calculating gettimeofday. This
fixes problems resulting from TSC skew found in multi-CEC system.
If you are suffering from time skew using a multi-CEC system, say YES.
Otherwise it is safe to say NO.
CONFIG_X86_UP_IOAPIC CONFIG_X86_UP_IOAPIC
An IO-APIC (I/O Advanced Programmable Interrupt Controller) is an An IO-APIC (I/O Advanced Programmable Interrupt Controller) is an
SMP-capable replacement for PC-style interrupt controllers. Most SMP-capable replacement for PC-style interrupt controllers. Most
......
...@@ -53,7 +53,7 @@ HEAD := arch/i386/kernel/head.o arch/i386/kernel/init_task.o ...@@ -53,7 +53,7 @@ HEAD := arch/i386/kernel/head.o arch/i386/kernel/init_task.o
libs-y += arch/i386/lib/ libs-y += arch/i386/lib/
core-y += arch/i386/kernel/ arch/i386/mm/ \ core-y += arch/i386/kernel/ arch/i386/mm/ \
arch/i386/$(MACHINE)/ arch/i386/$(MACHINE)/ arch/i386/kernel/timers/
drivers-$(CONFIG_MATH_EMULATION) += arch/i386/math-emu/ drivers-$(CONFIG_MATH_EMULATION) += arch/i386/math-emu/
drivers-$(CONFIG_PCI) += arch/i386/pci/ drivers-$(CONFIG_PCI) += arch/i386/pci/
......
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
#include <asm/mpspec.h> #include <asm/mpspec.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/timer.h>
#include <linux/mc146818rtc.h> #include <linux/mc146818rtc.h>
#include <linux/timex.h> #include <linux/timex.h>
...@@ -73,161 +74,15 @@ u64 jiffies_64; ...@@ -73,161 +74,15 @@ u64 jiffies_64;
unsigned long cpu_khz; /* Detected as we calibrate the TSC */ unsigned long cpu_khz; /* Detected as we calibrate the TSC */
/* Number of usecs that the last interrupt was delayed */
static int delay_at_last_interrupt;
static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */
/* Cached *multiplier* to convert TSC counts to microseconds.
* (see the equation below).
* Equal to 2^32 * (1 / (clocks per usec) ).
* Initialized in time_init.
*/
unsigned long fast_gettimeoffset_quotient;
extern rwlock_t xtime_lock; extern rwlock_t xtime_lock;
extern unsigned long wall_jiffies; extern unsigned long wall_jiffies;
spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
static inline unsigned long do_fast_gettimeoffset(void)
{
register unsigned long eax, edx;
/* Read the Time Stamp Counter */
rdtsc(eax,edx);
/* .. relative to previous jiffy (32 bits is enough) */
eax -= last_tsc_low; /* tsc_low delta */
/*
* Time offset = (tsc_low delta) * fast_gettimeoffset_quotient
* = (tsc_low delta) * (usecs_per_clock)
* = (tsc_low delta) * (usecs_per_jiffy / clocks_per_jiffy)
*
* Using a mull instead of a divl saves up to 31 clock cycles
* in the critical path.
*/
__asm__("mull %2"
:"=a" (eax), "=d" (edx)
:"rm" (fast_gettimeoffset_quotient),
"0" (eax));
/* our adjusted time offset in microseconds */
return delay_at_last_interrupt + edx;
}
#define TICK_SIZE (tick_nsec / 1000)
spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED; spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED;
EXPORT_SYMBOL(i8253_lock); EXPORT_SYMBOL(i8253_lock);
#ifndef CONFIG_X86_TSC struct timer_opts* timer;
/* This function must be called with interrupts disabled
* It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs
*
* However, the pc-audio speaker driver changes the divisor so that
* it gets interrupted rather more often - it loads 64 into the
* counter rather than 11932! This has an adverse impact on
* do_gettimeoffset() -- it stops working! What is also not
* good is that the interval that our timer function gets called
* is no longer 10.0002 ms, but 9.9767 ms. To get around this
* would require using a different timing source. Maybe someone
* could use the RTC - I know that this can interrupt at frequencies
* ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix
* it so that at startup, the timer code in sched.c would select
* using either the RTC or the 8253 timer. The decision would be
* based on whether there was any other device around that needed
* to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz,
* and then do some jiggery to have a version of do_timer that
* advanced the clock by 1/1024 s. Every time that reached over 1/100
* of a second, then do all the old code. If the time was kept correct
* then do_gettimeoffset could just return 0 - there is no low order
* divider that can be accessed.
*
* Ideally, you would be able to use the RTC for the speaker driver,
* but it appears that the speaker driver really needs interrupt more
* often than every 120 us or so.
*
* Anyway, this needs more thought.... pjsg (1993-08-28)
*
* If you are really that interested, you should be reading
* comp.protocols.time.ntp!
*/
static unsigned long do_slow_gettimeoffset(void)
{
int count;
static int count_p = LATCH; /* for the first call after boot */
static unsigned long jiffies_p = 0;
/*
* cache volatile jiffies temporarily; we have IRQs turned off.
*/
unsigned long jiffies_t;
/* gets recalled with irq locally disabled */
spin_lock(&i8253_lock);
/* timer count may underflow right here */
outb_p(0x00, 0x43); /* latch the count ASAP */
count = inb_p(0x40); /* read the latched count */
/*
* We do this guaranteed double memory access instead of a _p
* postfix in the previous port access. Wheee, hackady hack
*/
jiffies_t = jiffies;
count |= inb_p(0x40) << 8;
/* VIA686a test code... reset the latch if count > max + 1 */
if (count > LATCH) {
outb_p(0x34, 0x43);
outb_p(LATCH & 0xff, 0x40);
outb(LATCH >> 8, 0x40);
count = LATCH - 1;
}
spin_unlock(&i8253_lock);
/*
* avoiding timer inconsistencies (they are rare, but they happen)...
* there are two kinds of problems that must be avoided here:
* 1. the timer counter underflows
* 2. hardware problem with the timer, not giving us continuous time,
* the counter does small "jumps" upwards on some Pentium systems,
* (see c't 95/10 page 335 for Neptun bug.)
*/
if( jiffies_t == jiffies_p ) {
if( count > count_p ) {
/* the nutcase */
count = do_timer_overflow(count);
}
} else
jiffies_p = jiffies_t;
count_p = count;
count = ((LATCH-1) - count) * TICK_SIZE;
count = (count + LATCH/2) / LATCH;
return count;
}
static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
#else
#define do_gettimeoffset() do_fast_gettimeoffset()
#endif
/* /*
* This version of gettimeofday has microsecond resolution * This version of gettimeofday has microsecond resolution
...@@ -239,7 +94,7 @@ void do_gettimeofday(struct timeval *tv) ...@@ -239,7 +94,7 @@ void do_gettimeofday(struct timeval *tv)
unsigned long usec, sec; unsigned long usec, sec;
read_lock_irqsave(&xtime_lock, flags); read_lock_irqsave(&xtime_lock, flags);
usec = do_gettimeoffset(); usec = timer->get_offset();
{ {
unsigned long lost = jiffies - wall_jiffies; unsigned long lost = jiffies - wall_jiffies;
if (lost) if (lost)
...@@ -267,7 +122,7 @@ void do_settimeofday(struct timeval *tv) ...@@ -267,7 +122,7 @@ void do_settimeofday(struct timeval *tv)
* wall time. Discover what correction gettimeofday() would have * wall time. Discover what correction gettimeofday() would have
* made, and then undo it! * made, and then undo it!
*/ */
tv->tv_usec -= do_gettimeoffset(); tv->tv_usec -= timer->get_offset();
tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ); tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ);
while (tv->tv_usec < 0) { while (tv->tv_usec < 0) {
...@@ -433,34 +288,7 @@ void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -433,34 +288,7 @@ void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/ */
write_lock(&xtime_lock); write_lock(&xtime_lock);
if (use_tsc) timer->mark_offset();
{
/*
* It is important that these two operations happen almost at
* the same time. We do the RDTSC stuff first, since it's
* faster. To avoid any inconsistencies, we need interrupts
* disabled locally.
*/
/*
* Interrupts are just disabled locally since the timer irq
* has the SA_INTERRUPT flag set. -arca
*/
/* read Pentium cycle counter */
rdtscl(last_tsc_low);
spin_lock(&i8253_lock);
outb_p(0x00, 0x43); /* latch the count ASAP */
count = inb_p(0x40); /* read the latched count */
count |= inb(0x40) << 8;
spin_unlock(&i8253_lock);
count = ((LATCH-1) - count) * TICK_SIZE;
delay_at_last_interrupt = (count + LATCH/2) / LATCH;
}
do_timer_interrupt(irq, NULL, regs); do_timer_interrupt(irq, NULL, regs);
...@@ -510,85 +338,7 @@ unsigned long get_cmos_time(void) ...@@ -510,85 +338,7 @@ unsigned long get_cmos_time(void)
return mktime(year, mon, day, hour, min, sec); return mktime(year, mon, day, hour, min, sec);
} }
/* ------ Calibrate the TSC ------- /* XXX this driverfs stuff should probably go elsewhere later -john */
* Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset().
* Too much 64-bit arithmetic here to do this cleanly in C, and for
* accuracy's sake we want to keep the overhead on the CTC speaker (channel 2)
* output busy loop as low as possible. We avoid reading the CTC registers
* directly because of the awkward 8-bit access mechanism of the 82C54
* device.
*/
#define CALIBRATE_LATCH (5 * LATCH)
#define CALIBRATE_TIME (5 * 1000020/HZ)
#ifdef CONFIG_X86_TSC
static unsigned long __init calibrate_tsc(void)
{
/* Set the Gate high, disable speaker */
outb((inb(0x61) & ~0x02) | 0x01, 0x61);
/*
* Now let's take care of CTC channel 2
*
* Set the Gate high, program CTC channel 2 for mode 0,
* (interrupt on terminal count mode), binary count,
* load 5 * LATCH count, (LSB and MSB) to begin countdown.
*/
outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */
outb(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */
outb(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */
{
unsigned long startlow, starthigh;
unsigned long endlow, endhigh;
unsigned long count;
rdtsc(startlow,starthigh);
count = 0;
do {
count++;
} while ((inb(0x61) & 0x20) == 0);
rdtsc(endlow,endhigh);
last_tsc_low = endlow;
/* Error: ECTCNEVERSET */
if (count <= 1)
goto bad_ctc;
/* 64-bit subtract - gcc just messes up with long longs */
__asm__("subl %2,%0\n\t"
"sbbl %3,%1"
:"=a" (endlow), "=d" (endhigh)
:"g" (startlow), "g" (starthigh),
"0" (endlow), "1" (endhigh));
/* Error: ECPUTOOFAST */
if (endhigh)
goto bad_ctc;
/* Error: ECPUTOOSLOW */
if (endlow <= CALIBRATE_TIME)
goto bad_ctc;
__asm__("divl %2"
:"=a" (endlow), "=d" (endhigh)
:"r" (endlow), "0" (0), "1" (CALIBRATE_TIME));
return endlow;
}
/*
* The CTC wasn't reliable: we got a hit on the very first read,
* or the CPU was so fast/slow that the quotient wouldn't fit in
* 32 bits..
*/
bad_ctc:
return 0;
}
#endif /* CONFIG_X86_TSC */
static struct sys_device device_i8253 = { static struct sys_device device_i8253 = {
.name = "rtc", .name = "rtc",
.id = 0, .id = 0,
...@@ -605,119 +355,13 @@ static int time_init_device(void) ...@@ -605,119 +355,13 @@ static int time_init_device(void)
device_initcall(time_init_device); device_initcall(time_init_device);
#ifdef CONFIG_CPU_FREQ
static int
time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{
struct cpufreq_freqs *freq = data;
unsigned int i;
if (!cpu_has_tsc)
return 0;
switch (val) {
case CPUFREQ_PRECHANGE:
if ((freq->old < freq->new) &&
((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == 0))) {
cpu_khz = cpufreq_scale(cpu_khz, freq->old, freq->new);
fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_quotient, freq->new, freq->old);
}
for (i=0; i<NR_CPUS; i++)
if ((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == i))
cpu_data[i].loops_per_jiffy = cpufreq_scale(cpu_data[i].loops_per_jiffy, freq->old, freq->new);
break;
case CPUFREQ_POSTCHANGE:
if ((freq->new < freq->old) &&
((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == 0))) {
cpu_khz = cpufreq_scale(cpu_khz, freq->old, freq->new);
fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_quotient, freq->new, freq->old);
}
for (i=0; i<NR_CPUS; i++)
if ((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == i))
cpu_data[i].loops_per_jiffy = cpufreq_scale(cpu_data[i].loops_per_jiffy, freq->old, freq->new);
break;
}
return 0;
}
static struct notifier_block time_cpufreq_notifier_block = {
notifier_call: time_cpufreq_notifier
};
#endif
void __init time_init(void) void __init time_init(void)
{ {
#ifdef CONFIG_X86_TSC
extern int x86_udelay_tsc;
#endif
xtime.tv_sec = get_cmos_time(); xtime.tv_sec = get_cmos_time();
xtime.tv_nsec = 0; xtime.tv_nsec = 0;
/*
* If we have APM enabled or the CPU clock speed is variable
* (CPU stops clock on HLT or slows clock to save power)
* then the TSC timestamps may diverge by up to 1 jiffy from
* 'real time' but nothing will break.
* The most frequent case is that the CPU is "woken" from a halt
* state by the timer interrupt itself, so we get 0 error. In the
* rare cases where a driver would "wake" the CPU and request a
* timestamp, the maximum error is < 1 jiffy. But timestamps are
* still perfectly ordered.
* Note that the TSC counter will be reset if APM suspends
* to disk; this won't break the kernel, though, 'cuz we're
* smart. See arch/i386/kernel/apm.c.
*/
#ifdef CONFIG_X86_TSC
/*
* Firstly we have to do a CPU check for chips with
* a potentially buggy TSC. At this point we haven't run
* the ident/bugs checks so we must run this hook as it
* may turn off the TSC flag.
*
* NOTE: this doesnt yet handle SMP 486 machines where only
* some CPU's have a TSC. Thats never worked and nobody has
* moaned if you have the only one in the world - you fix it!
*/
dodgy_tsc();
if (cpu_has_tsc) {
unsigned long tsc_quotient = calibrate_tsc();
if (tsc_quotient) {
fast_gettimeoffset_quotient = tsc_quotient;
use_tsc = 1;
/*
* We could be more selective here I suspect
* and just enable this for the next intel chips ?
*/
x86_udelay_tsc = 1;
#ifndef do_gettimeoffset
do_gettimeoffset = do_fast_gettimeoffset;
#endif
/* report CPU clock rate in Hz.
* The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
* clock/second. Our precision is about 100 ppm.
*/
{ unsigned long eax=0, edx=1000;
__asm__("divl %2"
:"=a" (cpu_khz), "=d" (edx)
:"r" (tsc_quotient),
"0" (eax), "1" (edx));
printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000);
}
#ifdef CONFIG_CPU_FREQ
cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
#endif
}
}
#endif /* CONFIG_X86_TSC */
timer = select_timer();
time_init_hook(); time_init_hook();
} }
#
# Makefile for x86 timers
#
obj-y := timer.o
obj-y += timer_tsc.o
obj-y += timer_pit.o
obj-$(CONFIG_X86_CYCLONE) += timer_cyclone.o
include $(TOPDIR)/Rules.make
#include <linux/kernel.h>
#include <asm/timer.h>
/* list of externed timers */
#ifndef CONFIG_X86_TSC
extern struct timer_opts timer_pit;
#endif
extern struct timer_opts timer_tsc;
/* list of timers, ordered by preference */
struct timer_opts* timers[] = {
&timer_tsc
#ifndef CONFIG_X86_TSC
,&timer_pit
#endif
};
#define NR_TIMERS (sizeof(timers)/sizeof(timers[0]))
/* iterates through the list of timers, returning the first
* one that initializes successfully.
*/
struct timer_opts* select_timer(void)
{
int i;
/* find most preferred working timer */
for(i=0; i < NR_TIMERS; i++)
if(timers[i]->init())
return timers[i];
panic("select_timer: Cannot find a suitable timer\n");
return 0;
}
/* Cyclone-timer:
* This code implements timer_ops for the cyclone counter found
* on IBM x440, x360, and other Summit based systems.
*
* Copyright (C) 2002 IBM, John Stultz (johnstul@us.ibm.com)
*/
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/timex.h>
#include <asm/timer.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/fixmap.h>
extern spinlock_t i8253_lock;
/* Number of usecs that the last interrupt was delayed */
static int delay_at_last_interrupt;
#define CYCLONE_CBAR_ADDR 0xFEB00CD0
#define CYCLONE_PMCC_OFFSET 0x51A0
#define CYCLONE_MPMC_OFFSET 0x51D0
#define CYCLONE_MPCS_OFFSET 0x51A8
#define CYCLONE_TIMER_FREQ 100000000
int use_cyclone = 0;
static u32* volatile cyclone_timer; /* Cyclone MPMC0 register */
static u32 last_cyclone_timer;
static void mark_offset_cyclone(void)
{
int count;
spin_lock(&i8253_lock);
/* quickly read the cyclone timer */
if(cyclone_timer)
last_cyclone_timer = cyclone_timer[0];
/* calculate delay_at_last_interrupt */
outb_p(0x00, 0x43); /* latch the count ASAP */
count = inb_p(0x40); /* read the latched count */
count |= inb(0x40) << 8;
spin_unlock(&i8253_lock);
count = ((LATCH-1) - count) * TICK_SIZE;
delay_at_last_interrupt = (count + LATCH/2) / LATCH;
}
static unsigned long get_offset_cyclone(void)
{
u32 offset;
if(!cyclone_timer)
return delay_at_last_interrupt;
/* Read the cyclone timer */
offset = cyclone_timer[0];
/* .. relative to previous jiffy */
offset = offset - last_cyclone_timer;
/* convert cyclone ticks to microseconds */
/* XXX slow, can we speed this up? */
offset = offset/(CYCLONE_TIMER_FREQ/1000000);
/* our adjusted time offset in microseconds */
return delay_at_last_interrupt + offset;
}
static int init_cyclone(void)
{
u32* reg;
u32 base; /* saved cyclone base address */
u32 pageaddr; /* page that contains cyclone_timer register */
u32 offset; /* offset from pageaddr to cyclone_timer register */
int i;
/*make sure we're on a summit box*/
/*XXX need to use proper summit hooks! such as xapic -john*/
if(!use_cyclone) return 0;
printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n");
/* find base address */
pageaddr = (CYCLONE_CBAR_ADDR)&PAGE_MASK;
offset = (CYCLONE_CBAR_ADDR)&(~PAGE_MASK);
set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
if(!reg){
printk(KERN_ERR "Summit chipset: Could not find valid CBAR register.\n");
return 0;
}
base = *reg;
if(!base){
printk(KERN_ERR "Summit chipset: Could not find valid CBAR value.\n");
return 0;
}
/* setup PMCC */
pageaddr = (base + CYCLONE_PMCC_OFFSET)&PAGE_MASK;
offset = (base + CYCLONE_PMCC_OFFSET)&(~PAGE_MASK);
set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
if(!reg){
printk(KERN_ERR "Summit chipset: Could not find valid PMCC register.\n");
return 0;
}
reg[0] = 0x00000001;
/* setup MPCS */
pageaddr = (base + CYCLONE_MPCS_OFFSET)&PAGE_MASK;
offset = (base + CYCLONE_MPCS_OFFSET)&(~PAGE_MASK);
set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
if(!reg){
printk(KERN_ERR "Summit chipset: Could not find valid MPCS register.\n");
return 0;
}
reg[0] = 0x00000001;
/* map in cyclone_timer */
pageaddr = (base + CYCLONE_MPMC_OFFSET)&PAGE_MASK;
offset = (base + CYCLONE_MPMC_OFFSET)&(~PAGE_MASK);
set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
cyclone_timer = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
if(!cyclone_timer){
printk(KERN_ERR "Summit chipset: Could not find valid MPMC register.\n");
return 0;
}
/*quick test to make sure its ticking*/
for(i=0; i<3; i++){
u32 old = cyclone_timer[0];
int stall = 100;
while(stall--) barrier();
if(cyclone_timer[0] == old){
printk(KERN_ERR "Summit chipset: Counter not counting! DISABLED\n");
cyclone_timer = 0;
return 0;
}
}
/* Everything looks good! */
return 1;
}
#if 0 /* XXX future work */
static void delay_cyclone(unsigned long loops)
{
unsigned long bclock, now;
if(!cyclone_timer)
return;
bclock = cyclone_timer[0];
do {
rep_nop();
now = cyclone_timer[0];
} while ((now-bclock) < loops);
}
#endif
/************************************************************/
/* cyclone timer_opts struct */
struct timer_opts timer_cyclone = {
init: init_cyclone,
mark_offset: mark_offset_cyclone,
get_offset: get_offset_cyclone
};
/*
* This code largely moved from arch/i386/kernel/time.c.
* See comments there for proper credits.
*/
#include <linux/spinlock.h>
#include <linux/module.h>
#include <linux/device.h>
#include <asm/timer.h>
#include <asm/io.h>
extern spinlock_t i8259A_lock;
extern spinlock_t i8253_lock;
#include "do_timer.h"
static int init_pit(void)
{
return 1;
}
static void mark_offset_pit(void)
{
/* nothing needed */
}
/* This function must be called with interrupts disabled
* It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs
*
* However, the pc-audio speaker driver changes the divisor so that
* it gets interrupted rather more often - it loads 64 into the
* counter rather than 11932! This has an adverse impact on
* do_gettimeoffset() -- it stops working! What is also not
* good is that the interval that our timer function gets called
* is no longer 10.0002 ms, but 9.9767 ms. To get around this
* would require using a different timing source. Maybe someone
* could use the RTC - I know that this can interrupt at frequencies
* ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix
* it so that at startup, the timer code in sched.c would select
* using either the RTC or the 8253 timer. The decision would be
* based on whether there was any other device around that needed
* to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz,
* and then do some jiggery to have a version of do_timer that
* advanced the clock by 1/1024 s. Every time that reached over 1/100
* of a second, then do all the old code. If the time was kept correct
* then do_gettimeoffset could just return 0 - there is no low order
* divider that can be accessed.
*
* Ideally, you would be able to use the RTC for the speaker driver,
* but it appears that the speaker driver really needs interrupt more
* often than every 120 us or so.
*
* Anyway, this needs more thought.... pjsg (1993-08-28)
*
* If you are really that interested, you should be reading
* comp.protocols.time.ntp!
*/
static unsigned long get_offset_pit(void)
{
int count;
static int count_p = LATCH; /* for the first call after boot */
static unsigned long jiffies_p = 0;
/*
* cache volatile jiffies temporarily; we have IRQs turned off.
*/
unsigned long jiffies_t;
/* gets recalled with irq locally disabled */
spin_lock(&i8253_lock);
/* timer count may underflow right here */
outb_p(0x00, 0x43); /* latch the count ASAP */
count = inb_p(0x40); /* read the latched count */
/*
* We do this guaranteed double memory access instead of a _p
* postfix in the previous port access. Wheee, hackady hack
*/
jiffies_t = jiffies;
count |= inb_p(0x40) << 8;
/* VIA686a test code... reset the latch if count > max + 1 */
if (count > LATCH) {
outb_p(0x34, 0x43);
outb_p(LATCH & 0xff, 0x40);
outb(LATCH >> 8, 0x40);
count = LATCH - 1;
}
spin_unlock(&i8253_lock);
/*
* avoiding timer inconsistencies (they are rare, but they happen)...
* there are two kinds of problems that must be avoided here:
* 1. the timer counter underflows
* 2. hardware problem with the timer, not giving us continuous time,
* the counter does small "jumps" upwards on some Pentium systems,
* (see c't 95/10 page 335 for Neptun bug.)
*/
if( jiffies_t == jiffies_p ) {
if( count > count_p ) {
/* the nutcase */
count = do_timer_overflow(count);
}
} else
jiffies_p = jiffies_t;
count_p = count;
count = ((LATCH-1) - count) * TICK_SIZE;
count = (count + LATCH/2) / LATCH;
return count;
}
/* tsc timer_opts struct */
struct timer_opts timer_pit = {
init: init_pit,
mark_offset: mark_offset_pit,
get_offset: get_offset_pit
};
/*
* This code largely moved from arch/i386/kernel/time.c.
* See comments there for proper credits.
*/
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/timex.h>
#include <asm/timer.h>
#include <asm/io.h>
extern int x86_udelay_tsc;
extern spinlock_t i8253_lock;
static int use_tsc;
/* Number of usecs that the last interrupt was delayed */
static int delay_at_last_interrupt;
static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */
/* Cached *multiplier* to convert TSC counts to microseconds.
* (see the equation below).
* Equal to 2^32 * (1 / (clocks per usec) ).
* Initialized in time_init.
*/
unsigned long fast_gettimeoffset_quotient;
static unsigned long get_offset_tsc(void)
{
register unsigned long eax, edx;
/* Read the Time Stamp Counter */
rdtsc(eax,edx);
/* .. relative to previous jiffy (32 bits is enough) */
eax -= last_tsc_low; /* tsc_low delta */
/*
* Time offset = (tsc_low delta) * fast_gettimeoffset_quotient
* = (tsc_low delta) * (usecs_per_clock)
* = (tsc_low delta) * (usecs_per_jiffy / clocks_per_jiffy)
*
* Using a mull instead of a divl saves up to 31 clock cycles
* in the critical path.
*/
__asm__("mull %2"
:"=a" (eax), "=d" (edx)
:"rm" (fast_gettimeoffset_quotient),
"0" (eax));
/* our adjusted time offset in microseconds */
return delay_at_last_interrupt + edx;
}
static void mark_offset_tsc(void)
{
int count;
/*
* It is important that these two operations happen almost at
* the same time. We do the RDTSC stuff first, since it's
* faster. To avoid any inconsistencies, we need interrupts
* disabled locally.
*/
/*
* Interrupts are just disabled locally since the timer irq
* has the SA_INTERRUPT flag set. -arca
*/
/* read Pentium cycle counter */
rdtscl(last_tsc_low);
spin_lock(&i8253_lock);
outb_p(0x00, 0x43); /* latch the count ASAP */
count = inb_p(0x40); /* read the latched count */
count |= inb(0x40) << 8;
spin_unlock(&i8253_lock);
count = ((LATCH-1) - count) * TICK_SIZE;
delay_at_last_interrupt = (count + LATCH/2) / LATCH;
}
/* ------ Calibrate the TSC -------
* Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset().
* Too much 64-bit arithmetic here to do this cleanly in C, and for
* accuracy's sake we want to keep the overhead on the CTC speaker (channel 2)
* output busy loop as low as possible. We avoid reading the CTC registers
* directly because of the awkward 8-bit access mechanism of the 82C54
* device.
*/
#define CALIBRATE_LATCH (5 * LATCH)
#define CALIBRATE_TIME (5 * 1000020/HZ)
static unsigned long __init calibrate_tsc(void)
{
/* Set the Gate high, disable speaker */
outb((inb(0x61) & ~0x02) | 0x01, 0x61);
/*
* Now let's take care of CTC channel 2
*
* Set the Gate high, program CTC channel 2 for mode 0,
* (interrupt on terminal count mode), binary count,
* load 5 * LATCH count, (LSB and MSB) to begin countdown.
*/
outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */
outb(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */
outb(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */
{
unsigned long startlow, starthigh;
unsigned long endlow, endhigh;
unsigned long count;
rdtsc(startlow,starthigh);
count = 0;
do {
count++;
} while ((inb(0x61) & 0x20) == 0);
rdtsc(endlow,endhigh);
last_tsc_low = endlow;
/* Error: ECTCNEVERSET */
if (count <= 1)
goto bad_ctc;
/* 64-bit subtract - gcc just messes up with long longs */
__asm__("subl %2,%0\n\t"
"sbbl %3,%1"
:"=a" (endlow), "=d" (endhigh)
:"g" (startlow), "g" (starthigh),
"0" (endlow), "1" (endhigh));
/* Error: ECPUTOOFAST */
if (endhigh)
goto bad_ctc;
/* Error: ECPUTOOSLOW */
if (endlow <= CALIBRATE_TIME)
goto bad_ctc;
__asm__("divl %2"
:"=a" (endlow), "=d" (endhigh)
:"r" (endlow), "0" (0), "1" (CALIBRATE_TIME));
return endlow;
}
/*
* The CTC wasn't reliable: we got a hit on the very first read,
* or the CPU was so fast/slow that the quotient wouldn't fit in
* 32 bits..
*/
bad_ctc:
return 0;
}
#ifdef CONFIG_CPU_FREQ
static int
time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{
struct cpufreq_freqs *freq = data;
unsigned int i;
if (!cpu_has_tsc)
return 0;
switch (val) {
case CPUFREQ_PRECHANGE:
if ((freq->old < freq->new) &&
((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == 0))) {
cpu_khz = cpufreq_scale(cpu_khz, freq->old, freq->new);
fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_quotient, freq->new, freq->old);
}
for (i=0; i<NR_CPUS; i++)
if ((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == i))
cpu_data[i].loops_per_jiffy = cpufreq_scale(cpu_data[i].loops_per_jiffy, freq->old, freq->new);
break;
case CPUFREQ_POSTCHANGE:
if ((freq->new < freq->old) &&
((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == 0))) {
cpu_khz = cpufreq_scale(cpu_khz, freq->old, freq->new);
fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_quotient, freq->new, freq->old);
}
for (i=0; i<NR_CPUS; i++)
if ((freq->cpu == CPUFREQ_ALL_CPUS) || (freq->cpu == i))
cpu_data[i].loops_per_jiffy = cpufreq_scale(cpu_data[i].loops_per_jiffy, freq->old, freq->new);
break;
}
return 0;
}
static struct notifier_block time_cpufreq_notifier_block = {
notifier_call: time_cpufreq_notifier
};
#endif
static int init_tsc(void)
{
/*
* If we have APM enabled or the CPU clock speed is variable
* (CPU stops clock on HLT or slows clock to save power)
* then the TSC timestamps may diverge by up to 1 jiffy from
* 'real time' but nothing will break.
* The most frequent case is that the CPU is "woken" from a halt
* state by the timer interrupt itself, so we get 0 error. In the
* rare cases where a driver would "wake" the CPU and request a
* timestamp, the maximum error is < 1 jiffy. But timestamps are
* still perfectly ordered.
* Note that the TSC counter will be reset if APM suspends
* to disk; this won't break the kernel, though, 'cuz we're
* smart. See arch/i386/kernel/apm.c.
*/
/*
* Firstly we have to do a CPU check for chips with
* a potentially buggy TSC. At this point we haven't run
* the ident/bugs checks so we must run this hook as it
* may turn off the TSC flag.
*
* NOTE: this doesnt yet handle SMP 486 machines where only
* some CPU's have a TSC. Thats never worked and nobody has
* moaned if you have the only one in the world - you fix it!
*/
dodgy_tsc();
if (cpu_has_tsc) {
unsigned long tsc_quotient = calibrate_tsc();
if (tsc_quotient) {
fast_gettimeoffset_quotient = tsc_quotient;
use_tsc = 1;
/*
* We could be more selective here I suspect
* and just enable this for the next intel chips ?
*/
x86_udelay_tsc = 1;
/* report CPU clock rate in Hz.
* The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
* clock/second. Our precision is about 100 ppm.
*/
{ unsigned long eax=0, edx=1000;
__asm__("divl %2"
:"=a" (cpu_khz), "=d" (edx)
:"r" (tsc_quotient),
"0" (eax), "1" (edx));
printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000);
}
#ifdef CONFIG_CPU_FREQ
cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
#endif
return 1;
}
}
return 0;
}
/************************************************************/
/* tsc timer_opts struct */
struct timer_opts timer_tsc = {
init: init_tsc,
mark_offset: mark_offset_tsc,
get_offset: get_offset_tsc
};
...@@ -30,6 +30,10 @@ static struct file_operations raw_ctl_fops; ...@@ -30,6 +30,10 @@ static struct file_operations raw_ctl_fops;
/* /*
* Open/close code for raw IO. * Open/close code for raw IO.
* *
* We just rewrite the i_mapping for the /dev/raw/rawN file descriptor to
* point at the blockdev's address_space and set the file handle to use
* O_DIRECT.
*
* Set the device's soft blocksize to the minimum possible. This gives the * Set the device's soft blocksize to the minimum possible. This gives the
* finest possible alignment and has no adverse impact on performance. * finest possible alignment and has no adverse impact on performance.
*/ */
...@@ -56,7 +60,12 @@ static int raw_open(struct inode *inode, struct file *filp) ...@@ -56,7 +60,12 @@ static int raw_open(struct inode *inode, struct file *filp)
err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW); err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW);
if (!err) { if (!err) {
err = set_blocksize(bdev, bdev_hardsect_size(bdev)); err = set_blocksize(bdev, bdev_hardsect_size(bdev));
raw_devices[minor].inuse++; if (err == 0) {
raw_devices[minor].inuse++;
filp->f_dentry->d_inode->i_mapping =
bdev->bd_inode->i_mapping;
filp->f_flags |= O_DIRECT;
}
} }
} }
up(&raw_mutex); up(&raw_mutex);
...@@ -200,72 +209,22 @@ raw_ctl_ioctl(struct inode *inode, struct file *filp, ...@@ -200,72 +209,22 @@ raw_ctl_ioctl(struct inode *inode, struct file *filp,
return err; return err;
} }
static ssize_t static ssize_t raw_file_write(struct file *file, const char *buf,
rw_raw_dev(int rw, struct file *filp, const struct iovec *iov, unsigned long nr_segs, loff_t *offp) size_t count, loff_t *ppos)
{
const int minor = minor(filp->f_dentry->d_inode->i_rdev);
struct block_device *bdev = raw_devices[minor].binding;
struct inode *inode = bdev->bd_inode;
size_t count = iov_length(iov, nr_segs);
ssize_t ret = 0;
if (count == 0)
goto out;
if ((ssize_t)count < 0)
return -EINVAL;
if (*offp >= inode->i_size)
return -ENXIO;
if (count + *offp > inode->i_size) {
count = inode->i_size - *offp;
nr_segs = iov_shorten((struct iovec *)iov, nr_segs, count);
}
ret = generic_file_direct_IO(rw, filp, iov, *offp, nr_segs);
if (ret > 0)
*offp += ret;
out:
return ret;
}
static ssize_t
raw_read(struct file *filp, char *buf, size_t size, loff_t *offp)
{
struct iovec local_iov = { .iov_base = buf, .iov_len = size};
return rw_raw_dev(READ, filp, &local_iov, 1, offp);
}
static ssize_t
raw_write(struct file *filp, const char *buf, size_t size, loff_t *offp)
{ {
struct iovec local_iov = { .iov_base = (char *)buf, .iov_len = size}; struct iovec local_iov = { .iov_base = (void *)buf, .iov_len = count };
return rw_raw_dev(WRITE, filp, &local_iov, 1, offp); return generic_file_write_nolock(file, &local_iov, 1, ppos);
}
static ssize_t
raw_readv(struct file *filp, const struct iovec *iov, unsigned long nr_segs, loff_t *offp)
{
return rw_raw_dev(READ, filp, iov, nr_segs, offp);
}
static ssize_t
raw_writev(struct file *filp, const struct iovec *iov, unsigned long nr_segs, loff_t *offp)
{
return rw_raw_dev(WRITE, filp, iov, nr_segs, offp);
} }
static struct file_operations raw_fops = { static struct file_operations raw_fops = {
.read = raw_read, .read = generic_file_read,
.write = raw_write, .write = raw_file_write,
.open = raw_open, .open = raw_open,
.release= raw_release, .release= raw_release,
.ioctl = raw_ioctl, .ioctl = raw_ioctl,
.readv = raw_readv, .readv = generic_file_readv,
.writev = raw_writev, .writev = generic_file_writev,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
......
...@@ -1434,9 +1434,10 @@ int journal_stop(handle_t *handle) ...@@ -1434,9 +1434,10 @@ int journal_stop(handle_t *handle)
* by 30x or more... * by 30x or more...
*/ */
if (handle->h_sync) { if (handle->h_sync) {
set_current_state(TASK_RUNNING);
do { do {
old_handle_count = transaction->t_handle_count; old_handle_count = transaction->t_handle_count;
yield(); schedule();
} while (old_handle_count != transaction->t_handle_count); } while (old_handle_count != transaction->t_handle_count);
} }
......
...@@ -316,7 +316,7 @@ static ssize_t do_readv_writev(int type, struct file *file, ...@@ -316,7 +316,7 @@ static ssize_t do_readv_writev(int type, struct file *file,
size_t tot_len; size_t tot_len;
struct iovec iovstack[UIO_FASTIOV]; struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov=iovstack; struct iovec *iov=iovstack;
ssize_t ret = -EINVAL; ssize_t ret;
int seg; int seg;
io_fn_t fn; io_fn_t fn;
iov_fn_t fnv; iov_fn_t fnv;
...@@ -325,8 +325,9 @@ static ssize_t do_readv_writev(int type, struct file *file, ...@@ -325,8 +325,9 @@ static ssize_t do_readv_writev(int type, struct file *file,
/* /*
* SuS says "The readv() function *may* fail if the iovcnt argument * SuS says "The readv() function *may* fail if the iovcnt argument
* was less than or equal to 0, or greater than {IOV_MAX}. Linux has * was less than or equal to 0, or greater than {IOV_MAX}. Linux has
* traditionally returned -EINVAL for zero segments, so... * traditionally returned zero for zero segments, so...
*/ */
ret = 0;
if (nr_segs == 0) if (nr_segs == 0)
goto out; goto out;
...@@ -334,6 +335,7 @@ static ssize_t do_readv_writev(int type, struct file *file, ...@@ -334,6 +335,7 @@ static ssize_t do_readv_writev(int type, struct file *file,
* First get the "struct iovec" from user memory and * First get the "struct iovec" from user memory and
* verify all the pointers * verify all the pointers
*/ */
ret = -EINVAL;
if ((nr_segs > UIO_MAXIOV) || (nr_segs <= 0)) if ((nr_segs > UIO_MAXIOV) || (nr_segs <= 0))
goto out; goto out;
if (!file->f_op) if (!file->f_op)
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
#define PAL_wrperfmon 57 #define PAL_wrperfmon 57
#define PAL_rdusp 58 #define PAL_rdusp 58
#define PAL_whami 60 #define PAL_whami 60
#define PAL_rtsys 61 #define PAL_retsys 61
#define PAL_rti 63 #define PAL_rti 63
#endif /* __ALPHA_PAL_H */ #endif /* __ALPHA_PAL_H */
...@@ -331,19 +331,19 @@ ...@@ -331,19 +331,19 @@
#define __NR_removexattr 391 #define __NR_removexattr 391
#define __NR_lremovexattr 392 #define __NR_lremovexattr 392
#define __NR_fremovexattr 393 #define __NR_fremovexattr 393
#define __NR_futex 394 #define __NR_futex 394
#define __NR_sched_setaffinity 395 #define __NR_sched_setaffinity 395
#define __NR_sched_getaffinity 396 #define __NR_sched_getaffinity 396
#define __NR_tuxcall 397 #define __NR_tuxcall 397
#define __NR_io_setup 398 #define __NR_io_setup 398
#define __NR_io_destroy 399 #define __NR_io_destroy 399
#define __NR_io_getevents 400 #define __NR_io_getevents 400
#define __NR_io_submit 401 #define __NR_io_submit 401
#define __NR_io_cancel 402 #define __NR_io_cancel 402
#define __NR_alloc_hugepages 403 #define __NR_alloc_hugepages 403
#define __NR_free_hugepages 404 #define __NR_free_hugepages 404
#define __NR_exit_group 405 #define __NR_exit_group 405
#define NR_SYSCALLS 406
#if defined(__GNUC__) #if defined(__GNUC__)
...@@ -598,7 +598,7 @@ static inline pid_t waitpid(int pid, int * wait_stat, int flags) ...@@ -598,7 +598,7 @@ static inline pid_t waitpid(int pid, int * wait_stat, int flags)
return sys_wait4(pid, wait_stat, flags, NULL); return sys_wait4(pid, wait_stat, flags, NULL);
} }
#endif #endif /* __KERNEL_SYSCALLS__ */
/* /*
* "Conditional" syscalls * "Conditional" syscalls
......
...@@ -91,7 +91,7 @@ typedef struct siginfo { ...@@ -91,7 +91,7 @@ typedef struct siginfo {
#define __SI_FAULT (3 << 16) #define __SI_FAULT (3 << 16)
#define __SI_CHLD (4 << 16) #define __SI_CHLD (4 << 16)
#define __SI_RT (5 << 16) #define __SI_RT (5 << 16)
#define __SI_CODE(T,N) ((T) << 16 | ((N) & 0xffff)) #define __SI_CODE(T,N) ((T) | ((N) & 0xffff))
#else #else
#define __SI_KILL 0 #define __SI_KILL 0
#define __SI_TIMER 0 #define __SI_TIMER 0
......
...@@ -65,6 +65,9 @@ enum fixed_addresses { ...@@ -65,6 +65,9 @@ enum fixed_addresses {
#ifdef CONFIG_X86_F00F_BUG #ifdef CONFIG_X86_F00F_BUG
FIX_F00F_IDT, /* Virtual mapping for IDT */ FIX_F00F_IDT, /* Virtual mapping for IDT */
#endif #endif
#ifdef CONFIG_X86_CYCLONE
FIX_CYCLONE_TIMER, /*cyclone timer register*/
#endif
#ifdef CONFIG_HIGHMEM #ifdef CONFIG_HIGHMEM
FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
......
...@@ -259,12 +259,21 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) ...@@ -259,12 +259,21 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
#define pte_offset_kernel(dir, address) \ #define pte_offset_kernel(dir, address) \
((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(address)) ((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(address))
#if defined(CONFIG_HIGHPTE)
#define pte_offset_map(dir, address) \ #define pte_offset_map(dir, address) \
((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + __pte_offset(address)) ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + __pte_offset(address))
#define pte_offset_map_nested(dir, address) \ #define pte_offset_map_nested(dir, address) \
((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + __pte_offset(address)) ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + __pte_offset(address))
#define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0) #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
#define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1) #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
#else
#define pte_offset_map(dir, address) \
((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
#define pte_unmap(pte) do { } while (0)
#define pte_unmap_nested(pte) do { } while (0)
#endif
#if defined(CONFIG_HIGHPTE) && defined(CONFIG_HIGHMEM4G) #if defined(CONFIG_HIGHPTE) && defined(CONFIG_HIGHMEM4G)
typedef u32 pte_addr_t; typedef u32 pte_addr_t;
......
#ifndef _ASMi386_TIMER_H
#define _ASMi386_TIMER_H
struct timer_opts{
/* probes and initializes timer. returns 1 on sucess, 0 on failure */
int (*init)(void);
/* called by the timer interrupt */
void (*mark_offset)(void);
/* called by gettimeofday. returns # ms since the last timer interrupt */
unsigned long (*get_offset)(void);
};
#define TICK_SIZE (tick_nsec / 1000)
struct timer_opts* select_timer(void);
#endif
...@@ -21,8 +21,6 @@ ...@@ -21,8 +21,6 @@
struct radix_tree_node; struct radix_tree_node;
#define RADIX_TREE_SLOT_RESERVED ((void *)~0UL)
struct radix_tree_root { struct radix_tree_root {
unsigned int height; unsigned int height;
int gfp_mask; int gfp_mask;
...@@ -41,7 +39,6 @@ do { \ ...@@ -41,7 +39,6 @@ do { \
(root)->rnode = NULL; \ (root)->rnode = NULL; \
} while (0) } while (0)
extern int radix_tree_reserve(struct radix_tree_root *, unsigned long, void ***);
extern int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); extern int radix_tree_insert(struct radix_tree_root *, unsigned long, void *);
extern void *radix_tree_lookup(struct radix_tree_root *, unsigned long); extern void *radix_tree_lookup(struct radix_tree_root *, unsigned long);
extern int radix_tree_delete(struct radix_tree_root *, unsigned long); extern int radix_tree_delete(struct radix_tree_root *, unsigned long);
......
...@@ -266,29 +266,31 @@ int del_timer(timer_t *timer) ...@@ -266,29 +266,31 @@ int del_timer(timer_t *timer)
int del_timer_sync(timer_t *timer) int del_timer_sync(timer_t *timer)
{ {
tvec_base_t *base = tvec_bases; tvec_base_t *base = tvec_bases;
int i, ret; int i, ret = 0;
ret = del_timer(timer); del_again:
ret += del_timer(timer);
for (i = 0; i < NR_CPUS; i++) { for (i = 0; i < NR_CPUS; i++, base++) {
if (!cpu_online(i)) if (!cpu_online(i))
continue; continue;
if (base->running_timer == timer) { if (base->running_timer == timer) {
while (base->running_timer == timer) { while (base->running_timer == timer) {
cpu_relax(); cpu_relax();
preempt_disable(); preempt_check_resched();
preempt_enable();
} }
break; break;
} }
base++;
} }
if (timer_pending(timer))
goto del_again;
return ret; return ret;
} }
#endif #endif
static void cascade(tvec_base_t *base, tvec_t *tv) static int cascade(tvec_base_t *base, tvec_t *tv)
{ {
/* cascade all the timers from tv up one level */ /* cascade all the timers from tv up one level */
struct list_head *head, *curr, *next; struct list_head *head, *curr, *next;
...@@ -310,7 +312,8 @@ static void cascade(tvec_base_t *base, tvec_t *tv) ...@@ -310,7 +312,8 @@ static void cascade(tvec_base_t *base, tvec_t *tv)
curr = next; curr = next;
} }
INIT_LIST_HEAD(head); INIT_LIST_HEAD(head);
tv->index = (tv->index + 1) & TVN_MASK;
return tv->index = (tv->index + 1) & TVN_MASK;
} }
/*** /***
...@@ -322,26 +325,18 @@ static void cascade(tvec_base_t *base, tvec_t *tv) ...@@ -322,26 +325,18 @@ static void cascade(tvec_base_t *base, tvec_t *tv)
*/ */
static inline void __run_timers(tvec_base_t *base) static inline void __run_timers(tvec_base_t *base)
{ {
unsigned long flags; spin_lock_irq(&base->lock);
spin_lock_irqsave(&base->lock, flags);
while ((long)(jiffies - base->timer_jiffies) >= 0) { while ((long)(jiffies - base->timer_jiffies) >= 0) {
struct list_head *head, *curr; struct list_head *head, *curr;
/* /*
* Cascade timers: * Cascade timers:
*/ */
if (!base->tv1.index) { if (!base->tv1.index &&
cascade(base, &base->tv2); (cascade(base, &base->tv2) == 1) &&
if (base->tv2.index == 1) { (cascade(base, &base->tv3) == 1) &&
cascade(base, &base->tv3); cascade(base, &base->tv4) == 1)
if (base->tv3.index == 1) { cascade(base, &base->tv5);
cascade(base, &base->tv4);
if (base->tv4.index == 1)
cascade(base, &base->tv5);
}
}
}
repeat: repeat:
head = base->tv1.vec + base->tv1.index; head = base->tv1.vec + base->tv1.index;
curr = head->next; curr = head->next;
...@@ -360,7 +355,10 @@ static inline void __run_timers(tvec_base_t *base) ...@@ -360,7 +355,10 @@ static inline void __run_timers(tvec_base_t *base)
base->running_timer = timer; base->running_timer = timer;
#endif #endif
spin_unlock_irq(&base->lock); spin_unlock_irq(&base->lock);
fn(data); if (!fn)
printk("Bad: timer %p has NULL fn. (data: %08lx)\n", timer, data);
else
fn(data);
spin_lock_irq(&base->lock); spin_lock_irq(&base->lock);
goto repeat; goto repeat;
} }
...@@ -370,7 +368,7 @@ static inline void __run_timers(tvec_base_t *base) ...@@ -370,7 +368,7 @@ static inline void __run_timers(tvec_base_t *base)
#if CONFIG_SMP #if CONFIG_SMP
base->running_timer = NULL; base->running_timer = NULL;
#endif #endif
spin_unlock_irqrestore(&base->lock, flags); spin_unlock_irq(&base->lock);
} }
/******************************************************************/ /******************************************************************/
......
...@@ -77,7 +77,6 @@ static inline unsigned long radix_tree_maxindex(unsigned int height) ...@@ -77,7 +77,6 @@ static inline unsigned long radix_tree_maxindex(unsigned int height)
return index; return index;
} }
/* /*
* Extend a radix tree so it can store key @index. * Extend a radix tree so it can store key @index.
*/ */
...@@ -109,16 +108,15 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index) ...@@ -109,16 +108,15 @@ static int radix_tree_extend(struct radix_tree_root *root, unsigned long index)
return 0; return 0;
} }
/** /**
* radix_tree_reserve - reserve space in a radix tree * radix_tree_insert - insert into a radix tree
* @root: radix tree root * @root: radix tree root
* @index: index key * @index: index key
* @pslot: pointer to reserved slot * @item: item to insert
* *
* Reserve a slot in a radix tree for the key @index. * Insert an item into the radix tree at position @index.
*/ */
int radix_tree_reserve(struct radix_tree_root *root, unsigned long index, void ***pslot) int radix_tree_insert(struct radix_tree_root *root, unsigned long index, void *item)
{ {
struct radix_tree_node *node = NULL, *tmp, **slot; struct radix_tree_node *node = NULL, *tmp, **slot;
unsigned int height, shift; unsigned int height, shift;
...@@ -158,36 +156,11 @@ int radix_tree_reserve(struct radix_tree_root *root, unsigned long index, void * ...@@ -158,36 +156,11 @@ int radix_tree_reserve(struct radix_tree_root *root, unsigned long index, void *
if (node) if (node)
node->count++; node->count++;
*pslot = (void **)slot; *slot = item;
**pslot = RADIX_TREE_SLOT_RESERVED;
return 0; return 0;
} }
EXPORT_SYMBOL(radix_tree_reserve);
/**
* radix_tree_insert - insert into a radix tree
* @root: radix tree root
* @index: index key
* @item: item to insert
*
* Insert an item into the radix tree at position @index.
*/
int radix_tree_insert(struct radix_tree_root *root, unsigned long index, void *item)
{
void **slot;
int error;
error = radix_tree_reserve(root, index, &slot);
if (!error)
*slot = item;
return error;
}
EXPORT_SYMBOL(radix_tree_insert); EXPORT_SYMBOL(radix_tree_insert);
/** /**
* radix_tree_lookup - perform lookup operation on a radix tree * radix_tree_lookup - perform lookup operation on a radix tree
* @root: radix tree root * @root: radix tree root
...@@ -267,8 +240,8 @@ __lookup(struct radix_tree_root *root, void **results, unsigned long index, ...@@ -267,8 +240,8 @@ __lookup(struct radix_tree_root *root, void **results, unsigned long index,
out: out:
*next_index = index; *next_index = index;
return nr_found; return nr_found;
} }
/** /**
* radix_tree_gang_lookup - perform multiple lookup on a radix tree * radix_tree_gang_lookup - perform multiple lookup on a radix tree
* @root: radix tree root * @root: radix tree root
...@@ -371,7 +344,6 @@ int radix_tree_delete(struct radix_tree_root *root, unsigned long index) ...@@ -371,7 +344,6 @@ int radix_tree_delete(struct radix_tree_root *root, unsigned long index)
return 0; return 0;
} }
EXPORT_SYMBOL(radix_tree_delete); EXPORT_SYMBOL(radix_tree_delete);
static void radix_tree_node_ctor(void *node, kmem_cache_t *cachep, unsigned long flags) static void radix_tree_node_ctor(void *node, kmem_cache_t *cachep, unsigned long flags)
......
...@@ -194,7 +194,8 @@ static inline unsigned long move_vma(struct vm_area_struct * vma, ...@@ -194,7 +194,8 @@ static inline unsigned long move_vma(struct vm_area_struct * vma,
prev->vm_end = next->vm_end; prev->vm_end = next->vm_end;
__vma_unlink(mm, next, prev); __vma_unlink(mm, next, prev);
spin_unlock(&mm->page_table_lock); spin_unlock(&mm->page_table_lock);
if (vma == next)
vma = prev;
mm->map_count--; mm->map_count--;
kmem_cache_free(vm_area_cachep, next); kmem_cache_free(vm_area_cachep, next);
} }
......
...@@ -199,16 +199,14 @@ void delete_from_swap_cache(struct page *page) ...@@ -199,16 +199,14 @@ void delete_from_swap_cache(struct page *page)
int move_to_swap_cache(struct page *page, swp_entry_t entry) int move_to_swap_cache(struct page *page, swp_entry_t entry)
{ {
struct address_space *mapping = page->mapping; struct address_space *mapping = page->mapping;
void **pslot;
int err; int err;
write_lock(&swapper_space.page_lock); write_lock(&swapper_space.page_lock);
write_lock(&mapping->page_lock); write_lock(&mapping->page_lock);
err = radix_tree_reserve(&swapper_space.page_tree, entry.val, &pslot); err = radix_tree_insert(&swapper_space.page_tree, entry.val, page);
if (!err) { if (!err) {
__remove_from_page_cache(page); __remove_from_page_cache(page);
*pslot = page;
___add_to_page_cache(page, &swapper_space, entry.val); ___add_to_page_cache(page, &swapper_space, entry.val);
} }
...@@ -231,7 +229,6 @@ int move_from_swap_cache(struct page *page, unsigned long index, ...@@ -231,7 +229,6 @@ int move_from_swap_cache(struct page *page, unsigned long index,
struct address_space *mapping) struct address_space *mapping)
{ {
swp_entry_t entry; swp_entry_t entry;
void **pslot;
int err; int err;
BUG_ON(!PageLocked(page)); BUG_ON(!PageLocked(page));
...@@ -243,10 +240,9 @@ int move_from_swap_cache(struct page *page, unsigned long index, ...@@ -243,10 +240,9 @@ int move_from_swap_cache(struct page *page, unsigned long index,
write_lock(&swapper_space.page_lock); write_lock(&swapper_space.page_lock);
write_lock(&mapping->page_lock); write_lock(&mapping->page_lock);
err = radix_tree_reserve(&mapping->page_tree, index, &pslot); err = radix_tree_insert(&mapping->page_tree, index, page);
if (!err) { if (!err) {
__delete_from_swap_cache(page); __delete_from_swap_cache(page);
*pslot = page;
___add_to_page_cache(page, mapping, index); ___add_to_page_cache(page, mapping, index);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment