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

Import 2.1.23

parent b5127d9b
......@@ -664,6 +664,15 @@ S: Reading
S: RG6 2NU
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
E: johnsonm@redhat.com
W: http://www.redhat.com/~johnsonm
......
\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
\oddsidemargin=0pt
......@@ -994,6 +994,10 @@ $ \version\ $
\def\versionlog{
$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
Added reasons for speed selection.
......
......@@ -176,12 +176,19 @@ vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
$(ARCHIVES) \
$(FILESYSTEMS) \
$(DRIVERS) \
$(LIBS) -o vmlinux
$(LIBS) \
-o vmlinux
$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)\|\(\.\.ng$$\)' | sort > System.map
symlinks:
rm -f include/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
$(CONFIG_SHELL) scripts/Configure -d arch/$(ARCH)/config.in
......@@ -315,7 +322,7 @@ clean: archclean
rm -f core `find . -type f -name 'core' -print`
rm -f vmlinux System.map
rm -f .tmp* drivers/sound/configure
rm -f modules/*
rm -f `find modules/ -type f -print`
rm -f submenu*
mrproper: clean
......@@ -331,7 +338,8 @@ mrproper: clean
rm -f .depend `find . -name .depend -print`
rm -f .hdepend scripts/mkdep
rm -f $(TOPDIR)/include/linux/modversions.h
rm -f $(TOPDIR)/include/linux/modules/*
rm -rf $(TOPDIR)/include/linux/modules
rm -rf modules
distclean: mrproper
......
......@@ -107,6 +107,9 @@ modules: $(ALL_MOBJS) dummy
ifdef MOD_SUB_DIRS
set -e; for i in $(MOD_SUB_DIRS); do $(MAKE) -C $$i modules; done
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))" ""
rm -f $$TOPDIR/modules/$(MOD_LIST_NAME)
ifdef MOD_SUB_DIRS
......@@ -116,6 +119,9 @@ endif
ifneq "$(strip $(ALL_MOBJS))" ""
echo $(ALL_MOBJS) >> $$TOPDIR/modules/$(MOD_LIST_NAME)
endif
ifneq "$(strip $(MOD_TO_LIST))" ""
echo $(MOD_TO_LIST) >> $$TOPDIR/modules/$(MOD_LIST_NAME)
endif
endif
ifneq "$(strip $(ALL_MOBJS))" ""
echo $(PDWN)
......
......@@ -10,9 +10,15 @@
#include <linux/string.h>
#include <linux/user.h>
#include <linux/elfcore.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <asm/io.h>
#include <asm/hwrpb.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
#include <asm/checksum.h>
extern void bcopy (const char *src, char *dst, int len);
......@@ -58,6 +64,7 @@ EXPORT_SYMBOL(strlen);
EXPORT_SYMBOL(strncmp);
EXPORT_SYMBOL(strncpy);
EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strncat);
EXPORT_SYMBOL(strstr);
EXPORT_SYMBOL(strtok);
EXPORT_SYMBOL(strchr);
......@@ -72,6 +79,11 @@ EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(hwrpb);
EXPORT_SYMBOL(wrusp);
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.
......
......@@ -24,6 +24,8 @@
* within the United States, $35 abroad.
*/
#include <linux/config.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#if 0
# define DBG_DEVS(args) printk args
......@@ -1217,6 +1219,7 @@ asmlinkage int sys_pciconfig_read(
unsigned int uint;
long err = 0;
lock_kernel();
switch (len) {
case 1:
err = pcibios_read_config_byte(bus, dfn, off, &ubyte);
......@@ -1240,6 +1243,7 @@ asmlinkage int sys_pciconfig_read(
err = -EINVAL;
break;
}
unlock_kernel();
return err;
}
asmlinkage int sys_pciconfig_write(
......@@ -1254,6 +1258,7 @@ asmlinkage int sys_pciconfig_write(
unsigned int uint;
long err = 0;
lock_kernel();
switch (len) {
case 1:
err = get_user(ubyte, buf);
......@@ -1286,6 +1291,7 @@ asmlinkage int sys_pciconfig_write(
err = -EINVAL;
break;
}
unlock_kernel();
return err;
}
......
......@@ -199,6 +199,8 @@ entIF:
.align 3
.ent kernel_clone
kernel_clone:
.frame $30, 0, $26
.prologue 0
subq $30,6*8,$30
stq $31,0($30)
stq $26,8($30)
......@@ -221,17 +223,19 @@ kernel_clone:
.globl __kernel_thread
.ent __kernel_thread
__kernel_thread:
.frame $30, 4*8, $26
subq $30,4*8,$30
stq $9,0($30)
stq $10,8($30)
stq $26,16($30)
stq $10,16($30)
stq $9,8($30)
stq $26,0($30)
.prologue 0
bis $17,$17,$9 /* save fn */
bis $18,$18,$10 /* save arg */
bsr $26,kernel_clone
bne $20,1f /* $20 is non-zero in child */
ldq $9,0($30)
ldq $10,8($30)
ldq $26,16($30)
ldq $26,0($30)
ldq $9,8($30)
ldq $10,16($30)
addq $30,4*8,$30
ret $31,($26),1
/* this is in child: look out as we don't have any stack here.. */
......
This diff is collapsed.
......@@ -13,6 +13,8 @@
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
......@@ -31,6 +33,9 @@
#include <asm/system.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,
unsigned long a3, unsigned long a4, unsigned long a5,
struct pt_regs regs)
......@@ -41,14 +46,21 @@ asmlinkage int sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2,
asmlinkage int sys_idle(void)
{
int ret = -EPERM;
lock_kernel();
if (current->pid != 0)
return -EPERM;
goto out;
/* endless idle loop with no priority at all */
current->counter = -100;
for (;;) {
schedule();
}
ret = 0;
out:
unlock_kernel();
return ret;
}
void hard_reset_now(void)
......@@ -246,10 +258,13 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
int error;
char * filename;
lock_kernel();
error = getname((char *) a0, &filename);
if (error)
return error;
goto out;
error = do_execve(filename, (char **) a1, (char **) a2, &regs);
putname(filename);
out:
unlock_kernel();
return error;
}
......@@ -8,6 +8,8 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>
......@@ -487,27 +489,30 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
int a4, int a5, struct pt_regs regs)
{
struct task_struct *child;
struct user * dummy;
dummy = NULL;
long ret;
lock_kernel();
DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",
request, pid, addr, data));
ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->flags & PF_PTRACED)
return -EPERM;
goto out;
/* set the ptrace bit in the process flags. */
current->flags |= PF_PTRACED;
return 0;
ret = 0;
goto out;
}
if (pid == 1) /* you may not mess with init */
return -EPERM;
goto out;
ret = -ESRCH;
if (!(child = get_task(pid)))
return -ESRCH;
goto out;
if (request == PTRACE_ATTACH) {
ret = -EPERM;
if (child == current)
return -EPERM;
goto out;
if ((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
......@@ -515,10 +520,10 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(current->gid != child->gid)) && !suser())
return -EPERM;
goto out;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
return -EPERM;
goto out;
child->flags |= PF_PTRACED;
if (child->p_pptr != current) {
REMOVE_LINKS(child);
......@@ -526,20 +531,22 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
SET_LINKS(child);
}
send_sig(SIGSTOP, child, 1);
return 0;
ret = 0;
goto out;
}
ret = -ESRCH;
if (!(child->flags & PF_PTRACED)) {
DBG(DBG_MEM, ("child not traced\n"));
return -ESRCH;
goto out;
}
if (child->state != TASK_STOPPED) {
DBG(DBG_MEM, ("child process not stopped\n"));
if (request != PTRACE_KILL)
return -ESRCH;
goto out;
}
if (child->p_pptr != current) {
DBG(DBG_MEM, ("child not parent of this process\n"));
return -ESRCH;
goto out;
}
switch (request) {
......@@ -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_PEEKDATA: {
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));
if (res < 0)
return res;
if (ret < 0)
goto out;
regs.r0 = 0; /* special return: no errors */
return tmp;
ret = tmp;
goto out;
}
/* read register number ADDR. */
case PTRACE_PEEKUSR:
regs.r0 = 0; /* special return: no errors */
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. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
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 */
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
(return from) syscall */
case PTRACE_CONT: { /* restart after signal. */
ret = -EIO;
if ((unsigned long) data > NSIG)
return -EIO;
goto out;
if (request == PTRACE_SYSCALL)
child->flags |= PF_TRACESYS;
else
......@@ -586,7 +597,8 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
wake_up_process(child);
/* make sure single-step breakpoint is gone. */
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,
}
/* make sure single-step breakpoint is gone. */
ptrace_cancel_bpt(child);
return 0;
ret = 0;
goto out;
}
case PTRACE_SINGLESTEP: { /* execute single instruction. */
ret = -EIO;
if ((unsigned long) data > NSIG)
return -EIO;
goto out;
child->debugreg[4] = -1; /* mark single-stepping */
child->flags &= ~PF_TRACESYS;
wake_up_process(child);
child->exit_code = data;
/* give it a chance to run. */
return 0;
ret = 0;
goto out;
}
case PTRACE_DETACH: { /* detach a process that was attached. */
ret = -EIO;
if ((unsigned long) data > NSIG)
return -EIO;
goto out;
child->flags &= ~(PF_PTRACED|PF_TRACESYS);
wake_up_process(child);
child->exit_code = data;
......@@ -626,19 +642,25 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
SET_LINKS(child);
/* make sure single-step breakpoint is gone. */
ptrace_cancel_bpt(child);
return 0;
ret = 0;
goto out;
}
default:
return -EIO;
ret = -EIO;
goto out;
}
out:
unlock_kernel();
return ret;
}
asmlinkage void syscall_trace(void)
{
lock_kernel();
if ((current->flags & (PF_PTRACED|PF_TRACESYS))
!= (PF_PTRACED|PF_TRACESYS))
return;
goto out;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
notify_parent(current);
......@@ -651,4 +673,6 @@ asmlinkage void syscall_trace(void)
if (current->exit_code)
current->signal |= (1 << (current->exit_code - 1));
current->exit_code = 0;
out:
unlock_kernel();
}
......@@ -12,6 +12,8 @@
#include <linux/ptrace.h>
#include <linux/unistd.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
......@@ -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
* 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,
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,
*/
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;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
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,
int i;
/* verify that it's a good sigcontext before using it */
lock_kernel();
if (verify_area(VERIFY_READ, sc, sizeof(*sc)))
do_exit(SIGSEGV);
get_user(ps, &sc->sc_ps);
......@@ -145,6 +157,7 @@ asmlinkage void do_sigreturn(struct sigcontext * sc,
/* send SIGTRAP if we're single-stepping: */
if (ptrace_cancel_bpt (current))
send_sig(SIGTRAP, current, 1);
unlock_kernel();
}
/*
......@@ -279,10 +292,13 @@ asmlinkage int do_signal(unsigned long oldmask,
struct switch_stack * sw,
unsigned long r0, unsigned long r19)
{
unsigned long mask = ~current->blocked;
unsigned long mask;
unsigned long signr, single_stepping;
struct sigaction * sa;
int ret;
lock_kernel();
mask = ~current->blocked;
single_stepping = ptrace_cancel_bpt(current);
while ((signr = current->signal & mask) != 0) {
......@@ -356,7 +372,8 @@ asmlinkage int do_signal(unsigned long oldmask,
if (single_stepping) {
ptrace_set_bpt(current); /* re-set breakpoint */
}
return 1;
ret = 1;
goto out;
}
if (r0 &&
(regs->r0 == ERESTARTNOHAND ||
......@@ -369,5 +386,8 @@ asmlinkage int do_signal(unsigned long oldmask,
if (single_stepping) {
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,
unsigned long *r9_15)
{
long i;
unsigned long sp;
unsigned long sp, ra;
unsigned int * pc;
if (regs->ps & 8)
return;
printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err);
sp = (unsigned long) (regs+1);
__get_user(ra, (unsigned long *)sp);
printk("pc = [<%016lx>] ps = %04lx\n", regs->pc, regs->ps);
printk("rp = [<%016lx>] 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("r2 = %016lx r3 = %016lx\n", regs->r2, regs->r3);
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,
printk("r20= %016lx r21= %016lx\n", regs->r20, regs->r21);
printk("r22= %016lx r23= %016lx\n", regs->r22, regs->r23);
printk("r24= %016lx r25= %016lx\n", regs->r24, regs->r25);
printk("r26= %016lx r27= %016lx\n", regs->r26, regs->r27);
printk("r28= %016lx r29= %016lx\n", regs->r28, regs->gp);
printk("r27= %016lx r28= %016lx\n", regs->r27, regs->r28);
printk("gp = %016lx sp = %016lx\n", regs->gp, sp);
printk("Code:");
pc = (unsigned int *) regs->pc;
for (i = -3; i < 6; i++)
printk("%c%08x%c",i?' ':'<',pc[i],i?' ':'>');
for (i = -3; i < 6; i++) {
unsigned int insn;
if (__get_user(insn, pc+i))
break;
printk("%c%08x%c",i?' ':'<',insn,i?' ':'>');
}
printk("\n");
do_exit(SIGSEGV);
}
......
......@@ -171,6 +171,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
return;
}
void free_initmem(void)
{
/* To be written */
}
void si_meminfo(struct sysinfo *val)
{
int i;
......
......@@ -111,7 +111,6 @@ install: vmlinux
archclean:
@$(MAKEBOOT) clean
$(MAKE) -C arch/$(ARCH)/kernel clean
archdep:
@$(MAKEBOOT) dep
......@@ -7,9 +7,6 @@
#
# Note 2! The CFLAGS definitions are now in the main makefile...
#.S.s:
# $(CPP) -D__ASSEMBLY__ -traditional $< -o $*.s
ifdef SMP
.S.o:
$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
......@@ -31,7 +28,7 @@ endif
ifdef SMP
O_OBJS += smp.o
O_OBJS += smp.o trampoline.o
head.o: head.S $(TOPDIR)/include/linux/tasks.h
$(CC) -D__ASSEMBLY__ -D__SMP__ -traditional -c $*.S -o $*.o
......@@ -43,30 +40,4 @@ head.o: head.S $(TOPDIR)/include/linux/tasks.h
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
......@@ -97,98 +97,7 @@ ENOSYS = 38
mov %dx,%ds; \
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 \
LEAVE_KERNEL \
popl %ebx; \
popl %ecx; \
popl %edx; \
......@@ -201,38 +110,30 @@ ENOSYS = 38
addl $4,%esp; \
iret
#define GET_CURRENT \
GET_PROCESSOR_OFFSET(%ebx) \
movl SYMBOL_NAME(current_set)(%ebx),%ebx
#ifdef __SMP__
/* Get the processor ID multiplied by 4 */
#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
#define GET_CURRENT \
movl SYMBOL_NAME(current_set),%ebx
#define GET_CURRENT(reg) \
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
ENTRY(lcall7)
pushfl # We get a different stack layout with call gates,
pushl %eax # which has to be cleaned up later..
SAVE_ALL
GET_CURRENT
#ifdef __SMP__
ENTER_KERNEL
#endif
GET_CURRENT(%ebx)
movl EIP(%esp),%eax # due to call gates, this is eflags, not eip..
movl CS(%esp),%edx # this is eip..
movl EFLAGS(%esp),%ecx # and this is cs..
......@@ -240,12 +141,7 @@ ENTRY(lcall7)
movl %edx,EIP(%esp) # Now we move them to their "normal" places
movl %ecx,CS(%esp) #
movl %esp,%eax
#ifdef __SMP__
GET_PROCESSOR_OFFSET(%edx) # Processor offset into edx
movl SYMBOL_NAME(current_set)(,%edx),%edx
#else
movl SYMBOL_NAME(current_set),%edx
#endif
GET_CURRENT(%edx)
pushl %eax
movl exec_domain(%edx),%edx # Get the execution domain
movl 4(%edx),%edx # Get the lcall7 handler for the domain
......@@ -253,12 +149,23 @@ ENTRY(lcall7)
popl %eax
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
handle_bottom_half:
incl SYMBOL_NAME(intr_count)
call SYMBOL_NAME(do_bottom_half)
decl SYMBOL_NAME(intr_count)
jmp 9f
pushl $9f
jmp SYMBOL_NAME(do_bottom_half)
ALIGN
reschedule:
pushl $ret_from_sys_call
......@@ -267,10 +174,7 @@ reschedule:
ENTRY(system_call)
pushl %eax # save orig_eax
SAVE_ALL
GET_CURRENT
#ifdef __SMP__
ENTER_KERNEL
#endif
GET_CURRENT(%ebx)
cmpl $(NR_syscalls),%eax
jae badsys
testb $0x20,flags(%ebx) # PF_TRACESYS
......@@ -280,9 +184,7 @@ ENTRY(system_call)
ALIGN
.globl ret_from_sys_call
ret_from_sys_call:
#ifdef __SMP__
GET_CURRENT
#endif
GET_CURRENT(%ebx)
cmpl $0,SYMBOL_NAME(intr_count)
jne 1f
9: movl SYMBOL_NAME(bh_mask),%eax
......@@ -358,10 +260,7 @@ error_code:
movl $(KERNEL_DS),%edx
mov %dx,%ds
mov %dx,%es
GET_CURRENT
#ifdef __SMP__
ENTER_KERNEL
#endif
GET_CURRENT(%ebx)
call *%ecx
addl $8,%esp
jmp ret_from_sys_call
......@@ -374,10 +273,7 @@ ENTRY(coprocessor_error)
ENTRY(device_not_available)
pushl $-1 # mark this as an int
SAVE_ALL
GET_CURRENT
#ifdef __SMP__
ENTER_KERNEL
#endif
GET_CURRENT(%ebx)
pushl $ret_from_sys_call
movl %cr0,%eax
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 @@
#include <linux/user.h>
#include <linux/elfcore.h>
#include <linux/mca.h>
#include <linux/sched.h>
#include <asm/semaphore.h>
#include <asm/processor.h>
......@@ -12,6 +13,7 @@
extern void dump_thread(struct pt_regs *, struct user *);
extern int dump_fpu(elf_fpregset_t *);
extern void __lock_kernel(void);
/* platform dependent support */
EXPORT_SYMBOL(EISA_bus);
......@@ -28,11 +30,10 @@ EXPORT_SYMBOL_NOVERS(__up_wakeup);
#ifdef __SMP__
EXPORT_SYMBOL(apic_reg); /* Needed internally for the I386 inlines */
EXPORT_SYMBOL(cpu_data);
EXPORT_SYMBOL(syscall_count);
EXPORT_SYMBOL(kernel_flag);
EXPORT_SYMBOL(kernel_counter);
EXPORT_SYMBOL(active_kernel_processor);
EXPORT_SYMBOL(smp_invalidate_needed);
EXPORT_SYMBOL_NOVERS(__lock_kernel);
#endif
#ifdef CONFIG_MCA
......
......@@ -10,6 +10,9 @@
#include <linux/errno.h>
#include <linux/types.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. */
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_
*/
asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
{
if (from + num <= from)
return -EINVAL;
if (from + num > IO_BITMAP_SIZE*32)
return -EINVAL;
if (!suser())
return -EPERM;
int ret = -EINVAL;
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);
return 0;
ret = 0;
out:
unlock_kernel();
return ret;
}
unsigned int *stack;
......@@ -79,11 +86,17 @@ asmlinkage int sys_iopl(long ebx,long ecx,long edx,
long eflags, long esp, long ss)
{
unsigned int level = ebx;
int ret = -EINVAL;
lock_kernel();
if (level > 3)
return -EINVAL;
goto out;
ret = -EPERM;
if (!suser())
return -EPERM;
goto out;
*(&eflags) = (eflags & 0xffffcfff) | (level << 12);
return 0;
ret = 0;
out:
unlock_kernel();
return ret;
}
......@@ -25,6 +25,8 @@
#include <linux/timex.h>
#include <linux/malloc.h>
#include <linux/random.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <asm/system.h>
#include <asm/io.h>
......@@ -346,6 +348,8 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
struct irqaction * action = *(irq + irq_action);
int do_random = 0;
lock_kernel();
intr_count++;
#ifdef __SMP__
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());
......@@ -362,6 +366,8 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
}
if (do_random & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
intr_count--;
unlock_kernel();
}
/*
......@@ -374,6 +380,8 @@ asmlinkage void do_fast_IRQ(int irq)
struct irqaction * action = *(irq + irq_action);
int do_random = 0;
lock_kernel();
intr_count++;
#ifdef __SMP__
/* IRQ 13 is allowed - that's a flush tlb */
if(smp_threads_ready && active_kernel_processor!=smp_processor_id() && irq!=13)
......@@ -391,6 +399,8 @@ asmlinkage void do_fast_IRQ(int irq)
}
if (do_random & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
intr_count--;
unlock_kernel();
}
int setup_x86_irq(int irq, struct irqaction * new)
......
......@@ -8,6 +8,8 @@
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/vmalloc.h>
#include <asm/uaccess.h>
......@@ -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)
{
int ret;
lock_kernel();
if (func == 0)
return read_ldt(ptr, bytecount);
if (func == 1)
return write_ldt(ptr, bytecount, 1);
if (func == 0x11)
return write_ldt(ptr, bytecount, 0);
return -ENOSYS;
ret = read_ldt(ptr, bytecount);
else if (func == 1)
ret = write_ldt(ptr, bytecount, 1);
else if (func == 0x11)
ret = write_ldt(ptr, bytecount, 0);
else
ret = -ENOSYS;
unlock_kernel();
return ret;
}
......@@ -15,6 +15,8 @@
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
......@@ -34,7 +36,11 @@
#include <asm/io.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");
#endif
#ifdef CONFIG_APM
extern int apm_do_idle(void);
......@@ -91,9 +97,11 @@ static void hard_idle(void)
asmlinkage int sys_idle(void)
{
unsigned long start_idle = 0;
int ret = -EPERM;
lock_kernel();
if (current->pid != 0)
return -EPERM;
goto out;
/* endless idle loop with no priority at all */
current->counter = -100;
for (;;)
......@@ -118,6 +126,10 @@ asmlinkage int sys_idle(void)
start_idle = 0;
schedule();
}
ret = 0;
out:
unlock_kernel();
return ret;
}
#else
......@@ -129,15 +141,21 @@ asmlinkage int sys_idle(void)
asmlinkage int sys_idle(void)
{
int ret = -EPERM;
lock_kernel();
if(current->pid != 0)
return -EPERM;
goto out;
#ifdef __SMP_PROF__
smp_spins_sys_idle[smp_processor_id()]+=
smp_spins_syscall_cur[smp_processor_id()];
#endif
current->counter= -100;
schedule();
return 0;
ret = 0;
out:
unlock_kernel();
return ret;
}
/*
......@@ -150,9 +168,10 @@ int cpu_idle(void *unused)
{
if(cpu_data[smp_processor_id()].hlt_works_ok && !hlt_counter && !need_resched)
__asm("hlt");
if(0==(0x7fffffff & smp_process_available))
if(0==(read_smp_counter(&smp_process_available)))
continue;
while(0x80000000 & smp_process_available);
while(0x80000000 & smp_process_available)
;
cli();
while(set_bit(31,&smp_process_available))
while(test_bit(31,&smp_process_available))
......@@ -163,7 +182,7 @@ int cpu_idle(void *unused)
if(clear_bit(smp_processor_id(), &smp_invalidate_needed))
local_flush_tlb();
}
if (0==(0x7fffffff & smp_process_available)){
if (0==(read_smp_counter(&smp_process_available))) {
clear_bit(31,&smp_process_available);
sti();
continue;
......@@ -473,13 +492,18 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
p->tss.tr = _TSS(nr);
childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 1;
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.eflags = regs->eflags & 0xffffcfff; /* iopl always 0 for a new process */
#endif
p->tss.ebx = (unsigned long) p;
*childregs = *regs;
childregs->eax = 0;
childregs->esp = esp;
p->tss.back_link = 0;
p->tss.eflags = regs->eflags & 0xffffcfff; /* iopl is always 0 for a new process */
p->tss.ldt = _LDT(nr);
if (p->ldt) {
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)
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)
{
unsigned long clone_flags;
unsigned long newsp;
int ret;
lock_kernel();
clone_flags = regs.ebx;
newsp = regs.ecx;
if (!newsp)
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)
int error;
char * filename;
lock_kernel();
error = getname((char *) regs.ebx, &filename);
if (error)
return error;
goto out;
error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);
putname(filename);
out:
unlock_kernel();
return error;
}
......@@ -6,6 +6,8 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>
......@@ -362,26 +364,29 @@ static unsigned long getreg(struct task_struct *child,
asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
struct user * dummy;
int i;
dummy = NULL;
struct user * dummy = NULL;
int i, ret;
lock_kernel();
ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->flags & PF_PTRACED)
return -EPERM;
goto out;
/* set the ptrace bit in the process flags. */
current->flags |= PF_PTRACED;
return 0;
ret = 0;
goto out;
}
if (pid == 1) /* you may not mess with init */
return -EPERM;
goto out;
ret = -ESRCH;
if (!(child = get_task(pid)))
return -ESRCH;
goto out;
ret = -EPERM;
if (request == PTRACE_ATTACH) {
if (child == current)
return -EPERM;
goto out;
if ((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
......@@ -389,10 +394,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(current->gid != child->gid)) && !suser())
return -EPERM;
goto out;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
return -EPERM;
goto out;
child->flags |= PF_PTRACED;
if (child->p_pptr != current) {
REMOVE_LINKS(child);
......@@ -400,37 +405,39 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
SET_LINKS(child);
}
send_sig(SIGSTOP, child, 1);
return 0;
ret = 0;
goto out;
}
ret = -ESRCH;
if (!(child->flags & PF_PTRACED))
return -ESRCH;
goto out;
if (child->state != TASK_STOPPED) {
if (request != PTRACE_KILL)
return -ESRCH;
goto out;
}
if (child->p_pptr != current)
return -ESRCH;
goto out;
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
unsigned long tmp;
int res;
res = read_long(child, addr, &tmp);
if (res < 0)
return res;
return put_user(tmp,(unsigned long *) data);
ret = read_long(child, addr, &tmp);
if (ret >= 0)
ret = put_user(tmp,(unsigned long *) data);
goto out;
}
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
unsigned long tmp;
ret = -EIO;
if ((addr & 3) || addr < 0 ||
addr > sizeof(struct user) - 3)
return -EIO;
goto out;
tmp = 0; /* Default return condition */
if(addr < 17*sizeof(long))
......@@ -441,21 +448,26 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
addr = addr >> 2;
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. */
case PTRACE_POKETEXT: /* write the word at location addr. */
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 */
ret = -EIO;
if ((addr & 3) || addr < 0 ||
addr > sizeof(struct user) - 3)
return -EIO;
goto out;
if (addr < 17*sizeof(long))
return putreg(child, addr, data);
if (addr < 17*sizeof(long)) {
ret = putreg(child, addr, data);
goto out;
}
/* We need to be very careful here. We implicitly
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)
if(addr < (long) &dummy->u_debugreg[4] &&
((unsigned long) data) >= 0xbffffffd) return -EIO;
ret = -EIO;
if(addr == (long) &dummy->u_debugreg[7]) {
data &= ~DR_CONTROL_RESERVED;
for(i=0; i<4; i++)
if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
return -EIO;
goto out;
};
addr -= (long) &dummy->u_debugreg;
addr = addr >> 2;
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_CONT: { /* restart after signal. */
long tmp;
ret = -EIO;
if ((unsigned long) data > NSIG)
return -EIO;
goto out;
if (request == PTRACE_SYSCALL)
child->flags |= PF_TRACESYS;
else
......@@ -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. */
tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
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)
case PTRACE_KILL: {
long tmp;
ret = 0;
if (child->state == TASK_ZOMBIE) /* already dead */
return 0;
goto out;
wake_up_process(child);
child->exit_code = SIGKILL;
/* make sure the single step bit is not set. */
tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
put_stack_long(child, EFL_OFFSET, tmp);
return 0;
goto out;
}
case PTRACE_SINGLESTEP: { /* set the trap flag. */
long tmp;
ret = -EIO;
if ((unsigned long) data > NSIG)
return -EIO;
goto out;
child->flags &= ~PF_TRACESYS;
tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
put_stack_long(child, EFL_OFFSET, tmp);
wake_up_process(child);
child->exit_code = data;
/* give it a chance to run. */
return 0;
ret = 0;
goto out;
}
case PTRACE_DETACH: { /* detach a process that was attached. */
long tmp;
ret = -EIO;
if ((unsigned long) data > NSIG)
return -EIO;
goto out;
child->flags &= ~(PF_PTRACED|PF_TRACESYS);
wake_up_process(child);
child->exit_code = 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. */
tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
put_stack_long(child, EFL_OFFSET, tmp);
return 0;
ret = 0;
goto out;
}
default:
return -EIO;
ret = -EIO;
goto out;
}
out:
unlock_kernel();
return ret;
}
asmlinkage void syscall_trace(void)
{
lock_kernel();
if ((current->flags & (PF_PTRACED|PF_TRACESYS))
!= (PF_PTRACED|PF_TRACESYS))
return;
goto out;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
notify_parent(current);
......@@ -573,4 +600,6 @@ asmlinkage void syscall_trace(void)
if (current->exit_code)
current->signal |= (1 << (current->exit_code - 1));
current->exit_code = 0;
out:
unlock_kernel();
}
......@@ -8,6 +8,8 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h>
......@@ -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)
{
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;
current->blocked = set & _BLOCKABLE;
regs->eax = -EINTR;
......@@ -39,8 +44,11 @@ asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long
current->state = TASK_INTERRUPTIBLE;
schedule();
if (do_signal(mask,regs))
return -EINTR;
goto out;
}
out:
unlock_kernel();
return res;
}
static inline void restore_i387_hard(struct _fpstate *buf)
......@@ -100,7 +108,9 @@ if ( (tmp & 0xfffc) /* not a NULL selectors */ \
__asm__("mov %w0,%%" #seg: :"r" (tmp)); }
struct sigcontext * context;
struct pt_regs * regs;
int res;
lock_kernel();
regs = (struct pt_regs *) &__unused;
context = (struct sigcontext *) regs->esp;
if (verify_area(VERIFY_READ, context, sizeof(*context)))
......@@ -126,7 +136,9 @@ __asm__("mov %w0,%%" #seg: :"r" (tmp)); }
goto badframe;
restore_i387(buf);
}
return context->eax;
res = context->eax;
unlock_kernel();
return res;
badframe:
do_exit(SIGSEGV);
}
......@@ -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)
{
unsigned long mask = ~current->blocked;
unsigned long mask;
unsigned long signr;
struct sigaction * sa;
int res;
lock_kernel();
mask = ~current->blocked;
while ((signr = current->signal & mask)) {
/*
* This stops gcc flipping out. Otherwise the assembler
......@@ -371,7 +386,8 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
}
}
handle_signal(signr, sa, oldmask, regs);
return 1;
res = 1;
goto out;
}
/* Did we come from a system call? */
......@@ -384,5 +400,8 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
regs->eip -= 2;
}
}
return 0;
res = 0;
out:
unlock_kernel();
return res;
}
......@@ -21,6 +21,7 @@
* Erich Boleyn : MP v1.4 and additional changes.
* Matthias Sattler : 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 @@
#include <linux/mc146818rtc.h>
#include <asm/i82489.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <asm/pgtable.h>
#include <asm/bitops.h>
#include <asm/pgtable.h>
......@@ -140,7 +143,7 @@ volatile unsigned long smp_idle_map=0; /* Map for idle processors */
#endif
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*/
......@@ -506,9 +509,8 @@ int smp_scan_config(unsigned long base, unsigned long length)
* Trampoline 80x86 program as an array.
*/
static unsigned char trampoline_data[]={
#include "trampoline.hex"
};
extern unsigned char trampoline_data [];
extern unsigned char trampoline_end [];
/*
* Currently trivial. Write the real->protected mode
......@@ -518,7 +520,7 @@ static unsigned char trampoline_data[]={
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)
* Until we are ready for SMP scheduling
*/
load_ldt(0);
/* printk("Testing faulting...\n");
*(long *)0=1; OOPS... */
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();
if (cpu_number_map[cpuid] == -1)
while(1);
SMP_PRINTK(("Commenced..\n"));
local_flush_tlb();
load_TR(cpu_number_map[cpuid]);
sti();
}
/*
......@@ -1253,27 +1261,20 @@ void smp_flush_tlb(void)
void smp_reschedule_irq(int cpl, struct pt_regs *regs)
{
/*#define DEBUGGING_SMP_RESCHED*/
#ifdef DEBUGGING_SMP_RESCHED
static int ct=0;
if(ct==0)
{
printk("Beginning scheduling on CPU#%d\n",smp_processor_id());
udelay(1000000);
ct=1;
}
#endif
lock_kernel();
intr_count++;
if(smp_processor_id()!=active_kernel_processor)
panic("SMP Reschedule on CPU #%d, but #%d is active.\n",
smp_processor_id(), active_kernel_processor);
need_resched=1;
/*
* Clear the IPI
*/
/* Clear the IPI */
apic_read(APIC_SPIV); /* Dummy read */
apic_write(APIC_EOI, 0); /* Docs say use 0 for future compatibility */
intr_count--;
unlock_kernel();
}
/*
......
......@@ -9,6 +9,8 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
......@@ -28,11 +30,13 @@ asmlinkage int sys_pipe(unsigned long * fildes)
int fd[2];
int error;
lock_kernel();
error = do_pipe(fd);
if (!error) {
if (copy_to_user(fildes, fd, 2*sizeof(int)))
error = -EFAULT;
}
unlock_kernel();
return error;
}
......@@ -53,18 +57,22 @@ struct mmap_arg_struct {
asmlinkage int old_mmap(struct mmap_arg_struct *arg)
{
int error;
int error = -EFAULT;
struct file * file = NULL;
struct mmap_arg_struct a;
lock_kernel();
if (copy_from_user(&a, arg, sizeof(a)))
return -EFAULT;
goto out;
if (!(a.flags & MAP_ANONYMOUS)) {
error = -EBADF;
if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd]))
return -EBADF;
goto out;
}
a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset);
out:
unlock_kernel();
return error;
}
......@@ -79,10 +87,15 @@ struct sel_arg_struct {
asmlinkage int old_select(struct sel_arg_struct *arg)
{
struct sel_arg_struct a;
int ret = -EFAULT;
lock_kernel();
if (copy_from_user(&a, arg, sizeof(a)))
return -EFAULT;
return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
goto out;
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)
*/
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 */
call &= 0xffff;
if (call <= SEMCTL)
switch (call) {
case SEMOP:
return sys_semop (first, (struct sembuf *)ptr, second);
ret = sys_semop (first, (struct sembuf *)ptr, second);
goto out;
case SEMGET:
return sys_semget (first, second, third);
ret = sys_semget (first, second, third);
goto out;
case SEMCTL: {
union semun fourth;
ret = -EINVAL;
if (!ptr)
return -EINVAL;
goto out;
ret = -EFAULT;
if (get_user(fourth.__pad, (void **) ptr))
return -EFAULT;
return sys_semctl (first, second, third, fourth);
goto out;
ret = sys_semctl (first, second, third, fourth);
goto out;
}
default:
return -EINVAL;
ret = -EINVAL;
goto out;
}
if (call <= MSGCTL)
switch (call) {
case MSGSND:
return sys_msgsnd (first, (struct msgbuf *) ptr,
second, third);
ret = sys_msgsnd (first, (struct msgbuf *) ptr,
second, third);
goto out;
case MSGRCV:
switch (version) {
case 0: {
struct ipc_kludge tmp;
ret = -EINVAL;
if (!ptr)
return -EINVAL;
goto out;
ret = -EFAULT;
if (copy_from_user(&tmp,(struct ipc_kludge *) ptr,
sizeof (tmp)))
return -EFAULT;
return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
goto out;
ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
goto out;
}
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:
return sys_msgget ((key_t) first, second);
ret = sys_msgget ((key_t) first, second);
goto out;
case MSGCTL:
return sys_msgctl (first, second, (struct msqid_ds *) ptr);
ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
goto out;
default:
return -EINVAL;
ret = -EINVAL;
goto out;
}
if (call <= SHMCTL)
switch (call) {
......@@ -146,25 +174,35 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
switch (version) {
case 0: default: {
ulong raddr;
int err;
err = sys_shmat (first, (char *) ptr, second, &raddr);
if (err)
return err;
return put_user (raddr, (ulong *) third);
ret = sys_shmat (first, (char *) ptr, second, &raddr);
if (ret)
goto out;
ret = put_user (raddr, (ulong *) third);
goto out;
}
case 1: /* iBCS2 emulator entry point */
ret = -EINVAL;
if (get_fs() != get_ds())
return -EINVAL;
return sys_shmat (first, (char *) ptr, second, (ulong *) third);
goto out;
ret = sys_shmat (first, (char *) ptr, second, (ulong *) third);
goto out;
}
case SHMDT:
return sys_shmdt ((char *)ptr);
ret = sys_shmdt ((char *)ptr);
goto out;
case SHMGET:
return sys_shmget (first, second, third);
ret = sys_shmget (first, second, third);
goto out;
case SHMCTL:
return sys_shmctl (first, second, (struct shmid_ds *) ptr);
ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
goto out;
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
!
! Entry: CS:IP point to the start of our code, we are
! in real mode with no stack, but the rest of the
! trampoline page to make our stack and everything else
! is a mystery.
!
! In fact we don't actually need a stack so we don't
! set one up.
!
! We jump into the boot/compressed/head.S code. So you'd
! better be running a compressed kernel image or you
! won't get very far.
!
#define __ASSEMBLY__
/*
*
* Trampoline.S Derived from Setup.S by Linus Torvalds
*
* 4 Jan 1997 Michael Chastain: changed to gnu as.
*
* Entry: CS:IP point to the start of our code, we are
* in real mode with no stack, but the rest of the
* trampoline page to make our stack and everything else
* is a mystery.
*
* In fact we don't actually need a stack so we don't
* set one up.
*
* We jump into the boot/compressed/head.S code. So you'd
* 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>
.text
extrn startup32
entry start
start:
! nop
! jmp start ! Test
mov ax,cs ! Code and data in the same place
mov ds,ax !
mov cx,ax ! Pass stack info to the 32bit boot
add cx,cx
add cx,cx
add cx,cx
add cx,cx ! Segment -> Offset
add cx, #4096 ! End of page is wanted
mov bx,#1 ! Flag an SMP trampoline
cli ! We should be safe anyway
lidt idt_48 ! load idt with 0,0
lgdt gdt_48 ! load gdt with whatever is appropriate
xor ax,ax
inc ax ! protected mode (PE) bit
lmsw ax ! Into protected mode
.data
.code16
ENTRY(trampoline_data)
r_base = .
p_base = . - 8192
mov %cs, %ax # Code and data in the same place
mov %ax, %ds
mov %ax, %cx # Pass stack info to the 32bit boot
shl $4, %cx # Segment -> Offset
add $4096, %cx # End of page is wanted
mov $1, %bx # Flag an SMP trampoline
cli # We should be safe anyway
movl $0xA5A5A5A5, trampoline_data - r_base
# write marker for master knows we're running
lidt idt_48 - r_base # load idt with 0, 0
lgdt gdt_48 - r_base # load gdt with whatever is appropriate
xor %ax, %ax
inc %ax # protected mode (PE) bit
lmsw %ax # into protected mode
jmp flush_instr
flush_instr:
jmpi 8192+startup32,KERNEL_CS ! Jump to the 32bit trampoline code
! jmpi 0x100000,KERNEL_CS ! Jump into the 32bit startup
! .byte 0x66,0x67 ! 32bit
! .byte 0xea,0x00,0x00,0x10,0x00,0x10,0x00 !jmpi .0x100000,KERNEL_CS
ljmp $KERNEL_CS, $0x00100000
# jump to startup_32
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:
.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
.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)
# walken modif
.word 0xFFFF ! 4Gb - (0x100000*0x1000 = 4Gb)
.word 0x0000 ! base address=0
.word 0x9200 ! data read/write
.word 0x00CF ! granularity=4096, 386 (+5th nibble of limit)
!walken modif
.word 0xFFFF # 4 Gb - (0x100000*0x1000 = 4Gb)
.word 0x0000 # base address = 0
.word 0x9A00 # code read / exec
.word 0x00CF # granularity = 4096, 386 (+5th nibble of limit)
! .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
! .word 0x0000 ! base address=0
! .word 0x9A00 ! code read/exec
! .word 0x00C0 ! granularity=4096, 386
.word 0xFFFF # 4 Gb - (0x100000*0x1000 = 4Gb)
.word 0x0000 # base address = 0
.word 0x9200 # data read / write
.word 0x00CF # granularity = 4096, 386 (+5th nibble of limit)
! .word 0x07FF ! 8Mb - limit=2047 (2048*4096=8Mb)
! .word 0x0000 ! base address=0
! .word 0x9200 ! data read/write
! .word 0x00C0 ! granularity=4096, 386
# walken modif
idt_48:
.word 0 ! idt limit=0
.word 0,0 ! idt base=0L
# .word 0x07FF # 8 Mb - limit = 2047 (2048 * 4096 = 8 Mb)
# .word 0x0000 # base address = 0
# .word 0x9A00 # code read / exec
# .word 0x00C0 # granularity = 4096, 386
gdt_48:
.word 0x800 ! gdt limit=2048, 256 GDT entries
.word 8192+gdt,0x0 ! gdt base = 8192+gdt (first SMP CPU)
! we load the others with the first table
! saves rewriting gdt_48 for each
# .word 0x07FF # 8 Mb - limit = 2047 (2048 * 4096 = 8 Mb)
# .word 0x0000 # base address = 0
# .word 0x9200 # data read / write
# .word 0x00C0 # granularity = 4096, 386
.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 @@
#include <linux/config.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <asm/system.h>
#include <asm/uaccess.h>
......@@ -38,24 +40,29 @@ static inline void console_verbose(void)
#define DO_ERROR(trapnr, signr, str, name, tsk) \
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
{ \
lock_kernel(); \
tsk->tss.error_code = error_code; \
tsk->tss.trap_no = trapnr; \
force_sig(signr, tsk); \
die_if_kernel(str,regs,error_code); \
unlock_kernel(); \
}
#define DO_VM86_ERROR(trapnr, signr, str, name, tsk) \
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
{ \
lock_kernel(); \
if (regs->eflags & VM_MASK) { \
if (!handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, trapnr)) \
return; \
goto out; \
/* else fall through */ \
} \
tsk->tss.error_code = error_code; \
tsk->tss.trap_no = trapnr; \
force_sig(signr, tsk); \
die_if_kernel(str,regs,error_code); \
out: \
unlock_kernel(); \
}
#define get_seg_byte(seg,addr) ({ \
......@@ -194,18 +201,22 @@ DO_ERROR(18, SIGSEGV, "reserved", reserved, current)
asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
{
lock_kernel();
if (regs->eflags & VM_MASK) {
handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
return;
goto out;
}
die_if_kernel("general protection",regs,error_code);
current->tss.error_code = error_code;
current->tss.trap_no = 13;
force_sig(SIGSEGV, current);
out:
unlock_kernel();
}
asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
{
lock_kernel();
#ifdef CONFIG_SMP_NMI_INVAL
smp_flush_tlb_rcv();
#else
......@@ -215,13 +226,15 @@ asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
printk("power saving mode enabled.\n");
#endif
#endif
unlock_kernel();
}
asmlinkage void do_debug(struct pt_regs * regs, long error_code)
{
lock_kernel();
if (regs->eflags & VM_MASK) {
handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
return;
goto out;
}
force_sig(SIGTRAP, current);
current->tss.trap_no = 1;
......@@ -231,9 +244,11 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
__asm__("movl %0,%%db7"
: /* no output */
: "r" (0));
return;
goto out;
}
die_if_kernel("debug",regs,error_code);
out:
unlock_kernel();
}
/*
......@@ -245,6 +260,7 @@ void math_error(void)
{
struct task_struct * task;
lock_kernel();
clts();
#ifdef __SMP__
task = current;
......@@ -253,7 +269,7 @@ void math_error(void)
last_task_used_math = NULL;
if (!task) {
__asm__("fnclex");
return;
goto out;
}
#endif
/*
......@@ -266,18 +282,26 @@ void math_error(void)
force_sig(SIGFPE, task);
task->tss.trap_no = 16;
task->tss.error_code = 0;
#ifndef __SMP__
out:
#endif
unlock_kernel();
}
asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code)
{
lock_kernel();
ignore_irq13 = 1;
math_error();
unlock_kernel();
}
asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs,
long error_code)
{
lock_kernel();
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,
*/
asmlinkage void math_state_restore(void)
{
lock_kernel();
__asm__ __volatile__("clts"); /* Allow maths ops (or we recurse) */
/*
......@@ -301,7 +326,7 @@ asmlinkage void math_state_restore(void)
*/
#ifndef __SMP__
if (last_task_used_math == current)
return;
goto out;
if (last_task_used_math)
__asm__("fnsave %0":"=m" (last_task_used_math->tss.i387));
else
......@@ -320,16 +345,22 @@ asmlinkage void math_state_restore(void)
current->used_math = 1;
}
current->flags|=PF_USEDFPU; /* So we fnsave on switch_to() */
#ifndef __SMP__
out:
#endif
unlock_kernel();
}
#ifndef CONFIG_MATH_EMULATION
asmlinkage void math_emulate(long arg)
{
printk("math-emulation not enabled and no coprocessor found.\n");
printk("killing %s.\n",current->comm);
force_sig(SIGFPE,current);
schedule();
lock_kernel();
printk("math-emulation not enabled and no coprocessor found.\n");
printk("killing %s.\n",current->comm);
force_sig(SIGFPE,current);
schedule();
unlock_kernel();
}
#endif /* CONFIG_MATH_EMULATION */
......
......@@ -10,6 +10,8 @@
#include <linux/string.h>
#include <linux/ptrace.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
......@@ -62,8 +64,10 @@
asmlinkage struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
{
struct pt_regs *ret;
unsigned long tmp;
lock_kernel();
if (!current->tss.vm86_info) {
printk("no vm86_info: BAD\n");
do_exit(SIGSEGV);
......@@ -79,7 +83,9 @@ asmlinkage struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
}
current->tss.esp0 = current->saved_kernel_stack;
current->saved_kernel_stack = 0;
return KVM86->regs32;
ret = KVM86->regs32;
unlock_kernel();
return ret;
}
static void mark_screen_rdonly(struct task_struct * tsk)
......@@ -126,21 +132,27 @@ asmlinkage int sys_vm86old(struct vm86_struct * v86)
* This remains on the stack until we
* return to 32 bit user space.
*/
struct task_struct *tsk = current;
int tmp;
struct task_struct *tsk;
int tmp, ret = -EPERM;
lock_kernel();
tsk = current;
if (tsk->saved_kernel_stack)
return -EPERM;
goto out;
tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1);
tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2,
(long)&info.vm86plus - (long)&info.regs.VM86_REGS_PART2);
ret = -EFAULT;
if (tmp)
return -EFAULT;
goto out;
memset(&info.vm86plus, 0, (int)&info.regs32 - (int)&info.vm86plus);
info.regs32 = (struct pt_regs *) &v86;
tsk->tss.vm86_info = v86;
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)
* This remains on the stack until we
* return to 32 bit user space.
*/
struct task_struct *tsk = current;
int tmp;
struct task_struct *tsk;
int tmp, ret;
lock_kernel();
tsk = current;
switch (subfunction) {
case VM86_REQUEST_IRQ:
case VM86_FREE_IRQ:
case VM86_GET_IRQ_BITS:
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:
/* NOTE: on old vm86 stuff this will return the error
from verify_area(), because the subfunction is
interpreted as (invalid) address to vm86_struct.
So the installation check works.
*/
return 0;
ret = 0;
goto out;
}
/* we come here only for functions VM86_ENTER, VM86_ENTER_NO_BYPASS */
ret = -EPERM;
if (tsk->saved_kernel_stack)
return -EPERM;
goto out;
tmp = copy_from_user(&info, v86, VM86_REGS_SIZE1);
tmp += copy_from_user(&info.regs.VM86_REGS_PART2, &v86->regs.VM86_REGS_PART2,
(long)&info.regs32 - (long)&info.regs.VM86_REGS_PART2);
ret = -EFAULT;
if (tmp)
return -EFAULT;
goto out;
info.regs32 = (struct pt_regs *) &subfunction;
info.vm86plus.is_vm86pus = 1;
tsk->tss.vm86_info = (struct vm86_struct *)v86;
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
tsk->tss.screen_bitmap = info->screen_bitmap;
if (info->flags & VM86_SCREEN_BITMAP)
mark_screen_rdonly(tsk);
unlock_kernel();
__asm__ __volatile__(
"xorl %%eax,%%eax; mov %%ax,%%fs; mov %%ax,%%gs\n\t"
"movl %0,%%esp\n\t"
......@@ -247,6 +269,7 @@ static inline void return_to_32bit(struct kernel_vm86_regs * regs16, int retval)
regs32 = save_v86_state(regs16);
regs32->eax = retval;
unlock_kernel();
__asm__ __volatile__("movl %0,%%esp\n\t"
"jmp ret_from_sys_call"
: : "r" (regs32), "b" (current));
......@@ -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 ret;
lock_kernel();
if (VMPI.is_vm86pus) {
if ( (trapno==3) || (trapno==1) )
return_to_32bit(regs, VM86_TRAP + (trapno << 8));
do_int(regs, trapno, (unsigned char *) (regs->ss << 4), SP(regs));
return 1;
ret = 1;
goto out;
}
ret = 0;
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)
current->blocked &= ~(1 << (SIGTRAP-1));
send_sig(SIGTRAP, current, 1);
current->tss.trap_no = trapno;
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)
#define VM86_FAULT_RETURN \
if (VMPI.force_return_for_pic && (VEFLAGS & IF_MASK)) \
return_to_32bit(regs, VM86_PICRETURN); \
return;
goto out;
lock_kernel();
csp = (unsigned char *) (regs->cs << 4);
ssp = (unsigned char *) (regs->ss << 4);
sp = SP(regs);
......@@ -501,7 +532,7 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
return_to_32bit(regs, VM86_INTx + (intno << 8));
}
do_int(regs, intno, ssp, sp);
return;
goto out;
}
/* iret */
......@@ -534,6 +565,8 @@ void handle_vm86_fault(struct kernel_vm86_regs * regs, long error_code)
default:
return_to_32bit(regs, VM86_UNKNOWN);
}
out:
unlock_kernel();
}
/* ---------------- vm86 special IRQ passing stuff ----------------- */
......@@ -554,18 +587,19 @@ static void irq_handler(int intno, void *dev_id, struct pt_regs * regs) {
int irq_bit;
unsigned long flags;
lock_kernel();
save_flags(flags);
cli();
irq_bit = 1 << intno;
if ((irqbits & irq_bit) || ! vm86_irqs[intno].tsk) {
restore_flags(flags);
return;
}
if ((irqbits & irq_bit) || ! vm86_irqs[intno].tsk)
goto out;
irqbits |= irq_bit;
if (vm86_irqs[intno].sig)
send_sig(vm86_irqs[intno].sig, vm86_irqs[intno].tsk, 1);
/* else user will poll for IRQs */
out:
restore_flags(flags);
unlock_kernel();
}
static inline void free_vm86_irq(int irqnumber)
......
......@@ -11,6 +11,6 @@ else
endif
L_TARGET = lib.a
L_OBJS = checksum.o semaphore.o
L_OBJS = checksum.o semaphore.o locks.o
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 @@
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <asm/system.h>
#include <asm/uaccess.h>
......@@ -96,6 +98,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
unsigned long fixup;
int write;
lock_kernel();
/* get the address */
__asm__("movl %%cr2,%0":"=r" (address));
down(&mm->mmap_sem);
......@@ -154,7 +158,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
if (bit < 32)
tsk->tss.screen_bitmap |= 1 << bit;
}
return;
goto out;
/*
* 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)
if ((fixup = search_exception_table(regs->eip)) != 0) {
printk(KERN_DEBUG "Exception at [<%lx>] (%lx)\n", regs->eip, fixup);
regs->eip = fixup;
return;
goto out;
}
if (error_code & 4) {
......@@ -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.trap_no = 14;
force_sig(SIGSEGV, tsk);
return;
goto out;
}
/*
* 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)
pg0[0] = pte_val(mk_pte(0, PAGE_SHARED));
flush_tlb();
printk("This processor honours the WP bit even when in supervisor mode. Good.\n");
return;
goto out;
}
if (address < PAGE_SIZE) {
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)
}
die_if_kernel("Oops", regs, error_code);
do_exit(SIGKILL);
out:
unlock_kernel();
}
......@@ -289,6 +289,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
return;
}
void free_initmem(void)
{
/* To be written */
}
void si_meminfo(struct sysinfo *val)
{
int i;
......
......@@ -20,32 +20,32 @@ extern int dump_fpu(elf_fpregset_t *);
/* platform dependent support */
EXPORT_SYMBOLS(memcmp);
EXPORT_SYMBOLS(m68k_machtype);
EXPORT_SYMBOLS(m68k_cputype);
EXPORT_SYMBOLS(m68k_is040or060);
EXPORT_SYMBOLS(cache_push);
EXPORT_SYMBOLS(cache_push_v);
EXPORT_SYMBOLS(cache_clear);
EXPORT_SYMBOLS(mm_vtop);
EXPORT_SYMBOLS(mm_ptov);
EXPORT_SYMBOLS(mm_end_of_chunk);
EXPORT_SYMBOLS(m68k_debug_device);
EXPORT_SYMBOLS(request_irq);
EXPORT_SYMBOLS(free_irq);
EXPORT_SYMBOLS(dump_fpu);
EXPORT_SYMBOLS(dump_thread);
EXPORT_SYMBOLS(strnlen);
EXPORT_SYMBOLS(strrchr);
EXPORT_SYMBOLS(strstr);
EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(m68k_machtype);
EXPORT_SYMBOL(m68k_cputype);
EXPORT_SYMBOL(m68k_is040or060);
EXPORT_SYMBOL(cache_push);
EXPORT_SYMBOL(cache_push_v);
EXPORT_SYMBOL(cache_clear);
EXPORT_SYMBOL(mm_vtop);
EXPORT_SYMBOL(mm_ptov);
EXPORT_SYMBOL(mm_end_of_chunk);
EXPORT_SYMBOL(m68k_debug_device);
EXPORT_SYMBOL(request_irq);
EXPORT_SYMBOL(free_irq);
EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(dump_thread);
EXPORT_SYMBOL(strnlen);
EXPORT_SYMBOL(strrchr);
EXPORT_SYMBOL(strstr);
/* The following are special because they're not called
explicitly (the C compiler generates them). Fortunately,
their interface isn't gonna change any time soon now, so
it's OK to leave it out of version control. */
EXPORT_SYMBOLS_NOVERS(__ashrdi3);
EXPORT_SYMBOLS_NOVERS(memcpy);
EXPORT_SYMBOLS_NOVERS(memset);
EXPORT_SYMBOL_NOVERS(__ashrdi3);
EXPORT_SYMBOL_NOVERS(memcpy);
EXPORT_SYMBOL_NOVERS(memset);
EXPORT_SYMBOLS_NOVERS(__down_failed);
EXPORT_SYMBOLS_NOVERS(__up_wakeup);
EXPORT_SYMBOL_NOVERS(__down_failed);
EXPORT_SYMBOL_NOVERS(__up_wakeup);
......@@ -14,6 +14,8 @@
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
......@@ -34,13 +36,20 @@ asmlinkage void ret_from_exception(void);
*/
asmlinkage int sys_idle(void)
{
int ret = -EPERM;
lock_kernel();
if (current->pid != 0)
return -EPERM;
goto out;
/* endless idle loop with no priority at all */
current->counter = -100;
for (;;)
schedule();
ret = 0;
out:
unlock_kernel();
return ret;
}
void hard_reset_now(void)
......@@ -86,20 +95,29 @@ void flush_thread(void)
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)
{
unsigned long clone_flags;
unsigned long newsp;
int ret;
lock_kernel();
/* syscall2 puts clone_flags in d1 and usp in d2 */
clone_flags = regs->d1;
newsp = regs->d2;
if (!newsp)
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)
......@@ -224,10 +242,13 @@ asmlinkage int sys_execve(char *name, char **argv, char **envp)
char * filename;
struct pt_regs *regs = (struct pt_regs *) &name;
lock_kernel();
error = getname(name, &filename);
if (error)
return error;
goto out;
error = do_execve(filename, argv, envp, regs);
putname(filename);
out:
unlock_kernel();
return error;
}
......@@ -14,6 +14,8 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>
......@@ -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)
{
struct task_struct *child;
struct user * dummy;
dummy = NULL;
struct user * dummy = NULL;
int ret;
lock_kernel();
ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->flags & PF_PTRACED)
return -EPERM;
goto out;
/* set the ptrace bit in the process flags. */
current->flags |= PF_PTRACED;
return 0;
ret = 0;
goto out;
}
if (pid == 1) /* you may not mess with init */
return -EPERM;
goto out;
ret = -ESRCH;
if (!(child = get_task(pid)))
return -ESRCH;
goto out;
ret = -EPERM;
if (request == PTRACE_ATTACH) {
if (child == current)
return -EPERM;
goto out;
if ((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
......@@ -348,10 +354,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
(current->gid != child->gid)) && !suser())
return -EPERM;
goto out;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
return -EPERM;
goto out;
child->flags |= PF_PTRACED;
if (child->p_pptr != current) {
REMOVE_LINKS(child);
......@@ -359,39 +365,42 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
SET_LINKS(child);
}
send_sig(SIGSTOP, child, 1);
return 0;
ret = 0;
goto out;
}
ret = -ESRCH;
if (!(child->flags & PF_PTRACED))
return -ESRCH;
goto out;
if (child->state != TASK_STOPPED) {
if (request != PTRACE_KILL)
return -ESRCH;
goto out;
}
if (child->p_pptr != current)
return -ESRCH;
goto out;
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
unsigned long tmp;
int res;
res = read_long(child, addr, &tmp);
if (res < 0)
return res;
return put_user(tmp, (unsigned long *) data);
ret = read_long(child, addr, &tmp);
if (ret >= 0)
ret = put_user(tmp, (unsigned long *) data);
goto out;
}
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
unsigned long tmp;
ret = -EIO;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
return -EIO;
goto out;
tmp = 0; /* Default return condition */
addr = addr >> 2; /* temporary hack. */
ret = -EIO;
if (addr < 19) {
tmp = get_reg(child, addr);
if (addr == PT_SR)
......@@ -400,23 +409,26 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
else if (addr >= 21 && addr < 49)
tmp = child->tss.fp[addr - 21];
else
return -EIO;
return put_user(tmp,(unsigned long *) data);
goto out;
ret = put_user(tmp,(unsigned long *) data);
goto out;
}
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
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 */
ret = -EIO;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
return -EIO;
goto out;
addr = addr >> 2; /* temporary hack. */
if (addr == PT_ORIG_D0)
return -EIO;
goto out;
if (addr == PT_SR) {
data &= SR_MASK;
data <<= 16;
......@@ -424,22 +436,24 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
}
if (addr < 19) {
if (put_reg(child, addr, data))
return -EIO;
return 0;
goto out;
ret = 0;
goto out;
}
if (addr >= 21 && addr < 48)
{
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_CONT: { /* restart after signal. */
long tmp;
ret = -EIO;
if ((unsigned long) data >= NSIG)
return -EIO;
goto out;
if (request == PTRACE_SYSCALL)
child->flags |= PF_TRACESYS;
else
......@@ -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. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
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)
case PTRACE_KILL: {
long tmp;
ret = 0;
if (child->state == TASK_ZOMBIE) /* already dead */
return 0;
goto out;
wake_up_process(child);
child->exit_code = SIGKILL;
/* make sure the single step bit is not set. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
return 0;
goto out;
}
case PTRACE_SINGLESTEP: { /* set the trap flag. */
long tmp;
ret = -EIO;
if ((unsigned long) data >= NSIG)
return -EIO;
goto out;
child->flags &= ~PF_TRACESYS;
tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
......@@ -482,14 +499,16 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
wake_up_process(child);
child->exit_code = data;
/* give it a chance to run. */
return 0;
ret = 0;
goto out;
}
case PTRACE_DETACH: { /* detach a process that was attached. */
long tmp;
ret = -EIO;
if ((unsigned long) data >= NSIG)
return -EIO;
goto out;
child->flags &= ~(PF_PTRACED|PF_TRACESYS);
wake_up_process(child);
child->exit_code = 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. */
tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
put_reg(child, PT_SR, tmp);
return 0;
ret = 0;
goto out;
}
default:
return -EIO;
ret = -EIO;
goto out;
}
out:
unlock_kernel();
return ret;
}
asmlinkage void syscall_trace(void)
{
lock_kernel();
if ((current->flags & (PF_PTRACED|PF_TRACESYS))
!= (PF_PTRACED|PF_TRACESYS))
return;
goto out;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
notify_parent(current);
......@@ -524,5 +549,6 @@ asmlinkage void syscall_trace(void)
if (current->exit_code)
current->signal |= (1 << (current->exit_code - 1));
current->exit_code = 0;
return;
out:
unlock_kernel();
}
......@@ -9,6 +9,8 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
......@@ -31,15 +33,18 @@ asmlinkage int sys_pipe(unsigned long * fildes)
int fd[2];
int error;
lock_kernel();
error = verify_area(VERIFY_WRITE,fildes,8);
if (error)
return error;
goto out;
error = do_pipe(fd);
if (error)
return error;
goto out;
put_user(fd[0],0+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)
struct file * file = NULL;
struct mmap_arg_struct a;
lock_kernel();
error = verify_area(VERIFY_READ, arg, sizeof(*arg));
if (error)
return error;
goto out;
copy_from_user(&a, arg, sizeof(a));
if (!(a.flags & MAP_ANONYMOUS)) {
error = -EBADF;
if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd]))
return -EBADF;
goto out;
}
a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset);
out:
unlock_kernel();
return error;
}
......@@ -89,10 +98,15 @@ struct sel_arg_struct {
asmlinkage int old_select(struct sel_arg_struct *arg)
{
struct sel_arg_struct a;
int ret = -EFAULT;
lock_kernel();
if (copy_from_user(&a, arg, sizeof(a)))
return -EFAULT;
return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
goto out;
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)
*/
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 */
call &= 0xffff;
......@@ -110,46 +124,58 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
if (call <= SEMCTL)
switch (call) {
case SEMOP:
return sys_semop (first, (struct sembuf *)ptr, second);
ret = sys_semop (first, (struct sembuf *)ptr, second);
goto out;
case SEMGET:
return sys_semget (first, second, third);
ret = sys_semget (first, second, third);
goto out;
case SEMCTL: {
union semun fourth;
int err;
ret = -EINVAL;
if (!ptr)
return -EINVAL;
if ((err = verify_area (VERIFY_READ, ptr, sizeof(long))))
return err;
goto out;
if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long))))
goto out;
get_user(fourth.__pad, (void **)ptr);
return sys_semctl (first, second, third, fourth);
ret = sys_semctl (first, second, third, fourth);
goto out;
}
default:
return -EINVAL;
ret = -EINVAL;
goto out;
}
if (call <= MSGCTL)
switch (call) {
case MSGSND:
return sys_msgsnd (first, (struct msgbuf *) ptr,
second, third);
ret = sys_msgsnd (first, (struct msgbuf *) ptr,
second, third);
goto out;
case MSGRCV:
switch (version) {
case 0: {
struct ipc_kludge tmp;
ret = -EINVAL;
if (!ptr)
return -EINVAL;
goto out;
ret = -EFAULT;
if (copy_from_user (&tmp, ptr, sizeof (tmp)))
return -EFAULT;
return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
goto out;
ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
goto out;
}
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:
return sys_msgget ((key_t) first, second);
ret = sys_msgget ((key_t) first, second);
goto out;
case MSGCTL:
return sys_msgctl (first, second, (struct msqid_ds *) ptr);
ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
goto out;
default:
return -EINVAL;
ret = -EINVAL;
goto out;
}
if (call <= SHMCTL)
switch (call) {
......@@ -157,30 +183,40 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
switch (version) {
case 0: default: {
ulong raddr;
int err;
if ((err = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
return err;
err = sys_shmat (first, (char *) ptr, second, &raddr);
if (err)
return err;
if ((ret = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
goto out;
ret = sys_shmat (first, (char *) ptr, second, &raddr);
if (ret)
goto out;
put_user (raddr, (ulong *) third);
return 0;
ret = 0;
goto out;
}
case 1: /* iBCS2 emulator entry point */
ret = -EINVAL;
if (get_fs() != get_ds())
return -EINVAL;
return sys_shmat (first, (char *) ptr, second, (ulong *) third);
goto out;
ret = sys_shmat (first, (char *) ptr, second, (ulong *) third);
goto out;
}
case SHMDT:
return sys_shmdt ((char *)ptr);
ret = sys_shmdt ((char *)ptr);
goto out;
case SHMGET:
return sys_shmget (first, second, third);
ret = sys_shmget (first, second, third);
goto out;
case SHMCTL:
return sys_shmctl (first, second, (struct shmid_ds *) ptr);
ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
goto out;
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)
......@@ -496,60 +532,63 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
asmlinkage int
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
|| cache & ~FLUSH_CACHE_BOTH)
return -EINVAL;
lock_kernel();
if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
cache & ~FLUSH_CACHE_BOTH)
goto out;
if (scope == FLUSH_SCOPE_ALL)
{
/* Only the superuser may flush the whole cache. */
if (!suser ())
return -EPERM;
}
else
{
/* Verify that the specified address region actually belongs to
this process. */
vma = find_vma (current->mm, addr);
if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
return -EINVAL;
}
if (scope == FLUSH_SCOPE_ALL) {
/* Only the superuser may flush the whole cache. */
ret = -EPERM;
if (!suser ())
goto out;
} else {
/* Verify that the specified address region actually belongs to
* this process.
*/
vma = find_vma (current->mm, addr);
ret = -EINVAL;
if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
goto out;
}
if (CPU_IS_020_OR_030) {
if (scope == FLUSH_SCOPE_LINE)
{
unsigned long cacr;
__asm__ ("movec %%cacr, %0" : "=r" (cacr));
if (cache & FLUSH_CACHE_INSN)
cacr |= 4;
if (cache & FLUSH_CACHE_DATA)
cacr |= 0x400;
len >>= 4;
while (len--)
{
__asm__ __volatile__ ("movec %1, %%caar\n\t"
"movec %0, %%cacr"
: /* no outputs */
: "r" (cacr), "r" (addr));
addr += 16;
}
}
else
{
/* Flush the whole cache, even if page granularity is requested. */
unsigned long cacr;
__asm__ ("movec %%cacr, %0" : "=r" (cacr));
if (cache & FLUSH_CACHE_INSN)
cacr |= 8;
if (cache & FLUSH_CACHE_DATA)
cacr |= 0x800;
__asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
}
return 0;
} else if (CPU_IS_040)
return cache_flush_040 (addr, scope, cache, len);
else if (CPU_IS_060)
return cache_flush_060 (addr, scope, cache, len);
if (CPU_IS_020_OR_030) {
if (scope == FLUSH_SCOPE_LINE) {
unsigned long cacr;
__asm__ ("movec %%cacr, %0" : "=r" (cacr));
if (cache & FLUSH_CACHE_INSN)
cacr |= 4;
if (cache & FLUSH_CACHE_DATA)
cacr |= 0x400;
len >>= 4;
while (len--) {
__asm__ __volatile__ ("movec %1, %%caar\n\t"
"movec %0, %%cacr"
: /* no outputs */
: "r" (cacr), "r" (addr));
addr += 16;
}
} else {
/* Flush the whole cache, even if page granularity requested. */
unsigned long cacr;
__asm__ ("movec %%cacr, %0" : "=r" (cacr));
if (cache & FLUSH_CACHE_INSN)
cacr |= 8;
if (cache & FLUSH_CACHE_DATA)
cacr |= 0x800;
__asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
}
ret = 0;
goto out;
} else if (CPU_IS_040) {
ret = cache_flush_040 (addr, scope, cache, len);
} else if (CPU_IS_060) {
ret = cache_flush_060 (addr, scope, cache, len);
}
out:
unlock_kernel();
return ret;
}
......@@ -477,6 +477,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
datapages << (PAGE_SHIFT-10));
}
void free_initmem(void)
{
/* To be written */
}
void si_meminfo(struct sysinfo *val)
{
unsigned long i;
......
......@@ -10,6 +10,8 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
......@@ -25,57 +27,67 @@
asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
{
#ifdef CONFIG_SYSVIPC
int version;
int version, ret;
lock_kernel();
version = call >> 16; /* hack for backward compatibility */
call &= 0xffff;
if (call <= SEMCTL)
switch (call) {
case SEMOP:
return sys_semop (first, (struct sembuf *)ptr, second);
ret = sys_semop (first, (struct sembuf *)ptr, second);
goto out;
case SEMGET:
return sys_semget (first, second, third);
ret = sys_semget (first, second, third);
goto out;
case SEMCTL: {
union semun fourth;
int err;
ret = -EINVAL;
if (!ptr)
return -EINVAL;
if ((err = verify_area (VERIFY_READ, ptr, sizeof(long))))
return err;
goto out;
if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long))))
goto out;
fourth.__pad = (void *) get_fs_long(ptr);
return sys_semctl (first, second, third, fourth);
ret = sys_semctl (first, second, third, fourth);
goto out;
}
default:
return -EINVAL;
ret = -EINVAL;
goto out;
}
if (call <= MSGCTL)
switch (call) {
case MSGSND:
return sys_msgsnd (first, (struct msgbuf *) ptr,
second, third);
ret = sys_msgsnd (first, (struct msgbuf *) ptr,
second, third);
goto out;
case MSGRCV:
switch (version) {
case 0: {
struct ipc_kludge tmp;
int err;
if (!ptr)
return -EINVAL;
if ((err = verify_area (VERIFY_READ, ptr, sizeof(tmp))))
return err;
if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp))))
goto out;
memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr,
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:
return sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
ret = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
goto out;
}
case MSGGET:
return sys_msgget ((key_t) first, second);
ret = sys_msgget ((key_t) first, second);
goto out;
case MSGCTL:
return sys_msgctl (first, second, (struct msqid_ds *) ptr);
ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
goto out;
default:
return -EINVAL;
ret = -EINVAL;
goto out;
}
if (call <= SHMCTL)
switch (call) {
......@@ -83,30 +95,40 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
switch (version) {
case 0: default: {
ulong raddr;
int err;
if ((err = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
return err;
err = sys_shmat (first, (char *) ptr, second, &raddr);
if (err)
return err;
if ((ret = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
goto out;
ret = sys_shmat (first, (char *) ptr, second, &raddr);
if (ret)
goto out;
put_fs_long (raddr, (ulong *) third);
return 0;
ret = 0;
goto out;
}
case 1: /* iBCS2 emulator entry point */
ret = -EINVAL;
if (get_fs() != get_ds())
return -EINVAL;
return sys_shmat (first, (char *) ptr, second, (ulong *) third);
goto out;
ret = sys_shmat (first, (char *) ptr, second, (ulong *) third);
goto out;
}
case SHMDT:
return sys_shmdt ((char *)ptr);
ret = sys_shmdt ((char *)ptr);
goto out;
case SHMGET:
return sys_shmget (first, second, third);
ret = sys_shmget (first, second, third);
goto out;
case SHMCTL:
return sys_shmctl (first, second, (struct shmid_ds *) ptr);
ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
goto out;
default:
return -EINVAL;
ret = -EINVAL;
goto out;
}
return -EINVAL;
else
ret = -EINVAL;
out:
unlock_kernel();
return ret;
#else /* CONFIG_SYSVIPC */
return -ENOSYS;
#endif /* CONFIG_SYSVIPC */
......
......@@ -5,6 +5,8 @@
*/
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h>
......@@ -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)
{
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;
current->blocked = set & _BLOCKABLE;
regs->reg2 = -EINTR;
......@@ -38,8 +43,11 @@ asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long
current->state = TASK_INTERRUPTIBLE;
schedule();
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
asmlinkage int sys_sigreturn(struct pt_regs *regs)
{
struct sigcontext_struct *context;
int ret;
lock_kernel();
/*
* 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
......@@ -99,10 +109,14 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
* disable syscall checks
*/
regs->orig_reg2 = -1;
return context->sc_v0;
goto out;
badframe:
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,
*/
asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
{
unsigned long mask = ~current->blocked;
unsigned long mask;
unsigned long handler_signal = 0;
struct sc *frame = NULL;
unsigned long pc = 0;
unsigned long signr;
struct sigaction * sa;
int ret;
lock_kernel();
mask = ~current->blocked;
while ((signr = current->signal & mask)) {
signr = ffz(~signr);
clear_bit(signr, &current->signal);
......@@ -331,8 +348,9 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
regs->reg2 = regs->orig_reg2;
regs->cp0_epc -= 8;
}
ret = 0;
if (!handler_signal) /* no handler will be called - return 0 */
return 0;
goto out;
pc = regs->cp0_epc;
frame = (struct sc *) regs->reg29;
signr = 1;
......@@ -353,5 +371,8 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
regs->reg31 = (unsigned long) frame->code; /* Return address */
regs->cp0_epc = pc; /* "return" to the first handler */
return 1;
ret = 1;
out:
unlock_kernel();
return ret;
}
......@@ -9,6 +9,8 @@
*/
#include <linux/linkage.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/mman.h>
#include <linux/sched.h>
#include <linux/unistd.h>
......@@ -28,32 +30,43 @@ asmlinkage int sys_pipe(struct pt_regs *regs)
int fd[2];
int error;
lock_kernel();
error = do_pipe(fd);
if (error)
return error;
goto out;
regs->reg2 = fd[0];
regs->reg3 = fd[1];
return 0;
out:
unlock_kernel();
return error;
}
asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, int prot,
int flags, int fd, off_t offset)
{
struct file * file = NULL;
int ret = -EBADF;
lock_kernel();
if (flags & MAP_RENAME) {
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
return -EBADF;
goto out;
}
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)
{
int ret = -EPERM;
lock_kernel();
if (current->pid != 0)
return -EPERM;
goto out;
/* endless idle loop with no priority at all */
current->counter = -100;
......@@ -67,23 +80,36 @@ asmlinkage int sys_idle(void)
".set\tmips0\n\t");
schedule();
}
ret = 0;
out:
unlock_kernel();
return ret;
}
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)
{
unsigned long clone_flags;
unsigned long newsp;
int ret;
lock_kernel();
clone_flags = regs->reg4;
newsp = regs->reg5;
if (!newsp)
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)
int error;
char * filename;
lock_kernel();
error = getname((char *) regs->reg4, &filename);
if (error)
return error;
goto out;
error = do_execve(filename, (char **) regs->reg5,
(char **) regs->reg6, regs);
putname(filename);
out:
unlock_kernel();
return error;
}
......
......@@ -10,6 +10,8 @@
#include <linux/errno.h>
#include <linux/linkage.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/utsname.h>
......@@ -54,44 +56,51 @@ sys_sysmips(int cmd, int arg1, int arg2, int arg3)
char *name;
int flags, len, retval = -EINVAL;
lock_kernel();
switch(cmd)
{
case SETNAME:
retval = -EPERM;
if (!suser())
return -EPERM;
goto out;
name = (char *) arg1;
len = get_max_hostname((unsigned long)name);
if (retval < 0)
return len;
retval = len;
if (len < 0)
goto out;
len = strnlen_user(name, retval);
retval = -EINVAL;
if (len == 0 || len > __NEW_UTS_LEN)
return -EINVAL;
goto out;
memcpy_fromfs(system_utsname.nodename, name, len);
system_utsname.nodename[len] = '\0';
return 0;
retval = 0;
goto out;
case MIPS_ATOMIC_SET:
p = (int *) arg1;
retval = verify_area(VERIFY_WRITE, p, sizeof(*p));
if(retval)
return -EINVAL;
retval = -EINVAL;
if(verify_area(VERIFY_WRITE, p, sizeof(*p)))
goto out;
save_flags(flags);
cli();
retval = *p;
*p = arg2;
restore_flags(flags);
return retval;
goto out;
case MIPS_FIXADE:
if (arg1)
current->tss.mflags |= MF_FIXADE;
else
current->tss.mflags |= MF_FIXADE;
retval = 0;
break;
goto out;
case FLUSH_CACHE:
sys_cacheflush(0, ~0, BCACHE);
break;
retval = 0;
goto out;
}
out:
unlock_kernel();
return retval;
}
......
......@@ -281,6 +281,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
return;
}
void free_initmem(void)
{
/* To be written */
}
void si_meminfo(struct sysinfo *val)
{
int i;
......
......@@ -14,6 +14,8 @@
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
......@@ -133,19 +135,30 @@ switch_to(struct task_struct *prev, struct task_struct *new)
asmlinkage int sys_debug(unsigned long r3)
{
if ( !strcmp(current->comm,"crashme"))
printk("sys_debug(): r3 (syscall) %d\n", r3);
lock_kernel();
if (!strcmp(current->comm,"crashme"))
printk("sys_debug(): r3 (syscall) %d\n", r3);
unlock_kernel();
return 0;
}
asmlinkage int sys_idle(void)
{
if (current->pid != 0)
return -EPERM;
/* endless idle loop with no priority at all */
current->counter = -100;
for (;;) {
schedule();
}
int ret = -EPERM;
lock_kernel();
if (current->pid != 0)
goto out;
/* 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)
......@@ -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)
{
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,
......@@ -242,6 +260,7 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
int error;
char * filename;
lock_kernel();
/* getname does it's own verification of the address
when it calls get_max_filename() but
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,
#endif
error = getname((char *) a0, &filename);
if (error)
{
return error;
}
goto out;
flush_instruction_cache();
error = do_execve(filename, (char **) a1, (char **) a2, regs);
#if 0
......@@ -277,6 +294,8 @@ printk("EXECVE - file = '%s', error = %d\n", filename, error);
}
#endif
putname(filename);
out:
unlock_kernel();
return error;
}
......@@ -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;
int res;
lock_kernel();
res = do_fork(clone_flags, regs->gpr[1], regs);
unlock_kernel();
return res;
}
......@@ -339,9 +361,9 @@ print_kernel_backtrace(void)
inline void start_thread(struct pt_regs * regs,
unsigned long eip, unsigned long esp)
{
regs->nip = eip;
regs->gpr[1] = esp;
regs->msr = MSR_USER;
set_fs(USER_DS);
regs->nip = eip;
regs->gpr[1] = esp;
regs->msr = MSR_USER;
set_fs(USER_DS);
}
......@@ -18,6 +18,8 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>
......@@ -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)
{
struct task_struct *child;
struct user * dummy;
dummy = NULL;
struct user * dummy = NULL;
int ret = -EPERM;
lock_kernel();
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->flags & PF_PTRACED)
return -EPERM;
goto out;
/* set the ptrace bit in the process flags. */
current->flags |= PF_PTRACED;
return 0;
ret = 0;
goto out;
}
if (pid == 1) /* you may not mess with init */
return -EPERM;
goto out;
ret = -ESRCH;
if (!(child = get_task(pid)))
return -ESRCH;
goto out;
ret = -EPERM;
if (request == PTRACE_ATTACH) {
if (child == current)
return -EPERM;
goto out;
if ((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->gid)) && !suser())
return -EPERM;
goto out;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
return -EPERM;
goto out;
child->flags |= PF_PTRACED;
if (child->p_pptr != current) {
REMOVE_LINKS(child);
......@@ -411,73 +416,75 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
SET_LINKS(child);
}
send_sig(SIGSTOP, child, 1);
return 0;
ret = 0;
goto out;
}
ret = -ESRCH;
if (!(child->flags & PF_PTRACED))
return -ESRCH;
goto out;
if (child->state != TASK_STOPPED) {
if (request != PTRACE_KILL)
return -ESRCH;
goto out;
}
if (child->p_pptr != current)
return -ESRCH;
goto out;
switch (request) {
/* If I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
unsigned long tmp;
int res;
res = read_long(child, addr, &tmp);
if (res < 0)
return res;
res = verify_area(VERIFY_WRITE, (void *) data, sizeof(long));
if (!res)
ret = read_long(child, addr, &tmp);
if (ret < 0)
goto out;
ret = verify_area(VERIFY_WRITE, (void *) data, sizeof(long));
if (!ret)
put_user(tmp, (unsigned long *) data);
return res;
goto out;
}
/* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
unsigned long tmp;
int res;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
return -EIO;
res = verify_area(VERIFY_WRITE, (void *) data,
ret = verify_area(VERIFY_WRITE, (void *) data,
sizeof(long));
if (res)
return res;
if (ret)
goto out;
tmp = 0; /* Default return condition */
addr = addr >> 2; /* temporary hack. */
if (addr < PT_FPR0) {
if (addr < PT_FPR0)
tmp = get_reg(child, addr);
}
#if 0
else if (addr >= PT_FPR0 && addr < PT_FPR31)
tmp = child->tss.fpr[addr - PT_FPR0];
#endif
else
return -EIO;
put_user(tmp,(unsigned long *) data);
return 0;
ret = -EIO;
if(!ret)
put_user(tmp,(unsigned long *) data);
goto out;
}
/* If I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
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 */
ret = -EIO;
if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
return -EIO;
goto out;
addr = addr >> 2; /* temporary hack. */
if (addr == PT_ORIG_R3)
return -EIO;
goto out;
#if 0 /* Let this check be in 'put_reg' */
if (addr == PT_SR) {
data &= SR_MASK;
......@@ -487,22 +494,24 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
#endif
if (addr < PT_FPR0) {
if (put_reg(child, addr, data))
return -EIO;
return 0;
goto out;
ret = 0;
goto out;
}
#if 0
if (addr >= 21 && addr < 48)
{
if (addr >= 21 && addr < 48) {
child->tss.fp[addr - 21] = data;
return 0;
ret = 0;
goto out;
}
#endif
return -EIO;
goto out;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */
ret = -EIO;
if ((unsigned long) data >= NSIG)
return -EIO;
goto out;
if (request == PTRACE_SYSCALL)
child->flags |= PF_TRACESYS;
else
......@@ -511,7 +520,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
wake_up_process(child);
/* make sure the single step bit is not set. */
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)
* exit.
*/
case PTRACE_KILL: {
ret = 0;
if (child->state == TASK_ZOMBIE) /* already dead */
return 0;
goto out;
wake_up_process(child);
child->exit_code = SIGKILL;
/* make sure the single step bit is not set. */
clear_single_step(child);
return 0;
goto out;
}
case PTRACE_SINGLESTEP: { /* set the trap flag. */
ret = -EIO;
if ((unsigned long) data >= NSIG)
return -EIO;
goto out;
child->flags &= ~PF_TRACESYS;
set_single_step(child);
wake_up_process(child);
child->exit_code = data;
/* give it a chance to run. */
return 0;
ret = 0;
goto out;
}
case PTRACE_DETACH: { /* detach a process that was attached. */
ret = -EIO;
if ((unsigned long) data >= NSIG)
return -EIO;
goto out;
child->flags &= ~(PF_PTRACED|PF_TRACESYS);
wake_up_process(child);
child->exit_code = data;
......@@ -551,19 +565,25 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
SET_LINKS(child);
/* make sure the single step bit is not set. */
clear_single_step(child);
return 0;
ret = 0;
goto out;
}
default:
return -EIO;
ret = -EIO;
goto out;
}
out:
unlock_kernel();
return ret;
}
asmlinkage void syscall_trace(void)
{
lock_kernel();
if ((current->flags & (PF_PTRACED|PF_TRACESYS))
!= (PF_PTRACED|PF_TRACESYS))
return;
goto out;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
notify_parent(current);
......@@ -576,5 +596,6 @@ asmlinkage void syscall_trace(void)
if (current->exit_code)
current->signal |= (1 << (current->exit_code - 1));
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)
return;
}
void free_initmem(void)
{
/* To be written */
}
void si_meminfo(struct sysinfo *val)
{
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
#
# Makefile for the architecture dependent flags and dependencies on the
......@@ -18,7 +18,8 @@ SHELL =/bin/bash
#CFLAGS := $(CFLAGS) -g -pipe
CFLAGS := $(CFLAGS) -pipe
LINKFLAGS = -N -Ttext 0xf0004000
#LINKFLAGS = -N -Ttext 0xf0004000
LINKFLAGS = -T arch/sparc/vmlinux.lds
HEAD := arch/sparc/kernel/head.o
......@@ -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 \
$(TOPDIR)/arch/sparc/lib/lib.a
INITOBJ = $(TOPDIR)/arch/sparc/kernel/initobj.o
FINITOBJ = $(TOPDIR)/arch/sparc/kernel/finitobj.o
ifdef CONFIG_AP1000
SUBDIRS := $(SUBDIRS) arch/sparc/ap1000 mpp
ARCHIVES := $(TOPDIR)/arch/sparc/ap1000/ap1000lib.o $(TOPDIR)/mpp/mpplib.o $(ARCHIVES)
......@@ -41,6 +39,5 @@ CFLAGS := $(CFLAGS) -D__MPP__=1
endif
archclean:
rm -f $(TOPDIR)/arch/sparc/boot/boot
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