diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-03-17 22:05:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-03-17 22:05:47 +0000 |
commit | 27cfca1ec98e91261b1a5355d10a8996464b63af (patch) | |
tree | 8e895a53e372fa682b4c0a585b9377d67ed70d0e /arch/sparc/kernel | |
parent | 6a76fb7214c477ccf6582bd79c5b4ccc4f9c41b1 (diff) |
Look Ma' what I found on my harddisk ...
o New faster syscalls for 2.1.x, too
o Upgrade to 2.1.89.
Don't try to run this. It's flaky as hell. But feel free to debug ...
Diffstat (limited to 'arch/sparc/kernel')
-rw-r--r-- | arch/sparc/kernel/Makefile | 4 | ||||
-rw-r--r-- | arch/sparc/kernel/entry.S | 60 | ||||
-rw-r--r-- | arch/sparc/kernel/head.S | 15 | ||||
-rw-r--r-- | arch/sparc/kernel/irq.c | 153 | ||||
-rw-r--r-- | arch/sparc/kernel/muldiv.c | 43 | ||||
-rw-r--r-- | arch/sparc/kernel/process.c | 6 | ||||
-rw-r--r-- | arch/sparc/kernel/ptrace.c | 10 | ||||
-rw-r--r-- | arch/sparc/kernel/rtrap.S | 28 | ||||
-rw-r--r-- | arch/sparc/kernel/setup.c | 118 | ||||
-rw-r--r-- | arch/sparc/kernel/signal.c | 329 | ||||
-rw-r--r-- | arch/sparc/kernel/smp.c | 24 | ||||
-rw-r--r-- | arch/sparc/kernel/sparc-stub.c | 41 | ||||
-rw-r--r-- | arch/sparc/kernel/sparc_ksyms.c | 4 | ||||
-rw-r--r-- | arch/sparc/kernel/sun4d_irq.c | 483 | ||||
-rw-r--r-- | arch/sparc/kernel/sun4m_irq.c | 8 | ||||
-rw-r--r-- | arch/sparc/kernel/sunos_ioctl.c | 6 | ||||
-rw-r--r-- | arch/sparc/kernel/sys_sparc.c | 103 | ||||
-rw-r--r-- | arch/sparc/kernel/sys_sunos.c | 110 | ||||
-rw-r--r-- | arch/sparc/kernel/systbls.S | 36 |
19 files changed, 1105 insertions, 476 deletions
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index d3307e463..7be8ddd3a 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.40 1997/05/01 01:40:36 davem Exp $ +# $Id: Makefile,v 1.41 1997/11/19 15:11:59 jj Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also @@ -31,7 +31,7 @@ endif all: kernel.o head.o init_task.o O_TARGET := kernel.o -IRQ_OBJS := irq.o sun4m_irq.o sun4c_irq.o +IRQ_OBJS := irq.o sun4m_irq.o sun4c_irq.o sun4d_irq.o O_OBJS := entry.o wof.o wuf.o etrap.o rtrap.o traps.o ${IRQ_OBJS} \ process.o signal.o ioport.o setup.o idprom.o \ sys_sparc.o sunos_asm.o sparc-stub.o systbls.o sys_sunos.o \ diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 59dd627b2..d82c098d5 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.138 1997/04/15 09:00:50 davem Exp $ +/* $Id: entry.S,v 1.142 1998/01/07 06:33:47 baccala Exp $ * arch/sparc/kernel/entry.S: Sparc trap low-level entry points. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -92,8 +92,8 @@ C_LABEL(trap_low): /* Load new kgdb register set. */ LOAD_KGDB_GLOBALS(sp) LOAD_KGDB_INS(sp) - LOAD_KGDB_SREGS(sp, l0, l2) - wr %l0, 0x0, %y + LOAD_KGDB_SREGS(sp, l4, l0, l3, l5, l1, l2) + wr %l4, 0x0, %y sethi %hi(in_trap_handler), %l4 ld [%lo(in_trap_handler) + %l4], %l5 @@ -108,7 +108,7 @@ C_LABEL(trap_low): STORE_PT_INS(sp) STORE_PT_GLOBALS(sp) STORE_PT_YREG(sp, g2) - STORE_PT_PRIV(sp, l1, l2, l3) + STORE_PT_PRIV(sp, l0, l1, l2) RESTORE_ALL @@ -283,7 +283,7 @@ bad_trap_handler: */ .align 4 - .globl real_irq_entry + .globl real_irq_entry, patch_handler_irq real_irq_entry: SAVE_ALL @@ -299,6 +299,7 @@ real_irq_continue: wr %g2, PSR_ET, %psr WRITE_PAUSE mov %l7, %o0 ! irq level +patch_handler_irq: call C_LABEL(handler_irq) add %sp, REGWIN_SZ, %o1 ! pt_regs ptr wr %l0, PSR_ET, %psr @@ -1109,7 +1110,7 @@ C_LABEL(sys_ptrace): call C_LABEL(do_ptrace) add %sp, REGWIN_SZ, %o0 - ld [%curptr + 0x14], %l5 + ld [%curptr + AOFF_task_flags], %l5 andcc %l5, 0x20, %g0 be 1f nop @@ -1143,7 +1144,7 @@ C_LABEL(sys_sigpause): call C_LABEL(do_sigpause) add %sp, REGWIN_SZ, %o1 - ld [%curptr + 0x14], %l5 + ld [%curptr + AOFF_task_flags], %l5 andcc %l5, 0x20, %g0 be 1f nop @@ -1161,7 +1162,26 @@ C_LABEL(sys_sigsuspend): call C_LABEL(do_sigsuspend) add %sp, REGWIN_SZ, %o0 - ld [%curptr + 0x14], %l5 + ld [%curptr + AOFF_task_flags], %l5 + andcc %l5, 0x20, %g0 + be 1f + nop + + call C_LABEL(syscall_trace) + nop + +1: + /* We are returning to a signal handler. */ + RESTORE_ALL + + .align 4 + .globl C_LABEL(sys_rt_sigsuspend) +C_LABEL(sys_rt_sigsuspend): + /* Note: %o0, %o1 already have correct value... */ + call C_LABEL(do_rt_sigsuspend) + add %sp, REGWIN_SZ, %o2 + + ld [%curptr + AOFF_task_flags], %l5 andcc %l5, 0x20, %g0 be 1f nop @@ -1179,7 +1199,7 @@ C_LABEL(sys_sigreturn): call C_LABEL(do_sigreturn) add %sp, REGWIN_SZ, %o0 - ld [%curptr + 0x14], %l5 + ld [%curptr + AOFF_task_flags], %l5 andcc %l5, 0x20, %g0 be 1f nop @@ -1193,6 +1213,24 @@ C_LABEL(sys_sigreturn): */ RESTORE_ALL + .align 4 + .globl C_LABEL(sys_rt_sigreturn) +C_LABEL(sys_rt_sigreturn): + call C_LABEL(do_rt_sigreturn) + add %sp, REGWIN_SZ, %o0 + + ld [%curptr + AOFF_task_flags], %l5 + andcc %l5, 0x20, %g0 + be 1f + nop + + call C_LABEL(syscall_trace) + nop + +1: + /* We are returning to a signal handler. */ + RESTORE_ALL + /* Now that we have a real sys_clone, sys_fork() is * implemented in terms of it. Our _real_ implementation * of SunOS vfork() will use sys_clone() instead. @@ -1301,7 +1339,7 @@ syscall_is_too_hard: mov %i1, %o1 mov %i2, %o2 - ld [%curptr + 0x14], %l5 + ld [%curptr + AOFF_task_flags], %l5 mov %i3, %o3 andcc %l5, 0x20, %g0 mov %i4, %o4 @@ -1315,7 +1353,7 @@ syscall_is_too_hard: .globl C_LABEL(ret_sys_call) C_LABEL(ret_sys_call): - ld [%curptr + 0x14], %l6 + ld [%curptr + AOFF_task_flags], %l6 cmp %o0, -ENOIOCTLCMD ld [%sp + REGWIN_SZ + PT_PSR], %g3 set PSR_C, %g2 diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S index 5742453ff..2de97e92b 100644 --- a/arch/sparc/kernel/head.S +++ b/arch/sparc/kernel/head.S @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.83 1997/08/28 11:10:39 jj Exp $ +/* $Id: head.S,v 1.84 1997/11/19 15:12:01 jj Exp $ * head.S: The initial boot code for the Sparc port of Linux. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -843,7 +843,7 @@ got_prop: cmp %l1, 'm' ! Test for sun4d, sun4e ? be sun4m_init cmp %l1, 'd' ! Let us see how the beast will die - be sun4m_init + be sun4d_init nop /* Jump into mmu context zero. */ @@ -853,6 +853,17 @@ got_prop: b sun4c_continue_boot nop +sun4d_init: + /* Need to patch call to handler_irq */ + set C_LABEL(patch_handler_irq), %g4 + set C_LABEL(sun4d_handler_irq), %g5 + sethi %hi(0x40000000), %g3 ! call + sub %g5, %g4, %g5 + srl %g5, 2, %g5 + or %g5, %g3, %g5 + st %g5, [%g4] + /* Fall through to sun4m_init */ + sun4m_init: /* XXX Fucking Cypress... */ lda [%g0] ASI_M_MMUREGS, %g5 diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c index b22f008a1..08c0be5c6 100644 --- a/arch/sparc/kernel/irq.c +++ b/arch/sparc/kernel/irq.c @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.75 1997/05/08 20:57:37 davem Exp $ +/* $Id: irq.c,v 1.77 1997/11/19 15:33:05 jj Exp $ * arch/sparc/kernel/irq.c: Interrupt request handling routines. On the * Sparc the IRQ's are basically 'cast in stone' * and you are supposed to probe the prom's device @@ -41,10 +41,6 @@ #include <asm/hardirq.h> #include <asm/softirq.h> -#ifdef __SMP_PROF__ -extern volatile unsigned long smp_local_timer_ticks[1+NR_CPUS]; -#endif - /* * Dave Redman (djhr@tadpole.co.uk) * @@ -101,10 +97,10 @@ void (*set_irq_udt)(int); * */ #define MAX_STATIC_ALLOC 4 -static struct irqaction static_irqaction[MAX_STATIC_ALLOC]; -static int static_irq_count = 0; +struct irqaction static_irqaction[MAX_STATIC_ALLOC]; +int static_irq_count = 0; -static struct irqaction *irq_action[NR_IRQS+1] = { +struct irqaction *irq_action[NR_IRQS+1] = { NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL }; @@ -114,6 +110,11 @@ int get_irq_list(char *buf) int i, len = 0; struct irqaction * action; + if (sparc_cpu_model == sun4d) { + extern int sun4d_get_irq_list(char *); + + return sun4d_get_irq_list(buf); + } for (i = 0 ; i < (NR_IRQS+1) ; i++) { action = *(i + irq_action); if (!action) @@ -132,109 +133,6 @@ int get_irq_list(char *buf) return len; } -#ifdef __SMP_PROF__ - -static unsigned int int_count[NR_CPUS][NR_IRQS] = {{0},}; - -extern unsigned int prof_multiplier[NR_CPUS]; -extern unsigned int prof_counter[NR_CPUS]; - -int get_smp_prof_list(char *buf) { - int i,j, len = 0; - struct irqaction * action; - unsigned long sum_spins = 0; - unsigned long sum_spins_syscall = 0; - unsigned long sum_spins_sys_idle = 0; - unsigned long sum_smp_idle_count = 0; - unsigned long sum_local_timer_ticks = 0; - - for (i=0;i<smp_num_cpus;i++) { - int cpunum = cpu_logical_map[i]; - sum_spins+=smp_spins[cpunum]; - sum_spins_syscall+=smp_spins_syscall[cpunum]; - sum_spins_sys_idle+=smp_spins_sys_idle[cpunum]; - sum_smp_idle_count+=smp_idle_count[cpunum]; - sum_local_timer_ticks+=smp_local_timer_ticks[cpunum]; - } - - len += sprintf(buf+len,"CPUS: %10i \n", smp_num_cpus); - len += sprintf(buf+len," SUM "); - for (i=0;i<smp_num_cpus;i++) - len += sprintf(buf+len," P%1d ",cpu_logical_map[i]); - len += sprintf(buf+len,"\n"); - for (i = 0 ; i < NR_IRQS ; i++) { - action = *(i + irq_action); - if (!action || !action->handler) - continue; - len += sprintf(buf+len, "%3d: %10d ", - i, kstat.interrupts[i]); - for (j=0;j<smp_num_cpus;j++) - len+=sprintf(buf+len, "%10d ", - int_count[cpu_logical_map[j]][i]); - len += sprintf(buf+len, "%c %s", - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - for (action=action->next; action; action = action->next) { - len += sprintf(buf+len, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); - } - len += sprintf(buf+len, "\n"); - } - len+=sprintf(buf+len, "LCK: %10lu", - sum_spins); - - for (i=0;i<smp_num_cpus;i++) - len+=sprintf(buf+len," %10lu",smp_spins[cpu_logical_map[i]]); - - len +=sprintf(buf+len," spins from int\n"); - - len+=sprintf(buf+len, "LCK: %10lu", - sum_spins_syscall); - - for (i=0;i<smp_num_cpus;i++) - len+=sprintf(buf+len," %10lu",smp_spins_syscall[cpu_logical_map[i]]); - - len +=sprintf(buf+len," spins from syscall\n"); - - len+=sprintf(buf+len, "LCK: %10lu", - sum_spins_sys_idle); - - for (i=0;i<smp_num_cpus;i++) - len+=sprintf(buf+len," %10lu",smp_spins_sys_idle[cpu_logical_map[i]]); - - len +=sprintf(buf+len," spins from sysidle\n"); - len+=sprintf(buf+len,"IDLE %10lu",sum_smp_idle_count); - - for (i=0;i<smp_num_cpus;i++) - len+=sprintf(buf+len," %10lu",smp_idle_count[cpu_logical_map[i]]); - - len +=sprintf(buf+len," idle ticks\n"); - - len+=sprintf(buf+len,"TICK %10lu",sum_local_timer_ticks); - for (i=0;i<smp_num_cpus;i++) - len+=sprintf(buf+len," %10lu",smp_local_timer_ticks[cpu_logical_map[i]]); - - len +=sprintf(buf+len," local APIC timer ticks\n"); - - len+=sprintf(buf+len,"MULT: "); - for (i=0;i<smp_num_cpus;i++) - len+=sprintf(buf+len," %10u",prof_multiplier[cpu_logical_map[i]]); - len +=sprintf(buf+len," profiling multiplier\n"); - - len+=sprintf(buf+len,"COUNT: "); - for (i=0;i<smp_num_cpus;i++) - len+=sprintf(buf+len," %10u",prof_counter[cpu_logical_map[i]]); - - len +=sprintf(buf+len," profiling counter\n"); - - len+=sprintf(buf+len, "IPI: %10lu received\n", - ipi_count); - - return len; -} -#endif - void free_irq(unsigned int irq, void *dev_id) { struct irqaction * action; @@ -242,6 +140,11 @@ void free_irq(unsigned int irq, void *dev_id) unsigned long flags; unsigned int cpu_irq; + if (sparc_cpu_model == sun4d) { + extern void sun4d_free_irq(unsigned int, void *); + + return sun4d_free_irq(irq, dev_id); + } cpu_irq = irq & NR_IRQS; action = *(cpu_irq + irq_action); if (cpu_irq > 14) { /* 14 irq levels on the sparc */ @@ -531,29 +434,28 @@ void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs) void handler_irq(int irq, struct pt_regs * regs) { struct irqaction * action; - unsigned int cpu_irq = irq & NR_IRQS; int cpu = smp_processor_id(); #ifdef __SMP__ extern void smp_irq_rotate(int cpu); #endif - disable_pil_irq(cpu_irq); + disable_pil_irq(irq); #ifdef __SMP__ /* Only rotate on lower priority IRQ's (scsi, ethernet, etc.). */ if(irq < 10) smp_irq_rotate(cpu); #endif - irq_enter(cpu, cpu_irq, regs); - action = *(cpu_irq + irq_action); - kstat.interrupts[cpu_irq]++; + irq_enter(cpu, irq, regs); + action = *(irq + irq_action); + kstat.interrupts[irq]++; do { if (!action || !action->handler) unexpected_irq(irq, 0, regs); action->handler(irq, action->dev_id, regs); action = action->next; } while (action); - irq_exit(cpu, cpu_irq); - enable_pil_irq(cpu_irq); + irq_exit(cpu, irq); + enable_pil_irq(irq); } #ifdef CONFIG_BLK_DEV_FD @@ -669,12 +571,22 @@ int request_irq(unsigned int irq, unsigned long flags; unsigned int cpu_irq; + if (sparc_cpu_model == sun4d) { + extern int sun4d_request_irq(unsigned int, + void (*)(int, void *, struct pt_regs *), + unsigned long, const char *, void *); + return sun4d_request_irq(irq, handler, irqflags, devname, dev_id); + } cpu_irq = irq & NR_IRQS; if(cpu_irq > 14) return -EINVAL; if (!handler) return -EINVAL; + + if (irqflags & SA_DCOOKIE) + dev_id = ((struct devid_cookie *)dev_id)->real_dev_id; + action = *(cpu_irq + irq_action); if (action) { if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) { @@ -751,6 +663,7 @@ __initfunc(void init_IRQ(void)) { extern void sun4c_init_IRQ( void ); extern void sun4m_init_IRQ( void ); + extern void sun4d_init_IRQ( void ); switch(sparc_cpu_model) { case sun4c: @@ -760,6 +673,10 @@ __initfunc(void init_IRQ(void)) case sun4m: sun4m_init_IRQ(); break; + + case sun4d: + sun4d_init_IRQ(); + break; case ap1000: #if CONFIG_AP1000 diff --git a/arch/sparc/kernel/muldiv.c b/arch/sparc/kernel/muldiv.c index 6a193200b..b2cc64bb0 100644 --- a/arch/sparc/kernel/muldiv.c +++ b/arch/sparc/kernel/muldiv.c @@ -1,4 +1,4 @@ -/* $Id: muldiv.c,v 1.4 1997/04/11 00:42:08 davem Exp $ +/* $Id: muldiv.c,v 1.5 1997/12/15 20:07:20 ecd Exp $ * muldiv.c: Hardware multiply/division illegal instruction trap * for sun4c/sun4 (which do not have those instructions) * @@ -69,18 +69,23 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2, ret; \ }) -static inline unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs) +static inline int +store_reg(unsigned int result, unsigned int reg, struct pt_regs *regs) { struct reg_window *win; - if(!reg) - return NULL; - else if(reg < 16) - return ®s->u_regs[reg]; - win = (struct reg_window *) regs->u_regs[UREG_FP]; - return &win->locals[reg - 16]; + if (!reg) + return 0; + if (reg < 16) { + regs->u_regs[reg] = result; + return 0; + } else { + /* need to use put_user() in this case: */ + win = (struct reg_window *)regs->u_regs[UREG_FP]; + return (put_user(result, &win->locals[reg - 16])); + } } - + extern void handle_hw_divzero (struct pt_regs *regs, unsigned long pc, unsigned long npc, unsigned long psr); @@ -90,7 +95,6 @@ int do_user_muldiv(struct pt_regs *regs, unsigned long pc) unsigned int insn; int inst; unsigned int rs1, rs2, rdv; - unsigned long *rd; if (!pc) return -1; /* This happens to often, I think */ if (get_user (insn, (unsigned int *)pc)) return -1; @@ -109,7 +113,6 @@ int do_user_muldiv(struct pt_regs *regs, unsigned long pc) rs2 = fetch_reg(rs2, regs); } rs1 = fetch_reg(rs1, regs); - rd = fetch_reg_addr(rdv, regs); switch (inst) { case 10: /* umul */ #ifdef DEBUG_MULDIV @@ -127,9 +130,8 @@ int do_user_muldiv(struct pt_regs *regs, unsigned long pc) #ifdef DEBUG_MULDIV printk ("0x%x%08x\n", rs2, rs1); #endif - if (rd) { - if (put_user (rs1, rd)) return -1; - } + if (store_reg(rs1, rdv, regs)) + return -1; regs->y = rs2; break; case 11: /* smul */ @@ -148,9 +150,8 @@ int do_user_muldiv(struct pt_regs *regs, unsigned long pc) #ifdef DEBUG_MULDIV printk ("0x%x%08x\n", rs2, rs1); #endif - if (rd) { - if (put_user (rs1, rd)) return -1; - } + if (store_reg(rs1, rdv, regs)) + return -1; regs->y = rs2; break; case 14: /* udiv */ @@ -179,8 +180,8 @@ int do_user_muldiv(struct pt_regs *regs, unsigned long pc) #ifdef DEBUG_MULDIV printk ("0x%x\n", rs1); #endif - if (rd) - if (put_user (rs1, rd)) return -1; + if (store_reg(rs1, rdv, regs)) + return -1; break; case 15: /* sdiv */ #ifdef DEBUG_MULDIV @@ -208,8 +209,8 @@ int do_user_muldiv(struct pt_regs *regs, unsigned long pc) #ifdef DEBUG_MULDIV printk ("0x%x\n", rs1); #endif - if (rd) - if (put_user (rs1, rd)) return -1; + if (store_reg(rs1, rdv, regs)) + return -1; break; } if (is_foocc (insn)) { diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index ff4a3f192..32feff3de 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.100 1997/08/10 04:49:23 davem Exp $ +/* $Id: process.c,v 1.102 1997/12/01 03:36:31 davem Exp $ * linux/arch/sparc/kernel/process.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -120,7 +120,7 @@ int cpu_idle(void *unused) } /* endless idle loop with no priority at all */ current->counter = -100; - if(!smp_commenced || resched_needed()) + if(!smp_commenced || need_resched) schedule(); } } @@ -197,7 +197,9 @@ void show_regwindow(struct reg_window *rw) rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]); } +#ifdef __SMP__ static spinlock_t sparc_backtrace_lock = SPIN_LOCK_UNLOCKED; +#endif void show_backtrace(void) { diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c index 933a5acfa..635623fb3 100644 --- a/arch/sparc/kernel/ptrace.c +++ b/arch/sparc/kernel/ptrace.c @@ -799,7 +799,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) addr = 1; case PTRACE_CONT: { /* restart after signal. */ - if ((unsigned long) data > NSIG) { + if ((unsigned long) data > _NSIG) { pt_error_return(regs, EIO); goto out; } @@ -851,7 +851,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) } case PTRACE_SUNDETACH: { /* detach a process that was attached. */ - if ((unsigned long) data > NSIG) { + if ((unsigned long) data > _NSIG) { pt_error_return(regs, EIO); goto out; } @@ -898,9 +898,7 @@ asmlinkage void syscall_trace(void) current->pid, current->exit_code); #endif if (current->exit_code) { - spin_lock_irq(¤t->sigmask_lock); - current->signal |= (1 << (current->exit_code - 1)); - spin_unlock_irq(¤t->sigmask_lock); + send_sig (current->exit_code, current, 1); + current->exit_code = 0; } - current->exit_code = 0; } diff --git a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap.S index 8d46d487e..68f3dc9af 100644 --- a/arch/sparc/kernel/rtrap.S +++ b/arch/sparc/kernel/rtrap.S @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.47 1997/08/10 04:49:24 davem Exp $ +/* $Id: rtrap.S,v 1.49 1997/12/14 23:24:24 ecd Exp $ * rtrap.S: Return from Sparc trap low-level code. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -65,27 +65,24 @@ C_LABEL(ret_trap_lockless_ipi): wr %t_psr, 0x0, %psr b ret_trap_kernel - mov 1, %o0 + nop 1: - ld [%curptr + AOFF_task_processor], %o1 ld [%twin_tmp1 + %lo(C_LABEL(need_resched))], %g2 - sll %o0, %o1, %o0 - - andcc %g2, %o0, %g0 + orcc %g2, %g0, %g0 be signal_p - nop + ld [%curptr + AOFF_task_sigpending], %g2 call C_LABEL(schedule) nop + ld [%curptr + AOFF_task_sigpending], %g2 signal_p: - ld [%curptr + AOFF_task_signal], %g2 - ld [%curptr + AOFF_task_blocked], %o0 - andncc %g2, %o0, %g0 - be,a ret_trap_continue + cmp %g2, 0 + bz,a ret_trap_continue ld [%sp + REGWIN_SZ + PT_PSR], %t_psr + clr %o0 mov %l5, %o2 mov %l6, %o3 call C_LABEL(do_signal) @@ -110,7 +107,8 @@ ret_trap_continue: call C_LABEL(try_to_clear_window_buffer) add %sp, REGWIN_SZ, %o0 - b,a signal_p + b signal_p + ld [%curptr + AOFF_task_sigpending], %g2 ret_trap_nobufwins: /* Load up the user's out registers so we can pull @@ -179,7 +177,8 @@ ret_trap_unaligned_pc: call C_LABEL(do_memaccess_unaligned) nop - b,a signal_p + b signal_p + ld [%curptr + AOFF_task_sigpending], %g2 ret_trap_kernel: /* Will the rett land us in the invalid window? */ @@ -228,7 +227,8 @@ ret_trap_user_stack_is_bolixed: call C_LABEL(window_ret_fault) add %sp, REGWIN_SZ, %o0 - b,a signal_p + b signal_p + ld [%curptr + AOFF_task_sigpending], %g2 .globl C_LABEL(sun4c_rett_stackchk) C_LABEL(sun4c_rett_stackchk): diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index a6b3f9e07..e53c343da 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.85 1997/05/27 06:45:54 davem Exp $ +/* $Id: setup.c,v 1.87 1997/12/18 02:42:42 ecd Exp $ * linux/arch/sparc/kernel/setup.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -25,6 +25,7 @@ #include <linux/blk.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/console.h> #include <asm/segment.h> #include <asm/system.h> @@ -118,7 +119,9 @@ extern void rs_kgdb_hook(int tty_num); /* sparc/serial.c */ unsigned int boot_flags; #define BOOTME_DEBUG 0x1 #define BOOTME_SINGLE 0x2 -#define BOOTME_KGDB 0x4 +#define BOOTME_KGDBA 0x4 +#define BOOTME_KGDBB 0x8 +#define BOOTME_KGDB 0xc #ifdef CONFIG_SUN_CONSOLE extern char *console_fb_path; @@ -188,15 +191,14 @@ __initfunc(static void boot_flags_init(char *commands)) process_switch(*commands++); } else if (strlen(commands) >= 9 && !strncmp(commands, "kgdb=tty", 8)) { - boot_flags |= BOOTME_KGDB; switch (commands[8]) { #ifdef CONFIG_SUN_SERIAL case 'a': - rs_kgdb_hook(0); + boot_flags |= BOOTME_KGDBA; prom_printf("KGDB: Using serial line /dev/ttya.\n"); break; case 'b': - rs_kgdb_hook(1); + boot_flags |= BOOTME_KGDBB; prom_printf("KGDB: Using serial line /dev/ttyb.\n"); break; #endif @@ -207,7 +209,6 @@ __initfunc(static void boot_flags_init(char *commands)) #endif default: printk("KGDB: Unknown tty line.\n"); - boot_flags &= ~BOOTME_KGDB; break; } commands += 9; @@ -273,8 +274,6 @@ extern unsigned ramdisk_size; extern int root_mountflags; -extern void register_console(void (*proc)(const char *)); - char saved_command_line[256]; char reboot_command[256]; enum sparc_cpu sparc_cpu_model; @@ -283,6 +282,16 @@ struct tt_entry *sparc_ttable; static struct pt_regs fake_swapper_regs = { 0, 0, 0, 0, { 0, } }; +static void prom_cons_write(struct console *con, const char *str, unsigned count) +{ + while (count--) + prom_printf("%c", *str++); +} + +static struct console prom_console = { + "PROM", prom_cons_write, 0, 0, 0, 0, 0, CON_PRINTBUFFER, 0, 0, 0 +}; + __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)) { @@ -335,7 +344,7 @@ __initfunc(void setup_arch(char **cmdline_p, printk("SUN4U\n"); break; case ap1000: - register_console((void (*) (const char *))prom_printf); + register_console(&prom_console); printk("AP1000\n"); packed = 1; break; @@ -345,16 +354,6 @@ __initfunc(void setup_arch(char **cmdline_p, }; boot_flags_init(*cmdline_p); - if((boot_flags&BOOTME_DEBUG) && (linux_dbvec!=0) && - ((*(short *)linux_dbvec) != -1)) { - printk("Booted under KADB. Syncing trap table.\n"); - (*(linux_dbvec->teach_debugger))(); - } - if((boot_flags & BOOTME_KGDB)) { - set_debug_traps(); - prom_printf ("Breakpoint!\n"); - breakpoint(); - } idprom_init(); load_mmu(); @@ -410,6 +409,56 @@ __initfunc(void setup_arch(char **cmdline_p, } not_relevant: +#ifdef CONFIG_SUN_SERIAL + *memory_start_p = sun_serial_setup(*memory_start_p); /* set this up ASAP */ +#endif + { + extern int serial_console; /* in console.c, of course */ +#if !CONFIG_SUN_SERIAL + serial_console = 0; +#else + switch (console_fb) { + case 0: /* Let get our io devices from prom */ + { + int idev = prom_query_input_device(); + int odev = prom_query_output_device(); + if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) { + serial_console = 0; + } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) { + serial_console = 1; + } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) { + serial_console = 2; + } else { + prom_printf("Inconsistent console\n"); + prom_halt(); + } + } + break; + case 1: serial_console = 0; break; /* Force one of the framebuffers as console */ + case 2: serial_console = 1; break; /* Force ttya as console */ + case 3: serial_console = 2; break; /* Force ttyb as console */ + } +#endif + } + + if ((boot_flags & BOOTME_KGDBA)) { + rs_kgdb_hook(0); + } + if ((boot_flags & BOOTME_KGDBB)) { + rs_kgdb_hook(1); + } + + if((boot_flags&BOOTME_DEBUG) && (linux_dbvec!=0) && + ((*(short *)linux_dbvec) != -1)) { + printk("Booted under KADB. Syncing trap table.\n"); + (*(linux_dbvec->teach_debugger))(); + } + if((boot_flags & BOOTME_KGDB)) { + set_debug_traps(); + prom_printf ("Breakpoint!\n"); + breakpoint(); + } + if (!root_flags) root_mountflags &= ~MS_RDONLY; ROOT_DEV = to_kdev_t(root_dev); @@ -443,37 +492,6 @@ not_relevant: init_task.mm->context = (unsigned long) NO_CONTEXT; init_task.tss.kregs = &fake_swapper_regs; -#ifdef CONFIG_SUN_SERIAL - *memory_start_p = sun_serial_setup(*memory_start_p); /* set this up ASAP */ -#endif - { - extern int serial_console; /* in console.c, of course */ -#if !CONFIG_SUN_SERIAL - serial_console = 0; -#else - switch (console_fb) { - case 0: /* Let get our io devices from prom */ - { - int idev = prom_query_input_device(); - int odev = prom_query_output_device(); - if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) { - serial_console = 0; - } else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) { - serial_console = 1; - } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) { - serial_console = 2; - } else { - prom_printf("Inconsistent console\n"); - prom_halt(); - } - } - break; - case 1: serial_console = 0; break; /* Force one of the framebuffers as console */ - case 2: serial_console = 1; break; /* Force ttya as console */ - case 3: serial_console = 2; break; /* Force ttyb as console */ - } -#endif - } } asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on) diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index fbb5578fa..5c10faa81 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.75 1997/08/05 19:19:26 davem Exp $ +/* $Id: signal.c,v 1.77 1997/12/22 03:06:32 ecd Exp $ * linux/arch/sparc/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -24,9 +24,7 @@ #include <asm/svr4.h> #include <asm/pgtable.h> -#define _S(nr) (1<<((nr)-1)) - -#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, int options, unsigned long *ru); @@ -35,7 +33,7 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr, void *fpqueue, unsigned long *fpqdepth); extern void fpload(unsigned long *fpregs, unsigned long *fsr); -asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs, +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, unsigned long orig_o0, int ret_from_syscall); /* This turned off for production... */ @@ -56,12 +54,13 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs, * ---------------------------------- <-- New %sp */ struct signal_sframe { - struct reg_window sig_window; - int sig_num; - int sig_code; - struct sigcontext *sig_scptr; - int sig_address; - struct sigcontext sig_context; + struct reg_window sig_window; + int sig_num; + int sig_code; + struct sigcontext *sig_scptr; + int sig_address; + struct sigcontext sig_context; + unsigned int extramask[_NSIG_WORDS - 1]; }; /* @@ -75,6 +74,7 @@ struct new_signal_frame { __siginfo_t info; __siginfo_fpu_t *fpu_save; unsigned long insns [2] __attribute__ ((aligned (8))); + unsigned int extramask[_NSIG_WORDS - 1]; __siginfo_fpu_t fpu_state; }; @@ -86,13 +86,15 @@ struct new_signal_frame { * atomically swap in the new signal mask, and wait for a signal. * This is really tricky on the Sparc, watch out... */ -asmlinkage void _sigpause_common(unsigned int set, struct pt_regs *regs) +asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs) { - unsigned long mask; + sigset_t saveset; + set &= _BLOCKABLE; spin_lock_irq(¤t->sigmask_lock); - mask = current->blocked; - current->blocked = set & _BLOCKABLE; + saveset = current->blocked; + siginitset(¤t->blocked, set); + recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); regs->pc = regs->npc; @@ -112,7 +114,7 @@ asmlinkage void _sigpause_common(unsigned int set, struct pt_regs *regs) */ regs->psr |= PSR_C; regs->u_regs[UREG_I0] = EINTR; - if (do_signal(mask, regs, 0, 0)) + if (do_signal(&saveset, regs, 0, 0)) return; } } @@ -127,6 +129,52 @@ asmlinkage void do_sigsuspend (struct pt_regs *regs) _sigpause_common(regs->u_regs[UREG_I0], regs); } +asmlinkage void do_rt_sigsuspend(sigset_t *uset, size_t sigsetsize, + struct pt_regs *regs) +{ + sigset_t oldset, set; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) { + regs->psr |= PSR_C; + regs->u_regs[UREG_I0] = EINVAL; + return; + } + + if (copy_from_user(&set, uset, sizeof(set))) { + regs->psr |= PSR_C; + regs->u_regs[UREG_I0] = EFAULT; + return; + } + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + oldset = current->blocked; + current->blocked = set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + regs->pc = regs->npc; + regs->npc += 4; + + /* Condition codes and return value where set here for sigpause, + * and so got used by setup_frame, which again causes sigreturn() + * to return -EINTR. + */ + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + /* + * Return -EINTR and set condition code here, + * so the interrupted system call actually returns + * these. + */ + regs->psr |= PSR_C; + regs->u_regs[UREG_I0] = EINTR; + if (do_signal(&oldset, regs, 0, 0)) + return; + } +} static inline void restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu) @@ -154,11 +202,12 @@ restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu) (sizeof(unsigned long *)))*16)); } -void do_new_sigreturn (struct pt_regs *regs) +static inline void do_new_sigreturn (struct pt_regs *regs) { struct new_signal_frame *sf; - unsigned long up_psr, pc, npc, mask; - + unsigned long up_psr, pc, npc; + sigset_t set; + sf = (struct new_signal_frame *) regs->u_regs [UREG_FP]; /* 1. Make sure we are not getting garbage from the user */ @@ -173,7 +222,7 @@ void do_new_sigreturn (struct pt_regs *regs) if ((pc | npc) & 3) goto segv_and_exit; - + /* 2. Restore the state */ up_psr = regs->psr; copy_from_user(regs, &sf->info.si_regs, sizeof (struct pt_regs)); @@ -181,28 +230,36 @@ void do_new_sigreturn (struct pt_regs *regs) /* User can only change condition codes and FPU enabling in %psr. */ regs->psr = (up_psr & ~(PSR_ICC | PSR_EF)) | (regs->psr & (PSR_ICC | PSR_EF)); - + if (sf->fpu_save) restore_fpu_state(regs, sf->fpu_save); /* This is pretty much atomic, no amount locking would prevent * the races which exist anyways. */ - __get_user(mask, &sf->info.si_mask); - current->blocked = (mask & _BLOCKABLE); + if (__get_user(set.sig[0], &sf->info.si_mask) || + copy_from_user(&set.sig[1], &sf->extramask, + (_NSIG_WORDS-1) * sizeof(unsigned int))) + goto segv_and_exit; + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); return; segv_and_exit: /* Ugh, we need to grab master lock in these rare cases ;-( */ lock_kernel(); do_exit(SIGSEGV); - unlock_kernel(); } asmlinkage void do_sigreturn(struct pt_regs *regs) { struct sigcontext *scptr; - unsigned long pc, npc, psr, mask; + unsigned long pc, npc, psr; + sigset_t set; synchronize_user_stack(); @@ -225,8 +282,17 @@ asmlinkage void do_sigreturn(struct pt_regs *regs) /* This is pretty much atomic, no amount locking would prevent * the races which exist anyways. */ - __get_user(mask, &scptr->sigc_mask); - current->blocked = (mask & _BLOCKABLE); + if (__get_user(set.sig[0], &scptr->sigc_mask) || + /* Note that scptr + 1 points to extramask */ + copy_from_user(&set.sig[1], scptr + 1, + (_NSIG_WORDS - 1) * sizeof(unsigned int))) + goto segv_and_exit; + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); __get_user(current->tss.sstk_info.cur_status, &scptr->sigc_onstack); current->tss.sstk_info.cur_status &= 1; @@ -248,11 +314,15 @@ segv_and_exit: /* Ugh, we need to grab master lock in these rare cases ;-( */ lock_kernel(); do_exit(SIGSEGV); - unlock_kernel(); +} + +asmlinkage void do_rt_sigreturn(struct pt_regs *regs) +{ + printk("XXX: FIXME: write do_rt_sigreturn\n"); } /* Checks if the fp is valid */ -int invalid_frame_pointer (void *fp, int fplen) +static inline int invalid_frame_pointer (void *fp, int fplen) { if ((((unsigned long) fp) & 7) || !__access_ok((unsigned long)fp, fplen) || @@ -263,8 +333,9 @@ int invalid_frame_pointer (void *fp, int fplen) return 0; } -static void setup_frame(struct sigaction *sa, unsigned long pc, unsigned long npc, - struct pt_regs *regs, int signr, unsigned long oldmask) +static inline void +setup_frame(struct sigaction *sa, unsigned long pc, unsigned long npc, + struct pt_regs *regs, int signr, sigset_t *oldset) { struct signal_sframe *sframep; struct sigcontext *sc; @@ -291,7 +362,9 @@ static void setup_frame(struct sigaction *sa, unsigned long pc, unsigned long np /* We've already made sure frame pointer isn't in kernel space... */ __put_user(old_status, &sc->sigc_onstack); - __put_user(oldmask, &sc->sigc_mask); + __put_user(oldset->sig[0], &sc->sigc_mask); + __copy_to_user(sframep->extramask, &oldset->sig[1], + (_NSIG_WORDS - 1) * sizeof(unsigned int)); __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp); __put_user(pc, &sc->sigc_pc); __put_user(npc, &sc->sigc_npc); @@ -334,7 +407,6 @@ sigill_and_return: /* Ugh, we need to grab master lock in these rare cases ;-( */ lock_kernel(); do_exit(SIGILL); - unlock_kernel(); } @@ -369,8 +441,9 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu) current->used_math = 0; } -static void new_setup_frame(struct sigaction *sa, struct pt_regs *regs, - int signo, unsigned long oldmask) +static inline void +new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs, + int signo, sigset_t *oldset) { struct new_signal_frame *sf; int sigframe_size; @@ -403,39 +476,51 @@ static void new_setup_frame(struct sigaction *sa, struct pt_regs *regs, sf->fpu_save = NULL; } - __put_user(oldmask, &sf->info.si_mask); + __put_user(oldset->sig[0], &sf->info.si_mask); + __copy_to_user(sf->extramask, &oldset->sig[1], + (_NSIG_WORDS - 1) * sizeof(unsigned int)); copy_to_user(sf, (char *) regs->u_regs [UREG_FP], sizeof (struct reg_window)); - /* 3. return to kernel instructions */ - __put_user(0x821020d8, &sf->insns [0]); /* mov __NR_sigreturn, %g1 */ - __put_user(0x91d02010, &sf->insns [1]); /* t 0x10 */ - - /* 4. signal handler back-trampoline and parameters */ + /* 3. signal handler back-trampoline and parameters */ regs->u_regs[UREG_FP] = (unsigned long) sf; regs->u_regs[UREG_I0] = signo; regs->u_regs[UREG_I1] = (unsigned long) &sf->info; - regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); - /* 5. signal handler */ - regs->pc = (unsigned long) sa->sa_handler; + /* 4. signal handler */ + regs->pc = (unsigned long) ka->sa.sa_handler; regs->npc = (regs->pc + 4); - /* Flush instruction space. */ - flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); + /* 5. return to kernel instructions */ + if (ka->ka_restorer) + regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; + else { + regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2); + + __put_user(0x821020d8, &sf->insns[0]); /* mov __NR_sigreturn, %g1 */ + __put_user(0x91d02010, &sf->insns[1]); /* t 0x10 */ + + /* Flush instruction space. */ + flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); + } return; sigill_and_return: lock_kernel(); do_exit(SIGILL); - unlock_kernel(); } +static inline void +new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, + int signo, sigset_t *oldset, siginfo_t *info) +{ + printk("XXX: FIXME: new_setup_rt_frame unimplemented\n"); +} /* Setup a Solaris stack frame */ static inline void setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc, - struct pt_regs *regs, int signr, unsigned long oldmask) + struct pt_regs *regs, int signr, sigset_t *oldset) { svr4_signal_frame_t *sfp; svr4_gregset_t *gr; @@ -443,6 +528,7 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc, svr4_mcontext_t *mc; svr4_gwindows_t *gw; svr4_ucontext_t *uc; + svr4_sigset_t setv; int window = 0; synchronize_user_stack(); @@ -470,7 +556,14 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc, * sc->sigc_onstack = old_status; * anyways, it does not look like it is used for anything at all. */ - __put_user(oldmask, &uc->sigmask.sigbits [0]); + setv.sigbits[0] = oldset->sig[0]; + setv.sigbits[1] = oldset->sig[1]; + if (_NSIG_WORDS >= 4) { + setv.sigbits[2] = oldset->sig[2]; + setv.sigbits[3] = oldset->sig[3]; + __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); + } else + __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned int)); /* Store registers */ __put_user(regs->pc, &((*gr) [SVR4_PC])); @@ -547,13 +640,13 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc, sigill_and_return: lock_kernel(); do_exit(SIGILL); - unlock_kernel(); } asmlinkage int svr4_getcontext (svr4_ucontext_t *uc, struct pt_regs *regs) { svr4_gregset_t *gr; svr4_mcontext_t *mc; + svr4_sigset_t setv; synchronize_user_stack(); @@ -566,9 +659,15 @@ asmlinkage int svr4_getcontext (svr4_ucontext_t *uc, struct pt_regs *regs) /* Setup convenience variables */ mc = &uc->mcontext; gr = &mc->greg; - - /* We only have < 32 signals, fill the first slot only */ - __put_user(current->blocked, &uc->sigmask.sigbits [0]); + + setv.sigbits[0] = current->blocked.sig[0]; + setv.sigbits[1] = current->blocked.sig[1]; + if (_NSIG_WORDS >= 4) { + setv.sigbits[2] = current->blocked.sig[2]; + setv.sigbits[3] = current->blocked.sig[3]; + __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); + } else + __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned int)); /* Store registers */ __put_user(regs->pc, &uc->mcontext.greg [SVR4_PC]); @@ -593,8 +692,6 @@ asmlinkage int svr4_getcontext (svr4_ucontext_t *uc, struct pt_regs *regs) sigsegv_and_return: lock_kernel(); do_exit(SIGSEGV); - unlock_kernel(); - return -EFAULT; } /* Set the context for a svr4 application, this is Solaris way to sigreturn */ @@ -602,7 +699,9 @@ asmlinkage int svr4_setcontext (svr4_ucontext_t *c, struct pt_regs *regs) { struct thread_struct *tp = ¤t->tss; svr4_gregset_t *gr; - unsigned long pc, npc, psr, mask; + unsigned long pc, npc, psr; + sigset_t set; + svr4_sigset_t setv; /* Fixme: restore windows, or is this already taken care of in * svr4_setup_frame when sync_user_windows is done? @@ -633,8 +732,19 @@ asmlinkage int svr4_setcontext (svr4_ucontext_t *c, struct pt_regs *regs) /* This is pretty much atomic, no amount locking would prevent * the races which exist anyways. */ - __get_user(mask, &c->sigmask.sigbits [0]); - current->blocked = (mask & _BLOCKABLE); + if (__copy_from_user(&setv, &c->sigmask, sizeof(svr4_sigset_t))) + goto sigsegv_and_return; + set.sig[0] = setv.sigbits[0]; + set.sig[1] = setv.sigbits[1]; + if (_NSIG_WORDS >= 4) { + set.sig[2] = setv.sigbits[2]; + set.sig[3] = setv.sigbits[3]; + } + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); regs->pc = pc; regs->npc = npc | 1; __get_user(regs->y, &((*gr) [SVR4_Y])); @@ -650,27 +760,29 @@ asmlinkage int svr4_setcontext (svr4_ucontext_t *c, struct pt_regs *regs) sigsegv_and_return: lock_kernel(); do_exit(SIGSEGV); - unlock_kernel(); - return -EFAULT; } -static inline void handle_signal(unsigned long signr, struct sigaction *sa, - unsigned long oldmask, struct pt_regs *regs, - int svr4_signal) +static inline void +handle_signal(unsigned long signr, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs *regs, + int svr4_signal) { - if(svr4_signal) - setup_svr4_frame(sa, regs->pc, regs->npc, regs, signr, oldmask); + if (svr4_signal) + setup_svr4_frame(&ka->sa, regs->pc, regs->npc, regs, signr, oldset); else { - if (current->tss.new_signal) - new_setup_frame (sa, regs, signr, oldmask); + if (ka->sa.sa_flags & SA_SIGINFO) + new_setup_rt_frame(ka, regs, signr, oldset, info); + else if (current->tss.new_signal) + new_setup_frame (ka, regs, signr, oldset); else - setup_frame(sa, regs->pc, regs->npc, regs, signr, oldmask); + setup_frame(&ka->sa, regs->pc, regs->npc, regs, signr, oldset); } - if(sa->sa_flags & SA_ONESHOT) - sa->sa_handler = NULL; - if(!(sa->sa_flags & SA_NOMASK)) { + if(ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + if(!(ka->sa.sa_flags & SA_NOMASK)) { spin_lock_irq(¤t->sigmask_lock); - current->blocked |= (sa->sa_mask | _S(signr)) & _BLOCKABLE; + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked, signr); spin_unlock_irq(¤t->sigmask_lock); } } @@ -699,22 +811,25 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs, +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, unsigned long orig_i0, int restart_syscall) { - unsigned long signr, mask = ~current->blocked; - struct sigaction *sa; + unsigned long signr; + struct k_sigaction *ka; + siginfo_t info; + int svr4_signal = current->personality == PER_SVR4; - - while ((signr = current->signal & mask) != 0) { - signr = ffz(~signr); + if (!oldset) + oldset = ¤t->blocked; + + for (;;) { spin_lock_irq(¤t->sigmask_lock); - current->signal &= ~(1 << signr); + signr = dequeue_signal(¤t->blocked, &info); spin_unlock_irq(¤t->sigmask_lock); - sa = current->sig->action + signr; - signr++; + if (!signr) break; + if ((current->flags & PF_PTRACED) && signr != SIGKILL) { current->exit_code = signr; current->state = TASK_STOPPED; @@ -729,15 +844,26 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs, current->exit_code = 0; if (signr == SIGSTOP) continue; - if (_S(signr) & current->blocked) { - spin_lock_irq(¤t->sigmask_lock); - current->signal |= _S(signr); - spin_unlock_irq(¤t->sigmask_lock); + + /* Update the siginfo structure. Is this good? */ + if (signr != info.si_signo) { + info.si_signo = signr; + info.si_errno = 0; + info.si_code = SI_USER; + info.si_pid = current->p_pptr->pid; + info.si_uid = current->p_pptr->uid; + } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(¤t->blocked, signr)) { + send_sig_info(signr, &info, current); continue; } - sa = current->sig->action + signr - 1; } - if(sa->sa_handler == SIG_IGN) { + + ka = ¤t->sig->action[signr-1]; + + if(ka->sa.sa_handler == SIG_IGN) { if(signr != SIGCHLD) continue; @@ -750,7 +876,9 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs, ; continue; } - if(sa->sa_handler == SIG_DFL) { + if(ka->sa.sa_handler == SIG_DFL) { + unsigned long exit_code = signr; + if(current->pid == 1) continue; switch(signr) { @@ -758,8 +886,9 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs, continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: - /* The operations performed by is_orphaned_pgrp() - * are protected by the tasklist_lock. + /* The operations performed by + * is_orphaned_pgrp() are protected by + * the tasklist_lock. */ if (is_orphaned_pgrp(current->pgrp)) continue; @@ -771,7 +900,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs, current->exit_code = signr; /* notify_parent() is SMP safe */ - if(!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & + if(!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); @@ -782,7 +911,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs, if(current->binfmt && current->binfmt->core_dump) { lock_kernel(); if(current->binfmt->core_dump(signr, regs)) - signr |= 0x80; + exit_code |= 0x80; unlock_kernel(); } #ifdef DEBUG_SIGNALS @@ -792,20 +921,16 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs, #endif /* fall through */ default: - spin_lock_irq(¤t->sigmask_lock); - current->signal |= _S(signr & 0x7f); - spin_unlock_irq(¤t->sigmask_lock); - + lock_kernel(); + sigaddset(¤t->signal, signr); current->flags |= PF_SIGNALED; - - lock_kernel(); /* 8-( */ - do_exit(signr); - unlock_kernel(); + do_exit(exit_code); + /* NOT REACHED */ } } if(restart_syscall) - syscall_restart(orig_i0, regs, sa); - handle_signal(signr, sa, oldmask, regs, svr4_signal); + syscall_restart(orig_i0, regs, &ka->sa); + handle_signal(signr, ka, &info, oldset, regs, svr4_signal); return 1; } if(restart_syscall && diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c index 17931fd55..15364d44f 100644 --- a/arch/sparc/kernel/smp.c +++ b/arch/sparc/kernel/smp.c @@ -3,6 +3,7 @@ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) */ +#include <linux/config.h> /* for CONFIG_PROFILE */ #include <asm/head.h> #include <linux/kernel.h> @@ -66,16 +67,6 @@ volatile int cpu_logical_map[NR_CPUS]; struct klock_info klock_info = { KLOCK_CLEAR, 0 }; volatile unsigned long ipi_count; -#ifdef __SMP_PROF__ -volatile unsigned long smp_spins[NR_CPUS]={0}; -volatile unsigned long smp_spins_syscall[NR_CPUS]={0}; -volatile unsigned long smp_spins_syscall_cur[NR_CPUS]={0}; -volatile unsigned long smp_spins_sys_idle[NR_CPUS]={0}; -volatile unsigned long smp_idle_count[1+NR_CPUS]={0,}; -#endif -#if defined (__SMP_PROF__) -volatile unsigned long smp_idle_map=0; -#endif volatile int smp_process_available=0; @@ -558,7 +549,7 @@ void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr) /* Reschedule call back. */ void smp_reschedule_irq(void) { - resched_force(); + need_resched = 1; } /* Running cross calls. */ @@ -583,6 +574,8 @@ void smp_stop_cpu_irq(void) /* Protects counters touched during level14 ticker */ spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED; +#ifdef CONFIG_PROFILE + /* 32-bit Sparc specific profiling function. */ static inline void sparc_do_profile(unsigned long pc) { @@ -601,7 +594,7 @@ static inline void sparc_do_profile(unsigned long pc) } } -volatile unsigned long smp_local_timer_ticks[1+NR_CPUS]={0,}; +#endif unsigned int prof_multiplier[NR_CPUS]; unsigned int prof_counter[NR_CPUS]; @@ -614,8 +607,10 @@ void smp_percpu_timer_interrupt(struct pt_regs *regs) int cpu = smp_processor_id(); clear_profile_irq(mid_xlate[cpu]); +#ifdef CONFIG_PROFILE if(!user_mode(regs)) sparc_do_profile(regs->pc); +#endif if(!--prof_counter[cpu]) { int user = user_mode(regs); if(current->pid) { @@ -623,7 +618,7 @@ void smp_percpu_timer_interrupt(struct pt_regs *regs) if(--current->counter < 0) { current->counter = 0; - resched_force(); + need_resched = 1; } spin_lock(&ticker_lock); @@ -639,9 +634,6 @@ void smp_percpu_timer_interrupt(struct pt_regs *regs) } prof_counter[cpu] = prof_multiplier[cpu]; } -#ifdef __SMP_PROF__ - smp_local_timer_ticks[cpu]++; -#endif } extern unsigned int lvl14_resolution; diff --git a/arch/sparc/kernel/sparc-stub.c b/arch/sparc/kernel/sparc-stub.c index 008e9c450..e259ffade 100644 --- a/arch/sparc/kernel/sparc-stub.c +++ b/arch/sparc/kernel/sparc-stub.c @@ -1,4 +1,4 @@ -/* $Id: sparc-stub.c,v 1.20 1997/01/06 06:52:31 davem Exp $ +/* $Id: sparc-stub.c,v 1.22 1998/01/07 06:33:48 baccala Exp $ * sparc-stub.c: KGDB support for the Linux kernel. * * Modifications to run under Linux @@ -323,7 +323,23 @@ mem2hex(char *mem, char *buf, int count) unsigned char ch; while (count-- > 0) { - ch = *mem++; + /* This assembler code is basically: ch = *mem++; + * except that we use the SPARC/Linux exception table + * mechanism (see how "fixup" works in kernel_mna_trap_fault) + * to arrange for a "return 0" upon a memory fault + */ + __asm__( + "1: ldub [%0], %1 + inc %0 + .section .fixup,#alloc,#execinstr + .align 4 + 2: retl + mov 0, %%o0 + .section __ex_table, #alloc + .align 4 + .word 1b, 2b + .text" + : "=r" (mem), "=r" (ch) : "0" (mem)); *buf++ = hexchars[ch >> 4]; *buf++ = hexchars[ch & 0xf]; } @@ -345,7 +361,19 @@ hex2mem(char *buf, char *mem, int count) ch = hex(*buf++) << 4; ch |= hex(*buf++); - *mem++ = ch; + /* Assembler code is *mem++ = ch; with return 0 on fault */ + __asm__( + "1: stb %1, [%0] + inc %0 + .section .fixup,#alloc,#execinstr + .align 4 + 2: retl + mov 0, %%o0 + .section __ex_table, #alloc + .align 4 + .word 1b, 2b + .text" + : "=r" (mem) : "r" (ch) , "0" (mem)); } return mem; } @@ -387,13 +415,18 @@ set_debug_traps(void) /* In case GDB is started before us, ack any packets (presumably * "$?#xx") sitting there. + * + * I've found this code causes more problems than it solves, + * so that's why it's commented out. GDB seems to work fine + * now starting either before or after the kernel -bwb */ - +#if 0 while((c = getDebugChar()) != '$'); while((c = getDebugChar()) != '#'); c = getDebugChar(); /* eat first csum byte */ c = getDebugChar(); /* eat second csum byte */ putDebugChar('+'); /* ack it */ +#endif initialized = 1; /* connect! */ restore_flags(flags); diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index cf4146c4a..df3eac300 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -1,10 +1,12 @@ -/* $Id: sparc_ksyms.c,v 1.60 1997/06/17 13:25:13 jj Exp $ +/* $Id: sparc_ksyms.c,v 1.61 1997/11/19 07:57:44 jj Exp $ * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) */ +/* Tell string.h we don't want memcpy etc. as cpp defines */ +#define EXPORT_SYMTAB_STROPS #define PROMLIB_INTERNAL #include <linux/config.h> diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c new file mode 100644 index 000000000..f22fe1495 --- /dev/null +++ b/arch/sparc/kernel/sun4d_irq.c @@ -0,0 +1,483 @@ +/* $Id: sun4d_irq.c,v 1.3 1997/12/22 16:09:15 jj Exp $ + * arch/sparc/kernel/sun4d_irq.c: + * SS1000/SC2000 interrupt handling. + * + * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Heavily based on arch/sparc/kernel/irq.c. + */ + +#include <linux/ptrace.h> +#include <linux/errno.h> +#include <linux/linkage.h> +#include <linux/kernel_stat.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/malloc.h> +#include <linux/random.h> +#include <linux/init.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> + +#include <asm/ptrace.h> +#include <asm/processor.h> +#include <asm/system.h> +#include <asm/psr.h> +#include <asm/smp.h> +#include <asm/vaddrs.h> +#include <asm/timer.h> +#include <asm/openprom.h> +#include <asm/oplib.h> +#include <asm/traps.h> +#include <asm/irq.h> +#include <asm/io.h> +#include <asm/pgtable.h> +#include <asm/spinlock.h> +#include <asm/sbus.h> +#include <asm/sbi.h> + +struct sun4d_timer_regs *sun4d_timers; +#define TIMER_IRQ 10 + +#define MAX_STATIC_ALLOC 4 +extern struct irqaction static_irqaction[MAX_STATIC_ALLOC]; +extern int static_irq_count; + +extern struct irqaction *irq_action[]; + +struct sbus_action { + struct irqaction *action; + unsigned char lock; + unsigned char active; + unsigned char disabled; +} *sbus_actions; + +static int pil_to_sbus[] = { + 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0, +}; + +static int nsbi; + +int sun4d_get_irq_list(char *buf) +{ + int i, j = 0, k = 0, len = 0, sbusl; + struct irqaction * action; + + for (i = 0 ; i < NR_IRQS ; i++) { + sbusl = pil_to_sbus[i]; + if (!sbusl) { + action = *(i + irq_action); + if (!action) + continue; + } else { + for (j = 0; j < nsbi; j++) { + for (k = 0; k < 4; k++) + if ((action = sbus_actions [(j << 5) + (sbusl << 2) + k].action)) + goto found_it; + } + continue; + } +found_it: len += sprintf(buf+len, "%2d: %8d %c %s", + i, kstat.interrupts[i], + (action->flags & SA_INTERRUPT) ? '+' : ' ', + action->name); + action = action->next; + for (;;) { + for (; action; action = action->next) { + len += sprintf(buf+len, ",%s %s", + (action->flags & SA_INTERRUPT) ? " +" : "", + action->name); + } + if (!sbusl) break; + k++; + if (k < 4) + action = sbus_actions [(j << 5) + (sbusl << 2) + k].action; + else { + j++; + if (j == nsbi) break; + k = 0; + action = sbus_actions [(j << 5) + (sbusl << 2)].action; + } + } + len += sprintf(buf+len, "\n"); + } + return len; +} + +void sun4d_free_irq(unsigned int irq, void *dev_id) +{ + struct irqaction *action, **actionp; + struct irqaction *tmp = NULL; + unsigned long flags; + + if (irq < 15) + actionp = irq + irq_action; + else + actionp = &(sbus_actions[irq - (1 << 5)].action); + action = *actionp; + if (!action) { + printk("Trying to free free IRQ%d\n",irq); + return; + } + if (dev_id) { + for (; action; action = action->next) { + if (action->dev_id == dev_id) + break; + tmp = action; + } + if (!action) { + printk("Trying to free free shared IRQ%d\n",irq); + return; + } + } else if (action->flags & SA_SHIRQ) { + printk("Trying to free shared IRQ%d with NULL device ID\n", irq); + return; + } + if (action->flags & SA_STATIC_ALLOC) + { + /* This interrupt is marked as specially allocated + * so it is a bad idea to free it. + */ + printk("Attempt to free statically allocated IRQ%d (%s)\n", + irq, action->name); + return; + } + + save_and_cli(flags); + if (action && tmp) + tmp->next = action->next; + else + *actionp = action->next; + + kfree_s(action, sizeof(struct irqaction)); + + if (!(*actionp)) + disable_irq(irq); + + restore_flags(flags); +} + +extern void unexpected_irq(int, void *, struct pt_regs *); + +void sun4d_handler_irq(int irq, struct pt_regs * regs) +{ + struct irqaction * action; + int cpu = smp_processor_id(); + /* SBUS IRQ level (1 - 7) */ + int sbusl = pil_to_sbus[irq]; + + /* FIXME: Is this necessary?? */ + cc_get_ipen(); + + cc_set_iclr(1 << irq); + + irq_enter(cpu, irq, regs); + kstat.interrupts[irq]++; + if (!sbusl) { + action = *(irq + irq_action); + if (!action) + unexpected_irq(irq, 0, regs); + do { + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + } else { + int bus_mask = bw_get_intr_mask(sbusl) & 0x3ffff; + int lock; + int sbino; + struct sbus_action *actionp; + unsigned mask, slot; + int sbil = (sbusl << 2); + + bw_clear_intr_mask(sbusl, bus_mask); + + /* Loop for each pending SBI */ + for (sbino = 0; bus_mask; sbino++, bus_mask >>= 1) + if (bus_mask & 1) { + mask = acquire_sbi(SBI2DEVID(sbino), 0xf << sbil); + mask &= (0xf << sbil); + actionp = sbus_actions + (sbino << 5) + (sbil); + /* Loop for each pending SBI slot */ + for (slot = (1 << sbil); mask; slot <<= 1, actionp++) + if (mask & slot) { + mask &= ~slot; + action = actionp->action; + __asm__ __volatile__ ("ldstub [%1 + 4], %0" + : "=r" (lock) : "r" (actionp)); + + if (!lock) { + if (!action) + unexpected_irq(irq, 0, regs); + do { + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + actionp->lock = 0; + } else + actionp->active = 1; + release_sbi(SBI2DEVID(sbino), slot); + } + } + } + irq_exit(cpu, irq); +} + +int sun4d_request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, const char * devname, void *dev_id) +{ + struct irqaction *action, *tmp = NULL, **actionp; + unsigned long flags; + int sbusl; + unsigned int *ret = NULL; + struct linux_sbus_device *sdev = NULL; + + if(irq > 14) + return -EINVAL; + + if (!handler) + return -EINVAL; + + if (irqflags & SA_DCOOKIE) { + struct devid_cookie *d = (struct devid_cookie *)dev_id; + + dev_id = d->real_dev_id; + sdev = (struct linux_sbus_device *)d->bus_cookie; + ret = &d->ret_ino; + } + + sbusl = pil_to_sbus[irq]; + if (sbusl && !sdev) { + printk ("Attempt to register SBUS IRQ %d without DCOOKIE\n", irq); + return -EINVAL; + } + if (sbusl) { + actionp = &(sbus_actions[(sdev->my_bus->board << 5) + + (sbusl << 2) + sdev->slot].action); + *ret = ((sdev->my_bus->board + 1) << 5) + + (sbusl << 2) + sdev->slot; + } else + actionp = irq + irq_action; + action = *actionp; + + if (action) { + if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) { + for (tmp = action; tmp->next; tmp = tmp->next); + } else { + return -EBUSY; + } + if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) { + printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq); + return -EBUSY; + } + action = NULL; /* Or else! */ + } + + save_and_cli(flags); + + /* If this is flagged as statically allocated then we use our + * private struct which is never freed. + */ + if (irqflags & SA_STATIC_ALLOC) + if (static_irq_count < MAX_STATIC_ALLOC) + action = &static_irqaction[static_irq_count++]; + else + printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",irq, devname); + + if (action == NULL) + action = (struct irqaction *)kmalloc(sizeof(struct irqaction), + GFP_KERNEL); + + if (!action) { + restore_flags(flags); + return -ENOMEM; + } + + action->handler = handler; + action->flags = irqflags; + action->mask = 0; + action->name = devname; + action->next = NULL; + action->dev_id = dev_id; + + if (tmp) + tmp->next = action; + else + *actionp = action; + + if (ret) irq = *ret; + + if (irq > NR_IRQS) { + struct sbus_action *s = sbus_actions + irq - (1 << 5); + + if (s->disabled) { + s->disabled = 0; + s->active = 0; + s->lock = 0; + } + } + + restore_flags(flags); + return 0; +} + +static void sun4d_disable_irq(unsigned int irq) +{ + struct sbus_action *s; + + if (irq < NR_IRQS) { + /* FIXME */ + printk ("Unable to disable IRQ %d\n", irq); + return; + } + s = sbus_actions + irq - (1 << 5); + + if (s->disabled) return; + s->disabled = 1; + __asm__ __volatile__ (" +1: ldstub [%0 + 4], %%g1 + orcc %%g1, 0, %%g0 + bne 1b" + : : "r" (s) : "g1", "cc"); +} + +static void sun4d_enable_irq(unsigned int irq) +{ + struct sbus_action *s; + struct irqaction *action; + + if (irq < NR_IRQS) + /* FIXME */ + return; + s = sbus_actions + irq - (1 << 5); + + if (!s->disabled) return; + action = s->action; + s->disabled = 0; + while (s->active) { + s->active = 0; + while (action) { + /* FIXME: Hope no sbus intr handler uses regs */ + action->handler(irq, action->dev_id, NULL); + action = action->next; + } + } + s->lock = 0; +} + +#ifdef __SMP__ + +/* +-------+-------------+-----------+------------------------------------+ + * | bcast | devid | sid | levels mask | + * +-------+-------------+-----------+------------------------------------+ + * 31 30 23 22 15 14 0 + */ +#define IGEN_MESSAGE(bcast, devid, sid, levels) \ + (((bcast) << 31) | ((devid) << 23) | ((sid) << 15) | (levels)) + +static void sun4d_send_ipi(int cpu, int level) +{ + cc_set_igen(IGEN_MESSAGE(0, cpu << 3, 6 + ((level >> 1) & 7), 1 << (level - 1))); +} + +static void sun4d_clear_ipi(int cpu, int level) +{ +} + +static void sun4d_set_udt(int cpu) +{ +} +#endif + +static void sun4d_clear_clock_irq(void) +{ + volatile unsigned int clear_intr; + clear_intr = sun4d_timers->l10_timer_limit; +} + +static void sun4d_clear_profile_irq(int cpu) +{ + bw_get_prof_limit(cpu); +} + +static void sun4d_load_profile_irq(int cpu, unsigned int limit) +{ + bw_set_prof_limit(cpu, limit); +} + +__initfunc(static void sun4d_init_timers(void (*counter_fn)(int, void *, struct pt_regs *))) +{ + int irq; + extern struct prom_cpuinfo linux_cpus[NCPUS]; + int cpu; + + /* Map the User Timer registers. */ + sun4d_timers = sparc_alloc_io(BW_LOCAL_BASE+BW_TIMER_LIMIT, 0, + PAGE_SIZE, "user timer", 0xf, 0x0); + + sun4d_timers->l10_timer_limit = (((1000000/HZ) + 1) << 10); + master_l10_counter = &sun4d_timers->l10_cur_count; + master_l10_limit = &sun4d_timers->l10_timer_limit; + + irq = request_irq(TIMER_IRQ, + counter_fn, + (SA_INTERRUPT | SA_STATIC_ALLOC), + "timer", NULL); + if (irq) { + prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); + prom_halt(); + } + + /* Enable user timer free run for CPU 0 in BW */ + /* bw_set_ctrl(0, bw_get_ctrl(0) | BW_CTRL_USER_TIMER); */ + + for(cpu = 0; cpu < NCPUS; cpu++) + sun4d_load_profile_irq(linux_cpus[cpu].mid, 0); +} + +__initfunc(unsigned long sun4d_init_sbi_irq(unsigned long memory_start)) +{ + struct linux_sbus *sbus; + struct sbus_action *s; + int i; + unsigned mask; + + nsbi = 0; + for_each_sbus(sbus) + nsbi++; + memory_start = ((memory_start + 7) & ~7); + sbus_actions = (struct sbus_action *)memory_start; + memory_start += (nsbi * 8 * 4 * sizeof(struct sbus_action)); + memset (sbus_actions, 0, (nsbi * 8 * 4 * sizeof(struct sbus_action))); + for (i = 0, s = sbus_actions; i < nsbi * 8 * 4; i++, s++) { + s->lock = 0xff; + s->disabled = 1; + } + for_each_sbus(sbus) { + /* Get rid of pending irqs from PROM */ + mask = acquire_sbi(sbus->devid, 0xffffffff); + if (mask) { + printk ("Clearing pending IRQs %08x on SBI %d\n", mask, sbus->board); + release_sbi(sbus->devid, mask); + } + } + return memory_start; +} + +__initfunc(void sun4d_init_IRQ(void)) +{ + __cli(); + + enable_irq = sun4d_enable_irq; + disable_irq = sun4d_disable_irq; + clear_clock_irq = sun4d_clear_clock_irq; + clear_profile_irq = sun4d_clear_profile_irq; + load_profile_irq = sun4d_load_profile_irq; + init_timers = sun4d_init_timers; +#ifdef __SMP__ + set_cpu_int = (void (*) (int, int))sun4d_send_ipi; + clear_cpu_int = (void (*) (int, int))sun4d_clear_ipi; + set_irq_udt = (void (*) (int))sun4d_set_udt; +#endif + /* Cannot enable interrupts until OBP ticker is disabled. */ +} diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index d6420ec68..81db1a4ce 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -163,7 +163,8 @@ static void sun4m_enable_pil_irq(unsigned int pil) sun4m_interrupts->clear = cpu_pil_to_imask[pil]; } -void sun4m_send_ipi(int cpu, int level) +#ifdef __SMP__ +static void sun4m_send_ipi(int cpu, int level) { unsigned long mask; @@ -171,7 +172,7 @@ void sun4m_send_ipi(int cpu, int level) sun4m_interrupts->cpu_intregs[cpu].set = mask; } -void sun4m_clear_ipi(int cpu, int level) +static void sun4m_clear_ipi(int cpu, int level) { unsigned long mask; @@ -179,10 +180,11 @@ void sun4m_clear_ipi(int cpu, int level) sun4m_interrupts->cpu_intregs[cpu].clear = mask; } -void sun4m_set_udt(int cpu) +static void sun4m_set_udt(int cpu) { sun4m_interrupts->undirected_target = cpu; } +#endif #define OBIO_INTR 0x20 #define TIMER_IRQ (OBIO_INTR | 10) diff --git a/arch/sparc/kernel/sunos_ioctl.c b/arch/sparc/kernel/sunos_ioctl.c index cc0166a41..4f6b2accc 100644 --- a/arch/sparc/kernel/sunos_ioctl.c +++ b/arch/sparc/kernel/sunos_ioctl.c @@ -1,4 +1,4 @@ -/* $Id: sunos_ioctl.c,v 1.28 1997/02/15 01:17:05 davem Exp $ +/* $Id: sunos_ioctl.c,v 1.29 1997/09/18 10:37:31 rth Exp $ * sunos_ioctl.c: The Linux Operating system: SunOS ioctl compatibility. * * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) @@ -45,8 +45,8 @@ asmlinkage int sunos_ioctl (int fd, unsigned long cmd, unsigned long arg) /* First handle an easy compat. case for tty ldisc. */ if(cmd == TIOCSETD) { - int *p, ntty = N_TTY; - int tmp, oldfs; + int *p, ntty = N_TTY, tmp; + mm_segment_t oldfs; p = (int *) arg; ret = -EFAULT; diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c index d4044f88f..5b82aa8eb 100644 --- a/arch/sparc/kernel/sys_sparc.c +++ b/arch/sparc/kernel/sys_sparc.c @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.35 1997/04/16 05:56:09 davem Exp $ +/* $Id: sys_sparc.c,v 1.38 1998/01/09 16:42:48 jj Exp $ * linux/arch/sparc/kernel/sys_sparc.c * * This file contains various random system calls that @@ -17,6 +17,7 @@ #include <linux/shm.h> #include <linux/stat.h> #include <linux/mman.h> +#include <linux/utsname.h> #include <linux/smp.h> #include <linux/smp_lock.h> @@ -248,53 +249,99 @@ sparc_breakpoint (struct pt_regs *regs) unlock_kernel(); } -extern void check_pending(int signum); - asmlinkage int -sparc_sigaction (int signum, const struct sigaction *action, struct sigaction *oldaction) +sparc_sigaction (int sig, const struct old_sigaction *act, + struct old_sigaction *oact) { - struct sigaction new_sa, *p; + struct k_sigaction new_ka, old_ka; + int ret; - if(signum < 0) { + if (sig < 0) { current->tss.new_signal = 1; - signum = -signum; + sig = -sig; } - if(signum<1 || signum>32) - return -EINVAL; - p = signum - 1 + current->sig->action; - if(action) { - if(verify_area(VERIFY_READ,action,sizeof(struct sigaction))) + if (act) { + unsigned long mask; + + if (verify_area(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) return -EFAULT; - if (signum==SIGKILL || signum==SIGSTOP) - return -EINVAL; - if(copy_from_user(&new_sa, action, sizeof(struct sigaction))) - return -EFAULT; - if (new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) { - if(verify_area(VERIFY_READ, new_sa.sa_handler, 1)) - return -EFAULT; - } + __get_user(new_ka.sa.sa_flags, &act->sa_flags); + __get_user(mask, &act->sa_mask); + siginitset(&new_ka.sa.sa_mask, mask); + new_ka.ka_restorer = NULL; } - if (oldaction) { + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { /* In the clone() case we could copy half consistant * state to the user, however this could sleep and * deadlock us if we held the signal lock on SMP. So for * now I take the easy way out and do no locking. */ - if (copy_to_user(oldaction, p, sizeof(struct sigaction))) - return -EFAULT; + if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + return -EFAULT; + __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } - if (action) { - spin_lock_irq(¤t->sig->siglock); - *p = new_sa; - check_pending(signum); - spin_unlock_irq(¤t->sig->siglock); + return ret; +} + +asmlinkage int +sys_rt_sigaction(int sig, const struct sigaction *act, struct sigaction *oact, + void *restorer, size_t sigsetsize) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + + if (act) { + new_ka.ka_restorer = restorer; + if (copy_from_user(&new_ka.sa, act, sizeof(*act))) + return -EFAULT; } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (copy_to_user(oact, &old_ka.sa, sizeof(*oact))) + return -EFAULT; + } + + return ret; +} + +/* Just in case some old old binary calls this. */ +asmlinkage int sys_pause(void) +{ + current->state = TASK_INTERRUPTIBLE; + schedule(); + return -ERESTARTNOHAND; +} + +asmlinkage int sys_getdomainname(char *name, int len) +{ + int nlen = strlen(system_utsname.domainname); + + if (nlen < len) + len = nlen; + if(len > __NEW_UTS_LEN) + return -EFAULT; + if(copy_to_user(name, system_utsname.domainname, len)) + return -EFAULT; return 0; } + #ifndef CONFIG_AP1000 /* only AP+ systems have sys_aplib */ asmlinkage int sys_aplib(void) diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c index f60ecbe9c..29f00f6b8 100644 --- a/arch/sparc/kernel/sys_sunos.c +++ b/arch/sparc/kernel/sys_sunos.c @@ -1,4 +1,4 @@ -/* $Id: sys_sunos.c,v 1.81 1997/07/20 05:59:31 davem Exp $ +/* $Id: sys_sunos.c,v 1.83 1997/12/14 23:24:28 ecd Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -348,35 +348,28 @@ asmlinkage long sunos_getdtablesize(void) { return SUNOS_NR_OPEN; } -#define _S(nr) (1<<((nr)-1)) -#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) asmlinkage unsigned long sunos_sigblock(unsigned long blk_mask) { - unsigned long flags; unsigned long old; - lock_kernel(); - save_and_cli(flags); - old = current->blocked; - current->blocked |= (blk_mask & _BLOCKABLE); - restore_flags(flags); - unlock_kernel(); + spin_lock_irq(¤t->sigmask_lock); + old = current->blocked.sig[0]; + current->blocked.sig[0] |= (blk_mask & _BLOCKABLE); + spin_unlock_irq(¤t->sigmask_lock); return old; } asmlinkage unsigned long sunos_sigsetmask(unsigned long newmask) { - unsigned long flags; unsigned long retval; - lock_kernel(); - save_and_cli(flags); - retval = current->blocked; - current->blocked = newmask & _BLOCKABLE; - restore_flags(flags); - unlock_kernel(); + spin_lock_irq(¤t->sigmask_lock); + retval = current->blocked.sig[0]; + current->blocked.sig[0] = (newmask & _BLOCKABLE); + spin_unlock_irq(¤t->sigmask_lock); return retval; } @@ -430,8 +423,6 @@ static int sunos_filldir(void * __buf, const char * name, int namlen, asmlinkage int sunos_getdents(unsigned int fd, void * dirent, int cnt) { struct file * file; - struct dentry * dentry; - struct inode * inode; struct sunos_dirent * lastdirent; struct sunos_dirent_callback buf; int error = -EBADF; @@ -444,14 +435,6 @@ asmlinkage int sunos_getdents(unsigned int fd, void * dirent, int cnt) if(!file) goto out; - dentry = file->f_dentry; - if(!dentry) - goto out; - - inode = dentry->d_inode; - if(!inode) - goto out; - error = -ENOTDIR; if (!file->f_op || !file->f_op->readdir) goto out; @@ -464,7 +447,7 @@ asmlinkage int sunos_getdents(unsigned int fd, void * dirent, int cnt) buf.previous = NULL; buf.count = cnt; buf.error = 0; - error = file->f_op->readdir(inode, file, &buf, sunos_filldir); + error = file->f_op->readdir(file, &buf, sunos_filldir); if (error < 0) goto out; lastdirent = buf.previous; @@ -520,8 +503,6 @@ static int sunos_filldirentry(void * __buf, const char * name, int namlen, asmlinkage int sunos_getdirentries(unsigned int fd, void * dirent, int cnt, unsigned int *basep) { struct file * file; - struct dentry * dentry; - struct inode * inode; struct sunos_direntry * lastdirent; struct sunos_direntry_callback buf; int error = -EBADF; @@ -534,14 +515,6 @@ asmlinkage int sunos_getdirentries(unsigned int fd, void * dirent, int cnt, unsi if(!file) goto out; - dentry = file->f_dentry; - if(!dentry) - goto out; - - inode = dentry->d_inode; - if(!inode) - goto out; - error = -ENOTDIR; if (!file->f_op || !file->f_op->readdir) goto out; @@ -554,7 +527,7 @@ asmlinkage int sunos_getdirentries(unsigned int fd, void * dirent, int cnt, unsi buf.previous = NULL; buf.count = cnt; buf.error = 0; - error = file->f_op->readdir(inode, file, &buf, sunos_filldirentry); + error = file->f_op->readdir(file, &buf, sunos_filldirentry); if (error < 0) goto out; lastdirent = buf.previous; @@ -1254,58 +1227,47 @@ asmlinkage int sunos_accept(int fd, struct sockaddr *sa, int *addrlen) #define SUNOS_SV_INTERRUPT 2 -extern void check_pending(int signum); - -asmlinkage int sunos_sigaction(int signum, const struct sigaction *action, - struct sigaction *oldaction) +asmlinkage int +sunos_sigaction(int sig, const struct old_sigaction *act, + struct old_sigaction *oact) { - struct sigaction new_sa, *p; - const int sigaction_size = sizeof (struct sigaction) - sizeof (void *); + struct k_sigaction new_ka, old_ka; + int ret; current->personality |= PER_BSD; - if(signum < 1 || signum > 32) - return -EINVAL; - p = signum - 1 + current->sig->action; + if(act) { + old_sigset_t mask; - if(action) { - if(copy_from_user(&new_sa, action, sigaction_size)) - return -EFAULT; - if (signum==SIGKILL || signum==SIGSTOP) - return -EINVAL; - memset(&new_sa, 0, sizeof(struct sigaction)); - if(copy_from_user(&new_sa, action, sigaction_size)) + if (verify_area(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags)) return -EFAULT; - if (new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) { - if(verify_area(VERIFY_READ, new_sa.sa_handler, 1)) - return -EFAULT; - } - new_sa.sa_flags ^= SUNOS_SV_INTERRUPT; + __get_user(mask, &act->sa_mask); + new_ka.sa.sa_restorer = NULL; + new_ka.ka_restorer = NULL; + siginitset(&new_ka.sa.sa_mask, mask); + new_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT; } - if (oldaction) { + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { /* In the clone() case we could copy half consistant * state to the user, however this could sleep and * deadlock us if we held the signal lock on SMP. So for * now I take the easy way out and do no locking. * But then again we don't support SunOS lwp's anyways ;-) */ - if (copy_to_user(oldaction, p, sigaction_size)) + old_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT; + if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_flags, &oact->sa_flags)) return -EFAULT; - - if (oldaction->sa_flags & SA_RESTART) - oldaction->sa_flags &= ~SA_RESTART; - else - oldaction->sa_flags |= SUNOS_SV_INTERRUPT; + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } - if (action) { - spin_lock_irq(¤t->sig->siglock); - *p = new_sa; - check_pending(signum); - spin_unlock_irq(¤t->sig->siglock); - } - return 0; + return ret; } diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S index 055b85b21..5ea64d2a4 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls.S @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.62 1997/04/23 23:01:08 ecd Exp $ +/* $Id: systbls.S,v 1.68 1997/12/24 17:26:38 ecd Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -30,11 +30,11 @@ C_LABEL(sys_call_table): .long C_LABEL(sys_setuid), C_LABEL(sys_getuid) /*25*/ .long C_LABEL(sys_time), C_LABEL(sys_ptrace), C_LABEL(sys_alarm) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_pause) -/*30*/ .long C_LABEL(sys_utime), C_LABEL(sys_stty), C_LABEL(sys_gtty) - .long C_LABEL(sys_access), C_LABEL(sys_nice), C_LABEL(sys_ftime) +/*30*/ .long C_LABEL(sys_utime), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) + .long C_LABEL(sys_access), C_LABEL(sys_nice), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_sync), C_LABEL(sys_kill), C_LABEL(sys_newstat) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_newlstat), C_LABEL(sys_dup) - .long C_LABEL(sys_pipe), C_LABEL(sys_times), C_LABEL(sys_profil) + .long C_LABEL(sys_pipe), C_LABEL(sys_times), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_setgid), C_LABEL(sys_getgid) .long C_LABEL(sys_signal), C_LABEL(sys_geteuid) /*50*/ .long C_LABEL(sys_getegid), C_LABEL(sys_acct), C_LABEL(sys_nis_syscall) @@ -42,8 +42,8 @@ C_LABEL(sys_call_table): .long C_LABEL(sys_nis_syscall), C_LABEL(sys_symlink), C_LABEL(sys_readlink) .long C_LABEL(sys_execve), C_LABEL(sys_umask), C_LABEL(sys_chroot) .long C_LABEL(sys_newfstat), C_LABEL(sys_nis_syscall), C_LABEL(sys_getpagesize) - .long C_LABEL(sys_msync), C_LABEL(sys_vfork), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) + .long C_LABEL(sys_msync), C_LABEL(sys_vfork), C_LABEL(sys_pread) + .long C_LABEL(sys_pwrite), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_mmap), C_LABEL(sys_nis_syscall), C_LABEL(sys_munmap) .long C_LABEL(sys_mprotect), C_LABEL(sys_nis_syscall), C_LABEL(sys_vhangup) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_getgroups) @@ -54,10 +54,10 @@ C_LABEL(sys_call_table): .long C_LABEL(sys_fcntl), C_LABEL(sys_select), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_fsync), C_LABEL(sys_setpriority), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) -/*100*/ .long C_LABEL(sys_getpriority), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) +/*100*/ .long C_LABEL(sys_getpriority), C_LABEL(sys_rt_sigreturn) + .long C_LABEL(sys_rt_sigaction), C_LABEL(sys_rt_sigprocmask) + .long C_LABEL(sys_rt_sigpending), C_LABEL(sys_rt_sigtimedwait) + .long C_LABEL(sys_rt_sigqueueinfo), C_LABEL(sys_rt_sigsuspend) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) @@ -73,13 +73,13 @@ C_LABEL(sys_call_table): .long C_LABEL(sys_mkdir), C_LABEL(sys_rmdir), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_getrlimit) - .long C_LABEL(sys_setrlimit), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) + .long C_LABEL(sys_setrlimit), C_LABEL(sys_nis_syscall), C_LABEL(sys_prctl) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) /*150*/ .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_poll), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_statfs), C_LABEL(sys_fstatfs) .long C_LABEL(sys_umount), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_nis_syscall), C_LABEL(sys_setdomainname) + .long C_LABEL(sys_getdomainname), C_LABEL(sys_setdomainname) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_quotactl), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_mount), C_LABEL(sys_ustat), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) @@ -89,12 +89,12 @@ C_LABEL(sys_call_table): .long C_LABEL(sys_nis_syscall), C_LABEL(sys_sigpending), C_LABEL(sys_query_module) .long C_LABEL(sys_setpgid), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_newuname), C_LABEL(sys_init_module) - .long C_LABEL(sys_personality), C_LABEL(sys_prof), C_LABEL(sys_break) - .long C_LABEL(sys_lock), C_LABEL(sys_mpx), C_LABEL(sys_ulimit) + .long C_LABEL(sys_personality), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) + .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_getppid), C_LABEL(sparc_sigaction), C_LABEL(sys_sgetmask) /*200*/ .long C_LABEL(sys_ssetmask), C_LABEL(sys_sigsuspend), C_LABEL(sys_newlstat) .long C_LABEL(sys_uselib), C_LABEL(old_readdir), C_LABEL(sys_nis_syscall) - .long C_LABEL(sys_socketcall), C_LABEL(sys_syslog), C_LABEL(sys_olduname) + .long C_LABEL(sys_socketcall), C_LABEL(sys_syslog), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_idle), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_waitpid), C_LABEL(sys_swapoff), C_LABEL(sys_sysinfo) .long C_LABEL(sys_ipc), C_LABEL(sys_sigreturn), C_LABEL(sys_clone) @@ -102,7 +102,7 @@ C_LABEL(sys_call_table): .long C_LABEL(sys_create_module), C_LABEL(sys_delete_module) .long C_LABEL(sys_get_kernel_syms), C_LABEL(sys_getpgid), C_LABEL(sys_bdflush) .long C_LABEL(sys_sysfs), C_LABEL(sys_nis_syscall), C_LABEL(sys_setfsuid) - .long C_LABEL(sys_setfsgid), C_LABEL(sys_llseek), C_LABEL(sys_time) + .long C_LABEL(sys_setfsgid), C_LABEL(sys_select), C_LABEL(sys_time) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_stime), C_LABEL(sys_nis_syscall) .long C_LABEL(sys_nis_syscall), C_LABEL(sys_llseek) /* "We are the Knights of the Forest of Ni!!" */ @@ -125,7 +125,6 @@ C_LABEL(sys_call_table): .long C_LABEL(sys_fdatasync) .long C_LABEL(sys_nfsservctl) /*255*/ .long C_LABEL(sys_aplib) - .long C_LABEL(sys_prctl) .long C_LABEL(sys_nis_syscall) /* Now the SunOS syscall table. */ @@ -147,7 +146,7 @@ C_LABEL(sunos_sys_table): .long C_LABEL(sys_access), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) .long C_LABEL(sys_sync), C_LABEL(sys_kill), C_LABEL(sys_newstat) .long C_LABEL(sunos_nosys), C_LABEL(sys_newlstat), C_LABEL(sys_dup) - .long C_LABEL(sys_pipe), C_LABEL(sunos_nosys), C_LABEL(sys_profil) + .long C_LABEL(sys_pipe), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_getgid) .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) /*50*/ .long C_LABEL(sunos_nosys), C_LABEL(sys_acct), C_LABEL(sunos_nosys) @@ -220,4 +219,3 @@ C_LABEL(sunos_sys_table): .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) /*250*/ .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys) .long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sys_aplib) - .long C_LABEL(sunos_nosys) |