diff -u --recursive --new-file v1.3.31/linux/CREDITS linux/CREDITS --- v1.3.31/linux/CREDITS Wed Oct 4 14:14:27 1995 +++ linux/CREDITS Thu Oct 5 15:33:14 1995 @@ -211,6 +211,15 @@ S: NN1 3QT S: United Kingdom +N: Ray Dassen +E: jdassen@wi.LeidenUniv.nl +U: http://www.wi.leidenuniv.nl/~jdassen/ +D: Debian GNU/Linux: www.debian.org maintainer, FAQ co-maintainer, +D: packages testing, nit-picking & fixing. Enjoying BugFree (TM) kernels. +S: Zuidsingel 10A +S: 2312 SB Leiden +S: The Netherlands + N: Wayne Davison E: davison@borland.com D: Second extended file system co-designer @@ -621,7 +630,6 @@ S: USA N: William (Bill) Metzenthen -E: billm@vaxc.cc.monash.edu.au E: billm@jacobi.maths.monash.edu.au D: Author of the FPU emulator. D: Minor kernel hacker for other lost causes (Hercules mono, etc). diff -u --recursive --new-file v1.3.31/linux/Makefile linux/Makefile --- v1.3.31/linux/Makefile Wed Oct 4 14:14:27 1995 +++ linux/Makefile Wed Oct 4 14:48:45 1995 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 3 -SUBLEVEL = 31 +SUBLEVEL = 32 ARCH = i386 diff -u --recursive --new-file v1.3.31/linux/arch/alpha/kernel/apecs.c linux/arch/alpha/kernel/apecs.c --- v1.3.31/linux/arch/alpha/kernel/apecs.c Sun Sep 3 12:26:48 1995 +++ linux/arch/alpha/kernel/apecs.c Fri Oct 6 11:31:11 1995 @@ -424,18 +424,17 @@ void apecs_machine_check(unsigned long vector, unsigned long la_ptr, struct pt_regs * regs) { - struct el_common_logout_header *mchk_header; + struct el_common *mchk_header; struct el_apecs_sysdata_mcheck *mchk_sysdata; - mchk_header = (struct el_common_logout_header *)la_ptr; + mchk_header = (struct el_common *)la_ptr; mchk_sysdata = - (struct el_apecs_sysdata_mcheck *)(la_ptr + mchk_header->elfl_sysoffset); + (struct el_apecs_sysdata_mcheck *)(la_ptr + mchk_header->sys_offset); DBG(("apecs_machine_check: vector=0x%lx la_ptr=0x%lx\n", vector, la_ptr)); DBG((" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->elfl_size, mchk_header->elfl_procoffset, - mchk_header->elfl_sysoffset)); + regs->pc, mchk_header->size, mchk_header->proc_offset, mchk_header->sys_offset)); DBG(("apecs_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n", apecs_mcheck_expected, mchk_sysdata->epic_dcsr, mchk_sysdata->epic_pear)); #ifdef DEBUG @@ -443,7 +442,7 @@ int i; ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->elfl_size / sizeof(long); i += 2) { + for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { printk(" +%x %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]); } #endif /* DEBUG */ diff -u --recursive --new-file v1.3.31/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c --- v1.3.31/linux/arch/alpha/kernel/bios32.c Wed Sep 27 15:59:56 1995 +++ linux/arch/alpha/kernel/bios32.c Fri Oct 6 11:31:12 1995 @@ -310,17 +310,17 @@ unsigned short index, unsigned char *bus, unsigned char *devfn) { - unsigned int current = 0; + unsigned int curr = 0; struct pci_dev *dev; for (dev = pci_devices; dev; dev = dev->next) { if (dev->vendor == vendor && dev->device == device_id) { - if (current == index) { + if (curr == index) { *devfn = dev->devfn; *bus = dev->bus->number; return PCIBIOS_SUCCESSFUL; } - ++current; + ++curr; } } return PCIBIOS_DEVICE_NOT_FOUND; @@ -334,17 +334,17 @@ int pcibios_find_class (unsigned int class_code, unsigned short index, unsigned char *bus, unsigned char *devfn) { - unsigned int current = 0; + unsigned int curr = 0; struct pci_dev *dev; for (dev = pci_devices; dev; dev = dev->next) { if (dev->class == class_code) { - if (current == index) { + if (curr == index) { *devfn = dev->devfn; *bus = dev->bus->number; return PCIBIOS_SUCCESSFUL; } - ++current; + ++curr; } } return PCIBIOS_DEVICE_NOT_FOUND; diff -u --recursive --new-file v1.3.31/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S --- v1.3.31/linux/arch/alpha/kernel/entry.S Wed Oct 4 14:14:27 1995 +++ linux/arch/alpha/kernel/entry.S Fri Oct 6 11:31:12 1995 @@ -478,7 +478,7 @@ beq $0,restore_all ret_from_reschedule: lda $0,need_resched - lda $1,current + lda $1,current_set ldl $2,0($0) lda $4,init_task ldq $3,0($1) diff -u --recursive --new-file v1.3.31/linux/arch/alpha/kernel/lca.c linux/arch/alpha/kernel/lca.c --- v1.3.31/linux/arch/alpha/kernel/lca.c Wed Oct 4 14:14:28 1995 +++ linux/arch/alpha/kernel/lca.c Fri Oct 6 11:31:12 1995 @@ -24,6 +24,29 @@ #define vulp volatile unsigned long * /* + * Machine check reasons. Defined according to PALcode sources + * (osf.h and platform.h). + */ +#define MCHK_K_TPERR 0x0080 +#define MCHK_K_TCPERR 0x0082 +#define MCHK_K_HERR 0x0084 +#define MCHK_K_ECC_C 0x0086 +#define MCHK_K_ECC_NC 0x0088 +#define MCHK_K_UNKNOWN 0x008A +#define MCHK_K_CACKSOFT 0x008C +#define MCHK_K_BUGCHECK 0x008E +#define MCHK_K_OS_BUGCHECK 0x0090 +#define MCHK_K_DCPERR 0x0092 +#define MCHK_K_ICPERR 0x0094 + +/* + * Platform-specific machine-check reasons: + */ +#define MCHK_K_SIO_SERR 0x204 /* all platforms so far */ +#define MCHK_K_SIO_IOCHK 0x206 /* all platforms so far */ +#define MCHK_K_DCSR 0x208 /* all but Noname */ + +/* * Given a bus, device, and function number, compute resulting * configuration space address and setup the LCA_IOC_CONF register * accordingly. It is therefore not safe to have concurrent @@ -280,19 +303,60 @@ } + + void lca_machine_check (unsigned long vector, unsigned long la, struct pt_regs *regs) { - unsigned long mces; + const char * reason; + union el_lca el; - mces = rdmces(); - wrmces(mces); /* reset machine check asap */ - printk("Machine check (la=0x%lx,mces=0x%lx)\n", la, mces); - printk("esr=%lx, ear=%lx, ioc_stat0=%lx, ioc_stat1=%lx\n", - *(unsigned long*)LCA_MEM_ESR, *(unsigned long*)LCA_MEM_EAR, - *(unsigned long*)LCA_IOC_STAT0, *(unsigned long*)LCA_IOC_STAT1); -#ifdef CONFIG_ALPHA_NONAME - printk("NMMI status & control (0x61)=%02x\n", inb(0x61)); -#endif + printk("lca: machine check (la=0x%lx)\n", la); + el.c = (struct el_common *) la; + /* + * The first quadword after the common header always seems to + * be the machine check reason---don't know why this isn't + * part of the common header instead. + */ + switch (el.s->reason) { + case MCHK_K_TPERR: reason = "tag parity error"; break; + case MCHK_K_TCPERR: reason = "tag something parity error"; break; + case MCHK_K_HERR: reason = "access to non-existent memory"; break; + case MCHK_K_ECC_C: reason = "correctable ECC error"; break; + case MCHK_K_ECC_NC: reason = "non-correctable ECC error"; break; + case MCHK_K_CACKSOFT: reason = "MCHK_K_CACKSOFT"; break; /* what's this? */ + case MCHK_K_BUGCHECK: reason = "illegal exception in PAL mode"; break; + case MCHK_K_OS_BUGCHECK: reason = "callsys in kernel mode"; break; + case MCHK_K_DCPERR: reason = "d-cache parity error"; break; + case MCHK_K_ICPERR: reason = "i-cache parity error"; break; + case MCHK_K_SIO_SERR: reason = "SIO SERR occurred on on PCI bus"; break; + case MCHK_K_SIO_IOCHK: reason = "SIO IOCHK occurred on ISA bus"; break; + case MCHK_K_DCSR: reason = "MCHK_K_DCSR"; break; + case MCHK_K_UNKNOWN: + default: reason = "reason for machine-check unknown"; break; + } + + switch (el.c->size) { + case sizeof(struct el_lca_mcheck_short): + printk(" Reason: %s (short frame%s):\n", + reason, el.h->retry ? ", retryable" : ""); + printk("\tesr: %lx ear: %lx\n", el.s->esr, el.s->ear); + printk("\tdc_stat: %lx ioc_stat0: %lx ioc_stat1: %lx\n", + el.s->dc_stat, el.s->ioc_stat0, el.s->ioc_stat1); + break; + + case sizeof(struct el_lca_mcheck_long): + printk(" Reason: %s (long frame%s):\n", + reason, el.h->retry ? ", retryable" : ""); + printk("\treason: %lx exc_addr: %lx dc_stat: %lx\n", + el.l->pt[0], el.l->exc_addr, el.l->dc_stat); + printk("\tesr: %lx ear: %lx car: %lx\n", el.l->esr, el.l->ear, el.l->car); + printk("\tioc_stat0: %lx ioc_stat1: %lx\n", el.l->ioc_stat0, el.l->ioc_stat1); + break; + + default: + printk(" Unknown errorlog size %d\n", el.c->size); + } + wrmces(rdmces()); /* reset machine check asap */ } #endif /* CONFIG_ALPHA_LCA */ diff -u --recursive --new-file v1.3.31/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c --- v1.3.31/linux/arch/alpha/kernel/process.c Mon Sep 18 14:53:48 1995 +++ linux/arch/alpha/kernel/process.c Thu Oct 5 08:31:40 1995 @@ -83,6 +83,10 @@ { } +void release_thread(struct task_struct *dead_task) +{ +} + /* * "alpha_clone()".. By the time we get here, the * non-volatile registers have also been saved on the diff -u --recursive --new-file v1.3.31/linux/arch/i386/config.in linux/arch/i386/config.in --- v1.3.31/linux/arch/i386/config.in Wed Oct 4 14:14:28 1995 +++ linux/arch/i386/config.in Fri Oct 6 10:56:03 1995 @@ -17,7 +17,7 @@ bool ' Use new IDE driver for primary/secondary i/f' CONFIG_BLK_DEV_IDE y fi if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then - bool ' Include support for IDE/ATAPI CDROMs' CONFIG_BLK_DEV_IDECD n + bool ' Include support for IDE/ATAPI CDROMs' CONFIG_BLK_DEV_IDECD y fi fi @@ -80,7 +80,7 @@ comment 'SCSI support' -tristate 'SCSI support' CONFIG_SCSI y +tristate 'SCSI support' CONFIG_SCSI n if [ "$CONFIG_SCSI" = "n" ]; then @@ -101,8 +101,8 @@ comment 'SCSI low-level drivers' -dep_tristate 'Adaptec AHA152X support' CONFIG_SCSI_AHA152X y $CONFIG_SCSI -dep_tristate 'Adaptec AHA1542 support' CONFIG_SCSI_AHA1542 n $CONFIG_SCSI +dep_tristate 'Adaptec AHA152X support' CONFIG_SCSI_AHA152X n $CONFIG_SCSI +dep_tristate 'Adaptec AHA1542 support' CONFIG_SCSI_AHA1542 y $CONFIG_SCSI dep_tristate 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 n $CONFIG_SCSI dep_tristate 'Adaptec AHA274X/284X/294X support' CONFIG_SCSI_AIC7XXX n $CONFIG_SCSI dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC n $CONFIG_SCSI diff -u --recursive --new-file v1.3.31/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- v1.3.31/linux/arch/i386/kernel/process.c Wed Oct 4 14:14:28 1995 +++ linux/arch/i386/kernel/process.c Thu Oct 5 08:31:40 1995 @@ -178,6 +178,10 @@ current->debugreg[i] = 0; } +void release_thread(struct task_struct *dead_task) +{ +} + void copy_thread(int nr, unsigned long clone_flags, unsigned long esp, struct task_struct * p, struct pt_regs * regs) { diff -u --recursive --new-file v1.3.31/linux/arch/i386/math-emu/README linux/arch/i386/math-emu/README --- v1.3.31/linux/arch/i386/math-emu/README Fri Aug 19 08:54:01 1994 +++ linux/arch/i386/math-emu/README Thu Oct 5 15:30:43 1995 @@ -1,9 +1,9 @@ +---------------------------------------------------------------------------+ | wm-FPU-emu an FPU emulator for 80386 and 80486SX microprocessors. | | | - | Copyright (C) 1992,1993,1994 | + | Copyright (C) 1992,1993,1994,1995 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | - | Australia. E-mail billm@vaxc.cc.monash.edu.au | + | Australia. E-mail billm@jacobi.maths.monash.edu.au | | | | This program is free software; you can redistribute it and/or modify | | it under the terms of the GNU General Public License version 2 as | @@ -42,13 +42,11 @@ some differences. Please report bugs, etc to me at: - billm@vaxc.cc.monash.edu.au - or at: billm@jacobi.maths.monash.edu.au --Bill Metzenthen - August 1994 + October 1995 ----------------------- Internals of wm-FPU-emu ----------------------- diff -u --recursive --new-file v1.3.31/linux/arch/i386/math-emu/div_Xsig.S linux/arch/i386/math-emu/div_Xsig.S --- v1.3.31/linux/arch/i386/math-emu/div_Xsig.S Thu Jun 29 19:02:39 1995 +++ linux/arch/i386/math-emu/div_Xsig.S Thu Oct 5 15:30:43 1995 @@ -4,9 +4,9 @@ | | | Division subroutine for 96 bit quantities | | | - | Copyright (C) 1994 | + | Copyright (C) 1994,1995 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | - | Australia. E-mail billm@vaxc.cc.monash.edu.au | + | Australia. E-mail billm@jacobi.maths.monash.edu.au | | | | | +---------------------------------------------------------------------------*/ @@ -28,7 +28,7 @@ +---------------------------------------------------------------------------*/ #include "exception.h" -#include "fpu_asm.h" +#include "fpu_emu.h" #define XsigLL(x) (x) diff -u --recursive --new-file v1.3.31/linux/arch/i386/math-emu/div_small.S linux/arch/i386/math-emu/div_small.S --- v1.3.31/linux/arch/i386/math-emu/div_small.S Thu Jun 29 19:02:39 1995 +++ linux/arch/i386/math-emu/div_small.S Thu Oct 5 15:30:43 1995 @@ -4,8 +4,9 @@ | | | Divide a 64 bit integer by a 32 bit integer & return remainder. | | | - | Copyright (C) 1992 W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | - | Australia. E-mail billm@vaxc.cc.monash.edu.au | + | Copyright (C) 1992,1995 | + | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | + | Australia. E-mail billm@jacobi.maths.monash.edu.au | | | | | +---------------------------------------------------------------------------*/ @@ -14,7 +15,7 @@ | unsigned long div_small(unsigned long long *x, unsigned long y) | +---------------------------------------------------------------------------*/ -#include "fpu_asm.h" +#include "fpu_emu.h" .text ENTRY(div_small) diff -u --recursive --new-file v1.3.31/linux/arch/i386/math-emu/fpu_asm.h linux/arch/i386/math-emu/fpu_asm.h --- v1.3.31/linux/arch/i386/math-emu/fpu_asm.h Thu Jun 29 19:02:39 1995 +++ linux/arch/i386/math-emu/fpu_asm.h Thu Oct 5 15:30:43 1995 @@ -1,8 +1,9 @@ /*---------------------------------------------------------------------------+ | fpu_asm.h | | | - | Copyright (C) 1992 W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | - | Australia. E-mail billm@vaxc.cc.monash.edu.au | + | Copyright (C) 1992,1995 | + | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | + | Australia. E-mail billm@jacobi.maths.monash.edu.au | | | +---------------------------------------------------------------------------*/ @@ -10,7 +11,6 @@ #define _FPU_ASM_H_ #include -#include "fpu_emu.h" #define EXCEPTION SYMBOL_NAME(exception) diff -u --recursive --new-file v1.3.31/linux/arch/i386/math-emu/mul_Xsig.S linux/arch/i386/math-emu/mul_Xsig.S --- v1.3.31/linux/arch/i386/math-emu/mul_Xsig.S Thu Jun 29 19:02:39 1995 +++ linux/arch/i386/math-emu/mul_Xsig.S Thu Oct 5 15:30:43 1995 @@ -3,9 +3,9 @@ | | | Multiply a 12 byte fixed point number by another fixed point number. | | | - | Copyright (C) 1992,1994 | + | Copyright (C) 1992,1994,1995 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | - | Australia. E-mail billm@vaxc.cc.monash.edu.au | + | Australia. E-mail billm@jacobi.maths.monash.edu.au | | | | Call from C as: | | void mul32_Xsig(Xsig *x, unsigned b) | @@ -21,7 +21,7 @@ .file "mul_Xsig.S" -#include "fpu_asm.h" +#include "fpu_emu.h" .text ENTRY(mul32_Xsig) diff -u --recursive --new-file v1.3.31/linux/arch/i386/math-emu/polynom_Xsig.S linux/arch/i386/math-emu/polynom_Xsig.S --- v1.3.31/linux/arch/i386/math-emu/polynom_Xsig.S Thu Jun 29 19:02:39 1995 +++ linux/arch/i386/math-emu/polynom_Xsig.S Thu Oct 5 15:30:43 1995 @@ -3,9 +3,9 @@ | | | Fixed point arithmetic polynomial evaluation. | | | - | Copyright (C) 1992,1993,1994 | + | Copyright (C) 1992,1993,1994,1995 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | - | Australia. E-mail billm@vaxc.cc.monash.edu.au | + | Australia. E-mail billm@jacobi.maths.monash.edu.au | | | | Call from C as: | | void polynomial_Xsig(Xsig *accum, unsigned long long x, | @@ -23,7 +23,7 @@ +---------------------------------------------------------------------------*/ .file "polynomial_Xsig.S" -#include "fpu_asm.h" +#include "fpu_emu.h" #define TERM_SIZE $8 diff -u --recursive --new-file v1.3.31/linux/arch/i386/math-emu/reg_div.S linux/arch/i386/math-emu/reg_div.S --- v1.3.31/linux/arch/i386/math-emu/reg_div.S Thu Jun 29 19:02:40 1995 +++ linux/arch/i386/math-emu/reg_div.S Thu Oct 5 15:30:43 1995 @@ -4,9 +4,9 @@ | | | Divide one FPU_REG by another and put the result in a destination FPU_REG.| | | - | Copyright (C) 1992,1993,1994 | + | Copyright (C) 1992,1993,1994,1995 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | - | Australia. E-mail billm@vaxc.cc.monash.edu.au | + | Australia. E-mail billm@jacobi.maths.monash.edu.au | | | | Call from C as: | | void reg_div(FPU_REG *a, FPU_REG *b, FPU_REG *dest, | @@ -15,7 +15,7 @@ +---------------------------------------------------------------------------*/ #include "exception.h" -#include "fpu_asm.h" +#include "fpu_emu.h" .text diff -u --recursive --new-file v1.3.31/linux/arch/i386/math-emu/reg_norm.S linux/arch/i386/math-emu/reg_norm.S --- v1.3.31/linux/arch/i386/math-emu/reg_norm.S Thu Jun 29 19:02:40 1995 +++ linux/arch/i386/math-emu/reg_norm.S Thu Oct 5 15:30:43 1995 @@ -1,9 +1,9 @@ /*---------------------------------------------------------------------------+ | reg_norm.S | | | - | Copyright (C) 1992,1993,1994 | + | Copyright (C) 1992,1993,1994,1995 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | - | Australia. E-mail billm@vaxc.cc.monash.edu.au | + | Australia. E-mail billm@jacobi.maths.monash.edu.au | | | | Normalize the value in a FPU_REG. | | | @@ -14,7 +14,7 @@ | | +---------------------------------------------------------------------------*/ -#include "fpu_asm.h" +#include "fpu_emu.h" .text diff -u --recursive --new-file v1.3.31/linux/arch/i386/math-emu/reg_round.S linux/arch/i386/math-emu/reg_round.S --- v1.3.31/linux/arch/i386/math-emu/reg_round.S Thu Jun 29 19:02:40 1995 +++ linux/arch/i386/math-emu/reg_round.S Thu Oct 5 15:30:43 1995 @@ -4,9 +4,9 @@ | | | Rounding/truncation/etc for FPU basic arithmetic functions. | | | - | Copyright (C) 1993 | + | Copyright (C) 1993,1995 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | - | Australia. E-mail billm@vaxc.cc.monash.edu.au | + | Australia. E-mail billm@jacobi.maths.monash.edu.au | | | | This code has four possible entry points. | | The following must be entered by a jmp instruction: | @@ -69,7 +69,7 @@ +---------------------------------------------------------------------------*/ -#include "fpu_asm.h" +#include "fpu_emu.h" #include "exception.h" #include "control_w.h" diff -u --recursive --new-file v1.3.31/linux/arch/i386/math-emu/reg_u_add.S linux/arch/i386/math-emu/reg_u_add.S --- v1.3.31/linux/arch/i386/math-emu/reg_u_add.S Thu Jun 29 19:02:40 1995 +++ linux/arch/i386/math-emu/reg_u_add.S Thu Oct 5 15:30:43 1995 @@ -5,9 +5,9 @@ | Add two valid (TW_Valid) FPU_REG numbers, of the same sign, and put the | | result in a destination FPU_REG. | | | - | Copyright (C) 1992,1993 | + | Copyright (C) 1992,1993,1995 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | - | Australia. E-mail billm@vaxc.cc.monash.edu.au | + | Australia. E-mail billm@jacobi.maths.monash.edu.au | | | | Call from C as: | | void reg_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ, | @@ -25,7 +25,7 @@ */ #include "exception.h" -#include "fpu_asm.h" +#include "fpu_emu.h" #include "control_w.h" .text diff -u --recursive --new-file v1.3.31/linux/arch/i386/math-emu/reg_u_div.S linux/arch/i386/math-emu/reg_u_div.S --- v1.3.31/linux/arch/i386/math-emu/reg_u_div.S Thu Jun 29 19:02:40 1995 +++ linux/arch/i386/math-emu/reg_u_div.S Thu Oct 5 15:30:43 1995 @@ -4,9 +4,9 @@ | | | Core division routines | | | - | Copyright (C) 1992,1993 | + | Copyright (C) 1992,1993,1995 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | - | Australia. E-mail billm@vaxc.cc.monash.edu.au | + | Australia. E-mail billm@jacobi.maths.monash.edu.au | | | | | +---------------------------------------------------------------------------*/ @@ -21,7 +21,7 @@ +---------------------------------------------------------------------------*/ #include "exception.h" -#include "fpu_asm.h" +#include "fpu_emu.h" #include "control_w.h" diff -u --recursive --new-file v1.3.31/linux/arch/i386/math-emu/reg_u_mul.S linux/arch/i386/math-emu/reg_u_mul.S --- v1.3.31/linux/arch/i386/math-emu/reg_u_mul.S Thu Jun 29 19:02:40 1995 +++ linux/arch/i386/math-emu/reg_u_mul.S Thu Oct 5 15:30:43 1995 @@ -4,9 +4,9 @@ | | | Core multiplication routine | | | - | Copyright (C) 1992,1993 | + | Copyright (C) 1992,1993,1995 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | - | Australia. E-mail billm@vaxc.cc.monash.edu.au | + | Australia. E-mail billm@jacobi.maths.monash.edu.au | | | | | +---------------------------------------------------------------------------*/ @@ -22,7 +22,7 @@ +---------------------------------------------------------------------------*/ #include "exception.h" -#include "fpu_asm.h" +#include "fpu_emu.h" #include "control_w.h" diff -u --recursive --new-file v1.3.31/linux/arch/i386/math-emu/reg_u_sub.S linux/arch/i386/math-emu/reg_u_sub.S --- v1.3.31/linux/arch/i386/math-emu/reg_u_sub.S Thu Jun 29 19:02:40 1995 +++ linux/arch/i386/math-emu/reg_u_sub.S Thu Oct 5 15:30:43 1995 @@ -4,9 +4,9 @@ | | | Core floating point subtraction routine. | | | - | Copyright (C) 1992,1993 | + | Copyright (C) 1992,1993,1995 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | - | Australia. E-mail billm@vaxc.cc.monash.edu.au | + | Australia. E-mail billm@jacobi.maths.monash.edu.au | | | | Call from C as: | | void reg_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ, | @@ -26,7 +26,7 @@ */ #include "exception.h" -#include "fpu_asm.h" +#include "fpu_emu.h" #include "control_w.h" .text diff -u --recursive --new-file v1.3.31/linux/arch/i386/math-emu/round_Xsig.S linux/arch/i386/math-emu/round_Xsig.S --- v1.3.31/linux/arch/i386/math-emu/round_Xsig.S Thu Jun 29 19:02:40 1995 +++ linux/arch/i386/math-emu/round_Xsig.S Thu Oct 5 15:30:43 1995 @@ -1,9 +1,9 @@ /*---------------------------------------------------------------------------+ | round_Xsig.S | | | - | Copyright (C) 1992,1993,1994 | + | Copyright (C) 1992,1993,1994,1995 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | - | Australia. E-mail billm@vaxc.cc.monash.edu.au | + | Australia. E-mail billm@jacobi.maths.monash.edu.au | | | | Normalize and round a 12 byte quantity. | | Call from C as: | @@ -18,7 +18,7 @@ +---------------------------------------------------------------------------*/ .file "round_Xsig.S" -#include "fpu_asm.h" +#include "fpu_emu.h" .text diff -u --recursive --new-file v1.3.31/linux/arch/i386/math-emu/shr_Xsig.S linux/arch/i386/math-emu/shr_Xsig.S --- v1.3.31/linux/arch/i386/math-emu/shr_Xsig.S Thu Jun 29 19:02:40 1995 +++ linux/arch/i386/math-emu/shr_Xsig.S Thu Oct 5 15:30:43 1995 @@ -4,9 +4,9 @@ | | | 12 byte right shift function | | | - | Copyright (C) 1992,1994 | + | Copyright (C) 1992,1994,1995 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | - | Australia. E-mail billm@vaxc.cc.monash.edu.au | + | Australia. E-mail billm@jacobi.maths.monash.edu.au | | | | Call from C as: | | void shr_Xsig(Xsig *arg, unsigned nr) | @@ -18,7 +18,7 @@ | | +---------------------------------------------------------------------------*/ -#include "fpu_asm.h" +#include "fpu_emu.h" .text ENTRY(shr_Xsig) diff -u --recursive --new-file v1.3.31/linux/arch/i386/math-emu/wm_shrx.S linux/arch/i386/math-emu/wm_shrx.S --- v1.3.31/linux/arch/i386/math-emu/wm_shrx.S Thu Jun 29 19:02:40 1995 +++ linux/arch/i386/math-emu/wm_shrx.S Thu Oct 5 15:30:43 1995 @@ -4,8 +4,9 @@ | | | 64 bit right shift functions | | | - | Copyright (C) 1992 W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | - | Australia. E-mail billm@vaxc.cc.monash.edu.au | + | Copyright (C) 1992,1995 | + | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | + | Australia. E-mail billm@jacobi.maths.monash.edu.au | | | | Call from C as: | | unsigned shrx(void *arg1, unsigned arg2) | @@ -14,7 +15,7 @@ | | +---------------------------------------------------------------------------*/ -#include "fpu_asm.h" +#include "fpu_emu.h" .text /*---------------------------------------------------------------------------+ diff -u --recursive --new-file v1.3.31/linux/arch/i386/math-emu/wm_sqrt.S linux/arch/i386/math-emu/wm_sqrt.S --- v1.3.31/linux/arch/i386/math-emu/wm_sqrt.S Thu Jun 29 19:02:40 1995 +++ linux/arch/i386/math-emu/wm_sqrt.S Thu Oct 5 15:30:43 1995 @@ -4,9 +4,9 @@ | | | Fixed point arithmetic square root evaluation. | | | - | Copyright (C) 1992,1993 | + | Copyright (C) 1992,1993,1995 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | - | Australia. E-mail billm@vaxc.cc.monash.edu.au | + | Australia. E-mail billm@jacobi.maths.monash.edu.au | | | | Call from C as: | | void wm_sqrt(FPU_REG *n, unsigned int control_word) | @@ -26,7 +26,7 @@ +---------------------------------------------------------------------------*/ #include "exception.h" -#include "fpu_asm.h" +#include "fpu_emu.h" #ifndef NON_REENTRANT_FPU diff -u --recursive --new-file v1.3.31/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c --- v1.3.31/linux/arch/mips/kernel/process.c Sun Sep 3 12:26:49 1995 +++ linux/arch/mips/kernel/process.c Thu Oct 5 08:31:41 1995 @@ -85,6 +85,13 @@ */ } +void release_thread(struct task_struct *dead_task) +{ + /* + * Nothing to do + */ +} + #define IS_CLONE (regs->orig_reg2 == __NR_clone) void copy_thread(int nr, unsigned long clone_flags, struct task_struct * p, struct pt_regs * regs) diff -u --recursive --new-file v1.3.31/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c --- v1.3.31/linux/arch/sparc/kernel/process.c Sun Sep 3 12:26:49 1995 +++ linux/arch/sparc/kernel/process.c Thu Oct 5 08:31:41 1995 @@ -72,6 +72,11 @@ halt(); } +void release_thread(struct task_struct *dead_task) +{ + halt(); +} + extern void ret_sys_call(void); /* diff -u --recursive --new-file v1.3.31/linux/drivers/net/3c507.c linux/drivers/net/3c507.c --- v1.3.31/linux/drivers/net/3c507.c Mon Sep 18 14:53:54 1995 +++ linux/drivers/net/3c507.c Fri Oct 6 11:33:04 1995 @@ -830,7 +830,7 @@ ushort pkt_len = data_frame[0]; if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22 - || pkt_len & 0xC000 != 0xC000) { + || (pkt_len & 0xC000) != 0xC000) { printk("%s: Rx frame at %#x corrupted, status %04x cmd %04x" "next %04x data-buf @%04x %04x.\n", dev->name, rx_head, frame_status, rfd_cmd, next_rx_frame, data_buffer_addr, diff -u --recursive --new-file v1.3.31/linux/drivers/net/at1700.c linux/drivers/net/at1700.c --- v1.3.31/linux/drivers/net/at1700.c Sat Sep 9 15:26:52 1995 +++ linux/drivers/net/at1700.c Fri Oct 6 11:33:17 1995 @@ -187,7 +187,7 @@ #endif if (at1700_probe_list[inb(ioaddr + IOCONFIG) & 0x07] != ioaddr || read_eeprom(ioaddr, 4) != 0x0000 - || read_eeprom(ioaddr, 5) & 0xff00 != 0xF400) + || (read_eeprom(ioaddr, 5) & 0xff00) != 0xF400) return -ENODEV; /* Reset the internal state machines. */ diff -u --recursive --new-file v1.3.31/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c --- v1.3.31/linux/drivers/net/eexpress.c Mon Sep 18 14:53:54 1995 +++ linux/drivers/net/eexpress.c Fri Oct 6 11:32:46 1995 @@ -923,7 +923,7 @@ pkt_len = inw(ioaddr); if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22 - || pkt_len & 0xC000 != 0xC000) { + || (pkt_len & 0xC000) != 0xC000) { printk("%s: Rx frame at %#x corrupted, status %04x cmd %04x" "next %04x data-buf @%04x %04x.\n", dev->name, rx_head, frame_status, rfd_cmd, next_rx_frame, data_buffer_addr, diff -u --recursive --new-file v1.3.31/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c --- v1.3.31/linux/drivers/net/ewrk3.c Sat Sep 9 15:26:52 1995 +++ linux/drivers/net/ewrk3.c Fri Oct 6 11:34:02 1995 @@ -417,7 +417,7 @@ */ DISABLE_IRQs; - if (nicsr == TXD|RXD) { + if (nicsr == (TXD|RXD)) { /* ** Check that the EEPROM is alive and well and not living on Pluto... diff -u --recursive --new-file v1.3.31/linux/drivers/net/slhc.c linux/drivers/net/slhc.c --- v1.3.31/linux/drivers/net/slhc.c Wed Aug 2 13:21:05 1995 +++ linux/drivers/net/slhc.c Fri Oct 6 11:31:12 1995 @@ -83,6 +83,10 @@ #include #include "slhc.h" +#ifdef __alpha__ +# include +#endif + int last_retran; static unsigned char *encode(unsigned char *cp, unsigned short n); @@ -621,7 +625,11 @@ cp += (ip->ihl - 5) * 4; } +#ifdef __alpha__ + stw_u(ip_fast_csum(icp, ip->ihl), &((struct iphdr *)icp)->check); +#else ((struct iphdr *)icp)->check = ip_fast_csum(icp, ((struct iphdr*)icp)->ihl); +#endif memcpy(cp, thp, 20); cp += 20; diff -u --recursive --new-file v1.3.31/linux/drivers/net/znet.c linux/drivers/net/znet.c --- v1.3.31/linux/drivers/net/znet.c Tue Aug 8 12:31:37 1995 +++ linux/drivers/net/znet.c Fri Oct 6 11:33:30 1995 @@ -448,7 +448,7 @@ if (!(tx_status & 0x0040)) lp->stats.tx_heartbeat_errors++; if (tx_status & 0x0020) lp->stats.tx_aborted_errors++; /* ...and the catch-all. */ - if (tx_status | 0x0760 != 0x0760) + if ((tx_status | 0x0760) != 0x0760) lp->stats.tx_errors++; } dev->tbusy = 0; diff -u --recursive --new-file v1.3.31/linux/fs/nfs/Makefile linux/fs/nfs/Makefile --- v1.3.31/linux/fs/nfs/Makefile Tue Aug 15 20:39:04 1995 +++ linux/fs/nfs/Makefile Wed Oct 4 15:41:42 1995 @@ -8,7 +8,7 @@ # Note 2! The CFLAGS definitions are now in the main makefile... O_TARGET := nfs.o -O_OBJS := proc.o sock.o inode.o file.o dir.o symlink.o mmap.o +O_OBJS := proc.o sock.o rpcsock.o inode.o file.o dir.o symlink.o mmap.o M_OBJS := $(O_TARGET) include $(TOPDIR)/Rules.make diff -u --recursive --new-file v1.3.31/linux/fs/nfs/inode.c linux/fs/nfs/inode.c --- v1.3.31/linux/fs/nfs/inode.c Mon Sep 18 14:54:07 1995 +++ linux/fs/nfs/inode.c Wed Oct 4 15:41:42 1995 @@ -59,6 +59,7 @@ void nfs_put_super(struct super_block *sb) { close_fp(sb->u.nfs_sb.s_server.file); + rpc_closesock(sb->u.nfs_sb.s_server.rsock); lock_super(sb); sb->s_dev = 0; unlock_super(sb); @@ -162,6 +163,12 @@ memcpy((char *)&(server->toaddr),(char *)(&data->addr),sizeof(server->toaddr)); } /* End of JSP NFS patch */ + + if ((server->rsock = rpc_makesock(filp)) == NULL) { + printk("NFS: cannot create RPC socket.\n"); + MOD_DEC_USE_COUNT; + return NULL; + } sb->u.nfs_sb.s_root = data->root; unlock_super(sb); diff -u --recursive --new-file v1.3.31/linux/fs/nfs/rpcsock.c linux/fs/nfs/rpcsock.c --- v1.3.31/linux/fs/nfs/rpcsock.c Thu Jan 1 02:00:00 1970 +++ linux/fs/nfs/rpcsock.c Wed Oct 4 15:41:42 1995 @@ -0,0 +1,391 @@ +/* + * linux/fs/nfs/rpcsock.c + * + * This is a generic RPC call interface for datagram sockets that is able + * to place several concurrent RPC requests at the same time. It works like + * this: + * + * - When a process places a call, it allocates a request slot if + * one is available. Otherwise, it sleeps on the backlog queue. + * - The first process on the receive queue waits for the next RPC reply, + * and peeks at the XID. If it finds a matching request, it receives + * the datagram on behalf of that process and wakes it up. Otherwise, + * the datagram is discarded. + * - If the process having received the datagram was the first one on + * the receive queue, it wakes up the next one to listen for replies. + * - It then removes itself from the request queue. If there are more + * callers waiting on the backlog queue, they are woken up, too. + * + * Copyright (C) 1995, Olaf Kirch + */ + +#ifdef MODULE +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define msleep(sec) { current->timeout = sec * HZ / 1000; \ + current->state = TAKS_INTERRUPTIBLE; \ + schedule(); \ + } +#define dprintk if (0) printk + +static inline void +rpc_insque(struct rpc_sock *rsock, struct rpc_wait *slot) +{ + struct rpc_wait *tmp; + + if ((tmp = rsock->tail) != NULL) { + tmp->next = slot; + } else { + rsock->head = slot; + } + rsock->tail = slot; + slot->prev = tmp; + slot->next = NULL; + dprintk("RPC: inserted %08lx into queue.\n", (long)slot); + dprintk("RPC: head = %08lx, tail = %08lx.\n", + (long) rsock->head, (long) rsock->tail); +} + +static inline void +rpc_remque(struct rpc_sock *rsock, struct rpc_wait *slot) +{ + struct rpc_wait *prev = slot->prev, + *next = slot->next; + + if (prev != NULL) + prev->next = next; + else + rsock->head = next; + if (next != NULL) + next->prev = prev; + else + rsock->tail = prev; + dprintk("RPC: removed %08lx from queue.\n", (long)slot); + dprintk("RPC: head = %08lx, tail = %08lx.\n", + (long) rsock->head, (long) rsock->tail); +} + +static inline int +rpc_sendto(struct rpc_sock *rsock, const int *buf, int len, + struct sockaddr *sap, int salen) +{ + struct socket *sock = rsock->sock; + unsigned long oldfs; + int result; + + dprintk("RPC: sending %d bytes (buf %08lx)\n", len, (long) buf); + oldfs = get_fs(); + set_fs(get_ds()); + result = sock->ops->sendto(sock, buf, len, 0, 0, sap, salen); + set_fs(oldfs); + dprintk("RPC: result = %d\n", result); + + return result; +} + +/* + * This code is slightly complicated. Since the networking code does not + * honor the current->timeout value, we have to select on the socket. + */ +static inline int +rpc_select(struct rpc_sock *rsock) +{ + struct select_table_entry entry; + struct file *file = rsock->file; + select_table wait_table; + + dprintk("RPC: selecting on socket...\n"); + wait_table.nr = 0; + wait_table.entry = &entry; + current->state = TASK_INTERRUPTIBLE; + if (!file->f_op->select(file->f_inode, file, SEL_IN, &wait_table) + && !file->f_op->select(file->f_inode, file, SEL_IN, NULL)) { + schedule(); + remove_wait_queue(entry.wait_address, &entry.wait); + current->state = TASK_RUNNING; + if (current->signal & ~current->blocked) + return -ERESTARTSYS; + if (current->timeout == 0) + return -ETIMEDOUT; + } else if (wait_table.nr) + remove_wait_queue(entry.wait_address, &entry.wait); + current->state = TASK_RUNNING; + dprintk("RPC: ...Okay, there appears to be some data.\n"); + return 0; +} + +static inline int +rpc_recvfrom(struct rpc_sock *rsock, int *buf, int len, + struct sockaddr *sap, int salen, int flags) +{ + struct socket *sock = rsock->sock; + struct sockaddr sa; + int alen = sizeof(sa); + unsigned long oldfs; + int result; + + dprintk("RPC: receiving %d bytes max (buf %08lx)\n", len, (long) buf); + oldfs = get_fs(); + set_fs(get_ds()); + result = sock->ops->recvfrom(sock, buf, len, 1, flags, &sa, &alen); + set_fs(oldfs); + dprintk("RPC: result = %d\n", result); + +#if 0 + if (alen != salen || memcmp(&sa, sap, alen)) { + dprintk("RPC: reply address mismatch... rejected.\n"); + result = -EAGAIN; + } +#endif + + return result; +} + +/* + * Place the actual RPC call. + */ +static int +rpc_call_one(struct rpc_sock *rsock, struct rpc_wait *slot, + struct sockaddr *sap, int salen, + const int *sndbuf, int slen, int *rcvbuf, int rlen) +{ + struct rpc_wait *rovr = NULL; + int result; + u32 xid; + int safe; + + dprintk("RPC: placing one call, rsock = %08lx, slot = %08lx, " + "sap = %08lx, salen = %d, " + "sndbuf = %08lx, slen = %d, rcvbuf = %08lx, rlen = %d\n", + (long) rsock, (long) slot, (long) sap, + salen, (long) sndbuf, slen, (long) rcvbuf, rlen); + + result = rpc_sendto(rsock, sndbuf, slen, sap, salen); + if (result < 0) + return result; + + do { + /* We are not the receiver. Wait on the side lines. */ + if (rsock->head != slot) { + slot->wait = NULL; + interruptible_sleep_on(&slot->wait); + if (slot->gotit) + break; + if (current->timeout != 0) + continue; + if (rsock->shutdown) { + printk("RPC: aborting call due to shutdown.\n"); + return -EIO; + } + return -ETIMEDOUT; + } + + /* wait for data to arrive */ + result = rpc_select(rsock); + if (result < 0) { + dprintk("RPC: select error = %d\n", result); + break; + } + + result = rpc_recvfrom(rsock, (int *)&xid, sizeof(xid), + sap, salen, MSG_PEEK); + if (result < 0) { + switch (-result) { + case EAGAIN: case ECONNREFUSED: + continue; + default: + dprintk("rpc_call: recv error = %d\n", result); + case ERESTARTSYS: + return result; + } + } + + /* Look for the caller */ + safe = 0; + for (rovr = rsock->head; rovr; rovr = rovr->next) { + if (safe++ > NRREQS) { + printk("RPC: loop in request Q!!\n"); + rovr = NULL; + break; + } + if (rovr->xid == xid) + break; + } + + if (!rovr || rovr->gotit) { + /* bad XID or duplicate reply, discard dgram */ + dprintk("RPC: bad XID or duplicate reply.\n"); + rpc_recvfrom(rsock, (int *)&xid, sizeof(xid), + sap, salen, 0); + continue; + } + rovr->gotit = 1; + + /* Now receive the reply */ + result = rpc_recvfrom(rsock, rovr->buf, rovr->len, + sap, salen, 0); + + /* If this is not for ourselves, wake up the caller */ + if (rovr != slot) + wake_up(&rovr->wait); + } while (rovr != slot); + + /* This is somewhat tricky. We rely on the fact that we are able to + * remove ourselves from the queues before the next reader is scheduled, + * otherwise it would find that we're still at the head of the queue + * and go to sleep again. + */ + if (rsock->head == slot && slot->next != NULL) + wake_up(&slot->next->wait); + + return result; +} + +/* + * Generic RPC call routine. This handles retries and timeouts etc pp + */ +int +rpc_call(struct rpc_sock *rsock, struct sockaddr *sap, int addrlen, + const int *sndbuf, int slen, int *rcvbuf, int rlen, + struct rpc_timeout *strategy, int flag) +{ + struct rpc_wait *slot; + int result, retries; + unsigned long timeout; + + timeout = strategy->init_timeout; + retries = 0; + slot = NULL; + + do { + dprintk("RPC call TP1\n"); + current->timeout = jiffies + timeout; + if (slot == NULL) { + while ((slot = rsock->free) == NULL) { + if (!flag) { + current->timeout = 0; + return -ENOBUFS; + } + interruptible_sleep_on(&rsock->backlog); + if (current->timeout == 0) { + result = -ETIMEDOUT; + goto timedout; + } + if (rsock->shutdown) { + printk("RPC: aborting call due to shutdown.\n"); + current->timeout = 0; + return -EIO; + } + } + dprintk("RPC call TP2\n"); + slot->gotit = 0; + slot->xid = *(u32 *)sndbuf; + slot->buf = rcvbuf; + slot->len = rlen; + rsock->free = slot->next; + rpc_insque(rsock, slot); + } + + dprintk("RPC call TP3\n"); + result = rpc_call_one(rsock, slot, sap, addrlen, + sndbuf, slen, rcvbuf, rlen); + if (result != -ETIMEDOUT) + break; + +timedout: + dprintk("RPC call TP4\n"); + dprintk("RPC: rpc_call_one returned timeout.\n"); + if (strategy->exponential) + timeout <<= 1; + else + timeout += strategy->increment; + if (strategy->max_timeout && timeout >= strategy->max_timeout) + timeout = strategy->max_timeout; + if (strategy->retries && ++retries >= strategy->retries) + break; + } while (1); + + dprintk("RPC call TP5\n"); + current->timeout = 0; + if (slot != NULL) { + dprintk("RPC call TP6\n"); + rpc_remque(rsock, slot); + slot->next = rsock->free; + rsock->free = slot; + + /* wake up tasks that haven't sent anything yet. (Waking + * up the first one the wait queue would be enough) */ + if (rsock->backlog) + wake_up(&rsock->backlog); + } + + if (rsock->shutdown) + wake_up(&rsock->shutwait); + + return result; +} + +struct rpc_sock * +rpc_makesock(struct file *file) +{ + struct rpc_sock *rsock; + struct rpc_wait *slot; + int i; + + dprintk("RPC: make RPC socket...\n"); + if ((rsock = kmalloc(sizeof(struct rpc_sock), GFP_KERNEL)) == NULL) + return NULL; + + rsock->sock = &file->f_inode->u.socket_i; + rsock->file = file; + + rsock->free = rsock->waiting; + for (i = 0, slot = rsock->waiting; i < NRREQS-1; i++, slot++) + slot->next = slot + 1; + slot->next = NULL; + + rsock->backlog = NULL; + rsock->head = rsock->tail = NULL; + + rsock->shutwait = NULL; + rsock->shutdown = 0; + + dprintk("RPC: made socket %08lx", (long) rsock); + return rsock; +} + +int +rpc_closesock(struct rpc_sock *rsock) +{ + unsigned long t0 = jiffies; + + rsock->shutdown = 1; + while (rsock->head) { + interruptible_sleep_on(&rsock->shutwait); + if (current->signal & ~current->blocked) + return -EINTR; +#if 1 + if (t0 && t0 - jiffies > 60 * HZ) { + printk("RPC: hanging in rpc_closesock.\n"); + t0 = 0; + } +#endif + } + + kfree(rsock); + return 0; +} diff -u --recursive --new-file v1.3.31/linux/fs/nfs/sock.c linux/fs/nfs/sock.c --- v1.3.31/linux/fs/nfs/sock.c Wed Sep 13 12:45:32 1995 +++ linux/fs/nfs/sock.c Wed Oct 4 15:41:42 1995 @@ -31,6 +31,7 @@ #include #include #include +#include /* JEJB/JSP 2/7/94 * this must match the value of NFS_SLACK_SPACE in linux/fs/nfs/proc.c @@ -49,197 +50,64 @@ * to the server socket. */ -static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size) +int +nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size) { - struct file *file; - struct inode *inode; - struct socket *sock; - unsigned short fs; - int result; - int xid; - int len; - select_table wait_table; - struct select_table_entry entry; - int (*select) (struct inode *, struct file *, int, select_table *); - int init_timeout, max_timeout; - int timeout; - int retrans; - int major_timeout_seen; - char *server_name; - int n; - int addrlen; - unsigned long old_mask; - /* JEJB/JSP 2/7/94 - * This is for a 4 byte recv of the xid only */ - int recv_xid; - - xid = start[0]; - len = ((char *) end) - ((char *) start); - file = server->file; - inode = file->f_inode; - select = file->f_op->select; - sock = &inode->u.socket_i; - if (!sock) { - printk("nfs_rpc_call: socki_lookup failed\n"); - return -EBADF; - } - init_timeout = server->timeo; - max_timeout = NFS_MAX_RPC_TIMEOUT*HZ/10; - retrans = server->retrans; - major_timeout_seen = 0; - server_name = server->hostname; - old_mask = current->blocked; + struct rpc_timeout timeout; + unsigned long maxtimeo; + unsigned long oldmask; + int major_timeout_seen, result; + + timeout.init_timeout = server->timeo; + timeout.max_timeout = maxtimeo = NFS_MAX_RPC_TIMEOUT*HZ/10; + timeout.retries = server->retrans; + timeout.exponential = 1; + + oldmask = current->blocked; current->blocked |= ~(_S(SIGKILL) -#if 0 - | _S(SIGSTOP) -#endif | ((server->flags & NFS_MOUNT_INTR) ? ((current->sig->action[SIGINT - 1].sa_handler == SIG_DFL ? _S(SIGINT) : 0) | (current->sig->action[SIGQUIT - 1].sa_handler == SIG_DFL ? _S(SIGQUIT) : 0)) : 0)); - fs = get_fs(); - set_fs(get_ds()); - for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) { - /* JSP 1995-07-01 Use sendto() not send() to cope with multi-homed hosts - as we have set the socket to have INADDR_ANY as it's desination */ - result = sock->ops->sendto(sock, (void *) start, len, 0, 0, - &(server->toaddr), sizeof((server->toaddr))) ; - if (result < 0) { - printk("nfs_rpc_call: send error = %d\n", result); - break; - } - re_select: - wait_table.nr = 0; - wait_table.entry = &entry; - current->state = TASK_INTERRUPTIBLE; - if (!select(inode, file, SEL_IN, &wait_table) - && !select(inode, file, SEL_IN, NULL)) { - if (timeout > max_timeout) { - /* JEJB/JSP 2/7/94 - * This is useful to see if the system is - * hanging */ - printk("NFS max timeout reached on %s\n", - server_name); - timeout = max_timeout; - } - current->timeout = jiffies + timeout; - schedule(); - remove_wait_queue(entry.wait_address, &entry.wait); - current->state = TASK_RUNNING; - if (current->signal & ~current->blocked) { - current->timeout = 0; - result = -ERESTARTSYS; + major_timeout_seen = 0; + + do { + result = rpc_call(server->rsock, + &server->toaddr, sizeof(server->toaddr), + start, ((char *) end) - ((char *) start), + start, size + 1024, + &timeout, 1); + if (current->signal & ~current->blocked) + result = -ERESTARTSYS; + if (result == -ETIMEDOUT) { + if (server->flags & NFS_MOUNT_SOFT) { + printk("NFS server %s not responding, " + "still trying.\n", server->hostname); + result = -EIO; break; } - if (!current->timeout) { - if (n < retrans) - continue; - if (server->flags & NFS_MOUNT_SOFT) { - printk("NFS server %s not responding, " - "timed out\n", server_name); - result = -EIO; - break; - } - n = 0; - timeout = init_timeout; - init_timeout <<= 1; - if (!major_timeout_seen) { - printk("NFS server %s not responding, " - "still trying\n", server_name); - } + if (!major_timeout_seen) { + printk("NFS server %s not responding, " + "timed out.\n", server->hostname); major_timeout_seen = 1; - continue; - } - else - current->timeout = 0; - } - else if (wait_table.nr) - remove_wait_queue(entry.wait_address, &entry.wait); - current->state = TASK_RUNNING; - addrlen = 0; - /* JEJB/JSP 2/7/94 - * Get the xid from the next packet using a peek, so keep it - * on the recv queue. If it is wrong, it will be some reply - * we don't now need, so discard it */ - result = sock->ops->recvfrom(sock, (void *)&recv_xid, - sizeof(recv_xid), 1, MSG_PEEK, - NULL, &addrlen); - if (result < 0) { - if (result == -EAGAIN) { -#if 0 - printk("nfs_rpc_call: bad select ready\n"); -#endif - goto re_select; - } - if (result == -ECONNREFUSED) { -#if 0 - printk("nfs_rpc_call: server playing coy\n"); -#endif - goto re_select; - } - if (result != -ERESTARTSYS) { - printk("nfs_rpc_call: recv error = %d\n", - -result); } - break; + if ((timeout.init_timeout <<= 1) >= maxtimeo) + timeout.init_timeout = maxtimeo; + } else if (result < 0) { + printk("NFS: notice message: result = %d.\n", result); } - if (recv_xid == xid) { - if (major_timeout_seen) - printk("NFS server %s OK\n", server_name); - break; - } - /* JEJB/JSP 2/7/94 - * we have xid mismatch, so discard the packet and start - * again. What a hack! but I can't call recvfrom with - * a null buffer yet. */ - (void)sock->ops->recvfrom(sock, (void *)&recv_xid, - sizeof(recv_xid), 1, 0, NULL, - &addrlen); -#if 0 - printk("nfs_rpc_call: XID mismatch\n"); -#endif - goto re_select; - } - /* JEJB/JSP 2/7/94 - * - * we have the correct xid, so read into the correct place and - * return it - * - */ - result=sock->ops->recvfrom(sock, (void *)start, - size + 1024, 1, 0, NULL, - /* Here is NFS_SLACK_SPACE..., hack */ - &addrlen); - if (result < 0) { - printk("NFS: notice message: result=%d\n", result); - } else if (result < addrlen) { - printk("NFS: just caught a too small read memory size..., email to NET channel\n"); - printk("NFS: result=%d,addrlen=%d\n", result, addrlen); + } while (result == -ETIMEDOUT && !(server->flags & NFS_MOUNT_SOFT)); + + if (result >= 0 && major_timeout_seen) + printk("NFS server %s OK.\n", server->hostname); + /* 20 is the minimum RPC reply header size */ + if (result >= 0 && result < 20) { + printk("NFS: too small read memory size (%d bytes)\n", result); result = -EIO; } - current->blocked = old_mask; - set_fs(fs); - return result; -} -/* - * For now we lock out other simultaneous nfs calls for the same filesystem - * because we are single-threaded and don't want to get mismatched - * RPC replies. - */ - -int nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size) -{ - int result; - - while (server->lock) - sleep_on(&server->wait); - server->lock = 1; - result = do_nfs_rpc_call(server, start, end, size); - server->lock = 0; - wake_up(&server->wait); + current->blocked = oldmask; return result; } - diff -u --recursive --new-file v1.3.31/linux/include/asm-alpha/apecs.h linux/include/asm-alpha/apecs.h --- v1.3.31/linux/include/asm-alpha/apecs.h Sun Sep 3 12:27:01 1995 +++ linux/include/asm-alpha/apecs.h Fri Oct 6 11:31:12 1995 @@ -351,17 +351,8 @@ #endif /* __KERNEL__ */ /* - * data structures for handling APECS machine checks + * Data structure for handling APECS machine checks: */ - -struct el_common_logout_header { - u_int elfl_size; /* size in bytes of logout area. */ - int elfl_sbz1:31; /* Should be zero. */ - char elfl_retry:1; /* Retry flag. */ - u_int elfl_procoffset; /* Processor-specific offset. */ - u_int elfl_sysoffset; /* Offset of system-specific. */ -}; - struct el_apecs_sysdata_mcheck { u_long coma_gcr; u_long coma_edsr; diff -u --recursive --new-file v1.3.31/linux/include/asm-alpha/lca.h linux/include/asm-alpha/lca.h --- v1.3.31/linux/include/asm-alpha/lca.h Sun Sep 3 12:27:01 1995 +++ linux/include/asm-alpha/lca.h Fri Oct 6 11:31:12 1995 @@ -52,6 +52,8 @@ * ugh). */ +#include + #define LCA_DMA_WIN_BASE (1024*1024*1024) #define LCA_DMA_WIN_SIZE (1024*1024*1024) @@ -323,6 +325,45 @@ extern unsigned long lca_init (unsigned long mem_start, unsigned long mem_end); #endif /* __KERNEL__ */ + +/* + * Data structure for handling LCA machine checks. Correctable errors + * result in a short logout frame, uncorrectably ones in a long one. + */ +struct el_lca_mcheck_short { + struct el_common h; /* common logout header */ + unsigned long reason; /* reason for machine check */ + unsigned long esr; /* error-status register */ + unsigned long ear; /* error-address register */ + unsigned long dc_stat; /* dcache status register */ + unsigned long ioc_stat0; /* I/O controller status register 0 */ + unsigned long ioc_stat1; /* I/O controller status register 1 */ +}; + +struct el_lca_mcheck_long { + struct el_common h; /* common logout header */ + unsigned long pt[32]; /* PAL temps (pt[0] is reason) */ + unsigned long exc_addr; /* exception address */ + unsigned long pal_base; /* PALcode base address */ + unsigned long hier; /* hw interrupt enable */ + unsigned long hirr; /* hw interrupt request */ + unsigned long mm_csr; /* MMU control & status */ + unsigned long dc_stat; /* data cache status */ + unsigned long dc_addr; /* data cache addr register */ + unsigned long abox_ctl; /* address box control register */ + unsigned long esr; /* error status register */ + unsigned long ear; /* error address register */ + unsigned long car; /* cache control register */ + unsigned long ioc_stat0; /* I/O controller status register 0 */ + unsigned long ioc_stat1; /* I/O controller status register 1 */ + unsigned long va; /* virtual address register */ +}; + +union el_lca { + struct el_common * c; + struct el_lca_mcheck_long * l; + struct el_lca_mcheck_short * s; +}; #define RTC_PORT(x) (0x70 + (x)) #define RTC_ADDR(x) (0x80 | (x)) diff -u --recursive --new-file v1.3.31/linux/include/asm-alpha/system.h linux/include/asm-alpha/system.h --- v1.3.31/linux/include/asm-alpha/system.h Tue Jul 25 18:21:23 1995 +++ linux/include/asm-alpha/system.h Fri Oct 6 11:31:12 1995 @@ -31,6 +31,18 @@ #ifndef __ASSEMBLY__ +/* + * This is the logout header that should be common to all platforms + * (assuming they are running OSF/1 PALcode, I guess). + */ +struct el_common { + unsigned int size; /* size in bytes of logout area */ + int sbz1 : 31; /* should be zero */ + char retry : 1; /* retry flag */ + unsigned int proc_offset; /* processor-specific offset */ + unsigned int sys_offset; /* system-specific offset */ +}; + extern void wrent(void *, unsigned long); extern void wrkgp(unsigned long); extern void wrusp(unsigned long); diff -u --recursive --new-file v1.3.31/linux/include/asm-i386/byteorder.h linux/include/asm-i386/byteorder.h --- v1.3.31/linux/include/asm-i386/byteorder.h Tue Aug 15 20:39:04 1995 +++ linux/include/asm-i386/byteorder.h Thu Oct 5 08:31:40 1995 @@ -19,10 +19,10 @@ extern unsigned long int htonl(unsigned long int); extern unsigned short int htons(unsigned short int); -extern unsigned long int __ntohl(unsigned long int); -extern unsigned short int __ntohs(unsigned short int); -extern unsigned long int __constant_ntohl(unsigned long int); -extern unsigned short int __constant_ntohs(unsigned short int); +extern __inline__ unsigned long int __ntohl(unsigned long int); +extern __inline__ unsigned short int __ntohs(unsigned short int); +extern __inline__ unsigned long int __constant_ntohl(unsigned long int); +extern __inline__ unsigned short int __constant_ntohs(unsigned short int); extern __inline__ unsigned long int __ntohl(unsigned long int x) diff -u --recursive --new-file v1.3.31/linux/include/asm-i386/ioctl.h linux/include/asm-i386/ioctl.h --- v1.3.31/linux/include/asm-i386/ioctl.h Sun Sep 3 12:27:02 1995 +++ linux/include/asm-i386/ioctl.h Wed Oct 4 14:13:18 1995 @@ -82,6 +82,7 @@ /* used to decode ioctl numbers.. */ #define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) +#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) #define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) #define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) diff -u --recursive --new-file v1.3.31/linux/include/linux/if_eql.h linux/include/linux/if_eql.h --- v1.3.31/linux/include/linux/if_eql.h Tue Jun 6 11:22:11 1995 +++ linux/include/linux/if_eql.h Thu Oct 5 08:31:40 1995 @@ -19,6 +19,8 @@ #ifndef _LINUX_IF_EQL_H #define _LINUX_IF_EQL_H +#include + #define EQL_DEFAULT_SLAVE_PRIORITY 28800 #define EQL_DEFAULT_MAX_SLAVES 4 #define EQL_DEFAULT_MTU 576 diff -u --recursive --new-file v1.3.31/linux/include/linux/mtio.h linux/include/linux/mtio.h --- v1.3.31/linux/include/linux/mtio.h Sun Sep 3 12:27:02 1995 +++ linux/include/linux/mtio.h Thu Oct 5 08:31:40 1995 @@ -140,6 +140,35 @@ }; +/* structure for MTIOCGETCONFIG/MTIOCSETCONFIG primarily intended + * as an interim solution for QIC-02 until DDI is fully implemented. + */ +struct mtconfiginfo { + long mt_type; /* drive type */ + long ifc_type; /* interface card type */ + unsigned short irqnr; /* IRQ number to use */ + unsigned short dmanr; /* DMA channel to use */ + unsigned short port; /* IO port base address */ + + unsigned long debug; /* debugging flags */ + + unsigned have_dens:1; + unsigned have_bsf:1; + unsigned have_fsr:1; + unsigned have_bsr:1; + unsigned have_eod:1; + unsigned have_seek:1; + unsigned have_tell:1; + unsigned have_ras1:1; + unsigned have_ras2:1; + unsigned have_ras3:1; + unsigned have_qfa:1; + + unsigned pad1:5; + char reserved[10]; +}; + + /* mag tape io control commands */ #define MTIOCTOP _IOW('m', 1, struct mtop) /* do a mag tape op */ #define MTIOCGET _IOR('m', 2, struct mtget) /* get tape status */ diff -u --recursive --new-file v1.3.31/linux/include/linux/nfs_fs_sb.h linux/include/linux/nfs_fs_sb.h --- v1.3.31/linux/include/linux/nfs_fs_sb.h Tue Jul 18 16:28:59 1995 +++ linux/include/linux/nfs_fs_sb.h Wed Oct 4 15:41:42 1995 @@ -1,10 +1,12 @@ #ifndef _NFS_FS_SB #define _NFS_FS_SB +#include #include struct nfs_server { struct file *file; + struct rpc_sock *rsock; struct sockaddr toaddr ; /* Added for change to NFS code to use sendto() 1995-06-02 JSP */ int lock; struct wait_queue *wait; diff -u --recursive --new-file v1.3.31/linux/include/linux/resource.h linux/include/linux/resource.h --- v1.3.31/linux/include/linux/resource.h Sat Jun 10 18:36:07 1995 +++ linux/include/linux/resource.h Thu Oct 5 08:31:40 1995 @@ -1,6 +1,8 @@ #ifndef _LINUX_RESOURCE_H #define _LINUX_RESOURCE_H +#include + /* * Resource control/accounting header file for linux */ diff -u --recursive --new-file v1.3.31/linux/include/linux/rpcsock.h linux/include/linux/rpcsock.h --- v1.3.31/linux/include/linux/rpcsock.h Thu Jan 1 02:00:00 1970 +++ linux/include/linux/rpcsock.h Wed Oct 4 15:41:42 1995 @@ -0,0 +1,57 @@ +/* + * rpcsock.h Declarations for the RPC call interface. + * + * Coypright (C) 1995 Olaf Kirch + * + */ + + +#ifndef _LINUX_RPCSOCK_H +#define _LINUX_RPCSOCK_H + +/* Maximum number of outstanding RPCs per socket. + * With 32 slots, IP fragment reassembly would frequently + * fail due to low memory. + */ +#define NRREQS 16 + +/* This describes a timeout strategy */ +struct rpc_timeout { + unsigned long init_timeout, + max_timeout, + increment; + int retries; + char exponential; +}; + +/* Wait information */ +struct rpc_wait { + struct rpc_wait *prev, *next; + struct wait_queue *wait; + int *buf; + int len; + char gotit; + u32 xid; +}; + +struct rpc_sock { + struct file *file; + struct socket *sock; + struct rpc_wait waiting[NRREQS]; + struct rpc_wait *head, *tail, *free; + struct wait_queue *backlog; + struct wait_queue *shutwait; + int shutdown; +}; + +#ifdef __KERNEL__ + +int rpc_call(struct rpc_sock *, struct sockaddr *, int, + const int *, int, int *, int, + struct rpc_timeout *, int); +struct rpc_sock * rpc_makesock(struct file *); +int rpc_closesock(struct rpc_sock *); + +#endif /* __KERNEL__*/ + +#endif /* _LINUX_RPCSOCK_H */ diff -u --recursive --new-file v1.3.31/linux/include/linux/sched.h linux/include/linux/sched.h --- v1.3.31/linux/include/linux/sched.h Wed Oct 4 14:14:34 1995 +++ linux/include/linux/sched.h Fri Oct 6 12:25:42 1995 @@ -325,6 +325,7 @@ extern void exit_fs(struct task_struct *); extern void exit_files(struct task_struct *); extern void exit_sighand(struct task_struct *); +extern void release_thread(struct task_struct *); extern int do_execve(char *, char **, char **, struct pt_regs *); extern int do_fork(unsigned long, unsigned long, struct pt_regs *); diff -u --recursive --new-file v1.3.31/linux/include/linux/serial.h linux/include/linux/serial.h --- v1.3.31/linux/include/linux/serial.h Sat Jun 10 19:13:13 1995 +++ linux/include/linux/serial.h Thu Oct 5 08:31:40 1995 @@ -107,6 +107,9 @@ * For definitions of the flags field, see tty.h */ +#include +#include + struct async_struct { int magic; int baud_base; diff -u --recursive --new-file v1.3.31/linux/include/linux/tpqic02.h linux/include/linux/tpqic02.h --- v1.3.31/linux/include/linux/tpqic02.h Sun Jan 1 19:49:19 1995 +++ linux/include/linux/tpqic02.h Fri Oct 6 12:28:09 1995 @@ -628,34 +628,6 @@ #define BLOCKS_BEYOND_EW 2 /* nr of blocks after Early Warning hole */ #define BOGUS_IRQ 32009 -/* structure for MTIOCGETCONFIG/MTIOCSETCONFIG primarily intended - * as an interim solution for QIC-02 until DDI is fully implemented. - */ -struct mtconfiginfo { - long mt_type; /* drive type */ - long ifc_type; /* interface card type */ - unsigned short irqnr; /* IRQ number to use */ - unsigned short dmanr; /* DMA channel to use */ - unsigned short port; /* IO port base address */ - - unsigned long debug; /* debugging flags */ - - unsigned have_dens:1; - unsigned have_bsf:1; - unsigned have_fsr:1; - unsigned have_bsr:1; - unsigned have_eod:1; - unsigned have_seek:1; - unsigned have_tell:1; - unsigned have_ras1:1; - unsigned have_ras2:1; - unsigned have_ras3:1; - unsigned have_qfa:1; - - unsigned pad1:5; - char reserved[10]; -}; - /* This is internal data, filled in based on the ifc_type field given * by the user. Everex is mapped to Wangtek with a different diff -u --recursive --new-file v1.3.31/linux/kernel/exit.c linux/kernel/exit.c --- v1.3.31/linux/kernel/exit.c Wed Oct 4 14:14:34 1995 +++ linux/kernel/exit.c Thu Oct 5 08:32:38 1995 @@ -94,6 +94,7 @@ nr_tasks--; task[i] = NULL; REMOVE_LINKS(p); + release_thread(p); if (STACK_MAGIC != *(unsigned long *)p->kernel_stack_page) printk(KERN_ALERT "release: %s kernel stack corruption. Aiee\n", p->comm); free_page(p->kernel_stack_page); diff -u --recursive --new-file v1.3.31/linux/net/ipv4/ip.c linux/net/ipv4/ip.c --- v1.3.31/linux/net/ipv4/ip.c Wed Oct 4 14:14:35 1995 +++ linux/net/ipv4/ip.c Thu Oct 5 08:48:15 1995 @@ -1527,12 +1527,12 @@ unsigned char *ptr; /* Data pointer */ unsigned long raddr; /* Router IP address */ struct options * opt = (struct options*)skb->proto_priv; + int encap = 0; /* Encap length */ #ifdef CONFIG_IP_FIREWALL int fw_res = 0; /* Forwarding result */ #ifdef CONFIG_IP_MASQUERADE struct sk_buff *skb_in = skb; /* So we can remember if the masquerader did some swaps */ #endif - int encap = 0; /* Encap length */ /* * See if we are allowed to forward this. diff -u --recursive --new-file v1.3.31/linux/scripts/ksymoops.cc linux/scripts/ksymoops.cc --- v1.3.31/linux/scripts/ksymoops.cc Wed Sep 13 12:45:36 1995 +++ linux/scripts/ksymoops.cc Wed Oct 4 14:56:39 1995 @@ -1,31 +1,47 @@ -/* ksymoops.c -- simple Linux Oops-log symbol resolver - Copyright (C) 1995 Greg McGary - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* This is a simple filter to resolve EIP and call-trace symbols from - a Linux kernel "Oops" log. Supply the symbol-map file name as a - command-line argument, and redirect the oops-log into stdin. - Out will come the EIP and call-trace in symbolic form. */ +// ksymoops.cc v1.7 -- A simple filter to resolve symbols in Linux Oops-logs +// Copyright (C) 1995 Greg McGary +// compile like so: g++ -o ksymoops ksymoops.cc -liostream + +////////////////////////////////////////////////////////////////////////////// + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; see the file COPYING. If not, write to the +// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +// This is a simple filter to resolve EIP and call-trace symbols from +// a Linux kernel "Oops" log. Supply the symbol-map file name as a +// command-line argument, and redirect the oops-log into stdin. Out +// will come the EIP and call-trace in symbolic form. + +////////////////////////////////////////////////////////////////////////////// + +// BUGS: +// * Doesn't deal with line-prefixes prepended by syslog--strip +// these off first, before submitting to ksymoops. +// * Only resolves operands of jump and call instructions. #include +#include +#include #include #include +#include +#include inline int strequ(char const* x, char const* y) { return (::strcmp(x, y) == 0); } +inline int strnequ(char const* x, char const* y, size_t n) { return (::strncmp(x, y, n) == 0); } + +const int code_size = 20; ////////////////////////////////////////////////////////////////////////////// @@ -35,37 +51,41 @@ private: long address_; - char type_; char* name_; long offset_; long extent_; - public: + private: + istream& scan(istream&); + ostream& print(ostream&) const; void set_extent(KSym const& next_ksym) { extent_ = next_ksym.address_ - address_; } - friend istream& operator >> (istream&, KSym&); - friend ostream& operator << (ostream&, const KSym&); + + public: + friend istream& operator >> (istream& is, KSym& k) { return k.scan(is); } + friend ostream& operator << (ostream& os, const KSym& k) { return k.print(os); } }; istream& -operator >> (istream& is, KSym& n) +KSym::scan(istream& is) { - is >> hex >> n.address_; - is >> n.type_; + is >> ::hex >> address_; + char type; + is >> type; char name[128]; is >> name; - n.name_ = new char [strlen(name)+1]; - strcpy(n.name_, name); - n.offset_ = 0; + name_ = new char [strlen(name)+1]; + strcpy(name_, name); + offset_ = 0; return is; } ostream& -operator << (ostream& os, const KSym& n) +KSym::print(ostream& os) const { - os << hex << n.address_ + n.offset_ << ' ' << n.type_ << ' ' << n.name_; - if (n.offset_) - os << '+' << hex << n.offset_ << '/' << hex << n.extent_; - return os; + os << ::hex << address_ + offset_ << ' ' << '<' << name_; + if (offset_) + os << '+' << ::hex << offset_ << '/' << ::hex << extent_; + return os << '>'; } ////////////////////////////////////////////////////////////////////////////// @@ -81,20 +101,30 @@ public: NameList() : cardinality_(0) { } + private: + istream& scan(istream&); + public: + int valid() { return (cardinality_ > 0); } + KSym* find(long address); + void decode(unsigned char* code, long eip_addr); public: - friend istream& operator >> (istream&, NameList&); + friend istream& operator >> (istream& is, NameList& n) { return n.scan(is); } }; KSym* NameList::find(long address) { + if (!valid()) + return 0; KSym* start = ksyms_0_; - KSym* end = &ksyms_0_[cardinality_]; - KSym* mid; + KSym* end = &ksyms_0_[cardinality_ - 1]; + if (address < start->address_ || address >= end->address_) + return 0; + KSym* mid; while (start <= end) { mid = &start[(end - start) / 2]; if (mid->address_ < address) @@ -112,18 +142,101 @@ return mid; } +void +NameList::decode(unsigned char* code, long eip_addr) +{ + /* This is a hack to avoid using gcc. We create an object file by + concatenating objfile_head, the twenty bytes of code, and + objfile_tail. */ + unsigned char objfile_head[] = { + 0x07, 0x01, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + unsigned char objfile_tail[] = { + 0x00, 0x90, 0x90, 0x90, + 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, + 'g', 'c', 'c', '2', '_', 'c', 'o', 'm', + 'p', 'i', 'l', 'e', 'd', '.', '\0', '_', + 'E', 'I', 'P', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0' + }; + char const* objdump_command = "objdump -d oops_decode.o"; + char const* objfile_name = &objdump_command[11]; + ofstream objfile_stream(objfile_name); + + objfile_stream.write(objfile_head, sizeof(objfile_head)); + objfile_stream.write(code, code_size); + objfile_stream.write(objfile_tail, sizeof(objfile_tail)); + objfile_stream.close(); + + FILE* objdump_FILE = popen(objdump_command, "r"); + if (objdump_FILE == 0) { + clog << "Sorry, without " << objdump_command << ", I can't disassemble the `Code' section." << endl; + return; + } + + char buf[1024]; + int lines = 0; + while (fgets(buf, sizeof(buf), objdump_FILE)) { + if (!strnequ(&buf[9], "<_EIP", 5)) + continue; + if (strstr(buf, " is out of bounds")) + break; + lines++; + cout << "Code: "; + if (!valid()) { + cout << buf; + continue; + } + long offset = strtol(buf, 0, 16); + char* bp_0 = strchr(buf, '>') + 2; + KSym* ksym = find(eip_addr + offset); + if (ksym) + cout << *ksym << ' '; + char* bp = bp_0; + while (!isspace(*bp)) + bp++; + while (isspace(*bp)) + bp++; + if (*bp != '0') { + cout << bp_0; + } else if (*bp_0 == 'j' || strnequ(bp_0, "call", 4)) { // a jump or call insn + long rel_addr = strtol(bp, 0, 16); + ksym = find(eip_addr + rel_addr); + if (ksym) { + *bp++ = '\0'; + cout << bp_0 << *ksym << endl; + } else + cout << bp_0; + } else { + cout << bp_0; + } + } + if (!lines) + clog << "Sorry, your " << objdump_command << " can't disassemble--you must upgrade your binutils." << endl; + pclose(objdump_FILE); + unlink(objfile_name); +} + istream& -operator >> (istream& is, NameList& n) +NameList::scan(istream& is) { - KSym* ksyms = n.ksyms_0_; + KSym* ksyms = ksyms_0_; int cardinality = 0; while (!is.eof()) { is >> *ksyms; - ksyms[-1].set_extent(*ksyms); + if (cardinality++ > 0) + ksyms[-1].set_extent(*ksyms); ksyms++; - cardinality++; } - n.cardinality_ = --cardinality; + cardinality_ = --cardinality; return is; } @@ -134,7 +247,7 @@ void usage() { - clog << "Usage: " << program_name << " system-map-file < oops-log" << endl; + clog << "Usage: " << program_name << " [ System.map ] < oops-log" << endl; exit(1); } @@ -142,38 +255,64 @@ main(int argc, char** argv) { program_name = (argc--, *argv++); - if (argc != 1) - usage(); - char const* map_file_name = (argc--, *argv++); - ifstream map(map_file_name); - if (map.bad()) { - clog << program_name << ": Can't open `" << map_file_name << "'" << endl; - return 1; - } - NameList names; - map >> names; + if (argc > 1) + usage(); + else if (argc == 1) { + char const* map_file_name = (argc--, *argv++); + ifstream map(map_file_name); + if (map.bad()) + clog << program_name << ": Can't open `" << map_file_name << "'" << endl; + else { + map >> names; + cout << "Using `" << map_file_name << "' to map addresses to symbols." << endl; + } + } + if (!names.valid()) + cout << "No symbol map. I'll only show you disassembled code." << endl; + cout << endl; char buffer[1024]; while (!cin.eof()) { - long address; + long eip_addr; cin >> buffer; - if (strequ(buffer, "EIP:")) { - cin >> hex >> address; + if (strequ(buffer, "EIP:") && names.valid()) { + cin >> ::hex >> eip_addr; cin >> buffer[0]; - cin >> hex >> address; - KSym* ksym = names.find(address); + cin >> ::hex >> eip_addr; + cin >> buffer; + if (!strequ(buffer, "EFLAGS:")) { + clog << "Please strip the line-prefixes and rerun " << program_name << endl; + exit(1); + } + KSym* ksym = names.find(eip_addr); if (ksym) - cout << "EIP: " << *ksym << endl; - } else if (strequ(buffer, "Trace:")) { - while ((cin >> address) && address > 0xc) { + cout << ">>EIP: " << *ksym << endl; + } else if (strequ(buffer, "Trace:") && names.valid()) { + long address; + while ((cin >> ::hex >> address) && address > 0xc) { + cout << "Trace: "; KSym* ksym = names.find(address); if (ksym) - cout << "Trace: " << *ksym << endl; + cout << *ksym; + else + cout << ::hex << address; + cout << endl; } cout << endl; + } else if (strequ(buffer, "ode:") || strequ(buffer, "Code:")) { + // The 'C' might have been consumed as a hex number + unsigned char code[code_size]; + unsigned char* cp = code; + unsigned char* end = &code[code_size]; + while (cp < end) { + int c; + cin >> ::hex >> c; + *cp++ = c; + } + names.decode(code, eip_addr); } } cout << flush;