From: Kenn H. <ke...@us...> - 2001-01-26 00:26:38
|
Update of /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel In directory usw-pr-cvs1:/tmp/cvs-serv25353/arch/vax/kernel Modified Files: Makefile cpu_ka42.c cpu_ka43.c entry.S interrupt.c interrupt.h process.c setup.c syscall.c time.c Added Files: signal.c Removed Files: delay.c softirq.c Log Message: Bring forward all 2.2 work from before new year. This should give us all a (somewhat) bootable kernel. --- NEW FILE --- /* $Id: signal.c,v 1.1 2001/01/26 00:27:00 kenn Exp $ This file contains the standard functions that the arch-independent kernel expects for signal handling */ #include <linux/errno.h> /* FIXME: obviously, these need to be filled in... */ int sys_sigaction(void) { return -ENOSYS; } int sys_sigsuspend(void) { return -ENOSYS; } int sys_sigreturn(void) { return -ENOSYS; } int sys_rt_sigreturn(void) { return -ENOSYS; } int sys_rt_sigsuspend(void) { return -ENOSYS; } int sys_sigaltstack(void) { return -ENOSYS; } Index: Makefile =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel/Makefile,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- Makefile 2001/01/20 13:51:05 1.2 +++ Makefile 2001/01/26 00:27:00 1.3 @@ -11,9 +11,9 @@ O_TARGET := kernel.o -obj-y := process.o setup.o regdump.o interrupt.o entry.o time.o delay.o \ - syscall.o \ - init_task.o softirq.o reboot.o cpu_generic.o \ +obj-y := process.o setup.o regdump.o interrupt.o entry.o time.o \ + syscall.o signal.o \ + init_task.o reboot.o cpu_generic.o \ cpu_ka630.o cpu_ka640.o cpu_ka650.o cpu_ka660.o \ cpu_ka410.o cpu_ka42.o cpu_ka43.o cpu_ka46.o OX_OBJS := Index: cpu_ka42.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel/cpu_ka42.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- cpu_ka42.c 2001/01/17 16:13:57 1.1 +++ cpu_ka42.c 2001/01/26 00:27:00 1.2 @@ -16,6 +16,7 @@ #include <asm/mtpr.h> #include <asm/mv.h> #include <asm/vaxcpu.h> +#include <asm/vsa.h> void ka42_init_devices(void); void ka42_pre_vm_init(void); @@ -72,6 +73,12 @@ void ka42_init_devices(void) { +#ifdef CONFIG_VSABUS + vsa_setup(); +#endif +#ifdef CONFIG_VAX_LANCE + vax_lance_probe(0); +#endif } const char *ka42_cpu_type_str(void) Index: cpu_ka43.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel/cpu_ka43.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- cpu_ka43.c 2001/01/17 16:13:57 1.1 +++ cpu_ka43.c 2001/01/26 00:27:00 1.2 @@ -16,9 +16,11 @@ #include <linux/config.h> +#include <asm/io.h> #include <asm/mtpr.h> #include <asm/mv.h> #include <asm/vaxcpu.h> +#include <asm/vsa.h> #include <asm/ka43.h> void ka43_pre_vm_init(void); @@ -30,6 +32,10 @@ void ka43_init_devices(void); const char *ka43_cpu_type_str(void); + +/* These are initialized at compile time with the physical addresses + of the KA43's CPU-specific data structures. Once VM is turned on, + we'll map in these physical ranges, and update these pointers. */ static volatile unsigned int *ka43_creg = (void*)KA43_CH2_CREG; static volatile unsigned int *ka43_ctag = (void*)KA43_CT2_BASE; @@ -67,14 +73,6 @@ void ka43_pre_vm_init(void) { - /* - * Resetting the cache involves disabling it, then clear it and enable again. - * - */ - ka43_cache_disable(); - ka43_cache_clear(); - ka43_cache_enable(); - mv_ka43.sidex = *(unsigned int *)RIGEL_SIDEX_ADDR; } @@ -83,6 +81,17 @@ init_dz11_console(0x200A0000, 3); dz_serial_console_init(0, 0); + + ka43_creg = ioremap(KA43_CH2_CREG, 1); + ka43_ctag = ioremap(KA43_CT2_BASE, KA43_CT2_SIZE); + + /* + * Resetting the cache involves disabling it, then clear it and enable again. + */ + ka43_cache_disable(); + ka43_cache_clear(); + ka43_cache_enable(); + } void ka43_cache_disable(void) @@ -132,9 +141,14 @@ void ka43_init_devices(void) { +#ifdef CONFIG_VSABUS + vsa_setup(); + #ifdef CONFIG_VAX_LANCE vax_lance_probe(0); -#endif +#endif /* CONFIG_VAX_LANCE */ + +#endif /* CONFIG_VSABUS */ } Index: entry.S =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel/entry.S,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- entry.S 2001/01/17 16:13:57 1.1 +++ entry.S 2001/01/26 00:27:00 1.2 @@ -8,6 +8,7 @@ */ #include <linux/sys.h> +#include <asm/mtpr.h> /* irqvec_handler is the generic handler for all interrupts and exceptions for which a driver (or other code) has registered @@ -59,7 +60,7 @@ pushl (sp)[r0] /* Push saved PSL again */ pushl (sp)[r0] /* Push saved PC again */ - pushal 12(sp)[r0] /* Save SP at time of exception */ + mfpr $PR_USP,-(sp) /* Save user SP at time of exception */ pushr $0x3ffe /* Push FP to R1 */ pushl 64(sp) /* Duplicate saved R0 */ @@ -68,7 +69,7 @@ SP: saved R0 +4 saved R1 ... - +56 saved SP + +56 saved user SP +60 saved PC +64 saved PSL +68 saved R0 @@ -89,6 +90,9 @@ calls $3, do_irq_excep +.globl ret_from_syscall +ret_from_syscall: + /* Now we need to restore all registers, clear the stack down to the original saved PC/PSL and dismiss the interrupt. The stack currently looks like the same as above. */ @@ -107,7 +111,7 @@ /* The stack now looks like: - SP: saved SP + SP: saved user SP +4 saved PC (maybe modified by exception handler) +8 saved PSL (end of struct pt_regs) +12 saved R0 (maybe modified by exception handler) @@ -131,7 +135,7 @@ /* The stack now looks like: - SP: saved SP + SP: saved user SP +4 saved PC (maybe modified by exception handler) +8 saved PSL (end of struct pt_regs) +12 saved R0 (maybe modified by exception handler) @@ -152,7 +156,7 @@ /* Stack now looks like - SP: saved R0 + SP: saved R0 +4 saved PC +8 saved PSL */ @@ -215,7 +219,7 @@ .long sys_lseek .long sys_getpid /* 20 */ .long sys_mount - .long sys_oldumount + .long sys_ni_syscall /* old umount syscall holder */ .long sys_setuid .long sys_getuid .long sys_stime /* 25 */ @@ -245,14 +249,14 @@ .long sys_geteuid .long sys_getegid /* 50 */ .long sys_acct - .long sys_umount /* recycled never used phys() */ + .long sys_umount /* recycled never used phys() */ .long sys_ni_syscall /* old lock syscall holder */ .long sys_ioctl .long sys_fcntl /* 55 */ .long sys_ni_syscall /* old mpx syscall holder */ .long sys_setpgid .long sys_ni_syscall /* old ulimit syscall holder */ - .long sys_olduname + .long sys_ni_syscall /* old uname syscall holder */ .long sys_umask /* 60 */ .long sys_chroot .long sys_ustat @@ -275,12 +279,15 @@ .long sys_settimeofday .long sys_getgroups /* 80 */ .long sys_setgroups + .long sys_select .long sys_symlink .long sys_lstat .long sys_readlink /* 85 */ .long sys_uselib .long sys_swapon .long sys_reboot + .long sys_ni_syscall /* old readdir syscall holder */ + .long sys_mmap /* 90 */ .long sys_munmap .long sys_truncate .long sys_ftruncate @@ -291,7 +298,7 @@ .long sys_ni_syscall /* old profil syscall holder */ .long sys_statfs .long sys_fstatfs /* 100 */ - .long sys_ioperm + .long sys_ni_syscall /* 101 ioperm in i386 */ .long sys_socketcall .long sys_syslog .long sys_setitimer @@ -300,9 +307,9 @@ .long sys_newlstat .long sys_newfstat .long sys_uname - .long sys_iopl /* 110 */ + .long sys_ni_syscall /* 110 iopl in i386 */ .long sys_vhangup - .long sys_idle + .long sys_ni_syscall /* old idle syscall */ .long sys_ni_syscall /* 113 vm86old in i386 */ .long sys_wait4 .long sys_swapoff /* 115 */ Index: interrupt.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel/interrupt.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- interrupt.c 2001/01/20 22:00:20 1.3 +++ interrupt.c 2001/01/26 00:27:00 1.4 @@ -29,12 +29,10 @@ union scb_and_device_vectors __attribute((__aligned__(VPAGE_SIZE))) scb; -/* These are now part of the irq_cpustat_t structure defined in - * include/asm-vax/hardirq.h, accessor functions in include/linux/irq_cpustat.h - * and variable declaration in linux/kernel/softirq.c - */ -/* unsigned int local_irq_count[NR_CPUS]; */ -/* unsigned int local_bh_count[NR_CPUS]; */ +#if 0 +unsigned int local_irq_count[NR_CPUS]; +unsigned int local_bh_count[NR_CPUS]; +#endif /* Statically-defined pool of irqvector structures. This will go once we have a working kmalloc()/kfree(). @@ -243,9 +241,8 @@ status = dispatch_irq(regs, vec); if (status) { - if ( in_softirq() ) { - /* Not ready for this yet */ - /* do_bottom_half(); */ + if (in_softirq()) { + do_softirq(); } } @@ -260,8 +257,12 @@ /* This is called from irqvec_handler in entry.S. At this point, inside_vec points to the excep_info_size field of the relevant struct irqvector. Locate the actual struct irqvector and dispatch the interrupt or - exception. */ + exception. + "Understanding the Linux Kernel" by Bovet & Cesati from O'Reilly + contains the best explanation I've found for the various exit paths + from this function. */ + void do_irq_excep(struct pt_regs *regs, void *inside_vec, void *excep_info) { struct irqvector *vec; @@ -275,9 +276,41 @@ if (vec->excep_handler != NULL) { do_exception(regs, vec, excep_info); + if (vec == scb.scb.chmk) { + goto ret_from_sys_call; + } else { + goto ret_from_exception; + } } else { do_irq(regs, vec); + goto ret_from_intr; + } + +ret_from_sys_call: + if (in_softirq()) { + do_softirq(); + goto ret_from_intr; + } + goto ret_with_reschedule; + +ret_from_exception: + if (in_softirq()) { + do_softirq(); + } + +ret_from_intr: + if (__psl.prevmode == 0) { + /* returning to kernel mode */ + goto done; + } + +ret_with_reschedule: + if (current->need_resched) { + schedule(); + goto ret_from_sys_call; } + /* Check for signals here */ +done: } /* These two functions, alloc_irqvector() and free_irqvector() are temporary Index: interrupt.h =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel/interrupt.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- interrupt.h 2001/01/20 22:00:20 1.2 +++ interrupt.h 2001/01/26 00:27:00 1.3 @@ -51,18 +51,17 @@ depends on it. */ unsigned short vec_num; /* Offset into SCB (in longwords, not bytes) */ struct irqaction action; /* Linux's normal interrupt vector structure */ - int (*excep_handler)(struct pt_regs *, void *); + void (*excep_handler)(struct pt_regs *, void *); unsigned char *orig_scb_vector; /* Original stray handler from SCB, restored when vector is un-hooked */ } __attribute__ ((__packed__)); /* And declarations of some standard interrupt handlers */ -/* The type for these is declared in asm-vax/irq.h */ extern void accvio_handler(struct pt_regs *regs, void *excep_info); extern void page_fault_handler(struct pt_regs *regs, void *excep_info); extern void reserved_operand_handler(struct pt_regs *regs, void *excep_info); extern void corrected_read_handler(struct pt_regs *regs, void *excep_info); -extern int syscall_handler(struct pt_regs *regs, void *excep_info); +extern void syscall_handler(struct pt_regs *regs, void *excep_info); Index: process.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel/process.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- process.c 2001/01/20 13:51:05 1.2 +++ process.c 2001/01/26 00:27:00 1.3 @@ -1,60 +1,227 @@ +/* + $Id$ + + This file contains the standard functions that the arch-independent + kernel expects for process handling and scheduling + +*/ + +#define __KERNEL_SYSCALLS__ + +#include <linux/smp_lock.h> +#include <linux/fs.h> +#include <linux/malloc.h> + #include <asm/current.h> #include <asm/processor.h> #include <asm/io.h> #include <asm/mtpr.h> +#include <asm/ptrace.h> -/* sys_idle seems to have been lost as a specific syscall. - * and replaced by cpu_idle. I'm renaming this cpu_idle. - */ -asmlinkage int cpu_idle(void) -{ - - - if (current->pid != 0) - return -EPERM; +#include <asm/unistd.h> +void cpu_idle(void) +{ /* endless idle loop with no priority at all */ - init_idle(); - current->nice = 20; - current->counter = -100; + current->nice = 20; + current->counter = -100; - while(1) { + /* Although we are an idle CPU, we do not want to + get into the scheduler unnecessarily. */ if (current->need_resched) { schedule(); check_pgt_cache(); } } - - return 0; } -#if 0 /* Removed KPH 2000-10-03 */ - struct task_struct* vax_switch_to(struct task_struct* prev, struct task_struct* next) { - unsigned long pcbb; /* physical address of pcbb */ + unsigned long pcbb; /* physical address of new pcb */ + struct task_struct *retval; + + printk("vax_switch_to: switching %08lx -> %08lx\n", + (unsigned long)prev, (unsigned long)next); - /* We should check that __pa((prev)->tss.pcb) == PR_PCBB */ - current = (next); - /* get phys address of next process pcb */ - pcbb = virt_to_phys(¤t->tss.pcb); + /* We should check that __pa((prev)->thread.pcb) == PR_PCBB */ + + /* Get phys address of next process pcb */ + pcbb = virt_to_phys(&next->thread.pcb); /* svpctx should deal with writing the stuff into *prev */ - asm( "svpctx\n\t" - "mtpr %0, %1\n\t\n\t" - "ldpctx\n" - : /* nothing */ - : "m" (pcbb), "g" (PR_PCBB) + asm(" movl %1, r11 \n + movpsl -(sp) \n + pushab 1f \n + mtpr %4,%5 \n + svpctx \n + mtpr %2, %3 \n + ldpctx \n + rei \n + 1: \n + movl r11, %0" + : "=g"(retval) + : "g"(prev), + "r"(pcbb), "g"(PR_PCBB), + "g"(31), "g"(PR_IPL) + : "r11" ); - return (prev); + return retval; } -#endif +/* This _must_ match the stack layout in effect at ret_from_syscall + in entry.S. + We do a bit of a hack here. The handler_PC (i.e. the saved PC + value from the JSB in the irqvector structure) normally points + to the excep_info_size member of the irqvector. When we build + the fake stack frame for the new thread, we don't have an + irqvector available. So what we do is pretend we have one longword + of exception info, we put the value 1 into this longword and we + point the handler_PC field at this 'exception info'. */ + +struct new_thread_stack { + struct pt_regs regs; + unsigned long saved_r0; /* will be overwritten by regs->r0 */ + unsigned long *excep_info_size; /* must point to excep_info */ + unsigned long excep_info; /* must contain the value 1 */ + unsigned long saved_pc; /* will be overwritten by regs->pc */ + struct psl_fields saved_psl; +}; + +/* Defined in entry.S */ +extern void ret_from_syscall(void); + +int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, + unsigned long unused, + struct task_struct *p, struct pt_regs *regs) +{ + struct new_thread_stack *child_stack; + struct pt_regs *child_regs; + void *stack_top; + + printk("copy_thread: creating new thread: pid %d, task 0x%08lx, usp 0x%08lx\n", + nr, (unsigned long)p, usp); + + stack_top = ((union task_union *)p) + 1; + + child_stack = (struct new_thread_stack *)(stack_top) - 1; + + child_regs = &child_stack->regs; + + *child_regs = *regs; + child_regs->r0 = 0; /* fork() returns 0 in child */ + + child_stack->excep_info = 1; + child_stack->excep_info_size = &child_stack->excep_info; + child_stack->saved_psl = regs->psl; + + p->thread.pcb.ksp = (unsigned long)child_stack; + p->thread.pcb.usp = usp; + p->thread.pcb.pc = (unsigned long)ret_from_syscall; + p->thread.pcb.psl = __psl; + + /* We could speed this up by loading the register values into + the PCB and start the new thread just before the REI in + entry.S, letting the regular context switching load the + registers from the PCB. However, once signal and bottom-half + handling go into the ret_from_syscall path, then things might + change. So I'll stick with this 'obviously correct' method + for now. KPH 2000-10-30 */ + + return 0; +} + +static ATTRIB_NORET void kernel_thread_exit(int exitcode) +{ + __chmk(__NR_exit); +} +/* + * Create a kernel thread + */ + +pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + asm(" clrl -(sp) \n + movl %0, -(sp) \n + pushl $0x2 \n + movl sp, ap \n + chmk %1 \n + tstl r0 \n + beql child \n + ret \n + child:" + : /* no outputs */ + : "g"(flags|CLONE_VM), + "g"(__NR_clone) + : "r0", "ap" + ); + + /* In child. At this point SP points to the very top of + our kernel stack, so we cannot pop anything off. That + means that we can never return from here. */ +/* printk("kernel_thread: child\n"); */ + kernel_thread_exit(fn(arg)); +} + +int sys_clone(unsigned long clone_flags, unsigned long newsp, struct pt_regs *regs) +{ + int retval; + + if (!newsp) { + newsp = regs->sp; + } + +/* printk("sys_clone: calling do_fork(0x%08lx, 0x%08lx, 0x%p)\n", + clone_flags, newsp, regs); */ + + retval = do_fork(clone_flags, newsp, regs, 0); + +/* printk("sys_clone: do_fork() returned %d\n", retval); */ + + return retval; +} + +int sys_fork(struct pt_regs *regs) +{ + return do_fork(SIGCHLD, regs->sp, regs, 0); +} + +int sys_vfork(struct pt_regs *regs) +{ + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0); +} + +int sys_ptrace(long request, long pid, long addr, long data) +{ + return -ENOSYS; +} + +/* + * sys_execve() executes a new program. + * + */ +int sys_execve(char *filename, char **argv, char **envp, + struct pt_regs *regs) +{ + int error; + char *tmpname; + + tmpname = getname(filename); + error = PTR_ERR(tmpname); + if (IS_ERR(tmpname)) + goto out; + error = do_execve(tmpname, argv, envp, regs); + if (error == 0) { + current->ptrace &= ~PT_DTRACE; + } + putname(tmpname); +out: + return error; +} Index: setup.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel/setup.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- setup.c 2001/01/17 16:13:57 1.1 +++ setup.c 2001/01/26 00:27:00 1.2 @@ -1,5 +1,5 @@ /* - * linux/arch/alpha/kernel/setup.c + * $Id$ * * Copyright (C) 1995 Linus Torvalds * VAX port copyright atp 1998. @@ -17,52 +17,24 @@ #include <linux/ptrace.h> #include <linux/malloc.h> #include <linux/user.h> -#include <linux/a.out.h> #include <linux/tty.h> #include <linux/delay.h> #include <linux/config.h> #include <linux/console.h> -#include <linux/errno.h> #include <linux/init.h> #include <linux/string.h> -#ifdef CONFIG_RTC -#include <linux/timex.h> -#endif -#ifdef CONFIG_BLK_DEV_INITRD -#include <linux/blk.h> -#endif #include <asm/pgtable.h> #include <asm/rpb.h> #define COMMAND_LINE_SIZE 256 -unsigned char aux_device_present = 0xaa; - static char command_line[COMMAND_LINE_SIZE]; char saved_command_line[COMMAND_LINE_SIZE]; -extern struct rpb_struct boot_rpb; - -unsigned long __init -find_end_memory(void) -{ - unsigned int phys_mem; - - /* get the end of physical memory out of RPB - * which has been put there by VMB. The system - * page table which covers this, is setup in boot/head.S */ - phys_mem = boot_rpb.l_pfncnt << PAGE_SHIFT; - - return (unsigned long) __va(phys_mem); -} - void __init -setup_arch(char **cmdline_p, unsigned long * memory_start_p, - unsigned long * memory_end_p) +setup_arch(char **cmdline_p) { - unsigned long mem_start; - /* * Locate the command line. - Don't have one yet... */ @@ -71,20 +43,15 @@ /* Get the SID */ vax_cpu.sid = __mfpr(PR_SID); - - /* - * Indentify and reconfigure for the current system. - */ - /* Find the virtual address of the end of memory. */ - *memory_end_p = find_end_memory(); + /* Set up the initial PCB. We can refer to current because head.S + has already set us up on the kernel stack of task 0. */ + __mtpr(__pa(¤t->thread.pcb), PR_PCBB); - /* For our purposes, available memory starts after the end - of the system page table */ - mem_start = (unsigned long) (pg0 + spt_size); + memset(¤t->thread.pcb, 0, sizeof(current->thread.pcb)); + current->thread.pcb.astlvl = 4; - /* Round memstart up to next page boundary */ - *memory_start_p = (mem_start + (PAGE_SIZE-1)) & PAGE_MASK; + SET_PAGE_DIR(current, swapper_pg_dir); /* No root filesystem yet */ ROOT_DEV = NODEV; Index: syscall.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel/syscall.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- syscall.c 2001/01/17 16:13:57 1.1 +++ syscall.c 2001/01/26 00:27:00 1.2 @@ -7,8 +7,23 @@ #include <linux/sys.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> +#include <linux/mman.h> +#include <linux/file.h> +#include <linux/sem.h> +#include <linux/msg.h> +#include <linux/shm.h> +#include <linux/utsname.h> + #include <asm/uaccess.h> #include <asm/ptrace.h> +#ifdef CONFIG_SYSVIPC +#include <asm/ipc.h> +#endif /* CONFIG_SYSVIPC */ #include "interrupt.h" /* Local, private definitions */ @@ -17,59 +32,214 @@ extern unsigned long *sys_call_table[256]; -int syscall_handler(struct pt_regs *regs, void *excep_info) +void syscall_handler(struct pt_regs *regs, void *excep_info) { unsigned int chmk_arg; - unsigned int *ap; + unsigned int *user_ap; unsigned int nr_args; - register unsigned int retval __asm__("r0"); chmk_arg = *(unsigned int *)(excep_info); if (chmk_arg >= NR_syscalls) { - return -ENOSYS; + regs->r0 = -ENOSYS; + return; } + + user_ap = (unsigned int *)(regs->ap); + + if (regs->psl.prevmode == PSL_MODE_USER) { + + /* syscall came from user mode */ + + if (user_ap >= (unsigned int *)0x80000000) { + regs->r0 = -EFAULT; + return; + } + + /* We don't need to deal with the case where AP + nr_args*4 + reaches up into S0 space because we've got a guard page + at 0x80000000 that will cause an exception in the movc3 + below that copies the argument list */ + + if (get_user(nr_args, user_ap)) { + regs->r0 = -EFAULT; + return; + } + + /* The SP value in the pt_regs structure should really + be the user stack pointer, not the kernel stack pointer */ + regs->sp = __mfpr(PR_USP); - ap = (unsigned int *)(regs->ap); + } else { - if (ap >= (unsigned int *)0x80000000) { - return -EFAULT; + /* syscall came from kernel mode - don't need to do + any access checks */ + + nr_args = *user_ap; } + +/* printk("Dispatching syscall %d with %d args\n", chmk_arg, nr_args); */ - /* We don't need to deal with the case where AP + nr_args*4 - reaches up into S0 space because we've got a guard page - at 0x80000000 that will cause an exception in the movc3 - below that copies the argument list */ - - __get_user_ret(nr_args, ap, -EFAULT); - - __asm__(" subl2 %0,sp \n - 1: movc3 %0,4(ap),(sp) \n - calls %1, %2 \n + /* We pass all the user-supplied args plus the pointer to the + regs to the syscall function. If the syscall is implemented + in the core kernel, then it will ignore the additional + argument. + + SECURITY FLAW: + This is severly broken, though. If the user passes too many + arguments, then the syscall handler will pick up the wrong + regs pointer. + + We may need to have a table that contains the number of args + each syscall expects and check this against the number supplied + by the user. + + We'll sort this out later... - KPH 2000-10-16 */ + + __asm__(" pushl %1 \n + subl2 %2,sp \n + 1: movc3 %2,4(%4),(sp) \n + calls %3, %5 \n brb 3f \n - 2: movl %3, r0 \n - 3: \n + 2: movl %6, r0 \n + 3: movl r0, %0 \n .section ex_table,\"a\" \n .align 2 \n .long 1b, 2b \n .text" - : /* implicit output in r0 (retval) */ - : "g"(nr_args*4), "g"(nr_args), + : "=g"(regs->r0) + : "g"(regs), + "g"(nr_args*4), "g"(nr_args+1), + "r"(user_ap), "g"(*sys_call_table[chmk_arg]), "g"(-EFAULT) : "r0","r1","r2","r3","r4","r5" /* clobbers*/ ); - return retval; +/* printk("syscall %d returned %ld (0x%08lx)\n", chmk_arg, regs->r0, regs->r0); */ + + return; } + /* - * copied from i386 version - cpg + * The syscall handlers from here on down are pretty much copied + * directly from other arches. Don't know whether they'll work or not... */ -asmlinkage int sys_pause(void) +int sys_pause(void) { current->state = TASK_INTERRUPTIBLE; schedule(); return -ERESTARTNOHAND; } +int sys_pipe(unsigned long *fildes) +{ + int fd[2]; + int error; + + lock_kernel(); + error = do_pipe(fd); + unlock_kernel(); + if (!error) { + if (copy_to_user(fildes, fd, 2*sizeof(int))) + error = -EFAULT; + } + return error; +} + +/* + * sys_ipc() is the de-multiplexer for the SysV IPC calls.. + * + * This is really horribly ugly. + */ +int sys_ipc (uint call, int first, int second, + int third, void *ptr, long fifth) +{ +#ifdef CONFIG_SYSVIPC + int ret; + + switch (call) { + case SEMOP: + return sys_semop (first, (struct sembuf *)ptr, second); + case SEMGET: + return sys_semget (first, second, third); + case SEMCTL: { + union semun fourth; + if (!ptr) + return -EINVAL; + if (get_user(fourth.__pad, (void **) ptr)) + return -EFAULT; + return sys_semctl (first, second, third, fourth); + } + case MSGSND: + return sys_msgsnd (first, (struct msgbuf *) ptr, + second, third); + break; + case MSGRCV: + return sys_msgrcv (first, + (struct msgbuf *) ptr, + second, fifth, third); + case MSGGET: + return sys_msgget ((key_t) first, second); + case MSGCTL: + return sys_msgctl (first, second, (struct msqid_ds *) ptr); + + case SHMAT: { + ulong raddr; + ret = sys_shmat (first, (char *) ptr, second, &raddr); + if (ret) + return ret; + return put_user (raddr, (ulong *) third); + break; + } + case SHMDT: + return sys_shmdt ((char *)ptr); + case SHMGET: + return sys_shmget (first, second, third); + case SHMCTL: + return sys_shmctl (first, second, + (struct shmid_ds *) ptr); + default: + return -EINVAL; + + } + + return -EINVAL; +#else /* CONFIG_SYSVIPC */ + return -ENOSYS; +#endif /* CONFIG_SYSVIPC */ +} + +int sys_uname(struct old_utsname * name) +{ + int err; + if (!name) + return -EFAULT; + down(&uts_sem); + err=copy_to_user(name, &system_utsname, sizeof (*name)); + up(&uts_sem); + return err?-EFAULT:0; +} + +unsigned long sys_mmap(unsigned long addr, size_t len, int prot, + int flags, int fd, off_t offset) +{ + struct file * file = NULL; + unsigned long error = -EFAULT; + + lock_kernel(); + if (!(flags & MAP_ANONYMOUS)) { + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + } + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + error = do_mmap(file, addr, len, prot, flags, offset); + if (file) + fput(file); +out: + unlock_kernel(); + return error; +} Index: time.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel/time.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- time.c 2001/01/17 16:13:57 1.1 +++ time.c 2001/01/26 00:27:00 1.2 @@ -1,5 +1,5 @@ /* - * linux/arch/vax/kernel/time.c + * $Id$ * * Copyright (C) 1995 Linus Torvalds * VAX port copyright atp 1998. @@ -17,17 +17,15 @@ #include <linux/kernel.h> #include <linux/sched.h> +#include <linux/init.h> -#include <asm/init.h> #include <asm/irq.h> #include <asm/mtpr.h> -#include <asm/system.h> #include <asm/clock.h> -#include <asm/ptrace.h> static void do_timer_interrupt(int vec_num, void *dev_id, struct pt_regs *regs); -__initfunc(void time_init(void)) +void __init time_init(void) { xtime.tv_usec = 0; xtime.tv_sec = 0; --- delay.c DELETED --- --- softirq.c DELETED --- |