Commit 32d4fbac authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.23

parent b5127d9b
...@@ -664,6 +664,15 @@ S: Reading ...@@ -664,6 +664,15 @@ S: Reading
S: RG6 2NU S: RG6 2NU
S: United Kingdom S: United Kingdom
N: Jakub Jelinek
E: jj@sunsite.mff.cuni.cz
W: http://sunsite.mff.cuni.cz/~jj
D: Sparc hacker, SILO, mc
D: Maintain sunsite.mff.cuni.cz
S: Na Orechovce 7
S: 160 00 Praha 6
S: Czech Republic
N: Michael K. Johnson N: Michael K. Johnson
E: johnsonm@redhat.com E: johnsonm@redhat.com
W: http://www.redhat.com/~johnsonm W: http://www.redhat.com/~johnsonm
......
\documentclass{article} \documentclass{article}
\def\version{$Id: cdrom-standard.tex,v 1.6 1996/12/23 21:17:44 david Exp $} \def\version{$Id: cdrom-standard.tex,v 1.6 1996/12/29 20:45:18 davem Exp $}
\evensidemargin=0pt \evensidemargin=0pt
\oddsidemargin=0pt \oddsidemargin=0pt
...@@ -994,6 +994,10 @@ $ \version\ $ ...@@ -994,6 +994,10 @@ $ \version\ $
\def\versionlog{ \def\versionlog{
$Log: cdrom-standard.tex,v $ $Log: cdrom-standard.tex,v $
Revision 1.6 1996/12/29 20:45:18 davem
Merge to 2.1.18, versioned module symbols are
disabled until new modutils is released.
Revision 1.6 1996/12/23 21:17:44 david Revision 1.6 1996/12/23 21:17:44 david
Added reasons for speed selection. Added reasons for speed selection.
......
...@@ -176,12 +176,19 @@ vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs ...@@ -176,12 +176,19 @@ vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
$(ARCHIVES) \ $(ARCHIVES) \
$(FILESYSTEMS) \ $(FILESYSTEMS) \
$(DRIVERS) \ $(DRIVERS) \
$(LIBS) -o vmlinux $(LIBS) \
-o vmlinux
$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)\|\(\.\.ng$$\)' | sort > System.map $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)\|\(\.\.ng$$\)' | sort > System.map
symlinks: symlinks:
rm -f include/asm rm -f include/asm
( cd include ; ln -sf asm-$(ARCH) asm) ( cd include ; ln -sf asm-$(ARCH) asm)
@if [ ! -d modules ]; then \
mkdir modules; \
fi
@if [ ! -d include/linux/modules ]; then \
mkdir include/linux/modules; \
fi
oldconfig: symlinks oldconfig: symlinks
$(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in $(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in
...@@ -315,7 +322,7 @@ clean: archclean ...@@ -315,7 +322,7 @@ clean: archclean
rm -f core `find . -type f -name 'core' -print` rm -f core `find . -type f -name 'core' -print`
rm -f vmlinux System.map rm -f vmlinux System.map
rm -f .tmp* drivers/sound/configure rm -f .tmp* drivers/sound/configure
rm -f modules/* rm -f `find modules/ -type f -print`
rm -f submenu* rm -f submenu*
mrproper: clean mrproper: clean
...@@ -331,7 +338,8 @@ mrproper: clean ...@@ -331,7 +338,8 @@ mrproper: clean
rm -f .depend `find . -name .depend -print` rm -f .depend `find . -name .depend -print`
rm -f .hdepend scripts/mkdep rm -f .hdepend scripts/mkdep
rm -f $(TOPDIR)/include/linux/modversions.h rm -f $(TOPDIR)/include/linux/modversions.h
rm -f $(TOPDIR)/include/linux/modules/* rm -rf $(TOPDIR)/include/linux/modules
rm -rf modules
distclean: mrproper distclean: mrproper
......
...@@ -107,6 +107,9 @@ modules: $(ALL_MOBJS) dummy ...@@ -107,6 +107,9 @@ modules: $(ALL_MOBJS) dummy
ifdef MOD_SUB_DIRS ifdef MOD_SUB_DIRS
set -e; for i in $(MOD_SUB_DIRS); do $(MAKE) -C $$i modules; done set -e; for i in $(MOD_SUB_DIRS); do $(MAKE) -C $$i modules; done
endif endif
ifdef MOD_IN_SUB_DIRS
set -e; for i in $(MOD_IN_SUB_DIRS); do $(MAKE) -C $$i modules; done
endif
ifneq "$(strip $(MOD_LIST_NAME))" "" ifneq "$(strip $(MOD_LIST_NAME))" ""
rm -f $$TOPDIR/modules/$(MOD_LIST_NAME) rm -f $$TOPDIR/modules/$(MOD_LIST_NAME)
ifdef MOD_SUB_DIRS ifdef MOD_SUB_DIRS
...@@ -116,6 +119,9 @@ endif ...@@ -116,6 +119,9 @@ endif
ifneq "$(strip $(ALL_MOBJS))" "" ifneq "$(strip $(ALL_MOBJS))" ""
echo $(ALL_MOBJS) >> $$TOPDIR/modules/$(MOD_LIST_NAME) echo $(ALL_MOBJS) >> $$TOPDIR/modules/$(MOD_LIST_NAME)
endif endif
ifneq "$(strip $(MOD_TO_LIST))" ""
echo $(MOD_TO_LIST) >> $$TOPDIR/modules/$(MOD_LIST_NAME)
endif
endif endif
ifneq "$(strip $(ALL_MOBJS))" "" ifneq "$(strip $(ALL_MOBJS))" ""
echo $(PDWN) echo $(PDWN)
......
...@@ -10,9 +10,15 @@ ...@@ -10,9 +10,15 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/user.h> #include <linux/user.h>
#include <linux/elfcore.h> #include <linux/elfcore.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/hwrpb.h> #include <asm/hwrpb.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/processor.h>
#include <asm/checksum.h>
extern void bcopy (const char *src, char *dst, int len); extern void bcopy (const char *src, char *dst, int len);
...@@ -58,6 +64,7 @@ EXPORT_SYMBOL(strlen); ...@@ -58,6 +64,7 @@ EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(strncmp); EXPORT_SYMBOL(strncmp);
EXPORT_SYMBOL(strncpy); EXPORT_SYMBOL(strncpy);
EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strncat);
EXPORT_SYMBOL(strstr); EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strtok); EXPORT_SYMBOL(strtok);
EXPORT_SYMBOL(strchr); EXPORT_SYMBOL(strchr);
...@@ -72,6 +79,11 @@ EXPORT_SYMBOL(dump_fpu); ...@@ -72,6 +79,11 @@ EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(hwrpb); EXPORT_SYMBOL(hwrpb);
EXPORT_SYMBOL(wrusp); EXPORT_SYMBOL(wrusp);
EXPORT_SYMBOL(__kernel_thread); EXPORT_SYMBOL(__kernel_thread);
EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(csum_tcpudp_magic);
EXPORT_SYMBOL(ip_fast_csum);
EXPORT_SYMBOL(ip_compute_csum);
/* /*
* The following are specially called from the uaccess assembly stubs. * The following are specially called from the uaccess assembly stubs.
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
* within the United States, $35 abroad. * within the United States, $35 abroad.
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#if 0 #if 0
# define DBG_DEVS(args) printk args # define DBG_DEVS(args) printk args
...@@ -1217,6 +1219,7 @@ asmlinkage int sys_pciconfig_read( ...@@ -1217,6 +1219,7 @@ asmlinkage int sys_pciconfig_read(
unsigned int uint; unsigned int uint;
long err = 0; long err = 0;
lock_kernel();
switch (len) { switch (len) {
case 1: case 1:
err = pcibios_read_config_byte(bus, dfn, off, &ubyte); err = pcibios_read_config_byte(bus, dfn, off, &ubyte);
...@@ -1240,6 +1243,7 @@ asmlinkage int sys_pciconfig_read( ...@@ -1240,6 +1243,7 @@ asmlinkage int sys_pciconfig_read(
err = -EINVAL; err = -EINVAL;
break; break;
} }
unlock_kernel();
return err; return err;
} }
asmlinkage int sys_pciconfig_write( asmlinkage int sys_pciconfig_write(
...@@ -1254,6 +1258,7 @@ asmlinkage int sys_pciconfig_write( ...@@ -1254,6 +1258,7 @@ asmlinkage int sys_pciconfig_write(
unsigned int uint; unsigned int uint;
long err = 0; long err = 0;
lock_kernel();
switch (len) { switch (len) {
case 1: case 1:
err = get_user(ubyte, buf); err = get_user(ubyte, buf);
...@@ -1286,6 +1291,7 @@ asmlinkage int sys_pciconfig_write( ...@@ -1286,6 +1291,7 @@ asmlinkage int sys_pciconfig_write(
err = -EINVAL; err = -EINVAL;
break; break;
} }
unlock_kernel();
return err; return err;
} }
......
...@@ -199,6 +199,8 @@ entIF: ...@@ -199,6 +199,8 @@ entIF:
.align 3 .align 3
.ent kernel_clone .ent kernel_clone
kernel_clone: kernel_clone:
.frame $30, 0, $26
.prologue 0
subq $30,6*8,$30 subq $30,6*8,$30
stq $31,0($30) stq $31,0($30)
stq $26,8($30) stq $26,8($30)
...@@ -221,17 +223,19 @@ kernel_clone: ...@@ -221,17 +223,19 @@ kernel_clone:
.globl __kernel_thread .globl __kernel_thread
.ent __kernel_thread .ent __kernel_thread
__kernel_thread: __kernel_thread:
.frame $30, 4*8, $26
subq $30,4*8,$30 subq $30,4*8,$30
stq $9,0($30) stq $10,16($30)
stq $10,8($30) stq $9,8($30)
stq $26,16($30) stq $26,0($30)
.prologue 0
bis $17,$17,$9 /* save fn */ bis $17,$17,$9 /* save fn */
bis $18,$18,$10 /* save arg */ bis $18,$18,$10 /* save arg */
bsr $26,kernel_clone bsr $26,kernel_clone
bne $20,1f /* $20 is non-zero in child */ bne $20,1f /* $20 is non-zero in child */
ldq $9,0($30) ldq $26,0($30)
ldq $10,8($30) ldq $9,8($30)
ldq $26,16($30) ldq $10,16($30)
addq $30,4*8,$30 addq $30,4*8,$30
ret $31,($26),1 ret $31,($26),1
/* this is in child: look out as we don't have any stack here.. */ /* this is in child: look out as we don't have any stack here.. */
......
This diff is collapsed.
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
...@@ -31,6 +33,9 @@ ...@@ -31,6 +33,9 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
/*
* No need to aquire the kernel lock, we're entirely local..
*/
asmlinkage int sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2, asmlinkage int sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2,
unsigned long a3, unsigned long a4, unsigned long a5, unsigned long a3, unsigned long a4, unsigned long a5,
struct pt_regs regs) struct pt_regs regs)
...@@ -41,14 +46,21 @@ asmlinkage int sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2, ...@@ -41,14 +46,21 @@ asmlinkage int sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2,
asmlinkage int sys_idle(void) asmlinkage int sys_idle(void)
{ {
int ret = -EPERM;
lock_kernel();
if (current->pid != 0) if (current->pid != 0)
return -EPERM; goto out;
/* endless idle loop with no priority at all */ /* endless idle loop with no priority at all */
current->counter = -100; current->counter = -100;
for (;;) { for (;;) {
schedule(); schedule();
} }
ret = 0;
out:
unlock_kernel();
return ret;
} }
void hard_reset_now(void) void hard_reset_now(void)
...@@ -246,10 +258,13 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, ...@@ -246,10 +258,13 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
int error; int error;
char * filename; char * filename;
lock_kernel();
error = getname((char *) a0, &filename); error = getname((char *) a0, &filename);
if (error) if (error)
return error; goto out;
error = do_execve(filename, (char **) a1, (char **) a2, &regs); error = do_execve(filename, (char **) a1, (char **) a2, &regs);
putname(filename); putname(filename);
out:
unlock_kernel();
return error; return error;
} }
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/user.h> #include <linux/user.h>
...@@ -487,27 +489,30 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, ...@@ -487,27 +489,30 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
int a4, int a5, struct pt_regs regs) int a4, int a5, struct pt_regs regs)
{ {
struct task_struct *child; struct task_struct *child;
struct user * dummy; long ret;
dummy = NULL;
lock_kernel();
DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n", DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",
request, pid, addr, data)); request, pid, addr, data));
ret = -EPERM;
if (request == PTRACE_TRACEME) { if (request == PTRACE_TRACEME) {
/* are we already being traced? */ /* are we already being traced? */
if (current->flags & PF_PTRACED) if (current->flags & PF_PTRACED)
return -EPERM; goto out;
/* set the ptrace bit in the process flags. */ /* set the ptrace bit in the process flags. */
current->flags |= PF_PTRACED; current->flags |= PF_PTRACED;
return 0; ret = 0;
goto out;
} }
if (pid == 1) /* you may not mess with init */ if (pid == 1) /* you may not mess with init */
return -EPERM; goto out;
ret = -ESRCH;
if (!(child = get_task(pid))) if (!(child = get_task(pid)))
return -ESRCH; goto out;
if (request == PTRACE_ATTACH) { if (request == PTRACE_ATTACH) {
ret = -EPERM;
if (child == current) if (child == current)
return -EPERM; goto out;
if ((!child->dumpable || if ((!child->dumpable ||
(current->uid != child->euid) || (current->uid != child->euid) ||
(current->uid != child->suid) || (current->uid != child->suid) ||
...@@ -515,10 +520,10 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, ...@@ -515,10 +520,10 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
(current->gid != child->egid) || (current->gid != child->egid) ||
(current->gid != child->sgid) || (current->gid != child->sgid) ||
(current->gid != child->gid)) && !suser()) (current->gid != child->gid)) && !suser())
return -EPERM; goto out;
/* the same process cannot be attached many times */ /* the same process cannot be attached many times */
if (child->flags & PF_PTRACED) if (child->flags & PF_PTRACED)
return -EPERM; goto out;
child->flags |= PF_PTRACED; child->flags |= PF_PTRACED;
if (child->p_pptr != current) { if (child->p_pptr != current) {
REMOVE_LINKS(child); REMOVE_LINKS(child);
...@@ -526,20 +531,22 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, ...@@ -526,20 +531,22 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
SET_LINKS(child); SET_LINKS(child);
} }
send_sig(SIGSTOP, child, 1); send_sig(SIGSTOP, child, 1);
return 0; ret = 0;
goto out;
} }
ret = -ESRCH;
if (!(child->flags & PF_PTRACED)) { if (!(child->flags & PF_PTRACED)) {
DBG(DBG_MEM, ("child not traced\n")); DBG(DBG_MEM, ("child not traced\n"));
return -ESRCH; goto out;
} }
if (child->state != TASK_STOPPED) { if (child->state != TASK_STOPPED) {
DBG(DBG_MEM, ("child process not stopped\n")); DBG(DBG_MEM, ("child process not stopped\n"));
if (request != PTRACE_KILL) if (request != PTRACE_KILL)
return -ESRCH; goto out;
} }
if (child->p_pptr != current) { if (child->p_pptr != current) {
DBG(DBG_MEM, ("child not parent of this process\n")); DBG(DBG_MEM, ("child not parent of this process\n"));
return -ESRCH; goto out;
} }
switch (request) { switch (request) {
...@@ -547,37 +554,41 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, ...@@ -547,37 +554,41 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: { case PTRACE_PEEKDATA: {
unsigned long tmp; unsigned long tmp;
int res;
res = read_long(child, addr, &tmp); ret = read_long(child, addr, &tmp);
DBG(DBG_MEM, ("peek %#lx->%#lx\n", addr, tmp)); DBG(DBG_MEM, ("peek %#lx->%#lx\n", addr, tmp));
if (res < 0) if (ret < 0)
return res; goto out;
regs.r0 = 0; /* special return: no errors */ regs.r0 = 0; /* special return: no errors */
return tmp; ret = tmp;
goto out;
} }
/* read register number ADDR. */ /* read register number ADDR. */
case PTRACE_PEEKUSR: case PTRACE_PEEKUSR:
regs.r0 = 0; /* special return: no errors */ regs.r0 = 0; /* special return: no errors */
DBG(DBG_MEM, ("peek $%ld=%#lx\n", addr, regs.r0)); DBG(DBG_MEM, ("peek $%ld=%#lx\n", addr, regs.r0));
return get_reg(child, addr); ret = get_reg(child, addr);
goto out;
/* when I and D space are separate, this will have to be fixed. */ /* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA: case PTRACE_POKEDATA:
DBG(DBG_MEM, ("poke %#lx<-%#lx\n", addr, data)); DBG(DBG_MEM, ("poke %#lx<-%#lx\n", addr, data));
return write_long(child, addr, data); ret = write_long(child, addr, data);
goto out;
case PTRACE_POKEUSR: /* write the specified register */ case PTRACE_POKEUSR: /* write the specified register */
DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data)); DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data));
return put_reg(child, addr, data); ret = put_reg(child, addr, data);
goto out;
case PTRACE_SYSCALL: /* continue and stop at next case PTRACE_SYSCALL: /* continue and stop at next
(return from) syscall */ (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */ case PTRACE_CONT: { /* restart after signal. */
ret = -EIO;
if ((unsigned long) data > NSIG) if ((unsigned long) data > NSIG)
return -EIO; goto out;
if (request == PTRACE_SYSCALL) if (request == PTRACE_SYSCALL)
child->flags |= PF_TRACESYS; child->flags |= PF_TRACESYS;
else else
...@@ -586,7 +597,8 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, ...@@ -586,7 +597,8 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
wake_up_process(child); wake_up_process(child);
/* make sure single-step breakpoint is gone. */ /* make sure single-step breakpoint is gone. */
ptrace_cancel_bpt(child); ptrace_cancel_bpt(child);
return data; ret = data;
goto out;
} }
/* /*
...@@ -601,23 +613,27 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, ...@@ -601,23 +613,27 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
} }
/* make sure single-step breakpoint is gone. */ /* make sure single-step breakpoint is gone. */
ptrace_cancel_bpt(child); ptrace_cancel_bpt(child);
return 0; ret = 0;
goto out;
} }
case PTRACE_SINGLESTEP: { /* execute single instruction. */ case PTRACE_SINGLESTEP: { /* execute single instruction. */
ret = -EIO;
if ((unsigned long) data > NSIG) if ((unsigned long) data > NSIG)
return -EIO; goto out;
child->debugreg[4] = -1; /* mark single-stepping */ child->debugreg[4] = -1; /* mark single-stepping */
child->flags &= ~PF_TRACESYS; child->flags &= ~PF_TRACESYS;
wake_up_process(child); wake_up_process(child);
child->exit_code = data; child->exit_code = data;
/* give it a chance to run. */ /* give it a chance to run. */
return 0; ret = 0;
goto out;
} }
case PTRACE_DETACH: { /* detach a process that was attached. */ case PTRACE_DETACH: { /* detach a process that was attached. */
ret = -EIO;
if ((unsigned long) data > NSIG) if ((unsigned long) data > NSIG)
return -EIO; goto out;
child->flags &= ~(PF_PTRACED|PF_TRACESYS); child->flags &= ~(PF_PTRACED|PF_TRACESYS);
wake_up_process(child); wake_up_process(child);
child->exit_code = data; child->exit_code = data;
...@@ -626,19 +642,25 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, ...@@ -626,19 +642,25 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
SET_LINKS(child); SET_LINKS(child);
/* make sure single-step breakpoint is gone. */ /* make sure single-step breakpoint is gone. */
ptrace_cancel_bpt(child); ptrace_cancel_bpt(child);
return 0; ret = 0;
goto out;
} }
default: default:
return -EIO; ret = -EIO;
goto out;
} }
out:
unlock_kernel();
return ret;
} }
asmlinkage void syscall_trace(void) asmlinkage void syscall_trace(void)
{ {
lock_kernel();
if ((current->flags & (PF_PTRACED|PF_TRACESYS)) if ((current->flags & (PF_PTRACED|PF_TRACESYS))
!= (PF_PTRACED|PF_TRACESYS)) != (PF_PTRACED|PF_TRACESYS))
return; goto out;
current->exit_code = SIGTRAP; current->exit_code = SIGTRAP;
current->state = TASK_STOPPED; current->state = TASK_STOPPED;
notify_parent(current); notify_parent(current);
...@@ -651,4 +673,6 @@ asmlinkage void syscall_trace(void) ...@@ -651,4 +673,6 @@ asmlinkage void syscall_trace(void)
if (current->exit_code) if (current->exit_code)
current->signal |= (1 << (current->exit_code - 1)); current->signal |= (1 << (current->exit_code - 1));
current->exit_code = 0; current->exit_code = 0;
out:
unlock_kernel();
} }
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -38,6 +40,9 @@ extern int ptrace_cancel_bpt (struct task_struct *child); ...@@ -38,6 +40,9 @@ extern int ptrace_cancel_bpt (struct task_struct *child);
* *
* We change the range to -1 .. 1 in order to let gcc easily * We change the range to -1 .. 1 in order to let gcc easily
* use the conditional move instructions. * use the conditional move instructions.
*
* Note that we don't need to aquire the kernel lock for SMP
* operation, as all of this is local to this thread.
*/ */
asmlinkage unsigned long osf_sigprocmask(int how, unsigned long newmask, asmlinkage unsigned long osf_sigprocmask(int how, unsigned long newmask,
long a2, long a3, long a4, long a5, struct pt_regs regs) long a2, long a3, long a4, long a5, struct pt_regs regs)
...@@ -73,14 +78,20 @@ asmlinkage unsigned long osf_sigprocmask(int how, unsigned long newmask, ...@@ -73,14 +78,20 @@ asmlinkage unsigned long osf_sigprocmask(int how, unsigned long newmask,
*/ */
asmlinkage int do_sigsuspend(unsigned long mask, struct pt_regs * regs, struct switch_stack * sw) asmlinkage int do_sigsuspend(unsigned long mask, struct pt_regs * regs, struct switch_stack * sw)
{ {
unsigned long oldmask = current->blocked; unsigned long oldmask;
lock_kernel();
oldmask = current->blocked;
current->blocked = mask & _BLOCKABLE; current->blocked = mask & _BLOCKABLE;
while (1) { while (1) {
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
schedule(); schedule();
if (do_signal(oldmask,regs, sw, 0, 0)) if (do_signal(oldmask,regs, sw, 0, 0))
return -EINTR; goto out;
} }
out:
unlock_kernel();
return -EINTR;
} }
/* /*
...@@ -93,6 +104,7 @@ asmlinkage void do_sigreturn(struct sigcontext * sc, ...@@ -93,6 +104,7 @@ asmlinkage void do_sigreturn(struct sigcontext * sc,
int i; int i;
/* verify that it's a good sigcontext before using it */ /* verify that it's a good sigcontext before using it */
lock_kernel();
if (verify_area(VERIFY_READ, sc, sizeof(*sc))) if (verify_area(VERIFY_READ, sc, sizeof(*sc)))
do_exit(SIGSEGV); do_exit(SIGSEGV);
get_user(ps, &sc->sc_ps); get_user(ps, &sc->sc_ps);
...@@ -145,6 +157,7 @@ asmlinkage void do_sigreturn(struct sigcontext * sc, ...@@ -145,6 +157,7 @@ asmlinkage void do_sigreturn(struct sigcontext * sc,
/* send SIGTRAP if we're single-stepping: */ /* send SIGTRAP if we're single-stepping: */
if (ptrace_cancel_bpt (current)) if (ptrace_cancel_bpt (current))
send_sig(SIGTRAP, current, 1); send_sig(SIGTRAP, current, 1);
unlock_kernel();
} }
/* /*
...@@ -279,10 +292,13 @@ asmlinkage int do_signal(unsigned long oldmask, ...@@ -279,10 +292,13 @@ asmlinkage int do_signal(unsigned long oldmask,
struct switch_stack * sw, struct switch_stack * sw,
unsigned long r0, unsigned long r19) unsigned long r0, unsigned long r19)
{ {
unsigned long mask = ~current->blocked; unsigned long mask;
unsigned long signr, single_stepping; unsigned long signr, single_stepping;
struct sigaction * sa; struct sigaction * sa;
int ret;
lock_kernel();
mask = ~current->blocked;
single_stepping = ptrace_cancel_bpt(current); single_stepping = ptrace_cancel_bpt(current);
while ((signr = current->signal & mask) != 0) { while ((signr = current->signal & mask) != 0) {
...@@ -356,7 +372,8 @@ asmlinkage int do_signal(unsigned long oldmask, ...@@ -356,7 +372,8 @@ asmlinkage int do_signal(unsigned long oldmask,
if (single_stepping) { if (single_stepping) {
ptrace_set_bpt(current); /* re-set breakpoint */ ptrace_set_bpt(current); /* re-set breakpoint */
} }
return 1; ret = 1;
goto out;
} }
if (r0 && if (r0 &&
(regs->r0 == ERESTARTNOHAND || (regs->r0 == ERESTARTNOHAND ||
...@@ -369,5 +386,8 @@ asmlinkage int do_signal(unsigned long oldmask, ...@@ -369,5 +386,8 @@ asmlinkage int do_signal(unsigned long oldmask,
if (single_stepping) { if (single_stepping) {
ptrace_set_bpt(current); /* re-set breakpoint */ ptrace_set_bpt(current); /* re-set breakpoint */
} }
return 0; ret = 0;
out:
unlock_kernel();
return ret;
} }
...@@ -21,15 +21,16 @@ void die_if_kernel(char * str, struct pt_regs * regs, long err, ...@@ -21,15 +21,16 @@ void die_if_kernel(char * str, struct pt_regs * regs, long err,
unsigned long *r9_15) unsigned long *r9_15)
{ {
long i; long i;
unsigned long sp; unsigned long sp, ra;
unsigned int * pc; unsigned int * pc;
if (regs->ps & 8) if (regs->ps & 8)
return; return;
printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err); printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err);
sp = (unsigned long) (regs+1); sp = (unsigned long) (regs+1);
__get_user(ra, (unsigned long *)sp);
printk("pc = [<%016lx>] ps = %04lx\n", regs->pc, regs->ps); printk("pc = [<%016lx>] ps = %04lx\n", regs->pc, regs->ps);
printk("rp = [<%016lx>] sp = %016lx\n", regs->r26, sp); printk("rp = [<%016lx>] ra = [<%016lx>]\n", regs->r26, ra);
printk("r0 = %016lx r1 = %016lx\n", regs->r0, regs->r1); printk("r0 = %016lx r1 = %016lx\n", regs->r0, regs->r1);
printk("r2 = %016lx r3 = %016lx\n", regs->r2, regs->r3); printk("r2 = %016lx r3 = %016lx\n", regs->r2, regs->r3);
printk("r4 = %016lx r5 = %016lx\n", regs->r4, regs->r5); printk("r4 = %016lx r5 = %016lx\n", regs->r4, regs->r5);
...@@ -49,13 +50,17 @@ void die_if_kernel(char * str, struct pt_regs * regs, long err, ...@@ -49,13 +50,17 @@ void die_if_kernel(char * str, struct pt_regs * regs, long err,
printk("r20= %016lx r21= %016lx\n", regs->r20, regs->r21); printk("r20= %016lx r21= %016lx\n", regs->r20, regs->r21);
printk("r22= %016lx r23= %016lx\n", regs->r22, regs->r23); printk("r22= %016lx r23= %016lx\n", regs->r22, regs->r23);
printk("r24= %016lx r25= %016lx\n", regs->r24, regs->r25); printk("r24= %016lx r25= %016lx\n", regs->r24, regs->r25);
printk("r26= %016lx r27= %016lx\n", regs->r26, regs->r27); printk("r27= %016lx r28= %016lx\n", regs->r27, regs->r28);
printk("r28= %016lx r29= %016lx\n", regs->r28, regs->gp); printk("gp = %016lx sp = %016lx\n", regs->gp, sp);
printk("Code:"); printk("Code:");
pc = (unsigned int *) regs->pc; pc = (unsigned int *) regs->pc;
for (i = -3; i < 6; i++) for (i = -3; i < 6; i++) {
printk("%c%08x%c",i?' ':'<',pc[i],i?' ':'>'); unsigned int insn;
if (__get_user(insn, pc+i))
break;
printk("%c%08x%c",i?' ':'<',insn,i?' ':'>');
}
printk("\n"); printk("\n");
do_exit(SIGSEGV); do_exit(SIGSEGV);
} }
......
...@@ -171,6 +171,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem) ...@@ -171,6 +171,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
return; return;
} }
void free_initmem(void)
{
/* To be written */
}
void si_meminfo(struct sysinfo *val) void si_meminfo(struct sysinfo *val)
{ {
int i; int i;
......
...@@ -111,7 +111,6 @@ install: vmlinux ...@@ -111,7 +111,6 @@ install: vmlinux
archclean: archclean:
@$(MAKEBOOT) clean @$(MAKEBOOT) clean
$(MAKE) -C arch/$(ARCH)/kernel clean
archdep: archdep:
@$(MAKEBOOT) dep @$(MAKEBOOT) dep
...@@ -7,9 +7,6 @@ ...@@ -7,9 +7,6 @@
# #
# Note 2! The CFLAGS definitions are now in the main makefile... # Note 2! The CFLAGS definitions are now in the main makefile...
#.S.s:
# $(CPP) -D__ASSEMBLY__ -traditional $< -o $*.s
ifdef SMP ifdef SMP
.S.o: .S.o:
$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
...@@ -31,7 +28,7 @@ endif ...@@ -31,7 +28,7 @@ endif
ifdef SMP ifdef SMP
O_OBJS += smp.o O_OBJS += smp.o trampoline.o
head.o: head.S $(TOPDIR)/include/linux/tasks.h head.o: head.S $(TOPDIR)/include/linux/tasks.h
$(CC) -D__ASSEMBLY__ -D__SMP__ -traditional -c $*.S -o $*.o $(CC) -D__ASSEMBLY__ -D__SMP__ -traditional -c $*.S -o $*.o
...@@ -43,30 +40,4 @@ head.o: head.S $(TOPDIR)/include/linux/tasks.h ...@@ -43,30 +40,4 @@ head.o: head.S $(TOPDIR)/include/linux/tasks.h
endif endif
hexify:
$(HOSTCC) hexify.c -o hexify
smp.c: trampoline.hex
trampoline.hex: trampoline hexify
(dd if=trampoline bs=1 skip=32 | ./hexify >trampoline.hex )
trampoline: trampoline.o trampoline32.o
$(LD86) -s -o $@ trampoline.o trampoline32.o
trampoline.o: trampoline.s
$(AS86) -o $@ $<
trampoline32.o: trampoline32.s
$(AS386) -o $@ $<
trampoline.s: trampoline.S $(CONFIGURE) $(TOPDIR)/include/linux/config.h Makefile
$(CPP) -D__SMP__ -traditional $< -o $@
trampoline32.s: trampoline32.S $(CONFIGURE) $(TOPDIR)/include/linux/config.h Makefile
$(CPP) -D__SMP__ -traditional $< -o $@
clean:
rm -f trampoline hexify trampoline.hex
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
...@@ -97,98 +97,7 @@ ENOSYS = 38 ...@@ -97,98 +97,7 @@ ENOSYS = 38
mov %dx,%ds; \ mov %dx,%ds; \
mov %dx,%es; mov %dx,%es;
#ifdef __SMP__
#define GET_PROCESSOR_ID \
movl SYMBOL_NAME(apic_reg), %edx; \
movl 32(%edx), %eax;\
movl %eax,SYMBOL_NAME(apic_retval); \
shrl $24,%eax; \
andb $0x0F,%al;
/*
* Get the processor ID multiplied by 4
*/
#define GET_PROCESSOR_OFFSET(x) \
movl SYMBOL_NAME(apic_reg), x ; \
movl 32( x ), x ; \
shrl $22, x ; \
andl $0x3C, x ;
/* macro LEAVE_KERNEL decrements kernel_counter and resets kernel_flag and
saves processor variables if zero */
#define LEAVE_KERNEL \
pushfl; \
cli; \
GET_PROCESSOR_ID \
btrl $ SMP_FROM_SYSCALL,SYMBOL_NAME(smp_proc_in_lock)(,%eax,4); \
decl SYMBOL_NAME(syscall_count); \
decl SYMBOL_NAME(kernel_counter); \
jnz 1f; \
movb $(NO_PROC_ID), SYMBOL_NAME(active_kernel_processor); \
lock; \
btrl $0, SYMBOL_NAME(kernel_flag); \
1: popfl;
/* macro ENTER_KERNEL waits for entering the kernel, increments
kernel_counter, and reloads the processor variables if necessary
uses : %eax, %edx (pushed and popped)
Note: We go to great pains to minimise the number of locked operations.
We want to spin without locking, and lock when we attempt an update.
The pentium has a MESI cache so the spin without lock will exit when
another CPU write invalidates our cache, and the lock is avoided when
possible so we don't play ping-pong games with the cache line.
*/
#ifndef __SMP_PROF__
#define SMP_PROF_A
#define SMP_PROF_B
#else
#define SMP_PROF_A movl $0,SYMBOL_NAME(smp_spins_syscall_cur)(,%eax,4);
#define SMP_PROF_B incl SYMBOL_NAME(smp_spins_syscall)(,%eax,4); \
incl SYMBOL_NAME(smp_spins_syscall_cur)(,%eax,4);
#endif
#define ENTER_KERNEL \
pushl %eax; \
pushl %edx; \
pushfl; \
cli; \
GET_PROCESSOR_ID \
btsl $ SMP_FROM_SYSCALL,SYMBOL_NAME(smp_proc_in_lock)(,%eax,4); \
SMP_PROF_A \
1: lock; \
btsl $0, SYMBOL_NAME(kernel_flag); \
jnc 3f; \
cmpb SYMBOL_NAME(active_kernel_processor), %al; \
je 4f; \
2: SMP_PROF_B \
btl %al, SYMBOL_NAME(smp_invalidate_needed); \
jnc 5f; \
lock; \
btrl %al, SYMBOL_NAME(smp_invalidate_needed); \
jnc 5f; \
movl %cr3,%edx; \
movl %edx,%cr3; \
5: btl $0, SYMBOL_NAME(kernel_flag); \
jc 2b; \
jmp 1b; \
3: movb %al, SYMBOL_NAME(active_kernel_processor); \
4: incl SYMBOL_NAME(kernel_counter); \
incl SYMBOL_NAME(syscall_count); \
popfl; \
popl %edx; \
popl %eax;
#define RESTORE_ALL \ #define RESTORE_ALL \
LEAVE_KERNEL \
popl %ebx; \ popl %ebx; \
popl %ecx; \ popl %ecx; \
popl %edx; \ popl %edx; \
...@@ -201,38 +110,30 @@ ENOSYS = 38 ...@@ -201,38 +110,30 @@ ENOSYS = 38
addl $4,%esp; \ addl $4,%esp; \
iret iret
#define GET_CURRENT \ #ifdef __SMP__
GET_PROCESSOR_OFFSET(%ebx) \ /* Get the processor ID multiplied by 4 */
movl SYMBOL_NAME(current_set)(%ebx),%ebx #define GET_PROCESSOR_OFFSET(reg) \
movl SYMBOL_NAME(apic_reg), reg; \
movl 32(reg), reg; \
shrl $22, reg; \
andl $0x3C, reg;
#define GET_CURRENT(reg) \
GET_PROCESSOR_OFFSET(reg) \
movl SYMBOL_NAME(current_set)(reg),reg
#else #else
#define GET_CURRENT \ #define GET_CURRENT(reg) \
movl SYMBOL_NAME(current_set),%ebx movl SYMBOL_NAME(current_set),reg
#define RESTORE_ALL \
popl %ebx; \
popl %ecx; \
popl %edx; \
popl %esi; \
popl %edi; \
popl %ebp; \
popl %eax; \
pop %ds; \
pop %es; \
addl $4,%esp; \
iret
#endif #endif
ENTRY(lcall7) ENTRY(lcall7)
pushfl # We get a different stack layout with call gates, pushfl # We get a different stack layout with call gates,
pushl %eax # which has to be cleaned up later.. pushl %eax # which has to be cleaned up later..
SAVE_ALL SAVE_ALL
GET_CURRENT GET_CURRENT(%ebx)
#ifdef __SMP__
ENTER_KERNEL
#endif
movl EIP(%esp),%eax # due to call gates, this is eflags, not eip.. movl EIP(%esp),%eax # due to call gates, this is eflags, not eip..
movl CS(%esp),%edx # this is eip.. movl CS(%esp),%edx # this is eip..
movl EFLAGS(%esp),%ecx # and this is cs.. movl EFLAGS(%esp),%ecx # and this is cs..
...@@ -240,12 +141,7 @@ ENTRY(lcall7) ...@@ -240,12 +141,7 @@ ENTRY(lcall7)
movl %edx,EIP(%esp) # Now we move them to their "normal" places movl %edx,EIP(%esp) # Now we move them to their "normal" places
movl %ecx,CS(%esp) # movl %ecx,CS(%esp) #
movl %esp,%eax movl %esp,%eax
#ifdef __SMP__ GET_CURRENT(%edx)
GET_PROCESSOR_OFFSET(%edx) # Processor offset into edx
movl SYMBOL_NAME(current_set)(,%edx),%edx
#else
movl SYMBOL_NAME(current_set),%edx
#endif
pushl %eax pushl %eax
movl exec_domain(%edx),%edx # Get the execution domain movl exec_domain(%edx),%edx # Get the execution domain
movl 4(%edx),%edx # Get the lcall7 handler for the domain movl 4(%edx),%edx # Get the lcall7 handler for the domain
...@@ -253,12 +149,23 @@ ENTRY(lcall7) ...@@ -253,12 +149,23 @@ ENTRY(lcall7)
popl %eax popl %eax
jmp ret_from_sys_call jmp ret_from_sys_call
#ifdef __SMP__
ALIGN
.globl ret_from_smpfork
ret_from_smpfork:
GET_CURRENT(%ebx)
movl $NO_PROC_ID, SYMBOL_NAME(active_kernel_processor)
lock
btrl $0, SYMBOL_NAME(kernel_flag)
sti
jmp 9f
#endif /* __SMP__ */
ALIGN ALIGN
handle_bottom_half: handle_bottom_half:
incl SYMBOL_NAME(intr_count) pushl $9f
call SYMBOL_NAME(do_bottom_half) jmp SYMBOL_NAME(do_bottom_half)
decl SYMBOL_NAME(intr_count)
jmp 9f
ALIGN ALIGN
reschedule: reschedule:
pushl $ret_from_sys_call pushl $ret_from_sys_call
...@@ -267,10 +174,7 @@ reschedule: ...@@ -267,10 +174,7 @@ reschedule:
ENTRY(system_call) ENTRY(system_call)
pushl %eax # save orig_eax pushl %eax # save orig_eax
SAVE_ALL SAVE_ALL
GET_CURRENT GET_CURRENT(%ebx)
#ifdef __SMP__
ENTER_KERNEL
#endif
cmpl $(NR_syscalls),%eax cmpl $(NR_syscalls),%eax
jae badsys jae badsys
testb $0x20,flags(%ebx) # PF_TRACESYS testb $0x20,flags(%ebx) # PF_TRACESYS
...@@ -280,9 +184,7 @@ ENTRY(system_call) ...@@ -280,9 +184,7 @@ ENTRY(system_call)
ALIGN ALIGN
.globl ret_from_sys_call .globl ret_from_sys_call
ret_from_sys_call: ret_from_sys_call:
#ifdef __SMP__ GET_CURRENT(%ebx)
GET_CURRENT
#endif
cmpl $0,SYMBOL_NAME(intr_count) cmpl $0,SYMBOL_NAME(intr_count)
jne 1f jne 1f
9: movl SYMBOL_NAME(bh_mask),%eax 9: movl SYMBOL_NAME(bh_mask),%eax
...@@ -358,10 +260,7 @@ error_code: ...@@ -358,10 +260,7 @@ error_code:
movl $(KERNEL_DS),%edx movl $(KERNEL_DS),%edx
mov %dx,%ds mov %dx,%ds
mov %dx,%es mov %dx,%es
GET_CURRENT GET_CURRENT(%ebx)
#ifdef __SMP__
ENTER_KERNEL
#endif
call *%ecx call *%ecx
addl $8,%esp addl $8,%esp
jmp ret_from_sys_call jmp ret_from_sys_call
...@@ -374,10 +273,7 @@ ENTRY(coprocessor_error) ...@@ -374,10 +273,7 @@ ENTRY(coprocessor_error)
ENTRY(device_not_available) ENTRY(device_not_available)
pushl $-1 # mark this as an int pushl $-1 # mark this as an int
SAVE_ALL SAVE_ALL
GET_CURRENT GET_CURRENT(%ebx)
#ifdef __SMP__
ENTER_KERNEL
#endif
pushl $ret_from_sys_call pushl $ret_from_sys_call
movl %cr0,%eax movl %cr0,%eax
testl $0x4,%eax # EM (math emulation bit) testl $0x4,%eax # EM (math emulation bit)
......
#include <stdio.h>
void main()
{
int c;
int comma=0;
int count=0;
while((c=getchar())!=EOF)
{
unsigned char x=c;
if(comma)
printf(",");
else
comma=1;
if(count==8)
{
count=0;
printf("\n");
}
if(count==0)
printf("\t");
printf("0x%02X",c);
count++;
}
if(count)
printf("\n");
exit(0);
}
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <linux/user.h> #include <linux/user.h>
#include <linux/elfcore.h> #include <linux/elfcore.h>
#include <linux/mca.h> #include <linux/mca.h>
#include <linux/sched.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <asm/processor.h> #include <asm/processor.h>
...@@ -12,6 +13,7 @@ ...@@ -12,6 +13,7 @@
extern void dump_thread(struct pt_regs *, struct user *); extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(elf_fpregset_t *); extern int dump_fpu(elf_fpregset_t *);
extern void __lock_kernel(void);
/* platform dependent support */ /* platform dependent support */
EXPORT_SYMBOL(EISA_bus); EXPORT_SYMBOL(EISA_bus);
...@@ -28,11 +30,10 @@ EXPORT_SYMBOL_NOVERS(__up_wakeup); ...@@ -28,11 +30,10 @@ EXPORT_SYMBOL_NOVERS(__up_wakeup);
#ifdef __SMP__ #ifdef __SMP__
EXPORT_SYMBOL(apic_reg); /* Needed internally for the I386 inlines */ EXPORT_SYMBOL(apic_reg); /* Needed internally for the I386 inlines */
EXPORT_SYMBOL(cpu_data); EXPORT_SYMBOL(cpu_data);
EXPORT_SYMBOL(syscall_count);
EXPORT_SYMBOL(kernel_flag); EXPORT_SYMBOL(kernel_flag);
EXPORT_SYMBOL(kernel_counter);
EXPORT_SYMBOL(active_kernel_processor); EXPORT_SYMBOL(active_kernel_processor);
EXPORT_SYMBOL(smp_invalidate_needed); EXPORT_SYMBOL(smp_invalidate_needed);
EXPORT_SYMBOL_NOVERS(__lock_kernel);
#endif #endif
#ifdef CONFIG_MCA #ifdef CONFIG_MCA
......
...@@ -10,6 +10,9 @@ ...@@ -10,6 +10,9 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
static void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value) static void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value)
...@@ -50,15 +53,19 @@ static void set_bitmap(unsigned long *bitmap, short base, short extent, int new_ ...@@ -50,15 +53,19 @@ static void set_bitmap(unsigned long *bitmap, short base, short extent, int new_
*/ */
asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on) asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
{ {
if (from + num <= from) int ret = -EINVAL;
return -EINVAL;
if (from + num > IO_BITMAP_SIZE*32)
return -EINVAL;
if (!suser())
return -EPERM;
lock_kernel();
if ((from + num <= from) || (from + num > IO_BITMAP_SIZE*32))
goto out;
ret = -EPERM;
if (!suser())
goto out;
set_bitmap((unsigned long *)current->tss.io_bitmap, from, num, !turn_on); set_bitmap((unsigned long *)current->tss.io_bitmap, from, num, !turn_on);
return 0; ret = 0;
out:
unlock_kernel();
return ret;
} }
unsigned int *stack; unsigned int *stack;
...@@ -79,11 +86,17 @@ asmlinkage int sys_iopl(long ebx,long ecx,long edx, ...@@ -79,11 +86,17 @@ asmlinkage int sys_iopl(long ebx,long ecx,long edx,
long eflags, long esp, long ss) long eflags, long esp, long ss)
{ {
unsigned int level = ebx; unsigned int level = ebx;
int ret = -EINVAL;
lock_kernel();
if (level > 3) if (level > 3)
return -EINVAL; goto out;
ret = -EPERM;
if (!suser()) if (!suser())
return -EPERM; goto out;
*(&eflags) = (eflags & 0xffffcfff) | (level << 12); *(&eflags) = (eflags & 0xffffcfff) | (level << 12);
return 0; ret = 0;
out:
unlock_kernel();
return ret;
} }
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include <linux/timex.h> #include <linux/timex.h>
#include <linux/malloc.h> #include <linux/malloc.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -346,6 +348,8 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) ...@@ -346,6 +348,8 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
struct irqaction * action = *(irq + irq_action); struct irqaction * action = *(irq + irq_action);
int do_random = 0; int do_random = 0;
lock_kernel();
intr_count++;
#ifdef __SMP__ #ifdef __SMP__
if(smp_threads_ready && active_kernel_processor!=smp_processor_id()) if(smp_threads_ready && active_kernel_processor!=smp_processor_id())
panic("IRQ %d: active processor set wrongly(%d not %d).\n", irq, active_kernel_processor, smp_processor_id()); panic("IRQ %d: active processor set wrongly(%d not %d).\n", irq, active_kernel_processor, smp_processor_id());
...@@ -362,6 +366,8 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs) ...@@ -362,6 +366,8 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
} }
if (do_random & SA_SAMPLE_RANDOM) if (do_random & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq); add_interrupt_randomness(irq);
intr_count--;
unlock_kernel();
} }
/* /*
...@@ -374,6 +380,8 @@ asmlinkage void do_fast_IRQ(int irq) ...@@ -374,6 +380,8 @@ asmlinkage void do_fast_IRQ(int irq)
struct irqaction * action = *(irq + irq_action); struct irqaction * action = *(irq + irq_action);
int do_random = 0; int do_random = 0;
lock_kernel();
intr_count++;
#ifdef __SMP__ #ifdef __SMP__
/* IRQ 13 is allowed - that's a flush tlb */ /* IRQ 13 is allowed - that's a flush tlb */
if(smp_threads_ready && active_kernel_processor!=smp_processor_id() && irq!=13) if(smp_threads_ready && active_kernel_processor!=smp_processor_id() && irq!=13)
...@@ -391,6 +399,8 @@ asmlinkage void do_fast_IRQ(int irq) ...@@ -391,6 +399,8 @@ asmlinkage void do_fast_IRQ(int irq)
} }
if (do_random & SA_SAMPLE_RANDOM) if (do_random & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq); add_interrupt_randomness(irq);
intr_count--;
unlock_kernel();
} }
int setup_x86_irq(int irq, struct irqaction * new) int setup_x86_irq(int irq, struct irqaction * new)
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -117,11 +119,17 @@ static int write_ldt(void * ptr, unsigned long bytecount, int oldmode) ...@@ -117,11 +119,17 @@ static int write_ldt(void * ptr, unsigned long bytecount, int oldmode)
asmlinkage int sys_modify_ldt(int func, void *ptr, unsigned long bytecount) asmlinkage int sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
{ {
int ret;
lock_kernel();
if (func == 0) if (func == 0)
return read_ldt(ptr, bytecount); ret = read_ldt(ptr, bytecount);
if (func == 1) else if (func == 1)
return write_ldt(ptr, bytecount, 1); ret = write_ldt(ptr, bytecount, 1);
if (func == 0x11) else if (func == 0x11)
return write_ldt(ptr, bytecount, 0); ret = write_ldt(ptr, bytecount, 0);
return -ENOSYS; else
ret = -ENOSYS;
unlock_kernel();
return ret;
} }
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
...@@ -34,7 +36,11 @@ ...@@ -34,7 +36,11 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/ldt.h> #include <asm/ldt.h>
#ifdef __SMP__
asmlinkage void ret_from_smpfork(void) __asm__("ret_from_smpfork");
#else
asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call"); asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
#endif
#ifdef CONFIG_APM #ifdef CONFIG_APM
extern int apm_do_idle(void); extern int apm_do_idle(void);
...@@ -91,9 +97,11 @@ static void hard_idle(void) ...@@ -91,9 +97,11 @@ static void hard_idle(void)
asmlinkage int sys_idle(void) asmlinkage int sys_idle(void)
{ {
unsigned long start_idle = 0; unsigned long start_idle = 0;
int ret = -EPERM;
lock_kernel();
if (current->pid != 0) if (current->pid != 0)
return -EPERM; goto out;
/* endless idle loop with no priority at all */ /* endless idle loop with no priority at all */
current->counter = -100; current->counter = -100;
for (;;) for (;;)
...@@ -118,6 +126,10 @@ asmlinkage int sys_idle(void) ...@@ -118,6 +126,10 @@ asmlinkage int sys_idle(void)
start_idle = 0; start_idle = 0;
schedule(); schedule();
} }
ret = 0;
out:
unlock_kernel();
return ret;
} }
#else #else
...@@ -129,15 +141,21 @@ asmlinkage int sys_idle(void) ...@@ -129,15 +141,21 @@ asmlinkage int sys_idle(void)
asmlinkage int sys_idle(void) asmlinkage int sys_idle(void)
{ {
int ret = -EPERM;
lock_kernel();
if(current->pid != 0) if(current->pid != 0)
return -EPERM; goto out;
#ifdef __SMP_PROF__ #ifdef __SMP_PROF__
smp_spins_sys_idle[smp_processor_id()]+= smp_spins_sys_idle[smp_processor_id()]+=
smp_spins_syscall_cur[smp_processor_id()]; smp_spins_syscall_cur[smp_processor_id()];
#endif #endif
current->counter= -100; current->counter= -100;
schedule(); schedule();
return 0; ret = 0;
out:
unlock_kernel();
return ret;
} }
/* /*
...@@ -150,9 +168,10 @@ int cpu_idle(void *unused) ...@@ -150,9 +168,10 @@ int cpu_idle(void *unused)
{ {
if(cpu_data[smp_processor_id()].hlt_works_ok && !hlt_counter && !need_resched) if(cpu_data[smp_processor_id()].hlt_works_ok && !hlt_counter && !need_resched)
__asm("hlt"); __asm("hlt");
if(0==(0x7fffffff & smp_process_available)) if(0==(read_smp_counter(&smp_process_available)))
continue; continue;
while(0x80000000 & smp_process_available); while(0x80000000 & smp_process_available)
;
cli(); cli();
while(set_bit(31,&smp_process_available)) while(set_bit(31,&smp_process_available))
while(test_bit(31,&smp_process_available)) while(test_bit(31,&smp_process_available))
...@@ -163,7 +182,7 @@ int cpu_idle(void *unused) ...@@ -163,7 +182,7 @@ int cpu_idle(void *unused)
if(clear_bit(smp_processor_id(), &smp_invalidate_needed)) if(clear_bit(smp_processor_id(), &smp_invalidate_needed))
local_flush_tlb(); local_flush_tlb();
} }
if (0==(0x7fffffff & smp_process_available)){ if (0==(read_smp_counter(&smp_process_available))) {
clear_bit(31,&smp_process_available); clear_bit(31,&smp_process_available);
sti(); sti();
continue; continue;
...@@ -473,13 +492,18 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, ...@@ -473,13 +492,18 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
p->tss.tr = _TSS(nr); p->tss.tr = _TSS(nr);
childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1; childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1;
p->tss.esp = (unsigned long) childregs; p->tss.esp = (unsigned long) childregs;
#ifdef __SMP__
p->tss.eip = (unsigned long) ret_from_smpfork;
p->tss.eflags = regs->eflags & 0xffffcdff; /* iopl always 0 for a new process */
#else
p->tss.eip = (unsigned long) ret_from_sys_call; p->tss.eip = (unsigned long) ret_from_sys_call;
p->tss.eflags = regs->eflags & 0xffffcfff; /* iopl always 0 for a new process */
#endif
p->tss.ebx = (unsigned long) p; p->tss.ebx = (unsigned long) p;
*childregs = *regs; *childregs = *regs;
childregs->eax = 0; childregs->eax = 0;
childregs->esp = esp; childregs->esp = esp;
p->tss.back_link = 0; p->tss.back_link = 0;
p->tss.eflags = regs->eflags & 0xffffcfff; /* iopl is always 0 for a new process */
p->tss.ldt = _LDT(nr); p->tss.ldt = _LDT(nr);
if (p->ldt) { if (p->ldt) {
p->ldt = (struct desc_struct*) vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE); p->ldt = (struct desc_struct*) vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE);
...@@ -568,19 +592,28 @@ void dump_thread(struct pt_regs * regs, struct user * dump) ...@@ -568,19 +592,28 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
asmlinkage int sys_fork(struct pt_regs regs) asmlinkage int sys_fork(struct pt_regs regs)
{ {
return do_fork(SIGCHLD, regs.esp, &regs); int ret;
lock_kernel();
ret = do_fork(SIGCHLD, regs.esp, &regs);
unlock_kernel();
return ret;
} }
asmlinkage int sys_clone(struct pt_regs regs) asmlinkage int sys_clone(struct pt_regs regs)
{ {
unsigned long clone_flags; unsigned long clone_flags;
unsigned long newsp; unsigned long newsp;
int ret;
lock_kernel();
clone_flags = regs.ebx; clone_flags = regs.ebx;
newsp = regs.ecx; newsp = regs.ecx;
if (!newsp) if (!newsp)
newsp = regs.esp; newsp = regs.esp;
return do_fork(clone_flags, newsp, &regs); ret = do_fork(clone_flags, newsp, &regs);
unlock_kernel();
return ret;
} }
/* /*
...@@ -591,10 +624,13 @@ asmlinkage int sys_execve(struct pt_regs regs) ...@@ -591,10 +624,13 @@ asmlinkage int sys_execve(struct pt_regs regs)
int error; int error;
char * filename; char * filename;
lock_kernel();
error = getname((char *) regs.ebx, &filename); error = getname((char *) regs.ebx, &filename);
if (error) if (error)
return error; goto out;
error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs); error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);
putname(filename); putname(filename);
out:
unlock_kernel();
return error; return error;
} }
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/user.h> #include <linux/user.h>
...@@ -362,26 +364,29 @@ static unsigned long getreg(struct task_struct *child, ...@@ -362,26 +364,29 @@ static unsigned long getreg(struct task_struct *child,
asmlinkage int sys_ptrace(long request, long pid, long addr, long data) asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{ {
struct task_struct *child; struct task_struct *child;
struct user * dummy; struct user * dummy = NULL;
int i; int i, ret;
dummy = NULL;
lock_kernel();
ret = -EPERM;
if (request == PTRACE_TRACEME) { if (request == PTRACE_TRACEME) {
/* are we already being traced? */ /* are we already being traced? */
if (current->flags & PF_PTRACED) if (current->flags & PF_PTRACED)
return -EPERM; goto out;
/* set the ptrace bit in the process flags. */ /* set the ptrace bit in the process flags. */
current->flags |= PF_PTRACED; current->flags |= PF_PTRACED;
return 0; ret = 0;
goto out;
} }
if (pid == 1) /* you may not mess with init */ if (pid == 1) /* you may not mess with init */
return -EPERM; goto out;
ret = -ESRCH;
if (!(child = get_task(pid))) if (!(child = get_task(pid)))
return -ESRCH; goto out;
ret = -EPERM;
if (request == PTRACE_ATTACH) { if (request == PTRACE_ATTACH) {
if (child == current) if (child == current)
return -EPERM; goto out;
if ((!child->dumpable || if ((!child->dumpable ||
(current->uid != child->euid) || (current->uid != child->euid) ||
(current->uid != child->suid) || (current->uid != child->suid) ||
...@@ -389,10 +394,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -389,10 +394,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
(current->gid != child->egid) || (current->gid != child->egid) ||
(current->gid != child->sgid) || (current->gid != child->sgid) ||
(current->gid != child->gid)) && !suser()) (current->gid != child->gid)) && !suser())
return -EPERM; goto out;
/* the same process cannot be attached many times */ /* the same process cannot be attached many times */
if (child->flags & PF_PTRACED) if (child->flags & PF_PTRACED)
return -EPERM; goto out;
child->flags |= PF_PTRACED; child->flags |= PF_PTRACED;
if (child->p_pptr != current) { if (child->p_pptr != current) {
REMOVE_LINKS(child); REMOVE_LINKS(child);
...@@ -400,37 +405,39 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -400,37 +405,39 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
SET_LINKS(child); SET_LINKS(child);
} }
send_sig(SIGSTOP, child, 1); send_sig(SIGSTOP, child, 1);
return 0; ret = 0;
goto out;
} }
ret = -ESRCH;
if (!(child->flags & PF_PTRACED)) if (!(child->flags & PF_PTRACED))
return -ESRCH; goto out;
if (child->state != TASK_STOPPED) { if (child->state != TASK_STOPPED) {
if (request != PTRACE_KILL) if (request != PTRACE_KILL)
return -ESRCH; goto out;
} }
if (child->p_pptr != current) if (child->p_pptr != current)
return -ESRCH; goto out;
switch (request) { switch (request) {
/* when I and D space are separate, these will need to be fixed. */ /* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: { case PTRACE_PEEKDATA: {
unsigned long tmp; unsigned long tmp;
int res;
res = read_long(child, addr, &tmp); ret = read_long(child, addr, &tmp);
if (res < 0) if (ret >= 0)
return res; ret = put_user(tmp,(unsigned long *) data);
return put_user(tmp,(unsigned long *) data); goto out;
} }
/* read the word at location addr in the USER area. */ /* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: { case PTRACE_PEEKUSR: {
unsigned long tmp; unsigned long tmp;
ret = -EIO;
if ((addr & 3) || addr < 0 || if ((addr & 3) || addr < 0 ||
addr > sizeof(struct user) - 3) addr > sizeof(struct user) - 3)
return -EIO; goto out;
tmp = 0; /* Default return condition */ tmp = 0; /* Default return condition */
if(addr < 17*sizeof(long)) if(addr < 17*sizeof(long))
...@@ -441,21 +448,26 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -441,21 +448,26 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
addr = addr >> 2; addr = addr >> 2;
tmp = child->debugreg[addr]; tmp = child->debugreg[addr];
}; };
return put_user(tmp,(unsigned long *) data); ret = put_user(tmp,(unsigned long *) data);
goto out;
} }
/* when I and D space are separate, this will have to be fixed. */ /* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA: case PTRACE_POKEDATA:
return write_long(child,addr,data); ret = write_long(child,addr,data);
goto out;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
ret = -EIO;
if ((addr & 3) || addr < 0 || if ((addr & 3) || addr < 0 ||
addr > sizeof(struct user) - 3) addr > sizeof(struct user) - 3)
return -EIO; goto out;
if (addr < 17*sizeof(long)) if (addr < 17*sizeof(long)) {
return putreg(child, addr, data); ret = putreg(child, addr, data);
goto out;
}
/* We need to be very careful here. We implicitly /* We need to be very careful here. We implicitly
want to modify a portion of the task_struct, and we want to modify a portion of the task_struct, and we
...@@ -470,26 +482,30 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -470,26 +482,30 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
if(addr < (long) &dummy->u_debugreg[4] && if(addr < (long) &dummy->u_debugreg[4] &&
((unsigned long) data) >= 0xbffffffd) return -EIO; ((unsigned long) data) >= 0xbffffffd) return -EIO;
ret = -EIO;
if(addr == (long) &dummy->u_debugreg[7]) { if(addr == (long) &dummy->u_debugreg[7]) {
data &= ~DR_CONTROL_RESERVED; data &= ~DR_CONTROL_RESERVED;
for(i=0; i<4; i++) for(i=0; i<4; i++)
if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1) if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
return -EIO; goto out;
}; };
addr -= (long) &dummy->u_debugreg; addr -= (long) &dummy->u_debugreg;
addr = addr >> 2; addr = addr >> 2;
child->debugreg[addr] = data; child->debugreg[addr] = data;
return 0; ret = 0;
goto out;
}; };
return -EIO; ret = -EIO;
goto out;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */ case PTRACE_CONT: { /* restart after signal. */
long tmp; long tmp;
ret = -EIO;
if ((unsigned long) data > NSIG) if ((unsigned long) data > NSIG)
return -EIO; goto out;
if (request == PTRACE_SYSCALL) if (request == PTRACE_SYSCALL)
child->flags |= PF_TRACESYS; child->flags |= PF_TRACESYS;
else else
...@@ -499,7 +515,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -499,7 +515,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
/* make sure the single step bit is not set. */ /* make sure the single step bit is not set. */
tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
put_stack_long(child, EFL_OFFSET,tmp); put_stack_long(child, EFL_OFFSET,tmp);
return 0; ret = 0;
goto out;
} }
/* /*
...@@ -510,35 +527,39 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -510,35 +527,39 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_KILL: { case PTRACE_KILL: {
long tmp; long tmp;
ret = 0;
if (child->state == TASK_ZOMBIE) /* already dead */ if (child->state == TASK_ZOMBIE) /* already dead */
return 0; goto out;
wake_up_process(child); wake_up_process(child);
child->exit_code = SIGKILL; child->exit_code = SIGKILL;
/* make sure the single step bit is not set. */ /* make sure the single step bit is not set. */
tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
put_stack_long(child, EFL_OFFSET, tmp); put_stack_long(child, EFL_OFFSET, tmp);
return 0; goto out;
} }
case PTRACE_SINGLESTEP: { /* set the trap flag. */ case PTRACE_SINGLESTEP: { /* set the trap flag. */
long tmp; long tmp;
ret = -EIO;
if ((unsigned long) data > NSIG) if ((unsigned long) data > NSIG)
return -EIO; goto out;
child->flags &= ~PF_TRACESYS; child->flags &= ~PF_TRACESYS;
tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG; tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
put_stack_long(child, EFL_OFFSET, tmp); put_stack_long(child, EFL_OFFSET, tmp);
wake_up_process(child); wake_up_process(child);
child->exit_code = data; child->exit_code = data;
/* give it a chance to run. */ /* give it a chance to run. */
return 0; ret = 0;
goto out;
} }
case PTRACE_DETACH: { /* detach a process that was attached. */ case PTRACE_DETACH: { /* detach a process that was attached. */
long tmp; long tmp;
ret = -EIO;
if ((unsigned long) data > NSIG) if ((unsigned long) data > NSIG)
return -EIO; goto out;
child->flags &= ~(PF_PTRACED|PF_TRACESYS); child->flags &= ~(PF_PTRACED|PF_TRACESYS);
wake_up_process(child); wake_up_process(child);
child->exit_code = data; child->exit_code = data;
...@@ -548,19 +569,25 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -548,19 +569,25 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
/* make sure the single step bit is not set. */ /* make sure the single step bit is not set. */
tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
put_stack_long(child, EFL_OFFSET, tmp); put_stack_long(child, EFL_OFFSET, tmp);
return 0; ret = 0;
goto out;
} }
default: default:
return -EIO; ret = -EIO;
goto out;
} }
out:
unlock_kernel();
return ret;
} }
asmlinkage void syscall_trace(void) asmlinkage void syscall_trace(void)
{ {
lock_kernel();
if ((current->flags & (PF_PTRACED|PF_TRACESYS)) if ((current->flags & (PF_PTRACED|PF_TRACESYS))
!= (PF_PTRACED|PF_TRACESYS)) != (PF_PTRACED|PF_TRACESYS))
return; goto out;
current->exit_code = SIGTRAP; current->exit_code = SIGTRAP;
current->state = TASK_STOPPED; current->state = TASK_STOPPED;
notify_parent(current); notify_parent(current);
...@@ -573,4 +600,6 @@ asmlinkage void syscall_trace(void) ...@@ -573,4 +600,6 @@ asmlinkage void syscall_trace(void)
if (current->exit_code) if (current->exit_code)
current->signal |= (1 << (current->exit_code - 1)); current->signal |= (1 << (current->exit_code - 1));
current->exit_code = 0; current->exit_code = 0;
out:
unlock_kernel();
} }
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -30,8 +32,11 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs); ...@@ -30,8 +32,11 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs);
asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set) asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set)
{ {
unsigned long mask; unsigned long mask;
struct pt_regs * regs = (struct pt_regs *) &restart; struct pt_regs * regs;
int res = -EINTR;
lock_kernel();
regs = (struct pt_regs *) &restart;
mask = current->blocked; mask = current->blocked;
current->blocked = set & _BLOCKABLE; current->blocked = set & _BLOCKABLE;
regs->eax = -EINTR; regs->eax = -EINTR;
...@@ -39,8 +44,11 @@ asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long ...@@ -39,8 +44,11 @@ asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
schedule(); schedule();
if (do_signal(mask,regs)) if (do_signal(mask,regs))
return -EINTR; goto out;
} }
out:
unlock_kernel();
return res;
} }
static inline void restore_i387_hard(struct _fpstate *buf) static inline void restore_i387_hard(struct _fpstate *buf)
...@@ -100,7 +108,9 @@ if ( (tmp & 0xfffc) /* not a NULL selectors */ \ ...@@ -100,7 +108,9 @@ if ( (tmp & 0xfffc) /* not a NULL selectors */ \
__asm__("mov %w0,%%" #seg: :"r" (tmp)); } __asm__("mov %w0,%%" #seg: :"r" (tmp)); }
struct sigcontext * context; struct sigcontext * context;
struct pt_regs * regs; struct pt_regs * regs;
int res;
lock_kernel();
regs = (struct pt_regs *) &__unused; regs = (struct pt_regs *) &__unused;
context = (struct sigcontext *) regs->esp; context = (struct sigcontext *) regs->esp;
if (verify_area(VERIFY_READ, context, sizeof(*context))) if (verify_area(VERIFY_READ, context, sizeof(*context)))
...@@ -126,7 +136,9 @@ __asm__("mov %w0,%%" #seg: :"r" (tmp)); } ...@@ -126,7 +136,9 @@ __asm__("mov %w0,%%" #seg: :"r" (tmp)); }
goto badframe; goto badframe;
restore_i387(buf); restore_i387(buf);
} }
return context->eax; res = context->eax;
unlock_kernel();
return res;
badframe: badframe:
do_exit(SIGSEGV); do_exit(SIGSEGV);
} }
...@@ -295,10 +307,13 @@ static void handle_signal(unsigned long signr, struct sigaction *sa, ...@@ -295,10 +307,13 @@ static void handle_signal(unsigned long signr, struct sigaction *sa,
*/ */
asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
{ {
unsigned long mask = ~current->blocked; unsigned long mask;
unsigned long signr; unsigned long signr;
struct sigaction * sa; struct sigaction * sa;
int res;
lock_kernel();
mask = ~current->blocked;
while ((signr = current->signal & mask)) { while ((signr = current->signal & mask)) {
/* /*
* This stops gcc flipping out. Otherwise the assembler * This stops gcc flipping out. Otherwise the assembler
...@@ -371,7 +386,8 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) ...@@ -371,7 +386,8 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
} }
} }
handle_signal(signr, sa, oldmask, regs); handle_signal(signr, sa, oldmask, regs);
return 1; res = 1;
goto out;
} }
/* Did we come from a system call? */ /* Did we come from a system call? */
...@@ -384,5 +400,8 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) ...@@ -384,5 +400,8 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
regs->eip -= 2; regs->eip -= 2;
} }
} }
return 0; res = 0;
out:
unlock_kernel();
return res;
} }
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
* Erich Boleyn : MP v1.4 and additional changes. * Erich Boleyn : MP v1.4 and additional changes.
* Matthias Sattler : Changes for 2.1 kernel map. * Matthias Sattler : Changes for 2.1 kernel map.
* Michel Lespinasse : Changes for 2.1 kernel map. * Michel Lespinasse : Changes for 2.1 kernel map.
* Michael Chastain : Change trampoline.S to gnu as.
* *
*/ */
...@@ -34,6 +35,8 @@ ...@@ -34,6 +35,8 @@
#include <linux/mc146818rtc.h> #include <linux/mc146818rtc.h>
#include <asm/i82489.h> #include <asm/i82489.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
...@@ -140,7 +143,7 @@ volatile unsigned long smp_idle_map=0; /* Map for idle processors */ ...@@ -140,7 +143,7 @@ volatile unsigned long smp_idle_map=0; /* Map for idle processors */
#endif #endif
volatile unsigned long smp_proc_in_lock[NR_CPUS] = {0,};/* for computing process time */ volatile unsigned long smp_proc_in_lock[NR_CPUS] = {0,};/* for computing process time */
volatile unsigned long smp_process_available=0; volatile int smp_process_available=0;
/*#define SMP_DEBUG*/ /*#define SMP_DEBUG*/
...@@ -506,9 +509,8 @@ int smp_scan_config(unsigned long base, unsigned long length) ...@@ -506,9 +509,8 @@ int smp_scan_config(unsigned long base, unsigned long length)
* Trampoline 80x86 program as an array. * Trampoline 80x86 program as an array.
*/ */
static unsigned char trampoline_data[]={ extern unsigned char trampoline_data [];
#include "trampoline.hex" extern unsigned char trampoline_end [];
};
/* /*
* Currently trivial. Write the real->protected mode * Currently trivial. Write the real->protected mode
...@@ -518,7 +520,7 @@ static unsigned char trampoline_data[]={ ...@@ -518,7 +520,7 @@ static unsigned char trampoline_data[]={
static void install_trampoline(unsigned char *mp) static void install_trampoline(unsigned char *mp)
{ {
memcpy(mp,trampoline_data,sizeof(trampoline_data)); memcpy(mp, trampoline_data, trampoline_end - trampoline_data);
} }
/* /*
...@@ -634,19 +636,25 @@ void smp_callin(void) ...@@ -634,19 +636,25 @@ void smp_callin(void)
* Until we are ready for SMP scheduling * Until we are ready for SMP scheduling
*/ */
load_ldt(0); load_ldt(0);
/* printk("Testing faulting...\n");
*(long *)0=1; OOPS... */
local_flush_tlb(); local_flush_tlb();
while(!smp_commenced); while(!task[cpuid] || current_set[cpuid] != task[cpuid])
barrier();
if (cpu_number_map[cpuid] == -1)
while(1);
local_flush_tlb();
load_TR(cpu_number_map[cpuid]);
while(!smp_commenced)
barrier();
local_flush_tlb(); local_flush_tlb();
if (cpu_number_map[cpuid] == -1)
while(1);
SMP_PRINTK(("Commenced..\n")); SMP_PRINTK(("Commenced..\n"));
local_flush_tlb(); local_flush_tlb();
load_TR(cpu_number_map[cpuid]); sti();
} }
/* /*
...@@ -1253,27 +1261,20 @@ void smp_flush_tlb(void) ...@@ -1253,27 +1261,20 @@ void smp_flush_tlb(void)
void smp_reschedule_irq(int cpl, struct pt_regs *regs) void smp_reschedule_irq(int cpl, struct pt_regs *regs)
{ {
/*#define DEBUGGING_SMP_RESCHED*/ lock_kernel();
#ifdef DEBUGGING_SMP_RESCHED intr_count++;
static int ct=0;
if(ct==0)
{
printk("Beginning scheduling on CPU#%d\n",smp_processor_id());
udelay(1000000);
ct=1;
}
#endif
if(smp_processor_id()!=active_kernel_processor) if(smp_processor_id()!=active_kernel_processor)
panic("SMP Reschedule on CPU #%d, but #%d is active.\n", panic("SMP Reschedule on CPU #%d, but #%d is active.\n",
smp_processor_id(), active_kernel_processor); smp_processor_id(), active_kernel_processor);
need_resched=1; need_resched=1;
/* /* Clear the IPI */
* Clear the IPI
*/
apic_read(APIC_SPIV); /* Dummy read */ apic_read(APIC_SPIV); /* Dummy read */
apic_write(APIC_EOI, 0); /* Docs say use 0 for future compatibility */ apic_write(APIC_EOI, 0); /* Docs say use 0 for future compatibility */
intr_count--;
unlock_kernel();
} }
/* /*
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h> #include <linux/sem.h>
#include <linux/msg.h> #include <linux/msg.h>
#include <linux/shm.h> #include <linux/shm.h>
...@@ -28,11 +30,13 @@ asmlinkage int sys_pipe(unsigned long * fildes) ...@@ -28,11 +30,13 @@ asmlinkage int sys_pipe(unsigned long * fildes)
int fd[2]; int fd[2];
int error; int error;
lock_kernel();
error = do_pipe(fd); error = do_pipe(fd);
if (!error) { if (!error) {
if (copy_to_user(fildes, fd, 2*sizeof(int))) if (copy_to_user(fildes, fd, 2*sizeof(int)))
error = -EFAULT; error = -EFAULT;
} }
unlock_kernel();
return error; return error;
} }
...@@ -53,18 +57,22 @@ struct mmap_arg_struct { ...@@ -53,18 +57,22 @@ struct mmap_arg_struct {
asmlinkage int old_mmap(struct mmap_arg_struct *arg) asmlinkage int old_mmap(struct mmap_arg_struct *arg)
{ {
int error; int error = -EFAULT;
struct file * file = NULL; struct file * file = NULL;
struct mmap_arg_struct a; struct mmap_arg_struct a;
lock_kernel();
if (copy_from_user(&a, arg, sizeof(a))) if (copy_from_user(&a, arg, sizeof(a)))
return -EFAULT; goto out;
if (!(a.flags & MAP_ANONYMOUS)) { if (!(a.flags & MAP_ANONYMOUS)) {
error = -EBADF;
if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd])) if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd]))
return -EBADF; goto out;
} }
a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset); error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset);
out:
unlock_kernel();
return error; return error;
} }
...@@ -79,10 +87,15 @@ struct sel_arg_struct { ...@@ -79,10 +87,15 @@ struct sel_arg_struct {
asmlinkage int old_select(struct sel_arg_struct *arg) asmlinkage int old_select(struct sel_arg_struct *arg)
{ {
struct sel_arg_struct a; struct sel_arg_struct a;
int ret = -EFAULT;
lock_kernel();
if (copy_from_user(&a, arg, sizeof(a))) if (copy_from_user(&a, arg, sizeof(a)))
return -EFAULT; goto out;
return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); ret = sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
out:
unlock_kernel();
return ret;
} }
/* /*
...@@ -92,53 +105,68 @@ asmlinkage int old_select(struct sel_arg_struct *arg) ...@@ -92,53 +105,68 @@ asmlinkage int old_select(struct sel_arg_struct *arg)
*/ */
asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth) asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
{ {
int version; int version, ret;
lock_kernel();
version = call >> 16; /* hack for backward compatibility */ version = call >> 16; /* hack for backward compatibility */
call &= 0xffff; call &= 0xffff;
if (call <= SEMCTL) if (call <= SEMCTL)
switch (call) { switch (call) {
case SEMOP: case SEMOP:
return sys_semop (first, (struct sembuf *)ptr, second); ret = sys_semop (first, (struct sembuf *)ptr, second);
goto out;
case SEMGET: case SEMGET:
return sys_semget (first, second, third); ret = sys_semget (first, second, third);
goto out;
case SEMCTL: { case SEMCTL: {
union semun fourth; union semun fourth;
ret = -EINVAL;
if (!ptr) if (!ptr)
return -EINVAL; goto out;
ret = -EFAULT;
if (get_user(fourth.__pad, (void **) ptr)) if (get_user(fourth.__pad, (void **) ptr))
return -EFAULT; goto out;
return sys_semctl (first, second, third, fourth); ret = sys_semctl (first, second, third, fourth);
goto out;
} }
default: default:
return -EINVAL; ret = -EINVAL;
goto out;
} }
if (call <= MSGCTL) if (call <= MSGCTL)
switch (call) { switch (call) {
case MSGSND: case MSGSND:
return sys_msgsnd (first, (struct msgbuf *) ptr, ret = sys_msgsnd (first, (struct msgbuf *) ptr,
second, third); second, third);
goto out;
case MSGRCV: case MSGRCV:
switch (version) { switch (version) {
case 0: { case 0: {
struct ipc_kludge tmp; struct ipc_kludge tmp;
ret = -EINVAL;
if (!ptr) if (!ptr)
return -EINVAL; goto out;
ret = -EFAULT;
if (copy_from_user(&tmp,(struct ipc_kludge *) ptr, if (copy_from_user(&tmp,(struct ipc_kludge *) ptr,
sizeof (tmp))) sizeof (tmp)))
return -EFAULT; goto out;
return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third); ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
goto out;
} }
case 1: default: case 1: default:
return sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third); ret = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
goto out;
} }
case MSGGET: case MSGGET:
return sys_msgget ((key_t) first, second); ret = sys_msgget ((key_t) first, second);
goto out;
case MSGCTL: case MSGCTL:
return sys_msgctl (first, second, (struct msqid_ds *) ptr); ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
goto out;
default: default:
return -EINVAL; ret = -EINVAL;
goto out;
} }
if (call <= SHMCTL) if (call <= SHMCTL)
switch (call) { switch (call) {
...@@ -146,25 +174,35 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, ...@@ -146,25 +174,35 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
switch (version) { switch (version) {
case 0: default: { case 0: default: {
ulong raddr; ulong raddr;
int err; ret = sys_shmat (first, (char *) ptr, second, &raddr);
err = sys_shmat (first, (char *) ptr, second, &raddr); if (ret)
if (err) goto out;
return err; ret = put_user (raddr, (ulong *) third);
return put_user (raddr, (ulong *) third); goto out;
} }
case 1: /* iBCS2 emulator entry point */ case 1: /* iBCS2 emulator entry point */
ret = -EINVAL;
if (get_fs() != get_ds()) if (get_fs() != get_ds())
return -EINVAL; goto out;
return sys_shmat (first, (char *) ptr, second, (ulong *) third); ret = sys_shmat (first, (char *) ptr, second, (ulong *) third);
goto out;
} }
case SHMDT: case SHMDT:
return sys_shmdt ((char *)ptr); ret = sys_shmdt ((char *)ptr);
goto out;
case SHMGET: case SHMGET:
return sys_shmget (first, second, third); ret = sys_shmget (first, second, third);
goto out;
case SHMCTL: case SHMCTL:
return sys_shmctl (first, second, (struct shmid_ds *) ptr); ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
goto out;
default: default:
return -EINVAL; ret = -EINVAL;
goto out;
} }
return -EINVAL; else
ret = -EINVAL;
out:
unlock_kernel();
return ret;
} }
! /*
! Trampoline.S Derived from Setup.S by Linus Torvalds *
! * Trampoline.S Derived from Setup.S by Linus Torvalds
! Entry: CS:IP point to the start of our code, we are *
! in real mode with no stack, but the rest of the * 4 Jan 1997 Michael Chastain: changed to gnu as.
! trampoline page to make our stack and everything else *
! is a mystery. * Entry: CS:IP point to the start of our code, we are
! * in real mode with no stack, but the rest of the
! In fact we don't actually need a stack so we don't * trampoline page to make our stack and everything else
! set one up. * is a mystery.
! *
! We jump into the boot/compressed/head.S code. So you'd * In fact we don't actually need a stack so we don't
! better be running a compressed kernel image or you * set one up.
! won't get very far. *
! * We jump into the boot/compressed/head.S code. So you'd
#define __ASSEMBLY__ * better be running a compressed kernel image or you
* won't get very far.
*
* On entry to trampoline_data, the processor is in real mode
* with 16-bit addressing and 16-bit data. CS has some value
* and IP is zero. Thus, data addresses need to be absolute
* (no relocation) and are taken with regard to r_base.
*
* On the transition to protected mode, this page appears at
* address 8192, so protected mode addresses are with regard
* to p_base.
*
* If you work on this file, check the object module with objdump
* --full-contents --reloc to make sure there are no relocation
* entries.
*/
#include <linux/linkage.h>
#include <asm/segment.h> #include <asm/segment.h>
.text .data
extrn startup32
.code16
entry start
start: ENTRY(trampoline_data)
! nop r_base = .
! jmp start ! Test p_base = . - 8192
mov ax,cs ! Code and data in the same place
mov ds,ax ! mov %cs, %ax # Code and data in the same place
mov cx,ax ! Pass stack info to the 32bit boot mov %ax, %ds
add cx,cx
add cx,cx mov %ax, %cx # Pass stack info to the 32bit boot
add cx,cx shl $4, %cx # Segment -> Offset
add cx,cx ! Segment -> Offset add $4096, %cx # End of page is wanted
add cx, #4096 ! End of page is wanted
mov bx,#1 ! Flag an SMP trampoline mov $1, %bx # Flag an SMP trampoline
cli ! We should be safe anyway cli # We should be safe anyway
lidt idt_48 ! load idt with 0,0 movl $0xA5A5A5A5, trampoline_data - r_base
lgdt gdt_48 ! load gdt with whatever is appropriate # write marker for master knows we're running
xor ax,ax lidt idt_48 - r_base # load idt with 0, 0
inc ax ! protected mode (PE) bit lgdt gdt_48 - r_base # load gdt with whatever is appropriate
lmsw ax ! Into protected mode
xor %ax, %ax
inc %ax # protected mode (PE) bit
lmsw %ax # into protected mode
jmp flush_instr jmp flush_instr
flush_instr: flush_instr:
jmpi 8192+startup32,KERNEL_CS ! Jump to the 32bit trampoline code ljmp $KERNEL_CS, $0x00100000
! jmpi 0x100000,KERNEL_CS ! Jump into the 32bit startup # jump to startup_32
! .byte 0x66,0x67 ! 32bit
! .byte 0xea,0x00,0x00,0x10,0x00,0x10,0x00 !jmpi .0x100000,KERNEL_CS idt_48:
.word 0 # idt limit = 0
.word 0, 0 # idt base = 0L
gdt_48:
.word 0x0800 # gdt limit = 2048, 256 GDT entries
.word gdt - p_base, 0x0 # gdt base = gdt (first SMP CPU)
# we load the others with first table
# saves rewriting gdt_48 for each
gdt: gdt:
.word 0,0,0,0 ! dummy .word 0, 0, 0, 0 # dummy
.word 0,0,0,0 ! unused .word 0, 0, 0, 0 # unused
!walken modif # walken modif
.word 0xFFFF ! 4Gb - (0x100000*0x1000 = 4Gb)
.word 0x0000 ! base address=0
.word 0x9A00 ! code read/exec
.word 0x00CF ! granularity=4096, 386 (+5th nibble of limit)
.word 0xFFFF ! 4Gb - (0x100000*0x1000 = 4Gb) .word 0xFFFF # 4 Gb - (0x100000*0x1000 = 4Gb)
.word 0x0000 ! base address=0 .word 0x0000 # base address = 0
.word 0x9200 ! data read/write .word 0x9A00 # code read / exec
.word 0x00CF ! granularity=4096, 386 (+5th nibble of limit) .word 0x00CF # granularity = 4096, 386 (+5th nibble of limit)
!walken modif
! .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb) .word 0xFFFF # 4 Gb - (0x100000*0x1000 = 4Gb)
! .word 0x0000 ! base address=0 .word 0x0000 # base address = 0
! .word 0x9A00 ! code read/exec .word 0x9200 # data read / write
! .word 0x00C0 ! granularity=4096, 386 .word 0x00CF # granularity = 4096, 386 (+5th nibble of limit)
! .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb) # walken modif
! .word 0x0000 ! base address=0
! .word 0x9200 ! data read/write
! .word 0x00C0 ! granularity=4096, 386
idt_48: # .word 0x07FF # 8 Mb - limit = 2047 (2048 * 4096 = 8 Mb)
.word 0 ! idt limit=0 # .word 0x0000 # base address = 0
.word 0,0 ! idt base=0L # .word 0x9A00 # code read / exec
# .word 0x00C0 # granularity = 4096, 386
gdt_48: # .word 0x07FF # 8 Mb - limit = 2047 (2048 * 4096 = 8 Mb)
.word 0x800 ! gdt limit=2048, 256 GDT entries # .word 0x0000 # base address = 0
.word 8192+gdt,0x0 ! gdt base = 8192+gdt (first SMP CPU) # .word 0x9200 # data read / write
! we load the others with the first table # .word 0x00C0 # granularity = 4096, 386
! saves rewriting gdt_48 for each
.globl SYMBOL_NAME(trampoline_end)
SYMBOL_NAME_LABEL(trampoline_end)
!
! 32bit side of the trampoline code
!
#define __ASSEMBLY__
#include <asm/segment.h>
!
!
! Anything but a relative address here will be wrong by 8K...
!
.globl startup32
.text
startup32:
! Run the kernel
mov eax,#KERNEL_DS
mov ds,ax
mov eax,#0xA5A5A5A5
mov [8192],eax
jmpi 0x100000,KERNEL_CS
l1:
.byte 0xEA,0x00,0x00,0x10,0x00,0x10,0x00
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -38,24 +40,29 @@ static inline void console_verbose(void) ...@@ -38,24 +40,29 @@ static inline void console_verbose(void)
#define DO_ERROR(trapnr, signr, str, name, tsk) \ #define DO_ERROR(trapnr, signr, str, name, tsk) \
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
{ \ { \
lock_kernel(); \
tsk->tss.error_code = error_code; \ tsk->tss.error_code = error_code; \
tsk->tss.trap_no = trapnr; \ tsk->tss.trap_no = trapnr; \
force_sig(signr, tsk); \ force_sig(signr, tsk); \
die_if_kernel(str,regs,error_code); \ die_if_kernel(str,regs,error_code); \
unlock_kernel(); \
} }
#define DO_VM86_ERROR(trapnr, signr, str, name, tsk) \ #define DO_VM86_ERROR(trapnr, signr, str, name, tsk) \
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
{ \ { \
lock_kernel(); \
if (regs->eflags & VM_MASK) { \ if (regs->eflags & VM_MASK) { \
if (!handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr)) \ if (!handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr)) \
return; \ goto out; \
/* else fall through */ \ /* else fall through */ \
} \ } \
tsk->tss.error_code = error_code; \ tsk->tss.error_code = error_code; \
tsk->tss.trap_no = trapnr; \ tsk->tss.trap_no = trapnr; \
force_sig(signr, tsk); \ force_sig(signr, tsk); \
die_if_kernel(str,regs,error_code); \ die_if_kernel(str,regs,error_code); \
out: \
unlock_kernel(); \
} }
#define get_seg_byte(seg,addr) ({ \ #define get_seg_byte(seg,addr) ({ \
...@@ -194,18 +201,22 @@ DO_ERROR(18, SIGSEGV, "reserved", reserved, current) ...@@ -194,18 +201,22 @@ DO_ERROR(18, SIGSEGV, "reserved", reserved, current)
asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
{ {
lock_kernel();
if (regs->eflags & VM_MASK) { if (regs->eflags & VM_MASK) {
handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code); handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
return; goto out;
} }
die_if_kernel("general protection",regs,error_code); die_if_kernel("general protection",regs,error_code);
current->tss.error_code = error_code; current->tss.error_code = error_code;
current->tss.trap_no = 13; current->tss.trap_no = 13;
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
out:
unlock_kernel();
} }
asmlinkage void do_nmi(struct pt_regs * regs, long error_code) asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
{ {
lock_kernel();
#ifdef CONFIG_SMP_NMI_INVAL #ifdef CONFIG_SMP_NMI_INVAL
smp_flush_tlb_rcv(); smp_flush_tlb_rcv();
#else #else
...@@ -215,13 +226,15 @@ asmlinkage void do_nmi(struct pt_regs * regs, long error_code) ...@@ -215,13 +226,15 @@ asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
printk("power saving mode enabled.\n"); printk("power saving mode enabled.\n");
#endif #endif
#endif #endif
unlock_kernel();
} }
asmlinkage void do_debug(struct pt_regs * regs, long error_code) asmlinkage void do_debug(struct pt_regs * regs, long error_code)
{ {
lock_kernel();
if (regs->eflags & VM_MASK) { if (regs->eflags & VM_MASK) {
handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1); handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
return; goto out;
} }
force_sig(SIGTRAP, current); force_sig(SIGTRAP, current);
current->tss.trap_no = 1; current->tss.trap_no = 1;
...@@ -231,9 +244,11 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code) ...@@ -231,9 +244,11 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
__asm__("movl %0,%%db7" __asm__("movl %0,%%db7"
: /* no output */ : /* no output */
: "r" (0)); : "r" (0));
return; goto out;
} }
die_if_kernel("debug",regs,error_code); die_if_kernel("debug",regs,error_code);
out:
unlock_kernel();
} }
/* /*
...@@ -245,6 +260,7 @@ void math_error(void) ...@@ -245,6 +260,7 @@ void math_error(void)
{ {
struct task_struct * task; struct task_struct * task;
lock_kernel();
clts(); clts();
#ifdef __SMP__ #ifdef __SMP__
task = current; task = current;
...@@ -253,7 +269,7 @@ void math_error(void) ...@@ -253,7 +269,7 @@ void math_error(void)
last_task_used_math = NULL; last_task_used_math = NULL;
if (!task) { if (!task) {
__asm__("fnclex"); __asm__("fnclex");
return; goto out;
} }
#endif #endif
/* /*
...@@ -266,18 +282,26 @@ void math_error(void) ...@@ -266,18 +282,26 @@ void math_error(void)
force_sig(SIGFPE, task); force_sig(SIGFPE, task);
task->tss.trap_no = 16; task->tss.trap_no = 16;
task->tss.error_code = 0; task->tss.error_code = 0;
#ifndef __SMP__
out:
#endif
unlock_kernel();
} }
asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code) asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code)
{ {
lock_kernel();
ignore_irq13 = 1; ignore_irq13 = 1;
math_error(); math_error();
unlock_kernel();
} }
asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs, asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs,
long error_code) long error_code)
{ {
lock_kernel();
printk("Ignoring P6 Local APIC Spurious Interrupt Bug...\n"); printk("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
unlock_kernel();
} }
/* /*
...@@ -289,6 +313,7 @@ asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs, ...@@ -289,6 +313,7 @@ asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs,
*/ */
asmlinkage void math_state_restore(void) asmlinkage void math_state_restore(void)
{ {
lock_kernel();
__asm__ __volatile__("clts"); /* Allow maths ops (or we recurse) */ __asm__ __volatile__("clts"); /* Allow maths ops (or we recurse) */
/* /*
...@@ -301,7 +326,7 @@ asmlinkage void math_state_restore(void) ...@@ -301,7 +326,7 @@ asmlinkage void math_state_restore(void)
*/ */
#ifndef __SMP__ #ifndef __SMP__
if (last_task_used_math == current) if (last_task_used_math == current)
return; goto out;
if (last_task_used_math) if (last_task_used_math)
__asm__("fnsave %0":"=m" (last_task_used_math->tss.i387)); __asm__("fnsave %0":"=m" (last_task_used_math->tss.i387));
else else
...@@ -320,16 +345,22 @@ asmlinkage void math_state_restore(void) ...@@ -320,16 +345,22 @@ asmlinkage void math_state_restore(void)
current->used_math = 1; current->used_math = 1;
} }
current->flags|=PF_USEDFPU; /* So we fnsave on switch_to() */ current->flags|=PF_USEDFPU; /* So we fnsave on switch_to() */
#ifndef __SMP__
out:
#endif
unlock_kernel();
} }
#ifndef CONFIG_MATH_EMULATION #ifndef CONFIG_MATH_EMULATION
asmlinkage void math_emulate(long arg) asmlinkage void math_emulate(long arg)
{ {
printk("math-emulation not enabled and no coprocessor found.\n"); lock_kernel();
printk("killing %s.\n",current->comm); printk("math-emulation not enabled and no coprocessor found.\n");
force_sig(SIGFPE,current); printk("killing %s.\n",current->comm);
schedule(); force_sig(SIGFPE,current);
schedule();
unlock_kernel();
} }
#endif /* CONFIG_MATH_EMULATION */ #endif /* CONFIG_MATH_EMULATION */
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
...@@ -62,8 +64,10 @@ ...@@ -62,8 +64,10 @@
asmlinkage struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs) asmlinkage struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
{ {
struct pt_regs *ret;
unsigned long tmp; unsigned long tmp;
lock_kernel();
if (!current->tss.vm86_info) { if (!current->tss.vm86_info) {
printk("no vm86_info: BAD\n"); printk("no vm86_info: BAD\n");
do_exit(SIGSEGV); do_exit(SIGSEGV);
...@@ -79,7 +83,9 @@ asmlinkage struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs) ...@@ -79,7 +83,9 @@ asmlinkage struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
} }
current->tss.esp0 = current->saved_kernel_stack; current->tss.esp0 = current->saved_kernel_stack;
current->saved_kernel_stack = 0; current->saved_kernel_stack = 0;
return KVM86->regs32; ret = KVM86->regs32;
unlock_kernel();
return ret;
} }
static void mark_screen_rdonly(struct task_struct * tsk) static void mark_screen_rdonly(struct task_struct * tsk)
...@@ -126,21 +132,27 @@ asmlinkage int sys_vm86old(struct vm86_struct * v86) ...@@ -126,21 +132,27 @@ asmlinkage int sys_vm86old(struct vm86_struct * v86)
* This remains on the stack until we * This remains on the stack until we
* return to 32 bit user space. * return to 32 bit user space.
*/ */
struct task_struct *tsk = current; struct task_struct *tsk;
int tmp; int tmp, ret = -EPERM;
lock_kernel();
tsk = current;
if (tsk->saved_kernel_stack) if (tsk->saved_kernel_stack)
return -EPERM; goto out;
tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1); tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1);
tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2, tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2,
(long)&info.vm86plus - (long)&info.regs.VM86_REGS_PART2); (long)&info.vm86plus - (long)&info.regs.VM86_REGS_PART2);
ret = -EFAULT;
if (tmp) if (tmp)
return -EFAULT; goto out;
memset(&info.vm86plus, 0, (int)&info.regs32 - (int)&info.vm86plus); memset(&info.vm86plus, 0, (int)&info.regs32 - (int)&info.vm86plus);
info.regs32 = (struct pt_regs *) &v86; info.regs32 = (struct pt_regs *) &v86;
tsk->tss.vm86_info = v86; tsk->tss.vm86_info = v86;
do_sys_vm86(&info, tsk); do_sys_vm86(&info, tsk);
return 0; /* we never return here */ ret = 0; /* we never return here */
out:
unlock_kernel();
return ret;
} }
...@@ -151,37 +163,46 @@ asmlinkage int sys_vm86(unsigned long subfunction, struct vm86plus_struct * v86) ...@@ -151,37 +163,46 @@ asmlinkage int sys_vm86(unsigned long subfunction, struct vm86plus_struct * v86)
* This remains on the stack until we * This remains on the stack until we
* return to 32 bit user space. * return to 32 bit user space.
*/ */
struct task_struct *tsk = current; struct task_struct *tsk;
int tmp; int tmp, ret;
lock_kernel();
tsk = current;
switch (subfunction) { switch (subfunction) {
case VM86_REQUEST_IRQ: case VM86_REQUEST_IRQ:
case VM86_FREE_IRQ: case VM86_FREE_IRQ:
case VM86_GET_IRQ_BITS: case VM86_GET_IRQ_BITS:
case VM86_GET_AND_RESET_IRQ: case VM86_GET_AND_RESET_IRQ:
return do_vm86_irq_handling(subfunction,(int)v86); ret = do_vm86_irq_handling(subfunction,(int)v86);
goto out;
case VM86_PLUS_INSTALL_CHECK: case VM86_PLUS_INSTALL_CHECK:
/* NOTE: on old vm86 stuff this will return the error /* NOTE: on old vm86 stuff this will return the error
from verify_area(), because the subfunction is from verify_area(), because the subfunction is
interpreted as (invalid) address to vm86_struct. interpreted as (invalid) address to vm86_struct.
So the installation check works. So the installation check works.
*/ */
return 0; ret = 0;
goto out;
} }
/* we come here only for functions VM86_ENTER, VM86_ENTER_NO_BYPASS */ /* we come here only for functions VM86_ENTER, VM86_ENTER_NO_BYPASS */
ret = -EPERM;
if (tsk->saved_kernel_stack) if (tsk->saved_kernel_stack)
return -EPERM; goto out;
tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1); tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1);
tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2, tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2,
(long)&info.regs32 - (long)&info.regs.VM86_REGS_PART2); (long)&info.regs32 - (long)&info.regs.VM86_REGS_PART2);
ret = -EFAULT;
if (tmp) if (tmp)
return -EFAULT; goto out;
info.regs32 = (struct pt_regs *) &subfunction; info.regs32 = (struct pt_regs *) &subfunction;
info.vm86plus.is_vm86pus = 1; info.vm86plus.is_vm86pus = 1;
tsk->tss.vm86_info = (struct vm86_struct *)v86; tsk->tss.vm86_info = (struct vm86_struct *)v86;
do_sys_vm86(&info, tsk); do_sys_vm86(&info, tsk);
return 0; /* we never return here */ ret = 0; /* we never return here */
out:
unlock_kernel();
return ret;
} }
...@@ -232,6 +253,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk ...@@ -232,6 +253,7 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
tsk->tss.screen_bitmap = info->screen_bitmap; tsk->tss.screen_bitmap = info->screen_bitmap;
if (info->flags & VM86_SCREEN_BITMAP) if (info->flags & VM86_SCREEN_BITMAP)
mark_screen_rdonly(tsk); mark_screen_rdonly(tsk);
unlock_kernel();
__asm__ __volatile__( __asm__ __volatile__(
"xorl %%eax,%%eax; mov %%ax,%%fs; mov %%ax,%%gs\n\t" "xorl %%eax,%%eax; mov %%ax,%%fs; mov %%ax,%%gs\n\t"
"movl %0,%%esp\n\t" "movl %0,%%esp\n\t"
...@@ -247,6 +269,7 @@ static inline void return_to_32bit(struct kernel_vm86_regs * regs16, int retval) ...@@ -247,6 +269,7 @@ static inline void return_to_32bit(struct kernel_vm86_regs * regs16, int retval)
regs32 = save_v86_state(regs16); regs32 = save_v86_state(regs16);
regs32->eax = retval; regs32->eax = retval;
unlock_kernel();
__asm__ __volatile__("movl %0,%%esp\n\t" __asm__ __volatile__("movl %0,%%esp\n\t"
"jmp ret_from_sys_call" "jmp ret_from_sys_call"
: : "r" (regs32), "b" (current)); : : "r" (regs32), "b" (current));
...@@ -408,20 +431,27 @@ static void do_int(struct kernel_vm86_regs *regs, int i, unsigned char * ssp, un ...@@ -408,20 +431,27 @@ static void do_int(struct kernel_vm86_regs *regs, int i, unsigned char * ssp, un
int handle_vm86_trap(struct kernel_vm86_regs * regs, long error_code, int trapno) int handle_vm86_trap(struct kernel_vm86_regs * regs, long error_code, int trapno)
{ {
int ret;
lock_kernel();
if (VMPI.is_vm86pus) { if (VMPI.is_vm86pus) {
if ( (trapno==3) || (trapno==1) ) if ( (trapno==3) || (trapno==1) )
return_to_32bit(regs, VM86_TRAP + (trapno << 8)); return_to_32bit(regs, VM86_TRAP + (trapno << 8));
do_int(regs, trapno, (unsigned char *) (regs->ss << 4), SP(regs)); do_int(regs, trapno, (unsigned char *) (regs->ss << 4), SP(regs));
return 1; ret = 1;
goto out;
} }
ret = 0;
if (trapno !=1) if (trapno !=1)
return 0; /* we let this handle by the calling routine */ goto out; /* we let this handle by the calling routine */
if (current->flags & PF_PTRACED) if (current->flags & PF_PTRACED)
current->blocked &= ~(1 << (SIGTRAP-1)); current->blocked &= ~(1 << (SIGTRAP-1));
send_sig(SIGTRAP, current, 1); send_sig(SIGTRAP, current, 1);
current->tss.trap_no = trapno; current->tss.trap_no = trapno;
current->tss.error_code = error_code; current->tss.error_code = error_code;
return 0; out:
unlock_kernel();
return ret;
} }
...@@ -436,8 +466,9 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code) ...@@ -436,8 +466,9 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
#define VM86_FAULT_RETURN \ #define VM86_FAULT_RETURN \
if (VMPI.force_return_for_pic && (VEFLAGS & IF_MASK)) \ if (VMPI.force_return_for_pic && (VEFLAGS & IF_MASK)) \
return_to_32bit(regs, VM86_PICRETURN); \ return_to_32bit(regs, VM86_PICRETURN); \
return; goto out;
lock_kernel();
csp = (unsigned char *) (regs->cs << 4); csp = (unsigned char *) (regs->cs << 4);
ssp = (unsigned char *) (regs->ss << 4); ssp = (unsigned char *) (regs->ss << 4);
sp = SP(regs); sp = SP(regs);
...@@ -501,7 +532,7 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code) ...@@ -501,7 +532,7 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
return_to_32bit(regs, VM86_INTx + (intno << 8)); return_to_32bit(regs, VM86_INTx + (intno << 8));
} }
do_int(regs, intno, ssp, sp); do_int(regs, intno, ssp, sp);
return; goto out;
} }
/* iret */ /* iret */
...@@ -534,6 +565,8 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code) ...@@ -534,6 +565,8 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
default: default:
return_to_32bit(regs, VM86_UNKNOWN); return_to_32bit(regs, VM86_UNKNOWN);
} }
out:
unlock_kernel();
} }
/* ---------------- vm86 special IRQ passing stuff ----------------- */ /* ---------------- vm86 special IRQ passing stuff ----------------- */
...@@ -554,18 +587,19 @@ static void irq_handler(int intno, void *dev_id, struct pt_regs * regs) { ...@@ -554,18 +587,19 @@ static void irq_handler(int intno, void *dev_id, struct pt_regs * regs) {
int irq_bit; int irq_bit;
unsigned long flags; unsigned long flags;
lock_kernel();
save_flags(flags); save_flags(flags);
cli(); cli();
irq_bit = 1 << intno; irq_bit = 1 << intno;
if ((irqbits & irq_bit) || ! vm86_irqs[intno].tsk) { if ((irqbits & irq_bit) || ! vm86_irqs[intno].tsk)
restore_flags(flags); goto out;
return;
}
irqbits |= irq_bit; irqbits |= irq_bit;
if (vm86_irqs[intno].sig) if (vm86_irqs[intno].sig)
send_sig(vm86_irqs[intno].sig, vm86_irqs[intno].tsk, 1); send_sig(vm86_irqs[intno].sig, vm86_irqs[intno].tsk, 1);
/* else user will poll for IRQs */ /* else user will poll for IRQs */
out:
restore_flags(flags); restore_flags(flags);
unlock_kernel();
} }
static inline void free_vm86_irq(int irqnumber) static inline void free_vm86_irq(int irqnumber)
......
...@@ -11,6 +11,6 @@ else ...@@ -11,6 +11,6 @@ else
endif endif
L_TARGET = lib.a L_TARGET = lib.a
L_OBJS = checksum.o semaphore.o L_OBJS = checksum.o semaphore.o locks.o
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
/* locks.S: Wheee... I'm coding Intel assembly...
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
*/
#include <linux/linkage.h>
/* Caller does atomic increment on current->lock_depth,
* if it was found to originally be zero then we get here,
* %eax contains callers PC and %edx holds this cpu ID.
*/
ENTRY(__lock_kernel)
pushl %eax ! return address
1:
lock
btsl $0, SYMBOL_NAME(kernel_flag)
jnc 3f
2:
btl %dl, SYMBOL_NAME(smp_invalidate_needed)
jnc 0f
lock
btrl %dl, SYMBOL_NAME(smp_invalidate_needed)
jnc 0f
movl %cr3, %eax
movl %eax, %cr3
0:
btl $0, SYMBOL_NAME(kernel_flag)
jc 2b
jmp 1b
3:
movb %dl, SYMBOL_NAME(active_kernel_processor)
ret
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/mman.h> #include <linux/mman.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -96,6 +98,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -96,6 +98,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
unsigned long fixup; unsigned long fixup;
int write; int write;
lock_kernel();
/* get the address */ /* get the address */
__asm__("movl %%cr2,%0":"=r" (address)); __asm__("movl %%cr2,%0":"=r" (address));
down(&mm->mmap_sem); down(&mm->mmap_sem);
...@@ -154,7 +158,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -154,7 +158,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
if (bit < 32) if (bit < 32)
tsk->tss.screen_bitmap |= 1 << bit; tsk->tss.screen_bitmap |= 1 << bit;
} }
return; goto out;
/* /*
* Something tried to access memory that isn't in our memory map.. * Something tried to access memory that isn't in our memory map..
...@@ -167,7 +171,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -167,7 +171,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
if ((fixup = search_exception_table(regs->eip)) != 0) { if ((fixup = search_exception_table(regs->eip)) != 0) {
printk(KERN_DEBUG "Exception at [<%lx>] (%lx)\n", regs->eip, fixup); printk(KERN_DEBUG "Exception at [<%lx>] (%lx)\n", regs->eip, fixup);
regs->eip = fixup; regs->eip = fixup;
return; goto out;
} }
if (error_code & 4) { if (error_code & 4) {
...@@ -175,7 +179,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -175,7 +179,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
tsk->tss.error_code = error_code; tsk->tss.error_code = error_code;
tsk->tss.trap_no = 14; tsk->tss.trap_no = 14;
force_sig(SIGSEGV, tsk); force_sig(SIGSEGV, tsk);
return; goto out;
} }
/* /*
* 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
...@@ -188,7 +192,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -188,7 +192,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
pg0[0] = pte_val(mk_pte(0, PAGE_SHARED)); pg0[0] = pte_val(mk_pte(0, PAGE_SHARED));
flush_tlb(); flush_tlb();
printk("This processor honours the WP bit even when in supervisor mode. Good.\n"); printk("This processor honours the WP bit even when in supervisor mode. Good.\n");
return; goto out;
} }
if (address < PAGE_SIZE) { if (address < PAGE_SIZE) {
printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
...@@ -209,4 +213,6 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -209,4 +213,6 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
} }
die_if_kernel("Oops", regs, error_code); die_if_kernel("Oops", regs, error_code);
do_exit(SIGKILL); do_exit(SIGKILL);
out:
unlock_kernel();
} }
...@@ -289,6 +289,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem) ...@@ -289,6 +289,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
return; return;
} }
void free_initmem(void)
{
/* To be written */
}
void si_meminfo(struct sysinfo *val) void si_meminfo(struct sysinfo *val)
{ {
int i; int i;
......
...@@ -20,32 +20,32 @@ extern int dump_fpu(elf_fpregset_t *); ...@@ -20,32 +20,32 @@ extern int dump_fpu(elf_fpregset_t *);
/* platform dependent support */ /* platform dependent support */
EXPORT_SYMBOLS(memcmp); EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOLS(m68k_machtype); EXPORT_SYMBOL(m68k_machtype);
EXPORT_SYMBOLS(m68k_cputype); EXPORT_SYMBOL(m68k_cputype);
EXPORT_SYMBOLS(m68k_is040or060); EXPORT_SYMBOL(m68k_is040or060);
EXPORT_SYMBOLS(cache_push); EXPORT_SYMBOL(cache_push);
EXPORT_SYMBOLS(cache_push_v); EXPORT_SYMBOL(cache_push_v);
EXPORT_SYMBOLS(cache_clear); EXPORT_SYMBOL(cache_clear);
EXPORT_SYMBOLS(mm_vtop); EXPORT_SYMBOL(mm_vtop);
EXPORT_SYMBOLS(mm_ptov); EXPORT_SYMBOL(mm_ptov);
EXPORT_SYMBOLS(mm_end_of_chunk); EXPORT_SYMBOL(mm_end_of_chunk);
EXPORT_SYMBOLS(m68k_debug_device); EXPORT_SYMBOL(m68k_debug_device);
EXPORT_SYMBOLS(request_irq); EXPORT_SYMBOL(request_irq);
EXPORT_SYMBOLS(free_irq); EXPORT_SYMBOL(free_irq);
EXPORT_SYMBOLS(dump_fpu); EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOLS(dump_thread); EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOLS(strnlen); EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOLS(strrchr); EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOLS(strstr); EXPORT_SYMBOL(strstr);
/* The following are special because they're not called /* The following are special because they're not called
explicitly (the C compiler generates them). Fortunately, explicitly (the C compiler generates them). Fortunately,
their interface isn't gonna change any time soon now, so their interface isn't gonna change any time soon now, so
it's OK to leave it out of version control. */ it's OK to leave it out of version control. */
EXPORT_SYMBOLS_NOVERS(__ashrdi3); EXPORT_SYMBOL_NOVERS(__ashrdi3);
EXPORT_SYMBOLS_NOVERS(memcpy); EXPORT_SYMBOL_NOVERS(memcpy);
EXPORT_SYMBOLS_NOVERS(memset); EXPORT_SYMBOL_NOVERS(memset);
EXPORT_SYMBOLS_NOVERS(__down_failed); EXPORT_SYMBOL_NOVERS(__down_failed);
EXPORT_SYMBOLS_NOVERS(__up_wakeup); EXPORT_SYMBOL_NOVERS(__up_wakeup);
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
...@@ -34,13 +36,20 @@ asmlinkage void ret_from_exception(void); ...@@ -34,13 +36,20 @@ asmlinkage void ret_from_exception(void);
*/ */
asmlinkage int sys_idle(void) asmlinkage int sys_idle(void)
{ {
int ret = -EPERM;
lock_kernel();
if (current->pid != 0) if (current->pid != 0)
return -EPERM; goto out;
/* endless idle loop with no priority at all */ /* endless idle loop with no priority at all */
current->counter = -100; current->counter = -100;
for (;;) for (;;)
schedule(); schedule();
ret = 0;
out:
unlock_kernel();
return ret;
} }
void hard_reset_now(void) void hard_reset_now(void)
...@@ -86,20 +95,29 @@ void flush_thread(void) ...@@ -86,20 +95,29 @@ void flush_thread(void)
asmlinkage int m68k_fork(struct pt_regs *regs) asmlinkage int m68k_fork(struct pt_regs *regs)
{ {
return do_fork(SIGCHLD, rdusp(), regs); int ret;
lock_kernel();
ret = do_fork(SIGCHLD, rdusp(), regs);
unlock_kernel();
return ret;
} }
asmlinkage int m68k_clone(struct pt_regs *regs) asmlinkage int m68k_clone(struct pt_regs *regs)
{ {
unsigned long clone_flags; unsigned long clone_flags;
unsigned long newsp; unsigned long newsp;
int ret;
lock_kernel();
/* syscall2 puts clone_flags in d1 and usp in d2 */ /* syscall2 puts clone_flags in d1 and usp in d2 */
clone_flags = regs->d1; clone_flags = regs->d1;
newsp = regs->d2; newsp = regs->d2;
if (!newsp) if (!newsp)
newsp = rdusp(); newsp = rdusp();
return do_fork(clone_flags, newsp, regs); ret = do_fork(clone_flags, newsp, regs);
unlock_kernel();
return ret;
} }
void release_thread(struct task_struct *dead_task) void release_thread(struct task_struct *dead_task)
...@@ -224,10 +242,13 @@ asmlinkage int sys_execve(char *name, char **argv, char **envp) ...@@ -224,10 +242,13 @@ asmlinkage int sys_execve(char *name, char **argv, char **envp)
char * filename; char * filename;
struct pt_regs *regs = (struct pt_regs *) &name; struct pt_regs *regs = (struct pt_regs *) &name;
lock_kernel();
error = getname(name, &filename); error = getname(name, &filename);
if (error) if (error)
return error; goto out;
error = do_execve(filename, argv, envp, regs); error = do_execve(filename, argv, envp, regs);
putname(filename); putname(filename);
out:
unlock_kernel();
return error; return error;
} }
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/user.h> #include <linux/user.h>
...@@ -322,25 +324,29 @@ static int write_long(struct task_struct * tsk, unsigned long addr, ...@@ -322,25 +324,29 @@ static int write_long(struct task_struct * tsk, unsigned long addr,
asmlinkage int sys_ptrace(long request, long pid, long addr, long data) asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{ {
struct task_struct *child; struct task_struct *child;
struct user * dummy; struct user * dummy = NULL;
int ret;
dummy = NULL;
lock_kernel();
ret = -EPERM;
if (request == PTRACE_TRACEME) { if (request == PTRACE_TRACEME) {
/* are we already being traced? */ /* are we already being traced? */
if (current->flags & PF_PTRACED) if (current->flags & PF_PTRACED)
return -EPERM; goto out;
/* set the ptrace bit in the process flags. */ /* set the ptrace bit in the process flags. */
current->flags |= PF_PTRACED; current->flags |= PF_PTRACED;
return 0; ret = 0;
goto out;
} }
if (pid == 1) /* you may not mess with init */ if (pid == 1) /* you may not mess with init */
return -EPERM; goto out;
ret = -ESRCH;
if (!(child = get_task(pid))) if (!(child = get_task(pid)))
return -ESRCH; goto out;
ret = -EPERM;
if (request == PTRACE_ATTACH) { if (request == PTRACE_ATTACH) {
if (child == current) if (child == current)
return -EPERM; goto out;
if ((!child->dumpable || if ((!child->dumpable ||
(current->uid != child->euid) || (current->uid != child->euid) ||
(current->uid != child->suid) || (current->uid != child->suid) ||
...@@ -348,10 +354,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -348,10 +354,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
(current->gid != child->egid) || (current->gid != child->egid) ||
(current->gid != child->sgid) || (current->gid != child->sgid) ||
(current->gid != child->gid)) && !suser()) (current->gid != child->gid)) && !suser())
return -EPERM; goto out;
/* the same process cannot be attached many times */ /* the same process cannot be attached many times */
if (child->flags & PF_PTRACED) if (child->flags & PF_PTRACED)
return -EPERM; goto out;
child->flags |= PF_PTRACED; child->flags |= PF_PTRACED;
if (child->p_pptr != current) { if (child->p_pptr != current) {
REMOVE_LINKS(child); REMOVE_LINKS(child);
...@@ -359,39 +365,42 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -359,39 +365,42 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
SET_LINKS(child); SET_LINKS(child);
} }
send_sig(SIGSTOP, child, 1); send_sig(SIGSTOP, child, 1);
return 0; ret = 0;
goto out;
} }
ret = -ESRCH;
if (!(child->flags & PF_PTRACED)) if (!(child->flags & PF_PTRACED))
return -ESRCH; goto out;
if (child->state != TASK_STOPPED) { if (child->state != TASK_STOPPED) {
if (request != PTRACE_KILL) if (request != PTRACE_KILL)
return -ESRCH; goto out;
} }
if (child->p_pptr != current) if (child->p_pptr != current)
return -ESRCH; goto out;
switch (request) { switch (request) {
/* when I and D space are separate, these will need to be fixed. */ /* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: { case PTRACE_PEEKDATA: {
unsigned long tmp; unsigned long tmp;
int res;
res = read_long(child, addr, &tmp); ret = read_long(child, addr, &tmp);
if (res < 0) if (ret >= 0)
return res; ret = put_user(tmp, (unsigned long *) data);
return put_user(tmp, (unsigned long *) data); goto out;
} }
/* read the word at location addr in the USER area. */ /* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: { case PTRACE_PEEKUSR: {
unsigned long tmp; unsigned long tmp;
ret = -EIO;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
return -EIO; goto out;
tmp = 0; /* Default return condition */ tmp = 0; /* Default return condition */
addr = addr >> 2; /* temporary hack. */ addr = addr >> 2; /* temporary hack. */
ret = -EIO;
if (addr < 19) { if (addr < 19) {
tmp = get_reg(child, addr); tmp = get_reg(child, addr);
if (addr == PT_SR) if (addr == PT_SR)
...@@ -400,23 +409,26 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -400,23 +409,26 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
else if (addr >= 21 && addr < 49) else if (addr >= 21 && addr < 49)
tmp = child->tss.fp[addr - 21]; tmp = child->tss.fp[addr - 21];
else else
return -EIO; goto out;
return put_user(tmp,(unsigned long *) data); ret = put_user(tmp,(unsigned long *) data);
goto out;
} }
/* when I and D space are separate, this will have to be fixed. */ /* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA: case PTRACE_POKEDATA:
return write_long(child,addr,data); ret = write_long(child,addr,data);
goto out;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
ret = -EIO;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
return -EIO; goto out;
addr = addr >> 2; /* temporary hack. */ addr = addr >> 2; /* temporary hack. */
if (addr == PT_ORIG_D0) if (addr == PT_ORIG_D0)
return -EIO; goto out;
if (addr == PT_SR) { if (addr == PT_SR) {
data &= SR_MASK; data &= SR_MASK;
data <<= 16; data <<= 16;
...@@ -424,22 +436,24 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -424,22 +436,24 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
} }
if (addr < 19) { if (addr < 19) {
if (put_reg(child, addr, data)) if (put_reg(child, addr, data))
return -EIO; goto out;
return 0; ret = 0;
goto out;
} }
if (addr >= 21 && addr < 48) if (addr >= 21 && addr < 48)
{ {
child->tss.fp[addr - 21] = data; child->tss.fp[addr - 21] = data;
return 0; ret = 0;
} }
return -EIO; goto out;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */ case PTRACE_CONT: { /* restart after signal. */
long tmp; long tmp;
ret = -EIO;
if ((unsigned long) data >= NSIG) if ((unsigned long) data >= NSIG)
return -EIO; goto out;
if (request == PTRACE_SYSCALL) if (request == PTRACE_SYSCALL)
child->flags |= PF_TRACESYS; child->flags |= PF_TRACESYS;
else else
...@@ -449,7 +463,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -449,7 +463,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
/* make sure the single step bit is not set. */ /* make sure the single step bit is not set. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
put_reg(child, PT_SR, tmp); put_reg(child, PT_SR, tmp);
return 0; ret = 0;
goto out;
} }
/* /*
...@@ -460,21 +475,23 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -460,21 +475,23 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_KILL: { case PTRACE_KILL: {
long tmp; long tmp;
ret = 0;
if (child->state == TASK_ZOMBIE) /* already dead */ if (child->state == TASK_ZOMBIE) /* already dead */
return 0; goto out;
wake_up_process(child); wake_up_process(child);
child->exit_code = SIGKILL; child->exit_code = SIGKILL;
/* make sure the single step bit is not set. */ /* make sure the single step bit is not set. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
put_reg(child, PT_SR, tmp); put_reg(child, PT_SR, tmp);
return 0; goto out;
} }
case PTRACE_SINGLESTEP: { /* set the trap flag. */ case PTRACE_SINGLESTEP: { /* set the trap flag. */
long tmp; long tmp;
ret = -EIO;
if ((unsigned long) data >= NSIG) if ((unsigned long) data >= NSIG)
return -EIO; goto out;
child->flags &= ~PF_TRACESYS; child->flags &= ~PF_TRACESYS;
tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16); tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
put_reg(child, PT_SR, tmp); put_reg(child, PT_SR, tmp);
...@@ -482,14 +499,16 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -482,14 +499,16 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
wake_up_process(child); wake_up_process(child);
child->exit_code = data; child->exit_code = data;
/* give it a chance to run. */ /* give it a chance to run. */
return 0; ret = 0;
goto out;
} }
case PTRACE_DETACH: { /* detach a process that was attached. */ case PTRACE_DETACH: { /* detach a process that was attached. */
long tmp; long tmp;
ret = -EIO;
if ((unsigned long) data >= NSIG) if ((unsigned long) data >= NSIG)
return -EIO; goto out;
child->flags &= ~(PF_PTRACED|PF_TRACESYS); child->flags &= ~(PF_PTRACED|PF_TRACESYS);
wake_up_process(child); wake_up_process(child);
child->exit_code = data; child->exit_code = data;
...@@ -499,19 +518,25 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -499,19 +518,25 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
/* make sure the single step bit is not set. */ /* make sure the single step bit is not set. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
put_reg(child, PT_SR, tmp); put_reg(child, PT_SR, tmp);
return 0; ret = 0;
goto out;
} }
default: default:
return -EIO; ret = -EIO;
goto out;
} }
out:
unlock_kernel();
return ret;
} }
asmlinkage void syscall_trace(void) asmlinkage void syscall_trace(void)
{ {
lock_kernel();
if ((current->flags & (PF_PTRACED|PF_TRACESYS)) if ((current->flags & (PF_PTRACED|PF_TRACESYS))
!= (PF_PTRACED|PF_TRACESYS)) != (PF_PTRACED|PF_TRACESYS))
return; goto out;
current->exit_code = SIGTRAP; current->exit_code = SIGTRAP;
current->state = TASK_STOPPED; current->state = TASK_STOPPED;
notify_parent(current); notify_parent(current);
...@@ -524,5 +549,6 @@ asmlinkage void syscall_trace(void) ...@@ -524,5 +549,6 @@ asmlinkage void syscall_trace(void)
if (current->exit_code) if (current->exit_code)
current->signal |= (1 << (current->exit_code - 1)); current->signal |= (1 << (current->exit_code - 1));
current->exit_code = 0; current->exit_code = 0;
return; out:
unlock_kernel();
} }
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h> #include <linux/sem.h>
#include <linux/msg.h> #include <linux/msg.h>
#include <linux/shm.h> #include <linux/shm.h>
...@@ -31,15 +33,18 @@ asmlinkage int sys_pipe(unsigned long * fildes) ...@@ -31,15 +33,18 @@ asmlinkage int sys_pipe(unsigned long * fildes)
int fd[2]; int fd[2];
int error; int error;
lock_kernel();
error = verify_area(VERIFY_WRITE,fildes,8); error = verify_area(VERIFY_WRITE,fildes,8);
if (error) if (error)
return error; goto out;
error = do_pipe(fd); error = do_pipe(fd);
if (error) if (error)
return error; goto out;
put_user(fd[0],0+fildes); put_user(fd[0],0+fildes);
put_user(fd[1],1+fildes); put_user(fd[1],1+fildes);
return 0; out:
unlock_kernel();
return error;
} }
/* /*
...@@ -64,16 +69,20 @@ asmlinkage int old_mmap(struct mmap_arg_struct *arg) ...@@ -64,16 +69,20 @@ asmlinkage int old_mmap(struct mmap_arg_struct *arg)
struct file * file = NULL; struct file * file = NULL;
struct mmap_arg_struct a; struct mmap_arg_struct a;
lock_kernel();
error = verify_area(VERIFY_READ, arg, sizeof(*arg)); error = verify_area(VERIFY_READ, arg, sizeof(*arg));
if (error) if (error)
return error; goto out;
copy_from_user(&a, arg, sizeof(a)); copy_from_user(&a, arg, sizeof(a));
if (!(a.flags & MAP_ANONYMOUS)) { if (!(a.flags & MAP_ANONYMOUS)) {
error = -EBADF;
if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd])) if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd]))
return -EBADF; goto out;
} }
a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset); error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset);
out:
unlock_kernel();
return error; return error;
} }
...@@ -89,10 +98,15 @@ struct sel_arg_struct { ...@@ -89,10 +98,15 @@ struct sel_arg_struct {
asmlinkage int old_select(struct sel_arg_struct *arg) asmlinkage int old_select(struct sel_arg_struct *arg)
{ {
struct sel_arg_struct a; struct sel_arg_struct a;
int ret = -EFAULT;
lock_kernel();
if (copy_from_user(&a, arg, sizeof(a))) if (copy_from_user(&a, arg, sizeof(a)))
return -EFAULT; goto out;
return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); ret = sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
out:
unlock_kernel();
return ret;
} }
/* /*
...@@ -102,7 +116,7 @@ asmlinkage int old_select(struct sel_arg_struct *arg) ...@@ -102,7 +116,7 @@ asmlinkage int old_select(struct sel_arg_struct *arg)
*/ */
asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth) asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
{ {
int version; int version, ret;
version = call >> 16; /* hack for backward compatibility */ version = call >> 16; /* hack for backward compatibility */
call &= 0xffff; call &= 0xffff;
...@@ -110,46 +124,58 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, ...@@ -110,46 +124,58 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
if (call <= SEMCTL) if (call <= SEMCTL)
switch (call) { switch (call) {
case SEMOP: case SEMOP:
return sys_semop (first, (struct sembuf *)ptr, second); ret = sys_semop (first, (struct sembuf *)ptr, second);
goto out;
case SEMGET: case SEMGET:
return sys_semget (first, second, third); ret = sys_semget (first, second, third);
goto out;
case SEMCTL: { case SEMCTL: {
union semun fourth; union semun fourth;
int err; ret = -EINVAL;
if (!ptr) if (!ptr)
return -EINVAL; goto out;
if ((err = verify_area (VERIFY_READ, ptr, sizeof(long)))) if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long))))
return err; goto out;
get_user(fourth.__pad, (void **)ptr); get_user(fourth.__pad, (void **)ptr);
return sys_semctl (first, second, third, fourth); ret = sys_semctl (first, second, third, fourth);
goto out;
} }
default: default:
return -EINVAL; ret = -EINVAL;
goto out;
} }
if (call <= MSGCTL) if (call <= MSGCTL)
switch (call) { switch (call) {
case MSGSND: case MSGSND:
return sys_msgsnd (first, (struct msgbuf *) ptr, ret = sys_msgsnd (first, (struct msgbuf *) ptr,
second, third); second, third);
goto out;
case MSGRCV: case MSGRCV:
switch (version) { switch (version) {
case 0: { case 0: {
struct ipc_kludge tmp; struct ipc_kludge tmp;
ret = -EINVAL;
if (!ptr) if (!ptr)
return -EINVAL; goto out;
ret = -EFAULT;
if (copy_from_user (&tmp, ptr, sizeof (tmp))) if (copy_from_user (&tmp, ptr, sizeof (tmp)))
return -EFAULT; goto out;
return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third); ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
goto out;
} }
case 1: default: case 1: default:
return sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third); ret = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
goto out;
} }
case MSGGET: case MSGGET:
return sys_msgget ((key_t) first, second); ret = sys_msgget ((key_t) first, second);
goto out;
case MSGCTL: case MSGCTL:
return sys_msgctl (first, second, (struct msqid_ds *) ptr); ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
goto out;
default: default:
return -EINVAL; ret = -EINVAL;
goto out;
} }
if (call <= SHMCTL) if (call <= SHMCTL)
switch (call) { switch (call) {
...@@ -157,30 +183,40 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, ...@@ -157,30 +183,40 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
switch (version) { switch (version) {
case 0: default: { case 0: default: {
ulong raddr; ulong raddr;
int err; if ((ret = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
if ((err = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong)))) goto out;
return err; ret = sys_shmat (first, (char *) ptr, second, &raddr);
err = sys_shmat (first, (char *) ptr, second, &raddr); if (ret)
if (err) goto out;
return err;
put_user (raddr, (ulong *) third); put_user (raddr, (ulong *) third);
return 0; ret = 0;
goto out;
} }
case 1: /* iBCS2 emulator entry point */ case 1: /* iBCS2 emulator entry point */
ret = -EINVAL;
if (get_fs() != get_ds()) if (get_fs() != get_ds())
return -EINVAL; goto out;
return sys_shmat (first, (char *) ptr, second, (ulong *) third); ret = sys_shmat (first, (char *) ptr, second, (ulong *) third);
goto out;
} }
case SHMDT: case SHMDT:
return sys_shmdt ((char *)ptr); ret = sys_shmdt ((char *)ptr);
goto out;
case SHMGET: case SHMGET:
return sys_shmget (first, second, third); ret = sys_shmget (first, second, third);
goto out;
case SHMCTL: case SHMCTL:
return sys_shmctl (first, second, (struct shmid_ds *) ptr); ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
goto out;
default: default:
return -EINVAL; ret = -EINVAL;
goto out;
} }
return -EINVAL; else
ret = -EINVAL;
out:
unlock_kernel();
return ret;
} }
asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on) asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
...@@ -496,60 +532,63 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len) ...@@ -496,60 +532,63 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
asmlinkage int asmlinkage int
sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
{ {
struct vm_area_struct *vma; struct vm_area_struct *vma;
int ret = -EINVAL;
if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL lock_kernel();
|| cache & ~FLUSH_CACHE_BOTH) if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
return -EINVAL; cache & ~FLUSH_CACHE_BOTH)
goto out;
if (scope == FLUSH_SCOPE_ALL) if (scope == FLUSH_SCOPE_ALL) {
{ /* Only the superuser may flush the whole cache. */
/* Only the superuser may flush the whole cache. */ ret = -EPERM;
if (!suser ()) if (!suser ())
return -EPERM; goto out;
} } else {
else /* Verify that the specified address region actually belongs to
{ * this process.
/* Verify that the specified address region actually belongs to */
this process. */ vma = find_vma (current->mm, addr);
vma = find_vma (current->mm, addr); ret = -EINVAL;
if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end) if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
return -EINVAL; goto out;
} }
if (CPU_IS_020_OR_030) { if (CPU_IS_020_OR_030) {
if (scope == FLUSH_SCOPE_LINE) if (scope == FLUSH_SCOPE_LINE) {
{ unsigned long cacr;
unsigned long cacr; __asm__ ("movec %%cacr, %0" : "=r" (cacr));
__asm__ ("movec %%cacr, %0" : "=r" (cacr)); if (cache & FLUSH_CACHE_INSN)
if (cache & FLUSH_CACHE_INSN) cacr |= 4;
cacr |= 4; if (cache & FLUSH_CACHE_DATA)
if (cache & FLUSH_CACHE_DATA) cacr |= 0x400;
cacr |= 0x400; len >>= 4;
len >>= 4; while (len--) {
while (len--) __asm__ __volatile__ ("movec %1, %%caar\n\t"
{ "movec %0, %%cacr"
__asm__ __volatile__ ("movec %1, %%caar\n\t" : /* no outputs */
"movec %0, %%cacr" : "r" (cacr), "r" (addr));
: /* no outputs */ addr += 16;
: "r" (cacr), "r" (addr)); }
addr += 16; } else {
} /* Flush the whole cache, even if page granularity requested. */
} unsigned long cacr;
else __asm__ ("movec %%cacr, %0" : "=r" (cacr));
{ if (cache & FLUSH_CACHE_INSN)
/* Flush the whole cache, even if page granularity is requested. */ cacr |= 8;
unsigned long cacr; if (cache & FLUSH_CACHE_DATA)
__asm__ ("movec %%cacr, %0" : "=r" (cacr)); cacr |= 0x800;
if (cache & FLUSH_CACHE_INSN) __asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
cacr |= 8; }
if (cache & FLUSH_CACHE_DATA) ret = 0;
cacr |= 0x800; goto out;
__asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr)); } else if (CPU_IS_040) {
} ret = cache_flush_040 (addr, scope, cache, len);
return 0; } else if (CPU_IS_060) {
} else if (CPU_IS_040) ret = cache_flush_060 (addr, scope, cache, len);
return cache_flush_040 (addr, scope, cache, len); }
else if (CPU_IS_060) out:
return cache_flush_060 (addr, scope, cache, len); unlock_kernel();
return ret;
} }
...@@ -477,6 +477,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem) ...@@ -477,6 +477,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
datapages << (PAGE_SHIFT-10)); datapages << (PAGE_SHIFT-10));
} }
void free_initmem(void)
{
/* To be written */
}
void si_meminfo(struct sysinfo *val) void si_meminfo(struct sysinfo *val)
{ {
unsigned long i; unsigned long i;
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h> #include <linux/sem.h>
#include <linux/msg.h> #include <linux/msg.h>
#include <linux/shm.h> #include <linux/shm.h>
...@@ -25,57 +27,67 @@ ...@@ -25,57 +27,67 @@
asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth) asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
{ {
#ifdef CONFIG_SYSVIPC #ifdef CONFIG_SYSVIPC
int version; int version, ret;
lock_kernel();
version = call >> 16; /* hack for backward compatibility */ version = call >> 16; /* hack for backward compatibility */
call &= 0xffff; call &= 0xffff;
if (call <= SEMCTL) if (call <= SEMCTL)
switch (call) { switch (call) {
case SEMOP: case SEMOP:
return sys_semop (first, (struct sembuf *)ptr, second); ret = sys_semop (first, (struct sembuf *)ptr, second);
goto out;
case SEMGET: case SEMGET:
return sys_semget (first, second, third); ret = sys_semget (first, second, third);
goto out;
case SEMCTL: { case SEMCTL: {
union semun fourth; union semun fourth;
int err; ret = -EINVAL;
if (!ptr) if (!ptr)
return -EINVAL; goto out;
if ((err = verify_area (VERIFY_READ, ptr, sizeof(long)))) if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long))))
return err; goto out;
fourth.__pad = (void *) get_fs_long(ptr); fourth.__pad = (void *) get_fs_long(ptr);
return sys_semctl (first, second, third, fourth); ret = sys_semctl (first, second, third, fourth);
goto out;
} }
default: default:
return -EINVAL; ret = -EINVAL;
goto out;
} }
if (call <= MSGCTL) if (call <= MSGCTL)
switch (call) { switch (call) {
case MSGSND: case MSGSND:
return sys_msgsnd (first, (struct msgbuf *) ptr, ret = sys_msgsnd (first, (struct msgbuf *) ptr,
second, third); second, third);
goto out;
case MSGRCV: case MSGRCV:
switch (version) { switch (version) {
case 0: { case 0: {
struct ipc_kludge tmp; struct ipc_kludge tmp;
int err;
if (!ptr) if (!ptr)
return -EINVAL; return -EINVAL;
if ((err = verify_area (VERIFY_READ, ptr, sizeof(tmp)))) if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp))))
return err; goto out;
memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr, memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr,
sizeof (tmp)); sizeof (tmp));
return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third); ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
goto out;
} }
case 1: default: case 1: default:
return sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third); ret = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
goto out;
} }
case MSGGET: case MSGGET:
return sys_msgget ((key_t) first, second); ret = sys_msgget ((key_t) first, second);
goto out;
case MSGCTL: case MSGCTL:
return sys_msgctl (first, second, (struct msqid_ds *) ptr); ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
goto out;
default: default:
return -EINVAL; ret = -EINVAL;
goto out;
} }
if (call <= SHMCTL) if (call <= SHMCTL)
switch (call) { switch (call) {
...@@ -83,30 +95,40 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, ...@@ -83,30 +95,40 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
switch (version) { switch (version) {
case 0: default: { case 0: default: {
ulong raddr; ulong raddr;
int err; if ((ret = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
if ((err = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong)))) goto out;
return err; ret = sys_shmat (first, (char *) ptr, second, &raddr);
err = sys_shmat (first, (char *) ptr, second, &raddr); if (ret)
if (err) goto out;
return err;
put_fs_long (raddr, (ulong *) third); put_fs_long (raddr, (ulong *) third);
return 0; ret = 0;
goto out;
} }
case 1: /* iBCS2 emulator entry point */ case 1: /* iBCS2 emulator entry point */
ret = -EINVAL;
if (get_fs() != get_ds()) if (get_fs() != get_ds())
return -EINVAL; goto out;
return sys_shmat (first, (char *) ptr, second, (ulong *) third); ret = sys_shmat (first, (char *) ptr, second, (ulong *) third);
goto out;
} }
case SHMDT: case SHMDT:
return sys_shmdt ((char *)ptr); ret = sys_shmdt ((char *)ptr);
goto out;
case SHMGET: case SHMGET:
return sys_shmget (first, second, third); ret = sys_shmget (first, second, third);
goto out;
case SHMCTL: case SHMCTL:
return sys_shmctl (first, second, (struct shmid_ds *) ptr); ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
goto out;
default: default:
return -EINVAL; ret = -EINVAL;
goto out;
} }
return -EINVAL; else
ret = -EINVAL;
out:
unlock_kernel();
return ret;
#else /* CONFIG_SYSVIPC */ #else /* CONFIG_SYSVIPC */
return -ENOSYS; return -ENOSYS;
#endif /* CONFIG_SYSVIPC */ #endif /* CONFIG_SYSVIPC */
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
*/ */
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -29,8 +31,11 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs); ...@@ -29,8 +31,11 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs);
asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set) asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set)
{ {
unsigned long mask; unsigned long mask;
struct pt_regs * regs = (struct pt_regs *) &restart; struct pt_regs * regs;
int ret = -EINTR;
lock_kernel();
regs = (struct pt_regs *) &restart;
mask = current->blocked; mask = current->blocked;
current->blocked = set & _BLOCKABLE; current->blocked = set & _BLOCKABLE;
regs->reg2 = -EINTR; regs->reg2 = -EINTR;
...@@ -38,8 +43,11 @@ asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long ...@@ -38,8 +43,11 @@ asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
schedule(); schedule();
if (do_signal(mask,regs)) if (do_signal(mask,regs))
return -EINTR; goto out;
} }
out:
unlock_kernel();
return ret;
} }
/* /*
...@@ -48,7 +56,9 @@ asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long ...@@ -48,7 +56,9 @@ asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long
asmlinkage int sys_sigreturn(struct pt_regs *regs) asmlinkage int sys_sigreturn(struct pt_regs *regs)
{ {
struct sigcontext_struct *context; struct sigcontext_struct *context;
int ret;
lock_kernel();
/* /*
* We don't support fixing ADEL/ADES exceptions for signal stack frames. * We don't support fixing ADEL/ADES exceptions for signal stack frames.
* No big loss - who doesn't care about the alignment of this stack * No big loss - who doesn't care about the alignment of this stack
...@@ -99,10 +109,14 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs) ...@@ -99,10 +109,14 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
* disable syscall checks * disable syscall checks
*/ */
regs->orig_reg2 = -1; regs->orig_reg2 = -1;
return context->sc_v0; goto out;
badframe: badframe:
do_exit(SIGSEGV); do_exit(SIGSEGV);
out:
ret = context->sc_v0;
unlock_kernel();
return ret;
} }
/* /*
...@@ -239,13 +253,16 @@ static void setup_frame(struct sigaction * sa, struct sc **fp, ...@@ -239,13 +253,16 @@ static void setup_frame(struct sigaction * sa, struct sc **fp,
*/ */
asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
{ {
unsigned long mask = ~current->blocked; unsigned long mask;
unsigned long handler_signal = 0; unsigned long handler_signal = 0;
struct sc *frame = NULL; struct sc *frame = NULL;
unsigned long pc = 0; unsigned long pc = 0;
unsigned long signr; unsigned long signr;
struct sigaction * sa; struct sigaction * sa;
int ret;
lock_kernel();
mask = ~current->blocked;
while ((signr = current->signal & mask)) { while ((signr = current->signal & mask)) {
signr = ffz(~signr); signr = ffz(~signr);
clear_bit(signr, &current->signal); clear_bit(signr, &current->signal);
...@@ -331,8 +348,9 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) ...@@ -331,8 +348,9 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
regs->reg2 = regs->orig_reg2; regs->reg2 = regs->orig_reg2;
regs->cp0_epc -= 8; regs->cp0_epc -= 8;
} }
ret = 0;
if (!handler_signal) /* no handler will be called - return 0 */ if (!handler_signal) /* no handler will be called - return 0 */
return 0; goto out;
pc = regs->cp0_epc; pc = regs->cp0_epc;
frame = (struct sc *) regs->reg29; frame = (struct sc *) regs->reg29;
signr = 1; signr = 1;
...@@ -353,5 +371,8 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) ...@@ -353,5 +371,8 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
regs->reg31 = (unsigned long) frame->code; /* Return address */ regs->reg31 = (unsigned long) frame->code; /* Return address */
regs->cp0_epc = pc; /* "return" to the first handler */ regs->cp0_epc = pc; /* "return" to the first handler */
return 1; ret = 1;
out:
unlock_kernel();
return ret;
} }
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
*/ */
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/mman.h> #include <linux/mman.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/unistd.h> #include <linux/unistd.h>
...@@ -28,32 +30,43 @@ asmlinkage int sys_pipe(struct pt_regs *regs) ...@@ -28,32 +30,43 @@ asmlinkage int sys_pipe(struct pt_regs *regs)
int fd[2]; int fd[2];
int error; int error;
lock_kernel();
error = do_pipe(fd); error = do_pipe(fd);
if (error) if (error)
return error; goto out;
regs->reg2 = fd[0]; regs->reg2 = fd[0];
regs->reg3 = fd[1]; regs->reg3 = fd[1];
return 0; out:
unlock_kernel();
return error;
} }
asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, int prot, asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, int prot,
int flags, int fd, off_t offset) int flags, int fd, off_t offset)
{ {
struct file * file = NULL; struct file * file = NULL;
int ret = -EBADF;
lock_kernel();
if (flags & MAP_RENAME) { if (flags & MAP_RENAME) {
if (fd >= NR_OPEN || !(file = current->files->fd[fd])) if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
return -EBADF; goto out;
} }
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
return do_mmap(file, addr, len, prot, flags, offset); ret = do_mmap(file, addr, len, prot, flags, offset);
out:
unlock_kernel();
return ret;
} }
asmlinkage int sys_idle(void) asmlinkage int sys_idle(void)
{ {
int ret = -EPERM;
lock_kernel();
if (current->pid != 0) if (current->pid != 0)
return -EPERM; goto out;
/* endless idle loop with no priority at all */ /* endless idle loop with no priority at all */
current->counter = -100; current->counter = -100;
...@@ -67,23 +80,36 @@ asmlinkage int sys_idle(void) ...@@ -67,23 +80,36 @@ asmlinkage int sys_idle(void)
".set\tmips0\n\t"); ".set\tmips0\n\t");
schedule(); schedule();
} }
ret = 0;
out:
unlock_kernel();
return ret;
} }
asmlinkage int sys_fork(struct pt_regs *regs) asmlinkage int sys_fork(struct pt_regs *regs)
{ {
return do_fork(SIGCHLD, regs->reg29, regs); int ret;
lock_kernel();
ret = do_fork(SIGCHLD, regs->reg29, regs);
unlock_kernel();
return ret;
} }
asmlinkage int sys_clone(struct pt_regs *regs) asmlinkage int sys_clone(struct pt_regs *regs)
{ {
unsigned long clone_flags; unsigned long clone_flags;
unsigned long newsp; unsigned long newsp;
int ret;
lock_kernel();
clone_flags = regs->reg4; clone_flags = regs->reg4;
newsp = regs->reg5; newsp = regs->reg5;
if (!newsp) if (!newsp)
newsp = regs->reg29; newsp = regs->reg29;
return do_fork(clone_flags, newsp, regs); ret = do_fork(clone_flags, newsp, regs);
unlock_kernel();
return ret;
} }
/* /*
...@@ -94,12 +120,15 @@ asmlinkage int sys_execve(struct pt_regs *regs) ...@@ -94,12 +120,15 @@ asmlinkage int sys_execve(struct pt_regs *regs)
int error; int error;
char * filename; char * filename;
lock_kernel();
error = getname((char *) regs->reg4, &filename); error = getname((char *) regs->reg4, &filename);
if (error) if (error)
return error; goto out;
error = do_execve(filename, (char **) regs->reg5, error = do_execve(filename, (char **) regs->reg5,
(char **) regs->reg6, regs); (char **) regs->reg6, regs);
putname(filename); putname(filename);
out:
unlock_kernel();
return error; return error;
} }
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/utsname.h> #include <linux/utsname.h>
...@@ -54,44 +56,51 @@ sys_sysmips(int cmd, int arg1, int arg2, int arg3) ...@@ -54,44 +56,51 @@ sys_sysmips(int cmd, int arg1, int arg2, int arg3)
char *name; char *name;
int flags, len, retval = -EINVAL; int flags, len, retval = -EINVAL;
lock_kernel();
switch(cmd) switch(cmd)
{ {
case SETNAME: case SETNAME:
retval = -EPERM;
if (!suser()) if (!suser())
return -EPERM; goto out;
name = (char *) arg1; name = (char *) arg1;
len = get_max_hostname((unsigned long)name); len = get_max_hostname((unsigned long)name);
if (retval < 0) retval = len;
return len; if (len < 0)
goto out;
len = strnlen_user(name, retval); len = strnlen_user(name, retval);
retval = -EINVAL;
if (len == 0 || len > __NEW_UTS_LEN) if (len == 0 || len > __NEW_UTS_LEN)
return -EINVAL; goto out;
memcpy_fromfs(system_utsname.nodename, name, len); memcpy_fromfs(system_utsname.nodename, name, len);
system_utsname.nodename[len] = '\0'; system_utsname.nodename[len] = '\0';
return 0; retval = 0;
goto out;
case MIPS_ATOMIC_SET: case MIPS_ATOMIC_SET:
p = (int *) arg1; p = (int *) arg1;
retval = verify_area(VERIFY_WRITE, p, sizeof(*p)); retval = -EINVAL;
if(retval) if(verify_area(VERIFY_WRITE, p, sizeof(*p)))
return -EINVAL; goto out;
save_flags(flags); save_flags(flags);
cli(); cli();
retval = *p; retval = *p;
*p = arg2; *p = arg2;
restore_flags(flags); restore_flags(flags);
return retval; goto out;
case MIPS_FIXADE: case MIPS_FIXADE:
if (arg1) if (arg1)
current->tss.mflags |= MF_FIXADE; current->tss.mflags |= MF_FIXADE;
else else
current->tss.mflags |= MF_FIXADE; current->tss.mflags |= MF_FIXADE;
retval = 0; retval = 0;
break; goto out;
case FLUSH_CACHE: case FLUSH_CACHE:
sys_cacheflush(0, ~0, BCACHE); sys_cacheflush(0, ~0, BCACHE);
break; retval = 0;
goto out;
} }
out:
unlock_kernel();
return retval; return retval;
} }
......
...@@ -281,6 +281,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem) ...@@ -281,6 +281,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
return; return;
} }
void free_initmem(void)
{
/* To be written */
}
void si_meminfo(struct sysinfo *val) void si_meminfo(struct sysinfo *val)
{ {
int i; int i;
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
...@@ -133,19 +135,30 @@ switch_to(struct task_struct *prev, struct task_struct *new) ...@@ -133,19 +135,30 @@ switch_to(struct task_struct *prev, struct task_struct *new)
asmlinkage int sys_debug(unsigned long r3) asmlinkage int sys_debug(unsigned long r3)
{ {
if ( !strcmp(current->comm,"crashme")) lock_kernel();
printk("sys_debug(): r3 (syscall) %d\n", r3); if (!strcmp(current->comm,"crashme"))
printk("sys_debug(): r3 (syscall) %d\n", r3);
unlock_kernel();
return 0;
} }
asmlinkage int sys_idle(void) asmlinkage int sys_idle(void)
{ {
if (current->pid != 0) int ret = -EPERM;
return -EPERM;
/* endless idle loop with no priority at all */ lock_kernel();
current->counter = -100; if (current->pid != 0)
for (;;) { goto out;
schedule();
} /* endless idle loop with no priority at all */
current->counter = -100;
for (;;) {
schedule();
}
ret = 0;
out:
unlock_kernel();
return ret;
} }
void show_regs(struct pt_regs * regs) void show_regs(struct pt_regs * regs)
...@@ -232,7 +245,12 @@ void dump_thread(struct pt_regs * regs, struct user * dump) ...@@ -232,7 +245,12 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs) asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs)
{ {
return do_fork(SIGCHLD, regs->gpr[1], regs); int ret;
lock_kernel();
ret = do_fork(SIGCHLD, regs->gpr[1], regs);
unlock_kernel();
return ret;
} }
asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
...@@ -242,6 +260,7 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, ...@@ -242,6 +260,7 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
int error; int error;
char * filename; char * filename;
lock_kernel();
/* getname does it's own verification of the address /* getname does it's own verification of the address
when it calls get_max_filename() but when it calls get_max_filename() but
it will assume it's valid if get_fs() == KERNEL_DS it will assume it's valid if get_fs() == KERNEL_DS
...@@ -265,9 +284,7 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, ...@@ -265,9 +284,7 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
#endif #endif
error = getname((char *) a0, &filename); error = getname((char *) a0, &filename);
if (error) if (error)
{ goto out;
return error;
}
flush_instruction_cache(); flush_instruction_cache();
error = do_execve(filename, (char **) a1, (char **) a2, regs); error = do_execve(filename, (char **) a1, (char **) a2, regs);
#if 0 #if 0
...@@ -277,6 +294,8 @@ printk("EXECVE - file = '%s', error = %d\n", filename, error); ...@@ -277,6 +294,8 @@ printk("EXECVE - file = '%s', error = %d\n", filename, error);
} }
#endif #endif
putname(filename); putname(filename);
out:
unlock_kernel();
return error; return error;
} }
...@@ -284,7 +303,10 @@ asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, struct ...@@ -284,7 +303,10 @@ asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, struct
{ {
unsigned long clone_flags = p1; unsigned long clone_flags = p1;
int res; int res;
lock_kernel();
res = do_fork(clone_flags, regs->gpr[1], regs); res = do_fork(clone_flags, regs->gpr[1], regs);
unlock_kernel();
return res; return res;
} }
...@@ -339,9 +361,9 @@ print_kernel_backtrace(void) ...@@ -339,9 +361,9 @@ print_kernel_backtrace(void)
inline void start_thread(struct pt_regs * regs, inline void start_thread(struct pt_regs * regs,
unsigned long eip, unsigned long esp) unsigned long eip, unsigned long esp)
{ {
regs->nip = eip; regs->nip = eip;
regs->gpr[1] = esp; regs->gpr[1] = esp;
regs->msr = MSR_USER; regs->msr = MSR_USER;
set_fs(USER_DS); set_fs(USER_DS);
} }
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/user.h> #include <linux/user.h>
...@@ -376,34 +378,37 @@ static int write_long(struct task_struct * tsk, unsigned long addr, ...@@ -376,34 +378,37 @@ static int write_long(struct task_struct * tsk, unsigned long addr,
asmlinkage int sys_ptrace(long request, long pid, long addr, long data) asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{ {
struct task_struct *child; struct task_struct *child;
struct user * dummy; struct user * dummy = NULL;
int ret = -EPERM;
dummy = NULL;
lock_kernel();
if (request == PTRACE_TRACEME) { if (request == PTRACE_TRACEME) {
/* are we already being traced? */ /* are we already being traced? */
if (current->flags & PF_PTRACED) if (current->flags & PF_PTRACED)
return -EPERM; goto out;
/* set the ptrace bit in the process flags. */ /* set the ptrace bit in the process flags. */
current->flags |= PF_PTRACED; current->flags |= PF_PTRACED;
return 0; ret = 0;
goto out;
} }
if (pid == 1) /* you may not mess with init */ if (pid == 1) /* you may not mess with init */
return -EPERM; goto out;
ret = -ESRCH;
if (!(child = get_task(pid))) if (!(child = get_task(pid)))
return -ESRCH; goto out;
ret = -EPERM;
if (request == PTRACE_ATTACH) { if (request == PTRACE_ATTACH) {
if (child == current) if (child == current)
return -EPERM; goto out;
if ((!child->dumpable || if ((!child->dumpable ||
(current->uid != child->euid) || (current->uid != child->euid) ||
(current->uid != child->uid) || (current->uid != child->uid) ||
(current->gid != child->egid) || (current->gid != child->egid) ||
(current->gid != child->gid)) && !suser()) (current->gid != child->gid)) && !suser())
return -EPERM; goto out;
/* the same process cannot be attached many times */ /* the same process cannot be attached many times */
if (child->flags & PF_PTRACED) if (child->flags & PF_PTRACED)
return -EPERM; goto out;
child->flags |= PF_PTRACED; child->flags |= PF_PTRACED;
if (child->p_pptr != current) { if (child->p_pptr != current) {
REMOVE_LINKS(child); REMOVE_LINKS(child);
...@@ -411,73 +416,75 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -411,73 +416,75 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
SET_LINKS(child); SET_LINKS(child);
} }
send_sig(SIGSTOP, child, 1); send_sig(SIGSTOP, child, 1);
return 0; ret = 0;
goto out;
} }
ret = -ESRCH;
if (!(child->flags & PF_PTRACED)) if (!(child->flags & PF_PTRACED))
return -ESRCH; goto out;
if (child->state != TASK_STOPPED) { if (child->state != TASK_STOPPED) {
if (request != PTRACE_KILL) if (request != PTRACE_KILL)
return -ESRCH; goto out;
} }
if (child->p_pptr != current) if (child->p_pptr != current)
return -ESRCH; goto out;
switch (request) { switch (request) {
/* If I and D space are separate, these will need to be fixed. */ /* If I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: { case PTRACE_PEEKDATA: {
unsigned long tmp; unsigned long tmp;
int res;
res = read_long(child, addr, &tmp); ret = read_long(child, addr, &tmp);
if (res < 0) if (ret < 0)
return res; goto out;
res = verify_area(VERIFY_WRITE, (void *) data, sizeof(long)); ret = verify_area(VERIFY_WRITE, (void *) data, sizeof(long));
if (!res) if (!ret)
put_user(tmp, (unsigned long *) data); put_user(tmp, (unsigned long *) data);
return res; goto out;
} }
/* read the word at location addr in the USER area. */ /* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: { case PTRACE_PEEKUSR: {
unsigned long tmp; unsigned long tmp;
int res;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
return -EIO; return -EIO;
res = verify_area(VERIFY_WRITE, (void *) data, ret = verify_area(VERIFY_WRITE, (void *) data,
sizeof(long)); sizeof(long));
if (res) if (ret)
return res; goto out;
tmp = 0; /* Default return condition */ tmp = 0; /* Default return condition */
addr = addr >> 2; /* temporary hack. */ addr = addr >> 2; /* temporary hack. */
if (addr < PT_FPR0) { if (addr < PT_FPR0)
tmp = get_reg(child, addr); tmp = get_reg(child, addr);
}
#if 0 #if 0
else if (addr >= PT_FPR0 && addr < PT_FPR31) else if (addr >= PT_FPR0 && addr < PT_FPR31)
tmp = child->tss.fpr[addr - PT_FPR0]; tmp = child->tss.fpr[addr - PT_FPR0];
#endif #endif
else else
return -EIO; ret = -EIO;
put_user(tmp,(unsigned long *) data); if(!ret)
return 0; put_user(tmp,(unsigned long *) data);
goto out;
} }
/* If I and D space are separate, this will have to be fixed. */ /* If I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA: case PTRACE_POKEDATA:
return write_long(child,addr,data); ret = write_long(child,addr,data);
goto out;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
ret = -EIO;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
return -EIO; goto out;
addr = addr >> 2; /* temporary hack. */ addr = addr >> 2; /* temporary hack. */
if (addr == PT_ORIG_R3) if (addr == PT_ORIG_R3)
return -EIO; goto out;
#if 0 /* Let this check be in 'put_reg' */ #if 0 /* Let this check be in 'put_reg' */
if (addr == PT_SR) { if (addr == PT_SR) {
data &= SR_MASK; data &= SR_MASK;
...@@ -487,22 +494,24 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -487,22 +494,24 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
#endif #endif
if (addr < PT_FPR0) { if (addr < PT_FPR0) {
if (put_reg(child, addr, data)) if (put_reg(child, addr, data))
return -EIO; goto out;
return 0; ret = 0;
goto out;
} }
#if 0 #if 0
if (addr >= 21 && addr < 48) if (addr >= 21 && addr < 48) {
{
child->tss.fp[addr - 21] = data; child->tss.fp[addr - 21] = data;
return 0; ret = 0;
goto out;
} }
#endif #endif
return -EIO; goto out;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */ case PTRACE_CONT: { /* restart after signal. */
ret = -EIO;
if ((unsigned long) data >= NSIG) if ((unsigned long) data >= NSIG)
return -EIO; goto out;
if (request == PTRACE_SYSCALL) if (request == PTRACE_SYSCALL)
child->flags |= PF_TRACESYS; child->flags |= PF_TRACESYS;
else else
...@@ -511,7 +520,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -511,7 +520,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
wake_up_process(child); wake_up_process(child);
/* make sure the single step bit is not set. */ /* make sure the single step bit is not set. */
clear_single_step(child); clear_single_step(child);
return 0; ret = 0;
goto out;
} }
/* /*
...@@ -520,29 +530,33 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -520,29 +530,33 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
* exit. * exit.
*/ */
case PTRACE_KILL: { case PTRACE_KILL: {
ret = 0;
if (child->state == TASK_ZOMBIE) /* already dead */ if (child->state == TASK_ZOMBIE) /* already dead */
return 0; goto out;
wake_up_process(child); wake_up_process(child);
child->exit_code = SIGKILL; child->exit_code = SIGKILL;
/* make sure the single step bit is not set. */ /* make sure the single step bit is not set. */
clear_single_step(child); clear_single_step(child);
return 0; goto out;
} }
case PTRACE_SINGLESTEP: { /* set the trap flag. */ case PTRACE_SINGLESTEP: { /* set the trap flag. */
ret = -EIO;
if ((unsigned long) data >= NSIG) if ((unsigned long) data >= NSIG)
return -EIO; goto out;
child->flags &= ~PF_TRACESYS; child->flags &= ~PF_TRACESYS;
set_single_step(child); set_single_step(child);
wake_up_process(child); wake_up_process(child);
child->exit_code = data; child->exit_code = data;
/* give it a chance to run. */ /* give it a chance to run. */
return 0; ret = 0;
goto out;
} }
case PTRACE_DETACH: { /* detach a process that was attached. */ case PTRACE_DETACH: { /* detach a process that was attached. */
ret = -EIO;
if ((unsigned long) data >= NSIG) if ((unsigned long) data >= NSIG)
return -EIO; goto out;
child->flags &= ~(PF_PTRACED|PF_TRACESYS); child->flags &= ~(PF_PTRACED|PF_TRACESYS);
wake_up_process(child); wake_up_process(child);
child->exit_code = data; child->exit_code = data;
...@@ -551,19 +565,25 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) ...@@ -551,19 +565,25 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
SET_LINKS(child); SET_LINKS(child);
/* make sure the single step bit is not set. */ /* make sure the single step bit is not set. */
clear_single_step(child); clear_single_step(child);
return 0; ret = 0;
goto out;
} }
default: default:
return -EIO; ret = -EIO;
goto out;
} }
out:
unlock_kernel();
return ret;
} }
asmlinkage void syscall_trace(void) asmlinkage void syscall_trace(void)
{ {
lock_kernel();
if ((current->flags & (PF_PTRACED|PF_TRACESYS)) if ((current->flags & (PF_PTRACED|PF_TRACESYS))
!= (PF_PTRACED|PF_TRACESYS)) != (PF_PTRACED|PF_TRACESYS))
return; goto out;
current->exit_code = SIGTRAP; current->exit_code = SIGTRAP;
current->state = TASK_STOPPED; current->state = TASK_STOPPED;
notify_parent(current); notify_parent(current);
...@@ -576,5 +596,6 @@ asmlinkage void syscall_trace(void) ...@@ -576,5 +596,6 @@ asmlinkage void syscall_trace(void)
if (current->exit_code) if (current->exit_code)
current->signal |= (1 << (current->exit_code - 1)); current->signal |= (1 << (current->exit_code - 1));
current->exit_code = 0; current->exit_code = 0;
return; out:
unlock_kernel();
} }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -174,6 +174,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem) ...@@ -174,6 +174,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
return; return;
} }
void free_initmem(void)
{
/* To be written */
}
void si_meminfo(struct sysinfo *val) void si_meminfo(struct sysinfo *val)
{ {
int i; int i;
......
# $Id: Makefile,v 1.22 1996/12/18 06:17:39 tridge Exp $ # $Id: Makefile,v 1.23 1997/01/02 14:14:17 jj Exp $
# sparc/Makefile # sparc/Makefile
# #
# Makefile for the architecture dependent flags and dependencies on the # Makefile for the architecture dependent flags and dependencies on the
...@@ -18,7 +18,8 @@ SHELL =/bin/bash ...@@ -18,7 +18,8 @@ SHELL =/bin/bash
#CFLAGS := $(CFLAGS) -g -pipe #CFLAGS := $(CFLAGS) -g -pipe
CFLAGS := $(CFLAGS) -pipe CFLAGS := $(CFLAGS) -pipe
LINKFLAGS = -N -Ttext 0xf0004000 #LINKFLAGS = -N -Ttext 0xf0004000
LINKFLAGS = -T arch/sparc/vmlinux.lds
HEAD := arch/sparc/kernel/head.o HEAD := arch/sparc/kernel/head.o
...@@ -30,9 +31,6 @@ ARCHIVES := arch/sparc/kernel/kernel.o arch/sparc/mm/mm.o $(ARCHIVES) ...@@ -30,9 +31,6 @@ ARCHIVES := arch/sparc/kernel/kernel.o arch/sparc/mm/mm.o $(ARCHIVES)
LIBS := $(TOPDIR)/lib/lib.a $(LIBS) $(TOPDIR)/arch/sparc/prom/promlib.a \ LIBS := $(TOPDIR)/lib/lib.a $(LIBS) $(TOPDIR)/arch/sparc/prom/promlib.a \
$(TOPDIR)/arch/sparc/lib/lib.a $(TOPDIR)/arch/sparc/lib/lib.a
INITOBJ = $(TOPDIR)/arch/sparc/kernel/initobj.o
FINITOBJ = $(TOPDIR)/arch/sparc/kernel/finitobj.o
ifdef CONFIG_AP1000 ifdef CONFIG_AP1000
SUBDIRS := $(SUBDIRS) arch/sparc/ap1000 mpp SUBDIRS := $(SUBDIRS) arch/sparc/ap1000 mpp
ARCHIVES := $(TOPDIR)/arch/sparc/ap1000/ap1000lib.o $(TOPDIR)/mpp/mpplib.o $(ARCHIVES) ARCHIVES := $(TOPDIR)/arch/sparc/ap1000/ap1000lib.o $(TOPDIR)/mpp/mpplib.o $(ARCHIVES)
...@@ -41,6 +39,5 @@ CFLAGS := $(CFLAGS) -D__MPP__=1 ...@@ -41,6 +39,5 @@ CFLAGS := $(CFLAGS) -D__MPP__=1
endif endif
archclean: archclean:
rm -f $(TOPDIR)/arch/sparc/boot/boot
archdep: archdep:
# Makefile for the AP1000 files in the Linux kernel
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
.S.s:
$(CPP) -D__ASSEMBLY__ -ansi $< -o $*.s
.S.o:
$(CC) -D__ASSEMBLY__ -ansi -c $< -o $*.o
all: ap1000lib.o
O_TARGET := ap1000lib.o
O_OBJS := bnet.o timer.o util.o dma.o kgdb.o irq.o \
msc.o hw.o tnet.o sync.o mpp.o \
apmmu.o aplib.o approm.o
include $(TOPDIR)/Rules.make
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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