diff options
Diffstat (limited to 'arch')
53 files changed, 2473 insertions, 1402 deletions
diff --git a/arch/alpha/config.in b/arch/alpha/config.in index e62ec31d0..774686ebd 100644 --- a/arch/alpha/config.in +++ b/arch/alpha/config.in @@ -94,10 +94,11 @@ bool 'System V IPC' CONFIG_SYSVIPC bool 'Sysctl support' CONFIG_SYSCTL tristate 'Kernel support for a.out (ECOFF) binaries' CONFIG_BINFMT_AOUT tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF -tristate 'Kernel support for Linux/Intel ELF binaries' CONFIG_BINFMT_EM86 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA fi +tristate 'Kernel support for Linux/Intel ELF binaries' CONFIG_BINFMT_EM86 tristate 'Parallel port support' CONFIG_PNP_PARPORT endmenu @@ -172,4 +173,5 @@ bool 'Kernel profiling support' CONFIG_PROFILE if [ "$CONFIG_PROFILE" = "y" ]; then int ' Profile shift count' CONFIG_PROFILE_SHIFT 2 fi +bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ endmenu diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index ef9576492..3b3d8574b 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -295,7 +295,7 @@ asmlinkage int osf_statfs(char *path, struct osf_statfs *buffer, unsigned long b retval = verify_area(VERIFY_WRITE, buffer, bufsiz); if (retval) goto out; - retval = namei(path, &inode); + retval = namei(NAM_FOLLOW_LINK, path, &inode); if (retval) goto out; retval = -ENOSYS; @@ -376,7 +376,7 @@ static int getdev(const char *name, int rdonly, struct inode **ino) struct file_operations *fops; int retval; - retval = namei(name, &inode); + retval = namei(NAM_FOLLOW_LINK, name, &inode); if (retval) return retval; if (!S_ISBLK(inode->i_mode)) { @@ -845,14 +845,12 @@ asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer, unsigned long nbytes, int *start, void *arg) { - extern unsigned long rdfpcr(void); unsigned long w; switch (op) { case GSI_IEEE_FP_CONTROL: - /* build and return current fp control word: */ - w = current->tss.flags & IEEE_TRAP_ENABLE_MASK; - w |= ((rdfpcr() >> 52) << 17) & IEEE_STATUS_MASK; + /* Return current software fp control & status bits. */ + w = current->tss.flags & IEEE_SW_MASK; if (put_user(w, (unsigned long *) buffer)) return -EFAULT; return 0; @@ -883,16 +881,32 @@ asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer, unsigned long nbytes, int *start, void *arg) { - unsigned long v, w, i; - switch (op) { - case SSI_IEEE_FP_CONTROL: - /* update trap enable bits: */ - if (get_user(w, (unsigned long *) buffer)) + case SSI_IEEE_FP_CONTROL: { + unsigned long swcr, fpcr; + + /* + * Alpha Architecture Handbook 4.7.7.3: + * To be fully IEEE compiant, we must track the current IEEE + * exception state in software, because spurrious bits can be + * set in the trap shadow of a software-complete insn. + */ + + /* Update softare trap enable bits. */ + if (get_user(swcr, (unsigned long *)buffer)) return -EFAULT; - current->tss.flags &= ~IEEE_TRAP_ENABLE_MASK; - current->tss.flags |= (w & IEEE_TRAP_ENABLE_MASK); + current->tss.flags &= ~IEEE_SW_MASK; + current->tss.flags |= swcr & IEEE_SW_MASK; + + /* Update the real fpcr. For exceptions that are disabled in + software but have not been seen, enable the exception in + hardware so that we can update our software status mask. */ + fpcr = rdfpcr() & (~FPCR_MASK | FPCR_DYN_MASK); + fpcr = ieee_swcr_to_fpcr(swcr | (~swcr & IEEE_STATUS_MASK)>>16); + wrfpcr(fpcr); + return 0; + } case SSI_IEEE_STATE_AT_SIGNAL: case SSI_IEEE_IGNORE_STATE_AT_SIGNAL: @@ -903,7 +917,9 @@ asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer, */ break; - case SSI_NVPAIRS: + case SSI_NVPAIRS: { + unsigned long v, w, i; + for (i = 0; i < nbytes; ++i) { if (get_user(v, 2*i + (unsigned int *)buffer)) return -EFAULT; @@ -922,6 +938,7 @@ asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer, } } return 0; + } default: break; diff --git a/arch/alpha/math-emu/fp-emul.c b/arch/alpha/math-emu/fp-emul.c index 38df501fd..f1ff5a2be 100644 --- a/arch/alpha/math-emu/fp-emul.c +++ b/arch/alpha/math-emu/fp-emul.c @@ -13,9 +13,9 @@ #define OPC_INTL 0x11 #define OPC_INTS 0x12 #define OPC_INTM 0x13 -#define OPC_FLTV 0x14 -#define OPC_FLTI 0x15 -#define OPC_FLTL 0x16 +#define OPC_FLTV 0x15 +#define OPC_FLTI 0x16 +#define OPC_FLTL 0x17 #define OPC_MISC 0x18 @@ -298,19 +298,26 @@ alpha_fp_emul (unsigned long pc) * * - Set the appropriate bits in the FPCR * - If the specified exception is enabled in the FPCR, - * return. The caller (mxr_signal_handler) will dispatch + * return. The caller (entArith) will dispatch * the appropriate signal to the translated program. + * + * In addition, properly track the exception state in software + * as described in the Alpha Architectre Handbook section 4.7.7.3. */ if (res) { - fpcr |= FPCR_SUM | res; + /* Record exceptions in software control word. */ + current->tss.flags = fpcw |= res >> 35; + + /* Update hardware control register */ + fpcr &= (~FPCR_MASK | FPCR_DYN_MASK); + fpcr |= ieee_swcr_to_fpcr(fpcw | (~fpcw&IEEE_STATUS_MASK)>>16); wrfpcr(fpcr); - if (((res & FPCR_INV) && (fpcw & IEEE_TRAP_ENABLE_INV)) || - ((res & FPCR_DZE) && (fpcw & IEEE_TRAP_ENABLE_DZE)) || - ((res & FPCR_OVF) && (fpcw & IEEE_TRAP_ENABLE_OVF)) || - ((res & FPCR_UNF) && (fpcw & IEEE_TRAP_ENABLE_UNF)) || - ((res & FPCR_INE) && (fpcw & IEEE_TRAP_ENABLE_INE))) + + /* Do we generate a signal? */ + if (res >> 51 & fpcw & IEEE_TRAP_ENABLE_MASK) return 0; } + /* * Whoo-kay... we got this far, and we're not generating a signal * to the translated program. All that remains is to write the @@ -326,6 +333,7 @@ alpha_fp_emul_imprecise (struct pt_regs *regs, unsigned long write_mask) { unsigned long trigger_pc = regs->pc - 4; unsigned long insn, opcode, rc; + /* * Turn off the bits corresponding to registers that are the * target of instructions that set bits in the exception diff --git a/arch/i386/config.in b/arch/i386/config.in index f95590407..1612b614f 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -34,6 +34,7 @@ bool 'System V IPC' CONFIG_SYSVIPC bool 'Sysctl support' CONFIG_SYSCTL tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA fi @@ -117,4 +118,5 @@ bool 'Kernel profiling support' CONFIG_PROFILE if [ "$CONFIG_PROFILE" = "y" ]; then int ' Profile shift count' CONFIG_PROFILE_SHIFT 2 fi +bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ endmenu diff --git a/arch/i386/defconfig b/arch/i386/defconfig index a27b6ebce..ab30a25c8 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -25,6 +25,7 @@ CONFIG_SYSVIPC=y CONFIG_SYSCTL=y CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y # CONFIG_M386 is not set # CONFIG_M486 is not set # CONFIG_M586 is not set @@ -190,6 +191,9 @@ CONFIG_EEXPRESS_PRO100=y # Filesystems # # CONFIG_QUOTA is not set +# CONFIG_DCACHE_PRELOAD is not set +# CONFIG_OMIRR is not set +# CONFIG_TRANS_NAMES is not set CONFIG_MINIX_FS=y CONFIG_EXT2_FS=y CONFIG_FAT_FS=y @@ -241,3 +245,4 @@ CONFIG_82C710_MOUSE=y # Kernel hacking # # CONFIG_PROFILE is not set +# CONFIG_MAGIC_SYSRQ is not set diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index a42b87b1b..bd4bf56cf 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -532,8 +532,8 @@ ENTRY(gdt) .quad 0x0000000000000000 /* not used */ .quad 0x00cf9a000000ffff /* 0x10 kernel 4GB code at 0x00000000 */ .quad 0x00cf92000000ffff /* 0x18 kernel 4GB data at 0x00000000 */ - .quad 0x00cbfa000000ffff /* 0x23 user 3GB code at 0x00000000 */ - .quad 0x00cbf2000000ffff /* 0x2b user 3GB data at 0x00000000 */ + .quad 0x00cffa000000ffff /* 0x23 user 4GB code at 0x00000000 */ + .quad 0x00cff2000000ffff /* 0x2b user 4GB data at 0x00000000 */ .quad 0x0000000000000000 /* not used */ .quad 0x0000000000000000 /* not used */ .fill 2*NR_TASKS,8,0 /* space for LDT's and TSS's etc */ diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index e5fb5acb1..eedb1d0fe 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -142,21 +142,6 @@ void enable_irq(unsigned int irq_nr) * the operations that are needed to keep the AT interrupt-controller * happy. They are also written to be fast - and to disable interrupts * as little as humanly possible. - * - * NOTE! These macros expand to three different handlers for each line: one - * complete handler that does all the fancy stuff (including signal handling), - * and one fast handler that is meant for simple IRQ's that want to be - * atomic. The specific handler is chosen depending on the SA_INTERRUPT - * flag when installing a handler. Finally, one "bad interrupt" handler, that - * is used when no handler is present. - * - * The timer interrupt is handled specially to insure that the jiffies - * variable is updated at all times. Specifically, the timer interrupt is - * just like the complete handlers except that it is invoked with interrupts - * disabled and should never re-enable them. If other interrupts were - * allowed to be processed while the timer interrupt is active, then the - * other interrupts would have to avoid using the jiffies variable for delay - * and interval timing operations to avoid hanging the system. */ #if NR_IRQS != 16 @@ -539,6 +524,9 @@ asmlinkage void do_IRQ(struct pt_regs regs) status = 0; action = *(irq + irq_action); if (action) { + if (!(action->flags & SA_INTERRUPT)) + __sti(); + do { status |= action->flags; action->handler(irq, action->dev_id, ®s); @@ -546,7 +534,6 @@ asmlinkage void do_IRQ(struct pt_regs regs) } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); - __cli(); spin_lock(&irq_controller_lock); unmask_irq(irq); diff --git a/arch/i386/kernel/irq.h b/arch/i386/kernel/irq.h index 1f9e89399..7d70264ba 100644 --- a/arch/i386/kernel/irq.h +++ b/arch/i386/kernel/irq.h @@ -9,24 +9,10 @@ #ifdef __SMP__ -#undef INIT_STUCK -#define INIT_STUCK 200000000 - -#undef STUCK -#define STUCK \ -if (!--stuck) {printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n",irq,cpu,global_irq_holder); stuck = INIT_STUCK;} - static inline void irq_enter(int cpu, int irq) { - int stuck = INIT_STUCK; - hardirq_enter(cpu); while (test_bit(0,&global_irq_lock)) { - if ((unsigned char) cpu == global_irq_holder) { - printk("BAD! Local interrupts enabled, global disabled\n"); - break; - } - STUCK; /* nothing */; } } diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index 1dc615501..5a020b723 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -870,6 +870,8 @@ __initfunc(static void do_boot_cpu(int i)) *((volatile unsigned long *)phys_to_virt(8192)) = 0; } +unsigned int prof_multiplier[NR_CPUS]; +unsigned int prof_counter[NR_CPUS]; /* * Cycle through the processors sending APIC IPI's to boot each. @@ -912,8 +914,15 @@ __initfunc(void smp_boot_cpus(void)) * of here now! */ - if (!smp_found_config) + if (!smp_found_config) { + /* + * For SMP-simulation on one CPU to work, we must initialize these + * values for the single CPU here: + */ + prof_counter[0] = prof_multiplier[0] = 1; + return; + } /* * Map the local APIC into kernel space @@ -1302,9 +1311,6 @@ void smp_flush_tlb(void) * value into /proc/profile. */ -unsigned int prof_multiplier[NR_CPUS]; -unsigned int prof_counter[NR_CPUS]; - void smp_local_timer_interrupt(struct pt_regs * regs) { int cpu = smp_processor_id(); diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index e45cc7279..a08c9c49c 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -515,7 +515,7 @@ unsigned long get_cmos_time(void) return mktime(year, mon, day, hour, min, sec); } -static struct irqaction irq0 = { timer_interrupt, 0, 0, "timer", NULL, NULL}; +static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL}; __initfunc(void time_init(void)) diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 696e37004..b397fc76d 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -191,8 +191,6 @@ spinlock_t die_lock; spin_lock_irq(&die_lock); printk("%s: %04lx\n", str, err & 0xffff); show_registers(regs); -do { int i=2000000000; while (i) i--; } while (0); -do { int i=2000000000; while (i) i--; } while (0); spin_unlock_irq(&die_lock); do_exit(SIGSEGV); } diff --git a/arch/m68k/amiga/amifb.c b/arch/m68k/amiga/amifb.c index eb72970d7..15e424ea7 100644 --- a/arch/m68k/amiga/amifb.c +++ b/arch/m68k/amiga/amifb.c @@ -1307,6 +1307,7 @@ static void ami_rebuild_copper(void); */ extern unsigned short ami_intena_vals[]; +extern void amiga_init_sound(void); /* * Support for Graphics Boards @@ -1810,6 +1811,11 @@ __initfunc(struct fb_info *amiga_fb_init(long *mem_start)) u_long chipptr; /* + * Our beloved beeper + */ + amiga_init_sound(); + + /* * Check for a Graphics Board */ diff --git a/arch/m68k/amiga/amikeyb.c b/arch/m68k/amiga/amikeyb.c index 1058270dd..06fe55d29 100644 --- a/arch/m68k/amiga/amikeyb.c +++ b/arch/m68k/amiga/amikeyb.c @@ -23,18 +23,17 @@ #include <linux/random.h> #include <linux/kernel.h> #include <linux/init.h> +#include <linux/kbd_ll.h> #include <asm/amigaints.h> #include <asm/amigahw.h> #include <asm/irq.h> -extern void handle_scancode(unsigned char); - #define AMIKEY_CAPS (0x62) #define BREAK_MASK (0x80) #define RESET_WARNING (0xf0) /* before rotation */ -static u_short amiplain_map[NR_KEYS] = { +static u_short amiplain_map[NR_KEYS] __initdata = { 0xf060, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf05c, 0xf200, 0xf300, 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, @@ -178,15 +177,13 @@ static unsigned char rep_scancode; static void amikeyb_rep(unsigned long ignore); static struct timer_list amikeyb_rep_timer = {NULL, NULL, 0, 0, amikeyb_rep}; -extern struct pt_regs *pt_regs; - static void amikeyb_rep(unsigned long ignore) { unsigned long flags; save_flags(flags); cli(); - pt_regs = NULL; + kbd_pt_regs = NULL; amikeyb_rep_timer.expires = jiffies + key_repeat_rate; amikeyb_rep_timer.prev = amikeyb_rep_timer.next = NULL; @@ -202,7 +199,7 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp) static int reset_warning = 0; /* save frame for register dump */ - pt_regs = (struct pt_regs *)fp; + kbd_pt_regs = fp; /* get and invert scancode (keyboard is active low) */ scancode = ~ciaa.sdr; @@ -302,14 +299,13 @@ __initfunc(int amiga_keyb_init(void)) return -EIO; /* setup key map */ - key_maps[0] = amiplain_map; + memcpy(plain_map, amiplain_map, sizeof(plain_map)); key_maps[1] = amishift_map; key_maps[2] = amialtgr_map; key_maps[4] = amictrl_map; key_maps[5] = amishift_ctrl_map; key_maps[8] = amialt_map; key_maps[12] = amictrl_alt_map; - memcpy(plain_map, amiplain_map, sizeof(plain_map)); /* * Initialize serial data direction. diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c index d5656d170..72d2091f5 100644 --- a/arch/m68k/amiga/amisound.c +++ b/arch/m68k/amiga/amisound.c @@ -40,7 +40,7 @@ u_short amiga_audio_period = MAX_PERIOD; static u_long clock_constant; -__initfunc(static void init_sound(void)) +__initfunc(void amiga_init_sound(void)) { snd_data = amiga_chip_alloc(sizeof(sine_data)); if (!snd_data) { @@ -58,14 +58,8 @@ static struct timer_list sound_timer = { NULL, NULL, 0, 0, nosound }; void amiga_mksound( unsigned int hz, unsigned int ticks ) { - static int inited = 0; unsigned long flags; - if (!inited) { - init_sound(); - inited = 1; - } - if (!snd_data) return; diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c index 7b6bd208f..e36016306 100644 --- a/arch/m68k/amiga/config.c +++ b/arch/m68k/amiga/config.c @@ -78,6 +78,7 @@ static void amiga_wait_key(void); extern struct consw fb_con; extern struct fb_info *amiga_fb_init(long *); extern void zorro_init(void); +extern void amiga_init_sound(void); static void amiga_savekmsg_init(void); static void amiga_mem_console_write(const char *b, unsigned int count); static void amiga_serial_console_write(const char *s, unsigned int count); diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c index b2887f7da..189095cfc 100644 --- a/arch/m68k/atari/ataints.c +++ b/arch/m68k/atari/ataints.c @@ -48,6 +48,7 @@ #include <asm/atariints.h> #include <asm/atari_stdma.h> #include <asm/irq.h> +#include <asm/entry.h> /* @@ -161,22 +162,6 @@ static int free_vme_vec_bitmap = 0; #define IRQ_NAME(nr) atari_slow_irq_##nr##_handler(void) -#define MFP_MK_BASE "0xfa13" - -/* This must agree with entry.S. */ -#define ORIG_DO "0x24" -#define FORMATVEC "0x32" -#define SR "0x2C" -#define SAVE_ALL \ - "clrl %%sp@-;" /* stk_adj */ \ - "pea -1:w;" /* orig d0 = -1 */ \ - "movel %%d0,%%sp@-;" /* d0 */ \ - "moveml %%d1-%%d5/%%a0-%%a2,%%sp@-" -#define GET_CURRENT(tmp) \ - "movel %%sp,"#tmp";" \ - "andw #-8192,"#tmp";" \ - "movel "#tmp",%%a2" - #define BUILD_SLOW_IRQ(n) \ asmlinkage void IRQ_NAME(n); \ /* Dummy function to allow asm with operands. */ \ @@ -184,29 +169,31 @@ void atari_slow_irq_##n##_dummy (void) { \ __asm__ (ALIGN_STR "\n" \ SYMBOL_NAME_STR(atari_slow_irq_) #n "_handler:\t" \ " addql #1,"SYMBOL_NAME_STR(local_irq_count)"\n" \ - SAVE_ALL "\n" \ + SAVE_ALL_INT "\n" \ GET_CURRENT(%%d0) "\n" \ -" andb #~(1<<(" #n "&7))," /* mask this interrupt */ \ - "("MFP_MK_BASE"+(((" #n "&8)^8)>>2)+((" #n "&16)<<3)):w\n" \ -" bfextu %%sp@("SR"){#5,#3},%%d0\n" /* get old IPL from stack frame */ \ +" andb #~(1<<(%c3&7)),%a4:w\n" /* mask this interrupt */ \ + /* get old IPL from stack frame */ \ +" bfextu %%sp@(%c2){#5,#3},%%d0\n" \ " movew %%sr,%%d1\n" \ " bfins %%d0,%%d1{#21,#3}\n" \ " movew %%d1,%%sr\n" /* set IPL = previous value */ \ " addql #1,%a0\n" \ -" lea "SYMBOL_NAME_STR(irq_handler)"+("#n"+8)*8,%%a0\n" \ +" lea %a1,%%a0\n" \ " pea %%sp@\n" /* push addr of frame */ \ " movel %%a0@(4),%%sp@-\n" /* push handler data */ \ -" pea (" #n "+8)\n" /* push int number */ \ +" pea (%c3+8)\n" /* push int number */ \ " movel %%a0@,%%a0\n" \ " jbsr %%a0@\n" /* call the handler */ \ " addql #8,%%sp\n" \ " addql #4,%%sp\n" \ " orw #0x0600,%%sr\n" \ " andw #0xfeff,%%sr\n" /* set IPL = 6 again */ \ -" orb #(1<<(" #n "&7))," /* now unmask the int again */ \ - "("MFP_MK_BASE"+(((" #n "&8)^8)>>2)+((" #n "&16)<<3)):w\n" \ +" orb #(1<<(%c3&7)),%a4:w\n" /* now unmask the int again */ \ " jbra "SYMBOL_NAME_STR(ret_from_interrupt)"\n" \ - : : "i" (&kstat.interrupts[n+8]) \ + : : "i" (&kstat.interrupts[n+8]), "i" (&irq_handler[n+8]), \ + "n" (PT_OFF_SR), "n" (n), \ + "i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &mfp.int_mk_a) \ + : (n & 16 ? &tt_mfp.int_mk_b : &mfp.int_mk_b)) \ ); \ } @@ -288,10 +275,10 @@ SYMBOL_NAME_STR(atari_fast_irq_handler) ": orw #0x700,%%sr /* disable all interrupts */ "SYMBOL_NAME_STR(atari_prio_irq_handler) ":\t addql #1,"SYMBOL_NAME_STR(local_irq_count)"\n" - SAVE_ALL "\n" + SAVE_ALL_INT "\n" GET_CURRENT(%%d0) " /* get vector number from stack frame and convert to source */ - bfextu %%sp@(" FORMATVEC "){#4,#10},%%d0 + bfextu %%sp@(%c1){#4,#10},%%d0 subw #(0x40-8),%%d0 jpl 1f addw #(0x40-8-0x18),%%d0 @@ -307,7 +294,7 @@ SYMBOL_NAME_STR(atari_fast_irq_handler) ": addql #8,%%sp addql #4,%%sp jbra "SYMBOL_NAME_STR(ret_from_interrupt) - : : "i" (&kstat.interrupts) + : : "i" (&kstat.interrupts), "n" (PT_OFF_FORMATVEC) ); } diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c index beccf9a84..d5d45be01 100644 --- a/arch/m68k/atari/atakeyb.c +++ b/arch/m68k/atari/atakeyb.c @@ -23,6 +23,7 @@ #include <linux/kd.h> #include <linux/random.h> #include <linux/init.h> +#include <linux/kbd_ll.h> #include <asm/atariints.h> #include <asm/atarihw.h> @@ -31,7 +32,6 @@ #include <asm/atari_joystick.h> #include <asm/irq.h> -extern void handle_scancode(unsigned char); extern int ovsc_switchmode; extern unsigned char mach_keyboard_type; static void atakeyb_rep( unsigned long ignore ); @@ -99,7 +99,7 @@ static unsigned long broken_keys[128/(sizeof(unsigned long)*8)] = { 0, }; * - Keypad Left/Right Parenthesis mapped to new K_PPAREN[LR] */ -static u_short ataplain_map[NR_KEYS] = { +static u_short ataplain_map[NR_KEYS] __initdata = { 0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009, 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, @@ -139,7 +139,7 @@ static u_short atashift_map[NR_KEYS] = { static u_short atactrl_map[NR_KEYS] = { 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e, - 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf07f, 0xf200, 0xf008, 0xf200, + 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200, 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, 0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013, 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200, @@ -158,18 +158,18 @@ static u_short atactrl_map[NR_KEYS] = { static u_short atashift_ctrl_map[NR_KEYS] = { 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf008, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf201, 0xf702, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf700, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf700, 0xf200, - 0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf117, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200, + 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, + 0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013, + 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200, + 0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016, + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf07f, 0xf700, 0xf200, + 0xf703, 0xf200, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf117, 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200, - 0xf600, 0xf200, 0xf115, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307, + 0xf200, 0xf1ff, 0xf11b, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307, 0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303, 0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200 @@ -207,7 +207,7 @@ static u_short atashift_alt_map[NR_KEYS] = { 0xf118, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200, 0xf119, 0xf200, 0xf115, 0xf87f, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307, + 0xf200, 0xf1ff, 0xf11b, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307, 0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303, 0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200 @@ -215,7 +215,7 @@ static u_short atashift_alt_map[NR_KEYS] = { static u_short atactrl_alt_map[NR_KEYS] = { 0xf200, 0xf200, 0xf200, 0xf800, 0xf81b, 0xf81c, 0xf81d, 0xf81e, - 0xf81f, 0xf87f, 0xf200, 0xf200, 0xf87f, 0xf200, 0xf808, 0xf200, + 0xf81f, 0xf87f, 0xf200, 0xf200, 0xf81f, 0xf200, 0xf808, 0xf200, 0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809, 0xf80f, 0xf810, 0xf81b, 0xf81d, 0xf201, 0xf702, 0xf801, 0xf813, 0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200, @@ -224,7 +224,7 @@ static u_short atactrl_alt_map[NR_KEYS] = { 0xf703, 0xf800, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114, 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200, - 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf600, 0xf200, 0xf115, 0xf87f, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf1ff, 0xf202, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307, 0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303, @@ -234,18 +234,18 @@ static u_short atactrl_alt_map[NR_KEYS] = { static u_short atashift_ctrl_alt_map[NR_KEYS] = { 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf808, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf201, 0xf702, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf700, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf700, 0xf200, - 0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf117, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf81f, 0xf200, 0xf808, 0xf200, + 0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809, + 0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813, + 0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200, + 0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816, + 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf87f, 0xf700, 0xf200, + 0xf703, 0xf200, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf117, 0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200, - 0xf600, 0xf200, 0xf115, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf600, 0xf200, 0xf115, 0xf87f, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf200, 0xf200, 0xf200, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307, + 0xf200, 0xf1ff, 0xf11b, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307, 0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303, 0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200 @@ -277,12 +277,10 @@ static unsigned int key_repeat_rate = DEFAULT_KEYB_REP_RATE; static unsigned char rep_scancode; static struct timer_list atakeyb_rep_timer = { NULL, NULL, 0, 0, atakeyb_rep }; -extern struct pt_regs *pt_regs; - static void atakeyb_rep( unsigned long ignore ) { - pt_regs = NULL; + kbd_pt_regs = NULL; /* Disable keyboard for the time we call handle_scancode(), else a race * in the keyboard tty queue may happen */ @@ -327,7 +325,7 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp) int break_flag; /* save frame for register dump */ - pt_regs = (struct pt_regs *)fp; + kbd_pt_regs = fp; repeat: if (acia.mid_ctrl & ACIA_IRQ) @@ -420,14 +418,14 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp) * make codes instead. Therefore, simply ignore * break_flag... * */ - int keyval = ataplain_map[scancode], keytyp; - + int keyval = plain_map[scancode], keytyp; + set_bit( scancode, broken_keys ); self_test_last_rcv = jiffies; - keyval = ataplain_map[scancode]; + keyval = plain_map[scancode]; keytyp = KTYP(keyval) - 0xf0; keyval = KVAL(keyval); - + printk( KERN_WARNING "Key with scancode %d ", scancode ); if (keytyp == KT_LATIN || keytyp == KT_LETTER) { if (keyval < ' ') @@ -440,7 +438,7 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp) } else if (test_bit( scancode, broken_keys )) break; - + if (break_flag) { del_timer( &atakeyb_rep_timer ); rep_scancode = 0; @@ -808,7 +806,7 @@ void atari_kbd_leds (unsigned int leds) __initfunc(int atari_keyb_init(void)) { /* setup key map */ - key_maps[0] = ataplain_map; + memcpy (plain_map, ataplain_map, sizeof(plain_map)); key_maps[1] = atashift_map; key_maps[2] = 0; /* ataaltgr_map */ key_maps[4] = atactrl_map; @@ -817,7 +815,6 @@ __initfunc(int atari_keyb_init(void)) key_maps[9] = atashift_alt_map; key_maps[12] = atactrl_alt_map; key_maps[13] = atashift_ctrl_alt_map; - memcpy (plain_map, ataplain_map, sizeof(plain_map)); keymap_count = 8; /* say that we don't have an AltGr key */ diff --git a/arch/m68k/console/fbcon.c b/arch/m68k/console/fbcon.c index 376249c90..62457c0cb 100644 --- a/arch/m68k/console/fbcon.c +++ b/arch/m68k/console/fbcon.c @@ -69,8 +69,8 @@ #include <asm/system.h> #include <asm/uaccess.h> -#include "../../../drivers/char/vt_kern.h" /* vt_cons and vc_resize_con() */ -#include "../../../drivers/char/console_struct.h" +#include <linux/vt_kern.h> +#include <linux/console_struct.h> /* Import console_blanked from console.c */ diff --git a/arch/m68k/fpsp040/skeleton.S b/arch/m68k/fpsp040/skeleton.S index 466cf3fbc..719bcc9ce 100644 --- a/arch/m68k/fpsp040/skeleton.S +++ b/arch/m68k/fpsp040/skeleton.S @@ -39,6 +39,7 @@ | #include <linux/linkage.h> +#include <asm/entry.h> |SKELETON idnt 2,1 | Motorola 040 Floating Point Software Package @@ -51,24 +52,6 @@ .include "fpsp.h" -/* - * This has to match entry.S - */ -LOFF_ORIG_D0 = 0x24 - -#define curptr a2 - -#define SAVE_ALL \ - clrl %sp@-; /* stk_adj */ \ - movel %d0,%sp@-; /* orig d0 */ \ - movel %d0,%sp@-; /* d0 */ \ - moveml %d1-%d5/%a0-%a1/%curptr,%sp@-; - -#define GET_CURRENT(tmp) \ - movel %sp,tmp; \ - andw &-8192,tmp; \ - movel tmp,%curptr; - |xref b1238_fix | @@ -86,11 +69,7 @@ real_dz: frestore (%sp)+ unlk %a6 - SAVE_ALL - moveq #-1,%d0 - movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field - | signifies that the stack frame - | is NOT for syscall + SAVE_ALL_INT GET_CURRENT(%d0) movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) @@ -181,11 +160,7 @@ inex_done: frestore (%sp)+ unlk %a6 - SAVE_ALL - moveq #-1,%d0 - movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field - | signifies that the stack frame - | is NOT for syscall + SAVE_ALL_INT GET_CURRENT(%d0) movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) @@ -211,11 +186,7 @@ ovfl_done: frestore (%sp)+ unlk %a6 - SAVE_ALL - moveq #-1,%d0 - movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field - | signifies that the stack frame - | is NOT for syscall + SAVE_ALL_INT GET_CURRENT(%d0) movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) @@ -241,11 +212,7 @@ unfl_done: frestore (%sp)+ unlk %a6 - SAVE_ALL - moveq #-1,%d0 - movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field - | signifies that the stack frame - | is NOT for syscall + SAVE_ALL_INT GET_CURRENT(%d0) movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) @@ -267,11 +234,7 @@ real_snan: frestore (%sp)+ unlk %a6 - SAVE_ALL - moveq #-1,%d0 - movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field - | signifies that the stack frame - | is NOT for syscall + SAVE_ALL_INT GET_CURRENT(%d0) movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) @@ -293,11 +256,7 @@ real_operr: frestore (%sp)+ unlk %a6 - SAVE_ALL - moveq #-1,%d0 - movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field - | signifies that the stack frame - | is NOT for syscall + SAVE_ALL_INT GET_CURRENT(%d0) movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) @@ -325,11 +284,7 @@ real_bsun: frestore (%sp)+ unlk %a6 - SAVE_ALL - moveq #-1,%d0 - movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field - | signifies that the stack frame - | is NOT for syscall + SAVE_ALL_INT GET_CURRENT(%d0) movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) @@ -350,11 +305,7 @@ fline: jmp fpsp_fline real_fline: - SAVE_ALL - moveq #-1,%d0 - movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field - | signifies that the stack frame - | is NOT for syscall + SAVE_ALL_INT GET_CURRENT(%d0) movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) @@ -376,11 +327,7 @@ real_unsupp: frestore (%sp)+ unlk %a6 - SAVE_ALL - moveq #-1,%d0 - movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field - | signifies that the stack frame - | is NOT for syscall + SAVE_ALL_INT GET_CURRENT(%d0) movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) @@ -435,9 +382,7 @@ Lnotkern: bne Lmustsched rte Lmustsched: - SAVE_ALL - moveq #-1,%d0 - movel %d0,%sp@(LOFF_ORIG_D0) | indicate stack frame not for syscall + SAVE_ALL_INT GET_CURRENT(%d0) bral SYMBOL_NAME(ret_from_exception) | deliver signals, reschedule etc.. diff --git a/arch/m68k/kernel/console.c b/arch/m68k/kernel/console.c index 468ae0b59..31608e904 100644 --- a/arch/m68k/kernel/console.c +++ b/arch/m68k/kernel/console.c @@ -109,7 +109,6 @@ #include <linux/interrupt.h> #include <linux/tty.h> #include <linux/tty_flip.h> -#include <linux/console.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/errno.h> @@ -119,17 +118,18 @@ #include <linux/major.h> #include <linux/mm.h> #include <linux/ioport.h> +#include <linux/init.h> #include <asm/io.h> #include <asm/uaccess.h> #include <asm/system.h> #include <asm/bitops.h> -#include "../../../drivers/char/kbd_kern.h" -#include "../../../drivers/char/vt_kern.h" -#include "../../../drivers/char/consolemap.h" -#include "../../../drivers/char/selection.h" -#include "../../../drivers/char/console_struct.h" +#include <linux/kbd_kern.h> +#include <linux/vt_kern.h> +#include <linux/consolemap.h> +#include <linux/selection.h> +#include <linux/console_struct.h> #ifndef MIN @@ -159,6 +159,8 @@ static void set_vesa_blanking(unsigned long arg); extern void vesa_blank(void); extern void vesa_unblank(void); extern void compute_shiftstate(void); +extern void reset_palette(int currcons); +extern void set_palette(void); void poke_blanked_console(void); void do_blank_screen(int); @@ -257,6 +259,7 @@ struct consw *conswitchp; #define ulcolor (vc_cons[currcons].d->vc_ulcolor) #define halfcolor (vc_cons[currcons].d->vc_halfcolor) #define tab_stop (vc_cons[currcons].d->vc_tab_stop) +#define palette (vc_cons[currcons].d->vc_palette) #define bell_pitch (vc_cons[currcons].d->vc_bell_pitch) #define bell_duration (vc_cons[currcons].d->vc_bell_duration) #define sw (vc_cons[currcons].d->vc_sw) @@ -539,6 +542,14 @@ void vc_disallocate(unsigned int currcons) static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7, 8,12,10,14, 9,13,11,15 }; +/* the default colour table, for VGA+ colour systems */ +int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa, + 0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff}; +int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa, + 0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff}; +int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa, + 0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff}; + /* * gotoxy() must verify all boundaries, because the arguments * might also be negative. If the given position is out of @@ -1655,7 +1666,7 @@ static int do_con_write(struct tty_struct * tty, int from_user, if (nextx == cols) { sw->con_putc(vc_cons[currcons].d, *putcs_buf, y, x); - ((unsigned short *)pos)--; + pos--; need_wrap = decawm; continue; } @@ -1837,9 +1848,7 @@ static int do_con_write(struct tty_struct * tty, int from_user, vc_state = ESpalette; continue; } else if (c=='R') { /* reset palette */ -#if 0 reset_palette (currcons); -#endif vc_state = ESnormal; } else vc_state = ESnormal; @@ -1848,7 +1857,6 @@ static int do_con_write(struct tty_struct * tty, int from_user, if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) { par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ; if (npar==7) { -#if 0 int i = par[0]*3, j = 1; palette[i] = 16*par[j++]; palette[i++] += par[j++]; @@ -1857,7 +1865,6 @@ static int do_con_write(struct tty_struct * tty, int from_user, palette[i] = 16*par[j++]; palette[i] += par[j]; set_palette() ; -#endif vc_state = ESnormal; } } else @@ -2283,7 +2290,7 @@ static void console_bh(void) * Reads the information preserved by setup.s to determine the current display * type and sets everything accordingly. */ -unsigned long con_init(unsigned long kmem_start) +__initfunc(unsigned long con_init(unsigned long kmem_start)) { const char *display_desc = "????"; unsigned int currcons = 0; @@ -2617,22 +2624,61 @@ static int set_get_font(char * arg, int set, int ch512) * map, 3 bytes per colour, 16 colours, range from 0 to 255. */ +static int set_get_cmap(unsigned char *arg, int set) +{ + int i, j, k; + + for (i = 0; i < 16; i++) + if (set) { + get_user(default_red[i], arg++); + get_user(default_grn[i], arg++); + get_user(default_blu[i], arg++); + } else { + put_user(default_red[i], arg++); + put_user(default_grn[i], arg++); + put_user(default_blu[i], arg++); + } + if (set) { + for (i = 0; i < MAX_NR_CONSOLES; i++) + if (vc_cons_allocated(i)) + for (j = k = 0; j < 16; j++) { + vc_cons[i].d->vc_palette[k++] = + default_red[j]; + vc_cons[i].d->vc_palette[k++] = + default_grn[j]; + vc_cons[i].d->vc_palette[k++] = + default_blu[j]; + } + set_palette(); + } + return 0; +} + int con_set_cmap (unsigned char *arg) { - return -EINVAL; + return set_get_cmap (arg, 1); } int con_get_cmap (unsigned char *arg) { - return -EINVAL; + return set_get_cmap (arg, 0); } void reset_palette(int currcons) { + int j, k; + for (j = k = 0; j < 16; j++) { + palette[k++] = default_red[j]; + palette[k++] = default_grn[j]; + palette[k++] = default_blu[j]; + } + set_palette() ; } void set_palette(void) { + if (vt_cons[fg_console]->vc_mode != KD_GRAPHICS) + conswitchp->con_set_palette(vc_cons[fg_console].d, color_table); } /* diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index ef5ef46d6..33542ca96 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S @@ -22,24 +22,6 @@ * NOTE: This code handles signal-recognition, which happens every time * after a timer-interrupt and after each system call. * - * Stack layout in 'ret_from_exception': - * - * This allows access to the syscall arguments in registers d1-d5 - * - * 0(sp) - d1 - * 4(sp) - d2 - * 8(sp) - d3 - * C(sp) - d4 - * 10(sp) - d5 - * 14(sp) - a0 - * 18(sp) - a1 - * 1C(sp) - a2 - * 20(sp) - d0 - * 24(sp) - orig_d0 - * 28(sp) - stack adjustment - * 2C(sp) - sr - * 2E(sp) - pc - * 32(sp) - format & vector */ /* @@ -48,94 +30,12 @@ * number 0 in the 'current_set' list. */ -/* - * 97/05/14 Andreas: Register %a2 is now set to the current task throughout - * the whole kernel. - */ - #include <linux/sys.h> #include <linux/config.h> #include <linux/linkage.h> +#include <asm/entry.h> #include <asm/setup.h> #include <asm/segment.h> -#ifdef CONFIG_KGDB -#include <asm/kgdb.h> -.globl SYMBOL_NAME(kgdb_registers) -#endif - -#define curptr a2 - -LENOSYS = 38 - -/* - * these are offsets into the task-struct - */ -LTASK_STATE = 0 -LTASK_COUNTER = 4 -LTASK_PRIORITY = 8 -LTASK_SIGNAL = 12 -LTASK_BLOCKED = 16 -LTASK_FLAGS = 20 - -/* the following macro is used when enabling interrupts */ -#if defined(MACH_ATARI_ONLY) - /* block out HSYNC on the atari */ -#define ALLOWINT 0xfbff -#define MAX_NOINT_IPL 3 -#else - /* portable version */ -#define ALLOWINT 0xf8ff -#define MAX_NOINT_IPL 0 -#endif /* machine compilation types */ - -LD0 = 0x20 -LORIG_D0 = 0x24 -LSR = 0x2C -LFORMATVEC = 0x32 - -/* - * This defines the normal kernel pt-regs layout. - * - * regs a3-a6 and d6-d7 are preserved by C code - * the kernel doesn't mess with usp unless it needs to - */ -#ifndef CONFIG_KGDB -#define SAVE_ALL \ - clrl %sp@-; /* stk_adj */ \ - movel %d0,%sp@-; /* orig d0 */ \ - movel %d0,%sp@-; /* d0 */ \ - moveml %d1-%d5/%a0-%a1/%curptr,%sp@-; -#else -/* Need to save the "missing" registers for kgdb... - */ -#define SAVE_ALL \ - clrl %sp@-; /* stk_adj */ \ - movel %d0,%sp@-; /* orig d0 */ \ - movel %d0,%sp@-; /* d0 */ \ - moveml %d1-%d5/%a0-%a1/%curptr,%sp@-; \ - moveml %d6-%d7,SYMBOL_NAME(kgdb_registers)+GDBOFFA_D6; \ - moveml %a3-%a6,SYMBOL_NAME(kgdb_registers)+GDBOFFA_A3; -#endif - -#define RESTORE_ALL \ - moveml %sp@+,%a0-%a1/%curptr/%d1-%d5; \ - movel %sp@+,%d0; \ - addql #4,%sp; /* orig d0 */ \ - addl %sp@+,%sp; /* stk adj */ \ - rte - -#define SWITCH_STACK_SIZE (6*4+4) /* includes return address */ - -#define SAVE_SWITCH_STACK \ - moveml %a3-%a6/%d6-%d7,%sp@- - -#define RESTORE_SWITCH_STACK \ - moveml %sp@+,%a3-%a6/%d6-%d7 - -#define GET_CURRENT(tmp) \ - movel %sp,tmp; \ - andw &-8192,tmp; \ - movel tmp,%curptr; .globl SYMBOL_NAME(system_call), SYMBOL_NAME(buserr), SYMBOL_NAME(trap) .globl SYMBOL_NAME(resume), SYMBOL_NAME(ret_from_exception) @@ -146,12 +46,7 @@ LFORMATVEC = 0x32 .text ENTRY(buserr) - SAVE_ALL - moveq #-1,%d0 - movel %d0,%sp@(LORIG_D0) | a -1 in the ORIG_D0 field - | signifies that the stack frame - | is NOT for syscall - + SAVE_ALL_INT GET_CURRENT(%d0) movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(buserr_c) @@ -159,11 +54,7 @@ ENTRY(buserr) jra SYMBOL_NAME(ret_from_exception) ENTRY(trap) - SAVE_ALL - moveq #-1,%d0 - movel %d0,%sp@(LORIG_D0) | a -1 in the ORIG_D0 field - | signifies that the stack frame - | is NOT for syscall + SAVE_ALL_INT GET_CURRENT(%d0) movel %sp,%sp@- | stack frame pointer argument bsrl SYMBOL_NAME(trap_c) @@ -180,18 +71,18 @@ ENTRY(reschedule) jmp SYMBOL_NAME(schedule) badsys: - movel #-LENOSYS,LD0(%sp) + movel #-LENOSYS,LPT_OFF_D0(%sp) jra SYMBOL_NAME(ret_from_exception) do_trace: - movel #-LENOSYS,LD0(%sp) | needed for strace + movel #-LENOSYS,LPT_OFF_D0(%sp) | needed for strace subql #4,%sp SAVE_SWITCH_STACK jbsr SYMBOL_NAME(syscall_trace) RESTORE_SWITCH_STACK addql #4,%sp jbsr @(SYMBOL_NAME(sys_call_table),%d2:l:4)@(0) - movel %d0,%sp@(LD0) | save the return value + movel %d0,%sp@(LPT_OFF_D0) | save the return value subql #4,%sp | dummy return address SAVE_SWITCH_STACK jbsr SYMBOL_NAME(syscall_trace) @@ -202,7 +93,7 @@ SYMBOL_NAME_LABEL(ret_from_signal) jra SYMBOL_NAME(ret_from_exception) ENTRY(system_call) - SAVE_ALL + SAVE_ALL_SYS movel %d0,%d2 GET_CURRENT(%d0) @@ -213,19 +104,20 @@ ENTRY(system_call) cmpl #NR_syscalls,%d2 jcc badsys - btst #5,%curptr@(LTASK_FLAGS+3) | PF_TRACESYS + btst #LPF_TRACESYS_BIT,%curptr@(LTASK_FLAGS+LPF_TRACESYS_OFF) jne do_trace jbsr @(SYMBOL_NAME(sys_call_table),%d2:l:4)@(0) - movel %d0,%sp@(LD0) | save the return value + movel %d0,%sp@(LPT_OFF_D0) | save the return value SYMBOL_NAME_LABEL(ret_from_exception) - btst #5,%sp@(LSR) | check if returning to kernel + btst #5,%sp@(LPT_OFF_SR) | check if returning to kernel bnes 2f | if so, skip resched, signals tstl SYMBOL_NAME(need_resched) jne SYMBOL_NAME(reschedule) cmpl #SYMBOL_NAME(task),%curptr | task[0] cannot have signals jeq 2f - bclr #5,%curptr@(LTASK_FLAGS+1) | check for delayed trace + | check for delayed trace + bclr #LPF_DTRACE_BIT,%curptr@(LTASK_FLAGS+LPF_DTRACE_OFF) jne do_delayed_trace 5: tstl %curptr@(LTASK_STATE) | state @@ -236,7 +128,7 @@ SYMBOL_NAME_LABEL(ret_from_exception) movel %curptr@(LTASK_BLOCKED),%d0 movel %d0,%d1 | save blocked in d1 for sig handling notl %d0 - btst #4,%curptr@(LTASK_FLAGS+3) | PF_PTRACED + btst #LPF_PTRACED_BIT,%curptr@(LTASK_FLAGS+LPF_PTRACED_OFF) jeq 1f moveq #-1,%d0 | let the debugger see all signals 1: andl %curptr@(LTASK_SIGNAL),%d0 @@ -255,10 +147,10 @@ Lsignal_return: RESTORE_ALL do_delayed_trace: - bclr #7,%sp@(LSR) | clear trace bit in SR + bclr #7,%sp@(LPT_OFF_SR) | clear trace bit in SR pea 1 | send SIGTRAP - movel %a0,%sp@- - pea 5 + movel %curptr,%sp@- + pea LSIGTRAP jbsr SYMBOL_NAME(send_sig) addql #8,%sp addql #4,%sp @@ -268,15 +160,11 @@ do_delayed_trace: ** This is the main interrupt handler, responsible for calling process_int() */ SYMBOL_NAME_LABEL(inthandler) - SAVE_ALL - moveq #-1,%d0 - movel %d0,%sp@(LORIG_D0) | a -1 in the ORIG_D0 field - | signifies that the stack frame - | is NOT for syscall + SAVE_ALL_INT GET_CURRENT(%d0) addql #1,SYMBOL_NAME(local_irq_count) | put exception # in d0 - bfextu %sp@(LFORMATVEC){#4,#10},%d0 + bfextu %sp@(LPT_OFF_FORMATVEC){#4,#10},%d0 movel %sp,%sp@- movel %d0,%sp@- | put vector # on stack @@ -290,7 +178,7 @@ SYMBOL_NAME_LABEL(ret_from_interrupt) RESTORE_ALL 1: #if 1 - bfextu %sp@(LSR){#5,#3},%d0 | Check for nested interrupt. + bfextu %sp@(LPT_OFF_SR){#5,#3},%d0 | Check for nested interrupt. #if MAX_NOINT_IPL > 0 cmpiw #MAX_NOINT_IPL,%d0 #endif @@ -347,14 +235,6 @@ ENTRY(sys_sigreturn) RESTORE_SWITCH_STACK rts -LFLUSH_I_AND_D = 0x00000808 -LTSS_KSP = 0 -LTSS_USP = 4 -LTSS_SR = 8 -LTSS_FS = 10 -LTSS_CRP = 12 -LTSS_FPCTXT = 24 - SYMBOL_NAME_LABEL(resume) /* * Beware - when entering resume, offset of tss is in d1, @@ -460,8 +340,10 @@ SYMBOL_NAME_LABEL(resume) #if defined (CONFIG_M68060) /* is it a '060 ? */ +#if !defined(CPU_M68060_ONLY) btst #3,SYMBOL_NAME(m68k_cputype)+3 beqs 2f +#endif /* clear user entries in the branch cache */ movec %cacr,%d0 orl #0x00200000,%d0 diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c index def50a747..c27f7f320 100644 --- a/arch/m68k/kernel/setup.c +++ b/arch/m68k/kernel/setup.c @@ -142,8 +142,8 @@ __initfunc(static void m68k_parse_bootinfo(const struct bi_record *record)) } } - __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p, - unsigned long * memory_end_p)) +__initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p, + unsigned long * memory_end_p)) { unsigned long memory_start, memory_end; extern int _etext, _edata, _end; diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index 25be40007..44e45b9a0 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -201,7 +201,7 @@ static inline void access_error060 (struct frame *fp) if ((!(fslw & MMU060_ERR_BITS)) && !(fslw & MMU060_SEE)) return; } - + if (fslw & (MMU060_DESC_ERR | MMU060_WP)) { unsigned long errorcode; unsigned long addr = fp->un.fmt4.effaddr; diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c index b46037f80..02dff0eea 100644 --- a/arch/m68k/mm/init.c +++ b/arch/m68k/mm/init.c @@ -296,7 +296,8 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; * The parameters are pointers to where to stick the starting and ending * addresses of available kernel virtual memory. */ -__initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)) +__initfunc(unsigned long paging_init(unsigned long start_mem, + unsigned long end_mem)) { int chunk; unsigned long mem_avail = 0; diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c index 77eb2dbfe..dea7695e8 100644 --- a/arch/m68k/mm/memory.c +++ b/arch/m68k/mm/memory.c @@ -552,39 +552,26 @@ unsigned long mm_ptov (unsigned long paddr) void cache_clear (unsigned long paddr, int len) { if (CPU_IS_040_OR_060) { + int tmp; + /* * cwe need special treatment for the first page, in case it * is not page-aligned. */ - if (paddr & (PAGE_SIZE - 1)){ + if ((tmp = -paddr & (PAGE_SIZE - 1))) { pushcl040(paddr); - if (len <= PAGE_SIZE){ - if (((paddr + len - 1) ^ paddr) & PAGE_MASK) { - pushcl040(paddr + len - 1); - } + if ((len -= tmp) <= 0) return; - }else{ - len -=PAGE_SIZE; - paddr += PAGE_SIZE; - } + paddr += tmp; } - - while (len > PAGE_SIZE) { -#if 0 - pushcl040(paddr); -#else + tmp = PAGE_SIZE; + while ((len -= tmp) >= 0) { clear040(paddr); -#endif - len -= PAGE_SIZE; - paddr += PAGE_SIZE; + paddr += tmp; } - if (len > 0) { + if ((len += tmp)) + /* a page boundary gets crossed at the end */ pushcl040(paddr); - if (((paddr + len - 1) ^ paddr) & PAGE_MASK) { - /* a page boundary gets crossed at the end */ - pushcl040(paddr + len - 1); - } - } } else /* 68030 or 68020 */ asm volatile ("movec %/cacr,%/d0\n\t" @@ -605,26 +592,19 @@ void cache_clear (unsigned long paddr, int len) void cache_push (unsigned long paddr, int len) { if (CPU_IS_040_OR_060) { + int tmp = PAGE_SIZE; + /* * on 68040 or 68060, push cache lines for pages in the range; * on the '040 this also invalidates the pushed lines, but not on * the '060! */ - while (len > PAGE_SIZE) { - pushcli040(paddr); - len -= PAGE_SIZE; - paddr += PAGE_SIZE; - } - if (len > 0) { + len += paddr & (PAGE_SIZE - 1); + do { pushcli040(paddr); - if (((paddr + len - 1) ^ paddr) & PAGE_MASK) { - /* a page boundary gets crossed at the end */ - pushcli040(paddr + len - 1); - } - } - } - - + paddr += tmp; + } while ((len -= tmp) > 0); + } /* * 68030/68020 have no writeback cache. On the other hand, * cache_push is actually a superset of cache_clear (the lines @@ -654,34 +634,24 @@ void cache_push (unsigned long paddr, int len) void cache_push_v (unsigned long vaddr, int len) { if (CPU_IS_040) { + int tmp = PAGE_SIZE; + /* on 68040, push cache lines for pages in the range */ - while (len > PAGE_SIZE) { - pushv040(vaddr); - len -= PAGE_SIZE; - vaddr += PAGE_SIZE; - } - if (len > 0) { + len += vaddr & (PAGE_SIZE - 1); + do { pushv040(vaddr); - if (((vaddr + len - 1) ^ vaddr) & PAGE_MASK) { - /* a page boundary gets crossed at the end */ - pushv040(vaddr + len - 1); - } - } - } + vaddr += tmp; + } while ((len -= tmp) > 0); + } else if (CPU_IS_060) { + int tmp = PAGE_SIZE; + /* on 68040, push cache lines for pages in the range */ - while (len > PAGE_SIZE) { - pushv060(vaddr); - len -= PAGE_SIZE; - vaddr += PAGE_SIZE; - } - if (len > 0) { + len += vaddr & (PAGE_SIZE - 1); + do { pushv060(vaddr); - if (((vaddr + len - 1) ^ vaddr) & PAGE_MASK) { - /* a page boundary gets crossed at the end */ - pushv060(vaddr + len - 1); - } - } + vaddr += tmp; + } while ((len -= tmp) > 0); } /* 68030/68020 have no writeback cache; still need to clear icache. */ else /* 68030 or 68020 */ diff --git a/arch/mips/defconfig b/arch/mips/defconfig index 33f54a301..9c6fb9073 100644 --- a/arch/mips/defconfig +++ b/arch/mips/defconfig @@ -153,6 +153,9 @@ CONFIG_PCNET32=y # Filesystems # # CONFIG_QUOTA is not set +# CONFIG_DCACHE_PRELOAD is not set +# CONFIG_OMIRR is not set +# CONFIG_TRANS_NAMES is not set # CONFIG_MINIX_FS is not set CONFIG_EXT2_FS=y # CONFIG_FAT_FS is not set diff --git a/arch/mips/jazz/g364.c b/arch/mips/jazz/g364.c index 92e130522..1503cc559 100644 --- a/arch/mips/jazz/g364.c +++ b/arch/mips/jazz/g364.c @@ -25,6 +25,11 @@ #include <linux/major.h> #include <linux/mm.h> #include <linux/ioport.h> +#include <linux/kbd_kern.h> +#include <linux/vt_kern.h> +#include <linux/consolemap.h> +#include <linux/selection.h> +#include <linux/console_struct.h> #include <asm/io.h> #include <asm/system.h> @@ -33,12 +38,6 @@ #include <asm/bootinfo.h> #include <asm/types.h> -#include "../../../drivers/char/kbd_kern.h" -#include "../../../drivers/char/vt_kern.h" -#include "../../../drivers/char/consolemap.h" -#include "../../../drivers/char/selection.h" -#include "../../../drivers/char/console_struct.h" - extern void register_console(void (*proc)(const char *)); extern void console_print(const char *); unsigned video_res_x; diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c index d994155d0..fc0d542fc 100644 --- a/arch/mips/kernel/irixelf.c +++ b/arch/mips/kernel/irixelf.c @@ -465,7 +465,7 @@ static inline int look_for_irix_interpreter(char **name, goto losing; old_fs = get_fs(); set_fs(get_ds()); - retval = namei(*name, interpreter_inode); + retval = namei(NAM_FOLLOW_LINK, *name, interpreter_inode); set_fs(old_fs); if(retval < 0) goto losing; @@ -973,6 +973,7 @@ unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt) */ static int dump_write(struct file *file, const void *addr, int nr) { + file->f_inode->i_status |= ST_MODIFIED; return file->f_op->write(file->f_inode, file, addr, nr) == nr; } diff --git a/arch/sparc/config.in b/arch/sparc/config.in index 0005004be..85566667f 100644 --- a/arch/sparc/config.in +++ b/arch/sparc/config.in @@ -54,6 +54,7 @@ bool 'Sysctl support' CONFIG_SYSCTL tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA fi endmenu diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig index ff91819b0..a6df2dcc0 100644 --- a/arch/sparc/defconfig +++ b/arch/sparc/defconfig @@ -42,6 +42,7 @@ SUN_FB_CGFOURTEEN=y SUN_FB_BWTWO=y SUN_FB_LEO=y TADPOLE_FB_WEITEK=y +SUN_FB_CREATOR=y # # Misc Linux/SPARC drivers @@ -177,6 +178,9 @@ CONFIG_MYRI_SBUS=m # Filesystems # CONFIG_QUOTA=y +# CONFIG_DCACHE_PRELOAD is not set +# CONFIG_OMIRR is not set +# CONFIG_TRANS_NAMES is not set CONFIG_MINIX_FS=m CONFIG_EXT2_FS=y CONFIG_FAT_FS=m diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in index c8cdc0134..6354edded 100644 --- a/arch/sparc64/config.in +++ b/arch/sparc64/config.in @@ -59,6 +59,9 @@ fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA fi +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC +fi endmenu mainmenu_option next_comment diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 579fbb4c2..0d95e1b75 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.27 1997/05/27 19:30:11 jj Exp $ +/* $Id: entry.S,v 1.31 1997/06/02 06:33:25 davem Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -18,7 +18,7 @@ #include <asm/signal.h> #include <asm/pgtable.h> -/* define SYSCALL_TRACING */ +/* #define SYSCALL_TRACING */ #define curptr g6 @@ -39,82 +39,84 @@ * it will not get updated properly. */ sparc64_dtlb_prot_catch: - wr %g0, ASI_DMMU, %asi - rdpr %pstate, %g1 - wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate - rdpr %tl, %g2 - ldxa [%g0 + TLB_TAG_ACCESS] %asi, %g5 - ldxa [%g0 + TLB_SFSR] %asi, %g4 - cmp %g2, 1 - stxa %g0, [%g0 + TLB_SFSR] %asi - bgu,a %icc, winfix_trampoline - rdpr %tpc, %g5 - ba,pt %xcc, etrap - rd %pc, %g7 - b,a,pt %xcc, 1f + wr %g0, ASI_DMMU, %asi + rdpr %pstate, %g1 + wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate + rdpr %tl, %g3 + ldxa [%g0 + TLB_TAG_ACCESS] %asi, %g5 + ldxa [%g0 + TLB_SFSR] %asi, %g4 + cmp %g3, 1 + stxa %g0, [%g0 + TLB_SFSR] %asi + bgu,a,pn %icc, winfix_trampoline + rdpr %tpc, %g3 + ba,pt %xcc, etrap + rd %pc, %g7 + b,a,pt %xcc, 1f sparc64_dtlb_refbit_catch: - srlx %g5, 9, %g4 - and %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4 - cmp %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9) - be,a,pt %xcc, 2f - mov 1, %g4 - wr %g0, ASI_DMMU, %asi - rdpr %pstate, %g1 - wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate - rdpr %tl, %g2 - ldxa [%g0 + TLB_TAG_ACCESS] %asi, %g5 - cmp %g2, 1 - clr %g4 ! sfsr not updated for tlb misses - bgu,a %icc, winfix_trampoline - rdpr %tpc, %g5 - ba,pt %xcc, etrap - rd %pc, %g7 + srlx %g5, 9, %g4 + and %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4 + cmp %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9) + be,a,pt %xcc, 2f + mov 1, %g4 + wr %g0, ASI_DMMU, %asi + rdpr %pstate, %g1 + wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate + rdpr %tl, %g3 + ldxa [%g0 + TLB_TAG_ACCESS] %asi, %g5 + cmp %g3, 1 + clr %g4 ! sfsr not updated for tlb misses + bgu,a,pn %icc, winfix_trampoline + rdpr %tpc, %g3 + ba,pt %xcc, etrap + rd %pc, %g7 1: - mov %l5, %o4 ! raw tag access - mov %l4, %o5 ! raw sfsr - srlx %l5, PAGE_SHIFT, %o3 - clr %o1 ! text_fault == 0 - sllx %o3, PAGE_SHIFT, %o3 ! address - and %l4, 0x4, %o2 ! write == sfsr.W - call do_sparc64_fault - add %sp, STACK_BIAS + REGWIN_SZ, %o0 ! pt_regs ptr - ba,a,pt %xcc, rtrap + mov %l5, %o4 ! raw tag access + mov %l4, %o5 ! raw sfsr + srlx %l5, PAGE_SHIFT, %o3 + clr %o1 ! text_fault == 0 + sllx %o3, PAGE_SHIFT, %o3 ! address + and %l4, 0x4, %o2 ! write == sfsr.W + call do_sparc64_fault + add %sp, STACK_BIAS + REGWIN_SZ, %o0 ! pt_regs ptr + ba,pt %xcc, rtrap + clr %l6 sparc64_itlb_refbit_catch: - srlx %g5, 9, %g4 - and %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4 - cmp %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9) - be,a,pt %xcc, 3f - mov 1, %g4 - rdpr %pstate, %g1 - wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate - ba,pt %xcc, etrap - rd %pc, %g7 - - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC], %o3 - mov 1, %o1 ! text_fault == 1 - clr %o2 ! write == 0 - clr %o4 ! tag access (N/A) - clr %o5 ! raw sfsr (N/A) - call do_sparc64_fault - add %sp, STACK_BIAS + REGWIN_SZ, %o0 ! pt_regs ptr - ba,a,pt %xcc, rtrap + srlx %g5, 9, %g4 + and %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4 + cmp %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9) + be,a,pt %xcc, 3f + mov 1, %g4 + rdpr %pstate, %g1 + wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate + ba,pt %xcc, etrap + rd %pc, %g7 + + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC], %o3 + mov 1, %o1 ! text_fault == 1 + clr %o2 ! write == 0 + clr %o4 ! tag access (N/A) + clr %o5 ! raw sfsr (N/A) + call do_sparc64_fault + add %sp, STACK_BIAS + REGWIN_SZ, %o0 ! pt_regs ptr + ba,pt %xcc, rtrap + clr %l6 2: - sllx %g4, 63, %g4 ! _PAGE_VALID - or %g5, _PAGE_ACCESSED, %g5 - or %g5, %g4, %g5 - stxa %g5, [%g3 + %g1] ASI_PHYS_USE_EC ! store new PTE - stxa %g5, [%g0] ASI_DTLB_DATA_IN ! TLB load + sllx %g4, 63, %g4 ! _PAGE_VALID + or %g5, _PAGE_ACCESSED, %g5 + or %g5, %g4, %g5 + stxa %g5, [%g3 + %g1] ASI_PHYS_USE_EC ! store new PTE + stxa %g5, [%g0] ASI_DTLB_DATA_IN ! TLB load retry 3: - sllx %g4, 63, %g4 ! _PAGE_VALID - or %g5, _PAGE_ACCESSED, %g5 - or %g5, %g4, %g5 - stxa %g5, [%g3 + %g1] ASI_PHYS_USE_EC ! store new PTE - stxa %g5, [%g0] ASI_ITLB_DATA_IN ! TLB load + sllx %g4, 63, %g4 ! _PAGE_VALID + or %g5, _PAGE_ACCESSED, %g5 + or %g5, %g4, %g5 + stxa %g5, [%g3 + %g1] ASI_PHYS_USE_EC ! store new PTE + stxa %g5, [%g0] ASI_ITLB_DATA_IN ! TLB load retry /* Note check out head.h, this code isn't even used for UP, @@ -131,268 +133,285 @@ sparc64_itlb_refbit_catch: .align 4 .globl do_ivec do_ivec: - ldxa [%g0] ASI_INTR_RECEIVE, %g1 - andcc %g1, 0x20, %g0 - be,pn %xcc, do_ivec_return - mov 0x40, %g2 + ldxa [%g0] ASI_INTR_RECEIVE, %g1 + andcc %g1, 0x20, %g0 + be,pn %xcc, do_ivec_return + mov 0x40, %g2 /* Load up Interrupt Vector Data 0 register. */ - sethi %uhi(ivector_to_mask), %g4 - ldxa [%g2] ASI_UDB_INTR_R, %g3 - or %g4, %ulo(ivector_to_mask), %g4 - and %g3, 0x7ff, %g3 - sllx %g4, 32, %g4 - sethi %hi(ivector_to_mask), %g5 - sllx %g3, 3, %g3 - or %g5, %lo(ivector_to_mask), %g5 - add %g5, %g4, %g4 - ldx [%g4 + %g3], %g2 - brz,pn %g2, do_ivec_spurious + sethi %uhi(ivector_to_mask), %g4 + ldxa [%g2] ASI_UDB_INTR_R, %g3 + or %g4, %ulo(ivector_to_mask), %g4 + and %g3, 0x7ff, %g3 + sllx %g4, 32, %g4 + sethi %hi(ivector_to_mask), %g5 + sllx %g3, 3, %g3 + or %g5, %lo(ivector_to_mask), %g5 + add %g5, %g4, %g4 + ldx [%g4 + %g3], %g2 + brz,pn %g2, do_ivec_spurious nop /* No branches, worse case we don't know about this interrupt * yet, so we would just write a zero into the softint register * which is completely harmless. */ - wr %g2, 0x0, %set_softint + wr %g2, 0x0, %set_softint do_ivec_return: /* Acknowledge the UPA */ - stxa %g0, [%g0] ASI_INTR_RECEIVE - membar #Sync + stxa %g0, [%g0] ASI_INTR_RECEIVE + membar #Sync retry do_ivec_spurious: - stxa %g0, [%g0] ASI_INTR_RECEIVE - rdpr %pstate, %g1 - wrpr %g1, PSTATE_IG | PSTATE_AG, %pstate - ba,pt %xcc, etrap - rd %pc, %g7 - call report_spurious_ivec - add %sp, STACK_BIAS + REGWIN_SZ, %o0 - ba,pt %xcc, rtrap - nop + stxa %g0, [%g0] ASI_INTR_RECEIVE + rdpr %pstate, %g1 + wrpr %g1, PSTATE_IG | PSTATE_AG, %pstate + ba,pt %xcc, etrap + rd %pc, %g7 + call report_spurious_ivec + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + ba,pt %xcc, rtrap + clr %l6 + + .globl do_mna +do_mna: + rdpr %tl, %g3 + cmp %g3, 1 + bgu,a,pn %icc, winfix_mna + rdpr %tpc, %g3 + ba,pt %xcc, etrap + rd %pc, %g7 + call mem_address_unaligned + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + ba,pt %xcc, rtrap + clr %l6 -breakpoint_t: - .asciz "Breakpoint Trap %lx\n" - .align 4 .globl breakpoint_trap breakpoint_trap: - mov %o0, %o1 - sethi %hi(breakpoint_t), %o0 - or %o0, %lo(breakpoint_t), %o0 - call prom_printf - add %o0, %g4, %o0 - call prom_cmdline + call sparc_breakpoint + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + ba,pt %xcc, rtrap nop - ba,a,pt %xcc, rtrap .globl sys_pipe, sys_execve, sys_sigpause, sys_nis_syscall .globl sys_sigsuspend, sys_sigreturn .globl sys32_execve, sys_ptrace sys_pipe: - sethi %hi(sparc_pipe), %g1 - add %g1, %g4, %g1 - jmpl %g1 + %lo(sparc_pipe), %g0 - add %sp, STACK_BIAS + REGWIN_SZ, %o0 + sethi %hi(sparc_pipe), %g1 + add %g1, %g4, %g1 + jmpl %g1 + %lo(sparc_pipe), %g0 + add %sp, STACK_BIAS + REGWIN_SZ, %o0 sys_nis_syscall: - sethi %hi(c_sys_nis_syscall), %g1 - add %g1, %g4, %g1 - jmpl %g1 + %lo(c_sys_nis_syscall), %g0 - add %sp, STACK_BIAS + REGWIN_SZ, %o0 + sethi %hi(c_sys_nis_syscall), %g1 + add %g1, %g4, %g1 + jmpl %g1 + %lo(c_sys_nis_syscall), %g0 + add %sp, STACK_BIAS + REGWIN_SZ, %o0 sys_execve: - sethi %hi(sparc_execve), %g1 - add %g1, %g4, %g1 - jmpl %g1 + %lo(sparc_execve), %g0 - add %sp, STACK_BIAS + REGWIN_SZ, %o0 + sethi %hi(sparc_execve), %g1 + add %g1, %g4, %g1 + jmpl %g1 + %lo(sparc_execve), %g0 + add %sp, STACK_BIAS + REGWIN_SZ, %o0 sys32_execve: - sethi %hi(sparc32_execve), %g1 - add %g1, %g4, %g1 - jmpl %g1 + %lo(sparc32_execve), %g0 - add %sp, STACK_BIAS + REGWIN_SZ, %o0 + sethi %hi(sparc32_execve), %g1 + add %g1, %g4, %g1 + jmpl %g1 + %lo(sparc32_execve), %g0 + add %sp, STACK_BIAS + REGWIN_SZ, %o0 sys_sigpause: /* NOTE: %o0 has a correct value already */ - call do_sigpause - add %sp, STACK_BIAS + REGWIN_SZ, %o1 + call do_sigpause + add %sp, STACK_BIAS + REGWIN_SZ, %o1 - ld [%curptr + AOFF_task_flags], %l5 - andcc %l5, 0x20, %g0 - be,pt %icc, rtrap + ld [%curptr + AOFF_task_flags], %l5 + andcc %l5, 0x20, %g0 + be,pt %icc, rtrap + clr %l6 + call syscall_trace nop - call syscall_trace - nop - ba,a,pt %xcc, rtrap + ba,pt %xcc, rtrap + clr %l6 sys_sigsuspend: - call do_sigsuspend - add %sp, STACK_BIAS + REGWIN_SZ, %o0 + call do_sigsuspend + add %sp, STACK_BIAS + REGWIN_SZ, %o0 - ld [%curptr + AOFF_task_flags], %l5 - andcc %l5, 0x20, %g0 - be,pt %icc, rtrap - nop - call syscall_trace + ld [%curptr + AOFF_task_flags], %l5 + andcc %l5, 0x20, %g0 + be,pt %icc, rtrap + clr %l6 + call syscall_trace nop - ba,a,pt %xcc, rtrap + ba,pt %xcc, rtrap + clr %l6 sys_sigreturn: - call do_sigreturn - add %sp, STACK_BIAS + REGWIN_SZ, %o0 + call do_sigreturn + add %sp, STACK_BIAS + REGWIN_SZ, %o0 - ld [%curptr + AOFF_task_flags], %l5 - andcc %l5, 0x20, %g0 - be,pt %icc, rtrap + ld [%curptr + AOFF_task_flags], %l5 + andcc %l5, 0x20, %g0 + be,pt %icc, rtrap + clr %l6 + call syscall_trace nop - call syscall_trace - nop - ba,a,pt %xcc, rtrap + ba,pt %xcc, rtrap + clr %l6 sys_ptrace: - call do_ptrace - add %sp, STACK_BIAS + REGWIN_SZ, %o0 + call do_ptrace + add %sp, STACK_BIAS + REGWIN_SZ, %o0 - ld [%curptr + AOFF_task_flags], %l5 - andcc %l5, 0x20, %g0 - be,pt %icc, rtrap - nop - call syscall_trace + ld [%curptr + AOFF_task_flags], %l5 + andcc %l5, 0x20, %g0 + be,pt %icc, rtrap + clr %l6 + call syscall_trace nop - ba,a,pt %xcc, rtrap + ba,pt %xcc, rtrap + clr %l6 - /* This is how fork() was meant to be done, 10 instruction entry. -DaveM */ + /* This is how fork() was meant to be done, 12 instruction entry. -DaveM */ .globl sys_fork, sys_vfork, sys_clone sys_fork: sys_vfork: - mov SIGCHLD, %o0 - clr %o1 + mov SIGCHLD, %o0 + clr %o1 sys_clone: - mov %o7, %l5 + mov %o7, %l5 + save %sp, -REGWIN_SZ, %sp flushw - rdpr %cwp, %o4 - add %sp, STACK_BIAS + REGWIN_SZ, %o2 - movrz %o1, %fp, %o1 + restore %g0, %g0, %g0 + rdpr %cwp, %o4 + add %sp, STACK_BIAS + REGWIN_SZ, %o2 + movrz %o1, %fp, %o1 /* Don't try this at home. */ - stx %o4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G0] - call do_fork - mov %l5, %o7 + stx %o4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G0] + call do_fork + mov %l5, %o7 linux_sparc_ni_syscall: - sethi %hi(sys_ni_syscall), %l7 - or %l7, %lo(sys_ni_syscall), %l7 - ba,pt %xcc,syscall_is_too_hard - add %l7, %g4, %l7 + sethi %hi(sys_ni_syscall), %l7 + or %l7, %lo(sys_ni_syscall), %l7 + ba,pt %xcc,syscall_is_too_hard + add %l7, %g4, %l7 linux_fast_syscall: - andn %l7, 3, %l7 - mov %i0, %o0 - mov %i1, %o1 - mov %i2, %o2 - jmpl %l7 + %g0, %g0 - mov %i3, %o3 + andn %l7, 3, %l7 + mov %i0, %o0 + mov %i1, %o1 + mov %i2, %o2 + jmpl %l7 + %g0, %g0 + mov %i3, %o3 linux_syscall_trace: - call syscall_trace + call syscall_trace nop - mov %i0, %o0 - mov %i1, %o1 - mov %i2, %o2 - mov %i3, %o3 - ba,pt %xcc, 2f - mov %i4, %o4 + mov %i0, %o0 + mov %i1, %o1 + mov %i2, %o2 + mov %i3, %o3 + ba,pt %xcc, 2f + mov %i4, %o4 .globl ret_from_syscall ret_from_syscall: - ba,pt %xcc, ret_sys_call - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %o0 + ba,pt %xcc, ret_sys_call + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %o0 /* Linux native and SunOS system calls enter here... */ .align 4 .globl linux_sparc_syscall linux_sparc_syscall: /* Direct access to user regs, must faster. */ - cmp %g1, NR_SYSCALLS - add %l7, %g4, %l7 - bgeu,pn %xcc, linux_sparc_ni_syscall - sll %g1, 3, %l4 - ldx [%l7 + %l4], %l7 - andcc %l7, 1, %g0 - bne,pn %icc, linux_fast_syscall + cmp %g1, NR_SYSCALLS + add %l7, %g4, %l7 + bgeu,pn %xcc, linux_sparc_ni_syscall + sll %g1, 3, %l4 + ldx [%l7 + %l4], %l7 + andcc %l7, 1, %g0 + bne,pn %icc, linux_fast_syscall /* Just do the next insn in the delay slot */ .globl syscall_is_too_hard syscall_is_too_hard: #ifdef SYSCALL_TRACING /* Debugging... */ - mov %g1, %o0 ! o0=scall, o1=ptregs - call syscall_trace_entry - add %sp, STACK_BIAS + REGWIN_SZ, %o1 + mov %g1, %o0 ! o0=scall, o1=ptregs + call syscall_trace_entry + add %sp, STACK_BIAS + REGWIN_SZ, %o1 #endif - mov %i0, %o0 - mov %i1, %o1 - mov %i2, %o2 - - ldx [%curptr + AOFF_task_flags], %l5 - mov %i3, %o3 - mov %i4, %o4 - andcc %l5, 0x20, %g0 - bne,pn %icc, linux_syscall_trace - mov %i0, %l5 + mov %i0, %o0 + mov %i1, %o1 + mov %i2, %o2 + + ldx [%curptr + AOFF_task_flags], %l5 + mov %i3, %o3 + mov %i4, %o4 + andcc %l5, 0x20, %g0 + bne,pn %icc, linux_syscall_trace + mov %i0, %l5 2: - call %l7 - mov %i5, %o5 + call %l7 + mov %i5, %o5 #ifdef SYSCALL_TRACING /* Debugging... */ - call syscall_trace_exit ! o0=sysret, o1=ptregs - add %sp, STACK_BIAS + REGWIN_SZ, %o1 + call syscall_trace_exit ! o0=sysret, o1=ptregs + add %sp, STACK_BIAS + REGWIN_SZ, %o1 #endif - stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] + stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] .globl ret_sys_call ret_sys_call: - ldx [%curptr + AOFF_task_flags], %l6 - mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %g3 - cmp %o0, -ENOIOCTLCMD - sllx %g2, 32, %g2 - bgeu,pn %xcc, 1f - andcc %l6, 0x20, %l6 + ldx [%curptr + AOFF_task_flags], %l6 + ldx [%curptr + AOFF_task_tss + AOFF_thread_flags], %l2 + mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2 + and %l2, SPARC_FLAG_32BIT, %l2 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %g3 + brnz,a,pn %l2, 1f + sra %o0, 0, %o0 +1: + cmp %o0, -ENOIOCTLCMD + sllx %g2, 32, %g2 + bgeu,pn %xcc, 1f + andcc %l6, 0x20, %l6 /* System call success, clear Carry condition code. */ - andn %g3, %g2, %g3 - clr %l6 - stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE] - bne,pn %icc, linux_syscall_trace2 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 /* pc = npc */ - add %l1, 0x4, %l2 /* npc = npc+4 */ - stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC] - ba,pt %xcc, rtrap - stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC] + andn %g3, %g2, %g3 + clr %l6 + stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE] + bne,pn %icc, linux_syscall_trace2 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc + add %l1, 0x4, %l2 !npc = npc+4 + stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC] + ba,pt %xcc, rtrap + stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC] 1: /* System call failure, set Carry condition code. * Also, get abs(errno) to return to the process. */ - sub %g0, %o0, %o0 - or %g3, %g2, %g3 - stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] - mov 1, %l6 - stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE] - bne,pn %icc, linux_syscall_trace2 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 /* pc = npc */ - add %l1, 0x4, %l2 /* npc = npc+4 */ - stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC] - ba,pt %xcc, rtrap - stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC] + sub %g0, %o0, %o0 + or %g3, %g2, %g3 + stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] + mov 1, %l6 + stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE] + bne,pn %icc, linux_syscall_trace2 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc + add %l1, 0x4, %l2 !npc = npc+4 + stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC] + ba,pt %xcc, rtrap + stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC] linux_syscall_trace2: - call syscall_trace - add %l1, 0x4, %l2 /* npc = npc+4 */ - stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC] - ba,pt %xcc, rtrap - stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC] + call syscall_trace + add %l1, 0x4, %l2 /* npc = npc+4 */ + stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC] + ba,pt %xcc, rtrap + stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC] /* End of entry.S */ diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S index 0c166ec25..efb1b48fc 100644 --- a/arch/sparc64/kernel/etrap.S +++ b/arch/sparc64/kernel/etrap.S @@ -1,4 +1,4 @@ -/* $Id: etrap.S,v 1.18 1997/05/19 05:58:51 davem Exp $ +/* $Id: etrap.S,v 1.21 1997/06/02 06:33:28 davem Exp $ * etrap.S: Preparing for entry into the kernel on Sparc V9. * * Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -22,7 +22,7 @@ .text .align 32 - .globl etrap, etrap_irq + .globl etrap, etrap_irq, etraptl1 etrap: rdpr %pil, %g2 etrap_irq: @@ -45,13 +45,14 @@ etrap_irq: stx %g3, [%g2 + REGWIN_SZ + PT_V9_TNPC] stx %g1, [%g2 + REGWIN_SZ + PT_V9_Y] - rdpr %pstate, %g1 - save %g2, -STACK_BIAS, %sp - bne,pn %xcc, 1f + save %g2, -STACK_BIAS, %sp ! The ordering of these two instructions + rdpr %pstate, %g1 ! is critical, see winfixup.S for details + bne,pn %xcc, 2f rdpr %canrestore, %g3 rdpr %wstate, %g6 - wrpr %g0, 0, %canrestore + wrpr %g0, 7, %cleanwin + wrpr %g0, 0, %canrestore sll %g6, 3, %g6 wrpr %g3, 0, %otherwin wrpr %g6, %wstate @@ -59,17 +60,17 @@ etrap_irq: sllx %g3, 32, %g3 mov PRIMARY_CONTEXT, %g2 stxa %g0, [%g2] ASI_DMMU + flush %g3 -1: - wrpr %g0, 0x0, %tl +2: wrpr %g0, 0x0, %tl mov %g1, %l1 mov %g4, %l4 mov %g5, %l5 mov %g7, %l2 wrpr %l1, PSTATE_AG, %pstate stx %g1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1] - stx %g2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2] + stx %g2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2] stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3] stx %g4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4] stx %g5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5] @@ -77,8 +78,8 @@ etrap_irq: stx %g7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G7] stx %i0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] stx %i1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1] - stx %i2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2] + stx %i2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2] stx %i3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3] stx %i4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4] stx %i5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5] @@ -86,16 +87,13 @@ etrap_irq: stx %i7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7] wrpr %l1, (PSTATE_IE | PSTATE_AG), %pstate sethi %uhi(KERNBASE), %g4 - rd %pic, %g6 + rd %pic, %g6 jmpl %l2 + 0x4, %g0 sllx %g4, 32, %g4 - - .globl etraptl1 etraptl1: rdpr %tstate, %g1 + sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 ba,pt %xcc, 1b - sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 - nop - nop + andcc %g1, TSTATE_PRIV, %g0 nop diff --git a/arch/sparc64/kernel/hack.S b/arch/sparc64/kernel/hack.S index 6303bd9e9..843221395 100644 --- a/arch/sparc64/kernel/hack.S +++ b/arch/sparc64/kernel/hack.S @@ -24,16 +24,12 @@ do_fpother_tl1: retl;nop do_iae_tl1: retl;nop .globl do_ill_tl1 do_ill_tl1: retl;nop - .globl do_irq -do_irq: retl;nop .globl do_irq_tl1 do_irq_tl1: retl;nop .globl do_lddfmna do_lddfmna: retl;nop .globl do_lddfmna_tl1 do_lddfmna_tl1: retl;nop - .globl do_mna_tl1 -do_mna_tl1: retl;nop .globl do_paw do_paw: retl;nop .globl do_paw_tl1 @@ -51,7 +47,7 @@ do_vaw_tl1: retl;nop .globl floppy_hardint floppy_hardint: retl;nop .globl get_cpuid -get_cpuid: retl;nop +get_cpuid: retl;mov 0, %o0 .globl getcc getcc: retl;nop .globl halt diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 4babe3eb4..3844c24c3 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.30 1997/05/18 22:52:12 davem Exp $ +/* $Id: head.S,v 1.31 1997/05/30 22:35:28 davem Exp $ * head.S: Initial boot code for the Sparc64 port of Linux. * * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -55,7 +55,7 @@ ramdisk_image: .word 0 ramdisk_size: .word 0 - .word reboot_command + .xword reboot_command /* We must be careful, 32-bit OpenBOOT will get confused if it * tries to save away a register window to a 64-bit kernel diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 3db6fa945..d3792dec6 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.3 1997/05/27 19:30:13 jj Exp $ +/* $Id: ioctl32.c,v 1.8 1997/06/04 13:05:15 jj Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -7,22 +7,369 @@ * ioctls. */ +#include <linux/types.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/smp.h> #include <linux/smp_lock.h> #include <linux/ioctl.h> +#include <linux/if.h> +#include <linux/malloc.h> +#include <linux/hdreg.h> +#include <linux/md.h> +#include <linux/kd.h> +#include <linux/route.h> +#include <linux/netlink.h> #include <asm/types.h> #include <asm/uaccess.h> -/* As gcc will warn about casting u32 to some ptr, we have to cast it to unsigned long first, and that's what is A() for. - * You just do (void *)A(x), instead of having to type (void *)((unsigned long)x) or instead of just (void *)x, which will - * produce warnings */ +/* As gcc will warn about casting u32 to some ptr, we have to cast it to + * unsigned long first, and that's what is A() for. + * You just do (void *)A(x), instead of having to type (void *)((unsigned long)x) + * or instead of just (void *)x, which will produce warnings. + */ #define A(x) ((unsigned long)x) extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); + +static int w_long(unsigned int fd, unsigned int cmd, u32 arg) +{ + unsigned long old_fs = get_fs(); + int err; + unsigned long val; + + set_fs (KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&val); + set_fs (old_fs); + if (!err && put_user(val, (u32 *)A(arg))) + return -EFAULT; + return err; +} +struct ifmap32 { + u32 mem_start; + u32 mem_end; + unsigned short base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; +}; + +struct ifreq32 { +#define IFHWADDRLEN 6 +#define IFNAMSIZ 16 + union { + char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + } ifr_ifrn; + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + short ifru_flags; + int ifru_ivalue; + int ifru_mtu; + struct ifmap32 ifru_map; + char ifru_slave[IFNAMSIZ]; /* Just fits the size */ + __kernel_caddr_t32 ifru_data; + } ifr_ifru; +}; + +struct ifconf32 { + int ifc_len; /* size of buffer */ + __kernel_caddr_t32 ifcbuf; +}; + +static inline int dev_ifconf(unsigned int fd, u32 arg) +{ + struct ifconf32 ifc32; + struct ifconf ifc; + struct ifreq32 *ifr32; + struct ifreq *ifr; + unsigned long old_fs; + unsigned int i, j; + int err; + + if (copy_from_user(&ifc32, (struct ifconf32 *)A(arg), sizeof(struct ifconf32))) + return -EFAULT; + ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32)) + 1) * sizeof (struct ifreq); + ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL); + if (!ifc.ifc_buf) return -ENOMEM; + ifr = ifc.ifc_req; + ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf); + for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) { + if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) { + kfree (ifc.ifc_buf); + return -EFAULT; + } + } + old_fs = get_fs(); set_fs (KERNEL_DS); + err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc); + set_fs (old_fs); + if (!err) { + ifr = ifc.ifc_req; + ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf); + for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len; + i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) { + if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) { + err = -EFAULT; + break; + } + } + if (!err) { + if (i <= ifc32.ifc_len) + ifc32.ifc_len = i; + else + ifc32.ifc_len = i - sizeof (struct ifreq32); + if (copy_to_user((struct ifconf32 *)A(arg), &ifc32, sizeof(struct ifconf32))) + err = -EFAULT; + } + } + kfree (ifc.ifc_buf); + return err; +} + +static inline int dev_ifsioc(unsigned int fd, unsigned int cmd, u32 arg) +{ + struct ifreq ifr; + unsigned long old_fs; + int err; + + if (cmd == SIOCSIFMAP) { + if (copy_from_user(&ifr, (struct ifreq32 *)A(arg), sizeof(ifr.ifr_name)) || + __get_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.mem_start)) || + __get_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.mem_end)) || + __get_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.base_addr)) || + __get_user(ifr.ifr_map.irq, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.irq)) || + __get_user(ifr.ifr_map.dma, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.dma)) || + __get_user(ifr.ifr_map.port, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.port))) + return -EFAULT; + } else { + if (copy_from_user(&ifr, (struct ifreq32 *)A(arg), sizeof(struct ifreq32))) + return -EFAULT; + } + old_fs = get_fs(); + set_fs (KERNEL_DS); + err = sys_ioctl (fd, cmd, (unsigned long)&ifr); + set_fs (old_fs); + if (!err) { + switch (cmd) { + case SIOCGIFFLAGS: + case SIOCGIFMETRIC: + case SIOCGIFMTU: + case SIOCGIFMEM: + case SIOCGIFHWADDR: + case SIOGIFINDEX: + case SIOCGIFADDR: + case SIOCGIFBRDADDR: + case SIOCGIFDSTADDR: + case SIOCGIFNETMASK: + if (copy_to_user((struct ifreq32 *)A(arg), &ifr, sizeof(struct ifreq32))) + return -EFAULT; + break; + case SIOCGIFMAP: + if (copy_to_user((struct ifreq32 *)A(arg), &ifr, sizeof(ifr.ifr_name)) || + __put_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.mem_start)) || + __put_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.mem_end)) || + __put_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.base_addr)) || + __put_user(ifr.ifr_map.irq, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.irq)) || + __put_user(ifr.ifr_map.dma, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.dma)) || + __put_user(ifr.ifr_map.port, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.port))) + return -EFAULT; + break; + } + } + return err; +} + +struct rtentry32 { + u32 rt_pad1; + struct sockaddr rt_dst; /* target address */ + struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ + struct sockaddr rt_genmask; /* target network mask (IP) */ + unsigned short rt_flags; + short rt_pad2; + u32 rt_pad3; + unsigned char rt_tos; + unsigned char rt_class; + short rt_pad4; + short rt_metric; /* +1 for binary compatibility! */ + /* char * */ u32 rt_dev; /* forcing the device at add */ + u32 rt_mtu; /* per route MTU/Window */ + u32 rt_window; /* Window clamping */ + unsigned short rt_irtt; /* Initial RTT */ + +}; + +static inline int routing_ioctl(unsigned int fd, unsigned int cmd, u32 arg) +{ + struct rtentry r; + char devname[16]; + u32 rtdev; + int ret; + unsigned long old_fs = get_fs(); + + if (get_user (r.rt_pad1, &(((struct rtentry32 *)A(arg))->rt_pad1)) || + copy_from_user (&r.rt_dst, &(((struct rtentry32 *)A(arg))->rt_dst), 3 * sizeof(struct sockaddr)) || + __get_user (r.rt_flags, &(((struct rtentry32 *)A(arg))->rt_flags)) || + __get_user (r.rt_pad2, &(((struct rtentry32 *)A(arg))->rt_pad2)) || + __get_user (r.rt_pad3, &(((struct rtentry32 *)A(arg))->rt_pad3)) || + __get_user (r.rt_tos, &(((struct rtentry32 *)A(arg))->rt_tos)) || + __get_user (r.rt_class, &(((struct rtentry32 *)A(arg))->rt_class)) || + __get_user (r.rt_pad4, &(((struct rtentry32 *)A(arg))->rt_pad4)) || + __get_user (r.rt_metric, &(((struct rtentry32 *)A(arg))->rt_metric)) || + __get_user (r.rt_mtu, &(((struct rtentry32 *)A(arg))->rt_mtu)) || + __get_user (r.rt_window, &(((struct rtentry32 *)A(arg))->rt_window)) || + __get_user (r.rt_irtt, &(((struct rtentry32 *)A(arg))->rt_irtt)) || + __get_user (rtdev, &(((struct rtentry32 *)A(arg))->rt_dev)) || + (rtdev && copy_from_user (devname, (char *)A(rtdev), 15))) + return -EFAULT; + if (rtdev) { + r.rt_dev = devname; devname[15] = 0; + } else + r.rt_dev = 0; + set_fs (KERNEL_DS); + ret = sys_ioctl (fd, cmd, (long)&r); + set_fs (old_fs); + return ret; +} + +struct nlmsghdr32 { + u32 nlmsg_len; /* Length of message including header */ + u32 nlmsg_type; /* Message type */ + u32 nlmsg_seq; /* Sequence number */ + u32 nlmsg_pid; /* Sending process PID */ + unsigned char nlmsg_data[0]; +}; + +struct in_rtmsg32 { + struct in_addr rtmsg_prefix; + struct in_addr rtmsg_gateway; + unsigned rtmsg_flags; + u32 rtmsg_mtu; + u32 rtmsg_window; + unsigned short rtmsg_rtt; + short rtmsg_metric; + unsigned char rtmsg_tos; + unsigned char rtmsg_class; + unsigned char rtmsg_prefixlen; + unsigned char rtmsg_reserved; + int rtmsg_ifindex; +}; + +struct in_ifmsg32 { + struct sockaddr ifmsg_lladdr; + struct in_addr ifmsg_prefix; + struct in_addr ifmsg_brd; + unsigned ifmsg_flags; + u32 ifmsg_mtu; + short ifmsg_metric; + unsigned char ifmsg_prefixlen; + unsigned char ifmsg_reserved; + int ifmsg_index; + char ifmsg_name[16]; +}; + +static inline int rtmsg_ioctl(unsigned int fd, u32 arg) +{ + struct { + struct nlmsghdr n; + union { + struct in_rtmsg rt; + struct in_ifmsg iff; + struct in_rtctlmsg ctl; + struct in_rtrulemsg rule; + } u; + } nn; + char *p; + int ret; + unsigned long old_fs = get_fs(); + + if (get_user (nn.n.nlmsg_len, &(((struct nlmsghdr32 *)A(arg))->nlmsg_len)) || + __get_user (nn.n.nlmsg_type, &(((struct nlmsghdr32 *)A(arg))->nlmsg_type)) || + __get_user (nn.n.nlmsg_seq, &(((struct nlmsghdr32 *)A(arg))->nlmsg_seq)) || + __get_user (nn.n.nlmsg_pid, &(((struct nlmsghdr32 *)A(arg))->nlmsg_pid)) || + __get_user (nn.n.nlmsg_data[0], &(((struct nlmsghdr32 *)A(arg))->nlmsg_data[0]))) + return -EFAULT; + p = ((char *)(&nn.n)) + sizeof(struct nlmsghdr); + arg += sizeof(struct nlmsghdr32); + switch (nn.n.nlmsg_type) { + case RTMSG_NEWRULE: + case RTMSG_DELRULE: + if (nn.n.nlmsg_len < sizeof(struct nlmsghdr32) + sizeof(struct in_rtrulemsg) + - sizeof(struct in_rtmsg) + sizeof(struct in_rtmsg32)) + return -EINVAL; + if (copy_from_user (p, (struct in_rtrulemsg *)A(arg), sizeof(struct in_rtrulemsg) - sizeof(struct in_rtmsg))) + return -EFAULT; + nn.n.nlmsg_len = sizeof(struct nlmsghdr) + sizeof(struct in_rtrulemsg); + p += sizeof (struct in_rtrulemsg) - sizeof(struct in_rtmsg); + arg += sizeof (struct in_rtrulemsg) - sizeof(struct in_rtmsg); + goto newroute; + case RTMSG_NEWROUTE: + case RTMSG_DELROUTE: + if (nn.n.nlmsg_len < sizeof(struct nlmsghdr32) + sizeof(struct in_rtmsg)) + return -EINVAL; + nn.n.nlmsg_len = sizeof(struct nlmsghdr) + sizeof(struct in_rtmsg); +newroute: + if (copy_from_user (p, (struct in_rtmsg32 *)A(arg), 2*sizeof(struct in_addr) + sizeof(unsigned)) || + __get_user (((struct in_rtmsg *)p)->rtmsg_mtu, &((struct in_rtmsg32 *)A(arg))->rtmsg_mtu) || + __get_user (((struct in_rtmsg *)p)->rtmsg_window, &((struct in_rtmsg32 *)A(arg))->rtmsg_window) || + copy_from_user (&(((struct in_rtmsg *)p)->rtmsg_rtt), &((struct in_rtmsg32 *)A(arg))->rtmsg_rtt, + 2 * sizeof(short) + 4 + sizeof(int))) + return -EFAULT; + break; + case RTMSG_NEWDEVICE: + case RTMSG_DELDEVICE: + if (nn.n.nlmsg_len < sizeof(struct nlmsghdr32) + sizeof(struct in_ifmsg)) + return -EINVAL; + nn.n.nlmsg_len = sizeof(struct nlmsghdr) + sizeof(struct in_ifmsg); + if (copy_from_user (p, (struct in_ifmsg32 *)A(arg), + sizeof(struct sockaddr) + 2*sizeof(struct in_addr) + sizeof(unsigned)) || + __get_user (((struct in_ifmsg *)p)->ifmsg_mtu, &((struct in_ifmsg32 *)A(arg))->ifmsg_mtu) || + copy_from_user (&(((struct in_ifmsg *)p)->ifmsg_metric), &((struct in_ifmsg32 *)A(arg))->ifmsg_metric, + sizeof(short) + 2 + sizeof(int) + 16)) + return -EFAULT; + break; + case RTMSG_CONTROL: + if (nn.n.nlmsg_len < sizeof(struct nlmsghdr32) + sizeof(struct in_rtctlmsg)) + return -EINVAL; + nn.n.nlmsg_len = sizeof(struct nlmsghdr) + sizeof(struct in_rtctlmsg); + if (copy_from_user (p, (struct in_rtctlmsg *)A(arg), sizeof(struct in_rtctlmsg))) + return -EFAULT; + break; + } + set_fs (KERNEL_DS); + ret = sys_ioctl (fd, SIOCRTMSG, (long)&(nn.n)); + set_fs (old_fs); + return ret; +} + +struct hd_geometry32 { + unsigned char heads; + unsigned char sectors; + unsigned short cylinders; + u32 start; +}; + +static inline int hdio_getgeo(unsigned int fd, u32 arg) +{ + unsigned long old_fs = get_fs(); + struct hd_geometry geo; + int err; + + set_fs (KERNEL_DS); + err = sys_ioctl(fd, HDIO_GETGEO, (unsigned long)&geo); + set_fs (old_fs); + if (!err) { + if (copy_to_user ((struct hd_geometry32 *)A(arg), &geo, 4) || + __put_user (geo.start, &(((struct hd_geometry32 *)A(arg))->start))) + return -EFAULT; + } + return err; +} + asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg) { struct file * filp; @@ -35,16 +382,149 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg) error = sys_ioctl (fd, cmd, (unsigned long)arg); goto out; } - error = 0; + error = -EFAULT; switch (cmd) { - default: - error = sys_ioctl (fd, cmd, (unsigned long)arg); - goto out; + case SIOCGIFCONF: + error = dev_ifconf(fd, arg); + goto out; + + case SIOCGIFFLAGS: + case SIOCSIFFLAGS: + case SIOCGIFMETRIC: + case SIOCSIFMETRIC: + case SIOCGIFMTU: + case SIOCSIFMTU: + case SIOCGIFMEM: + case SIOCSIFMEM: + case SIOCGIFHWADDR: + case SIOCSIFHWADDR: + case SIOCADDMULTI: + case SIOCDELMULTI: + case SIOGIFINDEX: + case SIOCGIFMAP: + case SIOCSIFMAP: + case SIOCGIFADDR: + case SIOCSIFADDR: + case SIOCGIFBRDADDR: + case SIOCSIFBRDADDR: + case SIOCGIFDSTADDR: + case SIOCSIFDSTADDR: + case SIOCGIFNETMASK: + case SIOCSIFNETMASK: + error = dev_ifsioc(fd, cmd, arg); + goto out; + + case SIOCADDRT: + case SIOCDELRT: + error = routing_ioctl(fd, cmd, arg); + goto out; + + case SIOCRTMSG: + error = rtmsg_ioctl(fd, arg); + goto out; + + case HDIO_GETGEO: + error = hdio_getgeo(fd, arg); + goto out; + + case BLKRAGET: + case BLKGETSIZE: + error = w_long(fd, cmd, arg); + goto out; + + /* List here exlicitly which ioctl's are known to have + * compatable types passed or none at all... + */ + + /* Bit T */ + case TCGETA: + case TCSETA: + case TCSETAW: + case TCSETAF: + case TCSBRK: + case TCXONC: + case TCFLSH: + case TCGETS: + case TCSETS: + case TCSETSW: + case TCSETSF: + case TIOCLINUX: + + /* Little t */ + case TIOCGETD: + case TIOCSETD: + case TIOCEXCL: + case TIOCNXCL: + case TIOCCONS: + case TIOCGSOFTCAR: + case TIOCSSOFTCAR: + case TIOCSWINSZ: + case TIOCGWINSZ: + case TIOCMGET: + case TIOCMBIC: + case TIOCMBIS: + case TIOCMSET: + case TIOCPKT: + case TIOCNOTTY: + case TIOCSTI: + case TIOCOUTQ: + case TIOCSPGRP: + case TIOCGPGRP: + case TIOCSCTTY: + + /* Little f */ + case FIOCLEX: + case FIONCLEX: + case FIOASYNC: + case FIONBIO: + case FIONREAD: /* This is also TIOCINQ */ + + /* 0x12 */ + case BLKRRPART: + case BLKFLSBUF: + case BLKRASET: + + /* 0x09 */ + case REGISTER_DEV: + case START_MD: + case STOP_MD: + + /* Big K */ + case PIO_FONT: + case GIO_FONT: + case KDSIGACCEPT: + case KDGETKEYCODE: + case KDSETKEYCODE: + + /* Socket level stuff */ + case FIOSETOWN: + case SIOCSPGRP: + case FIOGETOWN: + case SIOCGPGRP: + case SIOCATMARK: + case SIOCGSTAMP: + case SIOCSIFLINK: + case SIOCSIFENCAP: + case SIOCGIFENCAP: + case SIOCSIFBR: + case SIOCGIFBR: + case SIOCSARP: + case SIOCGARP: + case SIOCDARP: + case SIOCADDDLCI: + case SIOCDELDLCI: + error = sys_ioctl (fd, cmd, (unsigned long)arg); + goto out; + break; + + default: + printk("sys32_ioctl: Unknown cmd fd(%d) cmd(%08x) arg(%08x)\n", + (int)fd, (unsigned int)cmd, (unsigned int)arg); + error = -EINVAL; + goto out; + break; } out: - if (error == -EINVAL) { - printk ("sys32_ioctl on %016lx's %08x returns EINVAL\n", filp->f_op ? (long)filp->f_op->ioctl : 0UL, cmd); - } unlock_kernel(); return error; } diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 593c1efc6..cc8183618 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.12 1997/05/23 09:35:43 jj Exp $ +/* $Id: process.c,v 1.17 1997/06/02 06:33:32 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) @@ -317,6 +317,13 @@ void exit_thread(void) #else if(current->flags & PF_USEDFPU) { #endif + fprs_write(FPRS_FEF); + if(current->tss.flags & SPARC_FLAG_32BIT) + fpsave32((unsigned long *)¤t->tss.float_regs[0], + ¤t->tss.fsr); + else + fpsave((unsigned long *)¤t->tss.float_regs[0], + ¤t->tss.fsr); #ifndef __SMP__ last_task_used_math = NULL; #else @@ -338,6 +345,13 @@ void flush_thread(void) #else if(current->flags & PF_USEDFPU) { #endif + fprs_write(FPRS_FEF); + if(current->tss.flags & SPARC_FLAG_32BIT) + fpsave32((unsigned long *)¤t->tss.float_regs[0], + ¤t->tss.fsr); + else + fpsave((unsigned long *)¤t->tss.float_regs[0], + ¤t->tss.fsr); #ifndef __SMP__ last_task_used_math = NULL; #else @@ -424,6 +438,8 @@ clone_stackframe(struct sparc_stackf *dst, struct sparc_stackf *src) return sp; } +/* #define DEBUG_WINFIXUPS */ + /* Standard stuff. */ static inline void shift_window_buffer(int first_win, int last_win, struct thread_struct *tp) @@ -440,12 +456,15 @@ static inline void shift_window_buffer(int first_win, int last_win, void synchronize_user_stack(void) { struct thread_struct *tp = ¤t->tss; - unsigned long window = tp->w_saved; + unsigned long window; flush_user_windows(); - if(window) { + if((window = tp->w_saved) != 0) { int winsize = REGWIN_SZ; +#ifdef DEBUG_WINFIXUPS + printk("sus(%d", (int)window); +#endif if(tp->flags & SPARC_FLAG_32BIT) winsize = REGWIN32_SZ; @@ -459,18 +478,26 @@ void synchronize_user_stack(void) tp->w_saved--; } } while(window--); +#ifdef DEBUG_WINFIXUPS + printk(")"); +#endif } } void fault_in_user_windows(struct pt_regs *regs) { struct thread_struct *tp = ¤t->tss; - unsigned long window = tp->w_saved; + unsigned long window; int winsize = REGWIN_SZ; if(tp->flags & SPARC_FLAG_32BIT) winsize = REGWIN32_SZ; - if(window) { + flush_user_windows(); + window = tp->w_saved; +#ifdef DEBUG_WINFIXUPS + printk("fiuw(%d", (int)window); +#endif + if(window != 0) { window -= 1; do { unsigned long sp = tp->rwbuf_stkptrs[window]; @@ -481,6 +508,9 @@ void fault_in_user_windows(struct pt_regs *regs) } while(window--); } current->tss.w_saved = 0; +#ifdef DEBUG_WINFIXUPS + printk(")"); +#endif } /* Copy a Sparc thread. The fork() return value conventions @@ -504,19 +534,17 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, struct reg_window *new_stack, *old_stack; unsigned long stack_offset; -#if 0 #ifndef __SMP__ if(last_task_used_math == current) { #else if(current->flags & PF_USEDFPU) { #endif - put_psr(get_psr() | PSR_EF); - fpsave(&p->tss.float_regs[0], &p->tss.fsr); + fprs_write(FPRS_FEF); + fpsave((unsigned long *)&p->tss.float_regs[0], &p->tss.fsr); #ifdef __SMP__ current->flags &= ~PF_USEDFPU; #endif } -#endif /* Calculate offset to stack_frame & pt_regs */ stack_offset = ((PAGE_SIZE<<1) - TRACEREG_SZ); diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S index 0f1dceb33..165b17ef0 100644 --- a/arch/sparc64/kernel/rtrap.S +++ b/arch/sparc64/kernel/rtrap.S @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.18 1997/05/27 06:28:05 davem Exp $ +/* $Id: rtrap.S,v 1.21 1997/06/02 07:26:54 davem Exp $ * rtrap.S: Preparing for return from trap on Sparc V9. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -17,109 +17,114 @@ .text .align 32 - .globl rtrap -rtrap: - sethi %hi(bh_active), %l2 - or %l2, %lo(bh_active), %l2 - sethi %hi(bh_mask), %l1 - or %l1, %lo(bh_mask), %l1 - ldx [%l2 + %g4], %l3 - ldx [%l1 + %g4], %l4 - andcc %l3, %l4, %g0 - nop + .globl rtrap_clr_l6, rtrap +rtrap_clr_l6: + ba,pt %xcc, rtrap + clr %l6 +rtrap: sethi %hi(bh_active), %l2 + or %l2, %lo(bh_active), %l2 + sethi %hi(bh_mask), %l1 + or %l1, %lo(bh_mask), %l1 + ldx [%l2 + %g4], %l3 + ldx [%l1 + %g4], %l4 - be,pt %xcc, 2f + andcc %l3, %l4, %g0 + be,pt %xcc, 2f nop - call do_bottom_half + call do_bottom_half nop -2: ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %l1 - sethi %hi(0xf << 20), %l4 - andcc %l1, TSTATE_PRIV, %l3 - and %l1, %l4, %l4 +2: ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %l1 + sethi %hi(0xf << 20), %l4 + andcc %l1, TSTATE_PRIV, %l3 + + and %l1, %l4, %l4 + rdpr %pstate, %l7 + andn %l1, %l4, %l1 + be,pt %icc, to_user + andn %l7, PSTATE_IE, %l7 +3: ldx [%g6 + AOFF_task_tss + AOFF_thread_ctx], %l0 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1], %g1 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2], %g2 - rdpr %pstate, %l7 - andn %l1, %l4, %l1 - be,pt %icc, to_user - andn %l7, PSTATE_IE, %l7 -3: ldx [%g6 + AOFF_task_tss + AOFF_thread_ctx], %l6 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1], %g1 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2], %g2 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3], %g3 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3], %g3 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4], %g4 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5], %g5 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G6], %g6 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G7], %g7 + wrpr %l7, PSTATE_AG, %pstate + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %i0 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1], %i1 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4], %g4 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5], %g5 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G6], %g6 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G7], %g7 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %i0 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1], %i1 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2], %i2 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3], %i3 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2], %i2 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3], %i3 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4], %i4 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5], %i5 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I6], %i6 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7], %i7 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_Y], %o3 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC], %l2 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4], %i4 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5], %i5 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I6], %i6 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7], %i7 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_Y], %o3 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC], %l2 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %o2 - wr %o3, %g0, %y + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %o2 + wr %o3, %g0, %y + srl %l4, 20, %l4 + wrpr %l4, 0x0, %pil + wrpr %g0, 0x1, %tl + wrpr %l1, %g0, %tstate + wrpr %l2, %g0, %tpc + mov PRIMARY_CONTEXT, %l7 - srl %l4, 20, %l4 - wrpr %l7, %g0, %pstate - wrpr %l4, 0x0, %pil - wrpr %g0, 0x1, %tl - wrpr %l1, %g0, %tstate - wrpr %l2, %g0, %tpc - brnz,pn %l3, 1f - wrpr %o2, %g0, %tnpc + wrpr %o2, %g0, %tnpc + brnz,a,pn %l3, 1f + restore + sethi %uhi(KERNBASE), %l5 + sllx %l5, 32, %l5 + stxa %l0, [%l7] ASI_DMMU + flush %l5 + rdpr %wstate, %l1 - mov PRIMARY_CONTEXT, %l7 - sethi %uhi(KERNBASE), %l5 - sllx %l5, 32, %l5 - stxa %l6, [%l7] ASI_DMMU - flush %l5 - rdpr %wstate, %l1 - rdpr %otherwin, %l2 - srl %l1, 3, %l1 + rdpr %otherwin, %l2 + srl %l1, 3, %l1 + wrpr %l2, %g0, %canrestore + wrpr %l1, %g0, %wstate + wrpr %g0, %g0, %otherwin + restore + rdpr %canrestore, %g1 + wrpr %g1, 0x0, %cleanwin - wrpr %l2, %g0, %canrestore - wrpr %l1, %g0, %wstate - wrpr %g0, %g0, %otherwin -1: restore - retry +1: retry to_user: sethi %hi(need_resched), %l0 or %l0, %lo(need_resched), %l0 ld [%l0 + %g4], %l0 - wrpr %l7, PSTATE_IE, %pstate brz,pt %l0, check_signal ldx [%g6 + AOFF_task_signal], %l0 + nop + call schedule nop - ldx [%g6 + AOFF_task_signal], %l0 - nop + ba,pt %xcc, check_signal + ldx [%g6 + AOFF_task_signal], %l0 check_signal: ldx [%g6 + AOFF_task_blocked], %o0 - - or %l7, PSTATE_AG, %l7 ! Will need this for setting back wstate andncc %l0, %o0, %g0 - be,pt %xcc, check_user_wins - mov %l5, %o2 + be,a,pt %xcc, check_user_wins + ldx [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2 + + mov %l5, %o2 mov %l6, %o3 call do_signal add %sp, STACK_BIAS + REGWIN_SZ, %o1 -check_user_wins: -#if 0 - call user_rtrap_report - add %sp, STACK_BIAS + REGWIN_SZ, %o0 -#endif ldx [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2 - + clr %l6 +check_user_wins: brz,pt %o2, 3b - add %sp, STACK_BIAS + REGWIN_SZ, %o1 + nop + call fault_in_user_windows - add %o7, 3b-.-4, %o7 + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + ba,a,pt %xcc, 3b + nop nop nop nop diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index f81e30093..fe4615a6b 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.4 1997/05/27 06:28:05 davem Exp $ +/* $Id: signal.c,v 1.6 1997/05/29 12:44:48 jj Exp $ * arch/sparc64/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -193,13 +193,17 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu) { #ifdef __SMP__ if (current->flags & PF_USEDFPU) { - fpsave(¤t->tss.float_regs[0], ¤t->tss.fsr); + fprs_write(FPRS_FEF); + fpsave((unsigned long *)¤t->tss.float_regs[0], + ¤t->tss.fsr); regs->tstate &= ~(TSTATE_PEF); current->flags &= ~(PF_USEDFPU); } #else if (current == last_task_used_math) { - fpsave((unsigned long *)¤t->tss.float_regs[0], ¤t->tss.fsr); + fprs_write(FPRS_FEF); + fpsave((unsigned long *)¤t->tss.float_regs[0], + ¤t->tss.fsr); last_task_used_math = 0; regs->tstate &= ~(TSTATE_PEF); } diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 33892065f..c0454658b 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -1,4 +1,4 @@ -/* $Id: signal32.c,v 1.10 1997/05/27 06:28:07 davem Exp $ +/* $Id: signal32.c,v 1.13 1997/06/01 05:46:09 davem Exp $ * arch/sparc64/kernel/signal32.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -139,35 +139,51 @@ restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu32_t *fpu) void do_new_sigreturn32(struct pt_regs *regs) { struct new_signal_frame32 *sf; - unsigned int psr, i; + unsigned int psr; unsigned pc, npc, fpu_save, mask; sf = (struct new_signal_frame32 *) regs->u_regs [UREG_FP]; + /* 1. Make sure we are not getting garbage from the user */ - if (verify_area (VERIFY_READ, sf, sizeof (*sf))){ - goto segv; - } - if (((unsigned long) sf) & 3){ + if (verify_area (VERIFY_READ, sf, sizeof (*sf)) || + (((unsigned long) sf) & 3)) goto segv; - } + get_user(pc, &sf->info.si_regs.pc); __get_user(npc, &sf->info.si_regs.npc); - if ((pc | npc) & 3){ + + if ((pc | npc) & 3) goto segv; - } + regs->tpc = pc; regs->tnpc = npc; /* 2. Restore the state */ __get_user(regs->y, &sf->info.si_regs.y); __get_user(psr, &sf->info.si_regs.psr); - for (i = 0; i < 16; i++) - __get_user(regs->u_regs[i], &sf->info.si_regs.u_regs[i]); + + __get_user(regs->u_regs[UREG_G1], &sf->info.si_regs.u_regs[UREG_G1]); + __get_user(regs->u_regs[UREG_G2], &sf->info.si_regs.u_regs[UREG_G2]); + __get_user(regs->u_regs[UREG_G3], &sf->info.si_regs.u_regs[UREG_G3]); + __get_user(regs->u_regs[UREG_G4], &sf->info.si_regs.u_regs[UREG_G4]); + __get_user(regs->u_regs[UREG_G5], &sf->info.si_regs.u_regs[UREG_G5]); + __get_user(regs->u_regs[UREG_G6], &sf->info.si_regs.u_regs[UREG_G6]); + __get_user(regs->u_regs[UREG_G7], &sf->info.si_regs.u_regs[UREG_G7]); + __get_user(regs->u_regs[UREG_I0], &sf->info.si_regs.u_regs[UREG_I0]); + __get_user(regs->u_regs[UREG_I1], &sf->info.si_regs.u_regs[UREG_I1]); + __get_user(regs->u_regs[UREG_I2], &sf->info.si_regs.u_regs[UREG_I2]); + __get_user(regs->u_regs[UREG_I3], &sf->info.si_regs.u_regs[UREG_I3]); + __get_user(regs->u_regs[UREG_I4], &sf->info.si_regs.u_regs[UREG_I4]); + __get_user(regs->u_regs[UREG_I5], &sf->info.si_regs.u_regs[UREG_I5]); + __get_user(regs->u_regs[UREG_I6], &sf->info.si_regs.u_regs[UREG_I6]); + __get_user(regs->u_regs[UREG_I7], &sf->info.si_regs.u_regs[UREG_I7]); /* User can only change condition codes and FPU enabling in %tstate. */ regs->tstate &= ~(TSTATE_ICC | TSTATE_PEF); regs->tstate |= psr_to_tstate_icc(psr); - if (psr & PSR_EF) regs->tstate |= TSTATE_PEF; + + if (psr & PSR_EF) + regs->tstate |= TSTATE_PEF; __get_user(fpu_save, &sf->fpu_save); if (fpu_save) @@ -193,11 +209,12 @@ asmlinkage void do_sigreturn32(struct pt_regs *regs) scptr = (struct sigcontext32 *) regs->u_regs[UREG_I0]; /* Check sanity of the user arg. */ if(verify_area(VERIFY_READ, scptr, sizeof(struct sigcontext32)) || - (((unsigned long) scptr) & 3)) { + (((unsigned long) scptr) & 3)) goto segv; - } + __get_user(pc, &scptr->sigc_pc); __get_user(npc, &scptr->sigc_npc); + if((pc | npc) & 3) goto segv; /* Nice try. */ @@ -241,7 +258,6 @@ setup_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc, int old_status = current->tss.sstk_info.cur_status; unsigned psr; int i; - u32 temp; synchronize_user_stack(); sframep = (struct signal_sframe32 *) regs->u_regs[UREG_FP]; @@ -285,7 +301,10 @@ setup_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc, } else #endif + /* XXX Perhaps we need a copy_in_user()? -DaveM */ for (i = 0; i < 16; i++) { + u32 temp; + get_user (temp, (((u32 *)(regs->u_regs[UREG_FP]))+i)); put_user (temp, (((u32 *)sframep)+i)); } @@ -315,13 +334,17 @@ save_fpu_state32(struct pt_regs *regs, __siginfo_fpu32_t *fpu) { #ifdef __SMP__ if (current->flags & PF_USEDFPU) { - fpsave32(¤t->tss.float_regs[0], ¤t->tss.fsr); + fprs_write(FPRS_FEF); + fpsave32((unsigned long *)¤t->tss.float_regs[0], + ¤t->tss.fsr); regs->tstate &= ~(TSTATE_PEF); current->flags &= ~(PF_USEDFPU); } #else if (current == last_task_used_math) { - fpsave32((unsigned long *)¤t->tss.float_regs[0], ¤t->tss.fsr); + fprs_write(FPRS_FEF); + fpsave32((unsigned long *)¤t->tss.float_regs[0], + ¤t->tss.fsr); last_task_used_math = 0; regs->tstate &= ~(TSTATE_PEF); } @@ -338,7 +361,7 @@ new_setup_frame32(struct sigaction *sa, struct pt_regs *regs, { struct new_signal_frame32 *sf; int sigframe_size; - u32 psr, tmp; + u32 psr; int i; /* 1. Make sure everything is clean */ @@ -349,12 +372,12 @@ new_setup_frame32(struct sigaction *sa, struct pt_regs *regs, sf = (struct new_signal_frame32 *)(regs->u_regs[UREG_FP] - sigframe_size); - if (invalid_frame_pointer (sf, sigframe_size)){ + if (invalid_frame_pointer (sf, sigframe_size)) { lock_kernel (); do_exit(SIGILL); } - if (current->tss.w_saved != 0){ + if (current->tss.w_saved != 0) { printk ("%s[%d]: Invalid user stack frame for " "signal delivery.\n", current->comm, current->pid); lock_kernel (); @@ -378,7 +401,11 @@ new_setup_frame32(struct sigaction *sa, struct pt_regs *regs, } __put_user(oldmask, &sf->info.si_mask); + + /* XXX Perhaps we need a copy_in_user()? -DaveM */ for (i = 0; i < sizeof(struct reg_window32)/4; i++) { + u32 tmp; + __get_user(tmp, (((u32 *)regs->u_regs[UREG_FP])+i)); __put_user(tmp, (((u32 *)sf)+i)); } diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index c54036de6..59815b7a8 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -1,7 +1,8 @@ -/* $Id: sys_sparc32.c,v 1.18 1997/05/27 06:28:08 davem Exp $ +/* $Id: sys_sparc32.c,v 1.26 1997/06/04 13:05:21 jj Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) * * These routines maintain argument size conversion between 32bit and 64bit * environment. @@ -28,6 +29,7 @@ #include <linux/smb_fs.h> #include <linux/ncp_fs.h> #include <linux/quota.h> +#include <linux/file.h> #include <asm/types.h> #include <asm/poll.h> @@ -42,112 +44,7 @@ */ #define A(x) ((unsigned long)x) -extern asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on); -extern asmlinkage unsigned long sys_brk(unsigned long brk); -extern asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off); -extern asmlinkage int sys_bdflush(int func, long data); -extern asmlinkage int sys_uselib(const char * library); -extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); -extern asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev); -extern asmlinkage int sys_mkdir(const char * pathname, int mode); -extern asmlinkage int sys_rmdir(const char * pathname); -extern asmlinkage int sys_unlink(const char * pathname); -extern asmlinkage int sys_symlink(const char * oldname, const char * newname); -extern asmlinkage int sys_link(const char * oldname, const char * newname); -extern asmlinkage int sys_rename(const char * oldname, const char * newname); -extern asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr); -extern asmlinkage int sys_statfs(const char * path, struct statfs * buf); -extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf); -extern asmlinkage int sys_truncate(const char * path, unsigned long length); -extern asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length); -extern asmlinkage int sys_utime(char * filename, struct utimbuf * times); -extern asmlinkage int sys_utimes(char * filename, struct timeval * utimes); -extern asmlinkage int sys_access(const char * filename, int mode); -extern asmlinkage int sys_chdir(const char * filename); -extern asmlinkage int sys_chroot(const char * filename); -extern asmlinkage int sys_chmod(const char * filename, mode_t mode); -extern asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group); -extern asmlinkage int sys_open(const char * filename,int flags,int mode); -extern asmlinkage int sys_creat(const char * pathname, int mode); -extern asmlinkage long sys_lseek(unsigned int fd, off_t offset, unsigned int origin); -extern asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t *result, unsigned int origin); -extern asmlinkage long sys_read(unsigned int fd, char * buf, unsigned long count); -extern asmlinkage long sys_write(unsigned int fd, const char * buf, unsigned long count); -extern asmlinkage long sys_readv(unsigned long fd, const struct iovec * vector, unsigned long count); -extern asmlinkage long sys_writev(unsigned long fd, const struct iovec * vector, unsigned long count); -extern asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp); -extern asmlinkage int sys_poll(struct pollfd * ufds, unsigned int nfds, int timeout); -extern asmlinkage int sys_newstat(char * filename, struct stat * statbuf); -extern asmlinkage int sys_newlstat(char * filename, struct stat * statbuf); -extern asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf); -extern asmlinkage int sys_readlink(const char * path, char * buf, int bufsiz); -extern asmlinkage int sys_sysfs(int option, ...); -extern asmlinkage int sys_ustat(dev_t dev, struct ustat * ubuf); -extern asmlinkage int sys_umount(char * name); -extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, unsigned long new_flags, void *data); -extern asmlinkage int sys_syslog(int type, char * bug, int count); -extern asmlinkage int sys_personality(unsigned long personality); -extern asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru); -extern asmlinkage int sys_waitpid(pid_t pid,unsigned int * stat_addr, int options); -extern asmlinkage int sys_sysinfo(struct sysinfo *info); -extern asmlinkage int sys_getitimer(int which, struct itimerval *value); -extern asmlinkage int sys_setitimer(int which, struct itimerval *value, struct itimerval *ovalue); -extern asmlinkage int sys_sched_setscheduler(pid_t pid, int policy, struct sched_param *param); -extern asmlinkage int sys_sched_setparam(pid_t pid, struct sched_param *param); -extern asmlinkage int sys_sched_getparam(pid_t pid, struct sched_param *param); -extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval); -extern asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp); -extern asmlinkage int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset); -extern asmlinkage int sys_sigpending(sigset_t *set); -extern asmlinkage unsigned long sys_signal(int signum, __sighandler_t handler); -extern asmlinkage int sys_reboot(int magic1, int magic2, int cmd, void * arg); -extern asmlinkage int sys_acct(const char *name); -extern asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); -extern asmlinkage long sys_times(struct tms * tbuf); -extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist); -extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist); -extern asmlinkage int sys_newuname(struct new_utsname * name); -extern asmlinkage int sys_olduname(struct oldold_utsname * name); -extern asmlinkage int sys_sethostname(char *name, int len); -extern asmlinkage int sys_gethostname(char *name, int len); -extern asmlinkage int sys_setdomainname(char *name, int len); -extern asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim); -extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim); -extern asmlinkage int sys_getrusage(int who, struct rusage *ru); -extern asmlinkage int sys_time(int * tloc); -extern asmlinkage int sys_gettimeofday(struct timeval *tv, struct timezone *tz); -extern asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz); -extern asmlinkage int sys_adjtimex(struct timex *txc_p); -extern asmlinkage int sys_msync(unsigned long start, size_t len, int flags); -extern asmlinkage int sys_mlock(unsigned long start, size_t len); -extern asmlinkage int sys_munlock(unsigned long start, size_t len); -extern asmlinkage int sys_munmap(unsigned long addr, size_t len); -extern asmlinkage int sys_mprotect(unsigned long start, size_t len, unsigned long prot); -extern asmlinkage unsigned long sys_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags); -extern asmlinkage int sys_swapoff(const char * specialfile); -extern asmlinkage int sys_swapon(const char * specialfile, int swap_flags); -extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); -extern asmlinkage int sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen); -extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen); -extern asmlinkage int sys_getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len); -extern asmlinkage int sys_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len); -extern asmlinkage int sys_send(int fd, void * buff, size_t len, unsigned flags); -extern asmlinkage int sys_sendto(int fd, void * buff, size_t len, unsigned flags, struct sockaddr *addr, int addr_len); -extern asmlinkage int sys_recv(int fd, void * ubuf, size_t size, unsigned flags); -extern asmlinkage int sys_recvfrom(int fd, void * ubuf, size_t size, unsigned flags, struct sockaddr *addr, int *addr_len); -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, char *optval, int optlen); -extern asmlinkage int sys_getsockopt(int fd, int level, int optname, char *optval, int *optlen); -extern asmlinkage int sys_sendmsg(int fd, struct msghdr *msg, unsigned flags); -extern asmlinkage int sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags); -extern asmlinkage int sys_socketcall(int call, unsigned long *args); -extern asmlinkage int sys_nfsservctl(int cmd, void *argp, void *resp); -extern asmlinkage int sys_listen(int fd, int backlog); -extern asmlinkage int sys_socket(int family, int type, int protocol); -extern asmlinkage int sys_socketpair(int family, int type, int protocol, int usockvec[2]); -extern asmlinkage int sys_shutdown(int fd, int how); - -/* - * In order to reduce some races, while at the same time doing additional +/* In order to reduce some races, while at the same time doing additional * checking and hopefully speeding things up, we copy filenames to the * kernel data space before using them.. * @@ -168,8 +65,7 @@ static inline int do_getname32(u32 filename, char *page) return retval; } -/* - * This is a single page for faster getname. +/* This is a single page for faster getname. * If the page is available when entering getname, use it. * If the page is not available, call __get_free_page instead. * This works even though do_getname can block (think about it). @@ -209,6 +105,8 @@ int getname32(u32 filename, char **result) return retval; } +extern asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on); + asmlinkage int sys32_ioperm(u32 from, u32 num, int on) { return sys_ioperm((unsigned long)from, (unsigned long)num, on); @@ -571,22 +469,56 @@ out: return err; } -asmlinkage unsigned long sys32_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off) +extern asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long off); + +asmlinkage unsigned long sys32_mmap(u32 addr, u32 len, u32 prot, + u32 flags, u32 fd, u32 off) { - return sys_mmap((unsigned long)addr, (unsigned long)len, (unsigned long)prot, (unsigned long)flags, + return sys_mmap((unsigned long)addr, (unsigned long)len, + (unsigned long)prot, (unsigned long)flags, (unsigned long)fd, (unsigned long)off); } +extern asmlinkage int sys_bdflush(int func, long data); + asmlinkage int sys32_bdflush(int func, s32 data) { return sys_bdflush(func, (long)data); } +extern asmlinkage int sys_uselib(const char * library); + asmlinkage int sys32_uselib(u32 library) { return sys_uselib((const char *)A(library)); } +static inline int get_flock(struct flock *kfl, struct flock32 *ufl) +{ + if(get_user(kfl->l_type, &ufl->l_type) || + __get_user(kfl->l_whence, &ufl->l_whence) || + __get_user(kfl->l_start, &ufl->l_start) || + __get_user(kfl->l_len, &ufl->l_len) || + __get_user(kfl->l_pid, &ufl->l_pid)) + return -EFAULT; + return 0; +} + +static inline int put_flock(struct flock *kfl, struct flock32 *ufl) +{ + if(__put_user(kfl->l_type, &ufl->l_type) || + __put_user(kfl->l_whence, &ufl->l_whence) || + __put_user(kfl->l_start, &ufl->l_start) || + __put_user(kfl->l_len, &ufl->l_len) || + __put_user(kfl->l_pid, &ufl->l_pid)) + return -EFAULT; + return 0; +} + +extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); + asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, u32 arg) { switch (cmd) { @@ -598,20 +530,12 @@ asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, u32 arg) unsigned long old_fs; long ret; - if (get_user (f.l_type, &(((struct flock32 *)A(arg))->l_type)) || - __get_user (f.l_whence, &(((struct flock32 *)A(arg))->l_whence)) || - __get_user (f.l_start, &(((struct flock32 *)A(arg))->l_start)) || - __get_user (f.l_len, &(((struct flock32 *)A(arg))->l_len)) || - __get_user (f.l_pid, &(((struct flock32 *)A(arg))->l_pid))) + if(get_flock(&f, (struct flock32 *)A(arg))) return -EFAULT; old_fs = get_fs(); set_fs (KERNEL_DS); ret = sys_fcntl(fd, cmd, (unsigned long)&f); set_fs (old_fs); - if (__put_user (f.l_type, &(((struct flock32 *)A(arg))->l_type)) || - __put_user (f.l_whence, &(((struct flock32 *)A(arg))->l_whence)) || - __put_user (f.l_start, &(((struct flock32 *)A(arg))->l_start)) || - __put_user (f.l_len, &(((struct flock32 *)A(arg))->l_len)) || - __put_user (f.l_pid, &(((struct flock32 *)A(arg))->l_pid))) + if(put_flock(&f, (struct flock32 *)A(arg))) return -EFAULT; return ret; } @@ -620,36 +544,50 @@ asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, u32 arg) } } +extern asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev); + asmlinkage int sys32_mknod(u32 filename, int mode, __kernel_dev_t32 dev) { return sys_mknod((const char *)A(filename), mode, dev); } +extern asmlinkage int sys_mkdir(const char * pathname, int mode); + asmlinkage int sys32_mkdir(u32 pathname, int mode) { return sys_mkdir((const char *)A(pathname), mode); } +extern asmlinkage int sys_rmdir(const char * pathname); + asmlinkage int sys32_rmdir(u32 pathname) { return sys_rmdir((const char *)A(pathname)); } +extern asmlinkage int sys_unlink(const char * pathname); + asmlinkage int sys32_unlink(u32 pathname) { return sys_unlink((const char *)A(pathname)); } +extern asmlinkage int sys_symlink(const char * oldname, const char * newname); + asmlinkage int sys32_symlink(u32 oldname, u32 newname) { return sys_symlink((const char *)A(oldname), (const char *)A(newname)); } +extern asmlinkage int sys_link(const char * oldname, const char * newname); + asmlinkage int sys32_link(u32 oldname, u32 newname) { return sys_link((const char *)A(oldname), (const char *)A(newname)); } +extern asmlinkage int sys_rename(const char * oldname, const char * newname); + asmlinkage int sys32_rename(u32 oldname, u32 newname) { return sys_rename((const char *)A(oldname), (const char *)A(newname)); @@ -666,12 +604,15 @@ struct dqblk32 { __kernel_time_t32 dqb_itime; }; +extern asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr); + asmlinkage int sys32_quotactl(int cmd, u32 special, int id, u32 addr) { int cmds = cmd >> SUBCMDSHIFT; int err; struct dqblk d; unsigned long old_fs; + char *spec; switch (cmds) { case Q_GETQUOTA: @@ -679,57 +620,73 @@ asmlinkage int sys32_quotactl(int cmd, u32 special, int id, u32 addr) case Q_SETQUOTA: case Q_SETUSE: case Q_SETQLIM: - if (copy_from_user (&d, (struct dqblk32 *)A(addr), sizeof (struct dqblk32))) + if (copy_from_user (&d, (struct dqblk32 *)A(addr), + sizeof (struct dqblk32))) return -EFAULT; d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime; d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime; break; default: - return sys_quotactl(cmd, (const char *)A(special), id, (caddr_t)A(addr)); + return sys_quotactl(cmd, (const char *)A(special), + id, (caddr_t)A(addr)); } + err = getname32 (special, &spec); + if (err) return err; old_fs = get_fs (); set_fs (KERNEL_DS); - err = sys_quotactl(cmd, (const char *)A(special), id, (caddr_t)A(addr)); + err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)A(addr)); set_fs (old_fs); + putname32 (spec); if (cmds == Q_GETQUOTA) { __kernel_time_t b = d.dqb_btime, i = d.dqb_itime; ((struct dqblk32 *)&d)->dqb_itime = i; ((struct dqblk32 *)&d)->dqb_btime = b; - if (copy_to_user ((struct dqblk32 *)A(addr), &d, sizeof (struct dqblk32))) + if (copy_to_user ((struct dqblk32 *)A(addr), &d, + sizeof (struct dqblk32))) return -EFAULT; } return err; } -static int put_statfs (u32 buf, struct statfs *s) +static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf) { - if (put_user (s->f_type, &(((struct statfs32 *)A(buf))->f_type)) || - __put_user (s->f_bsize, &(((struct statfs32 *)A(buf))->f_bsize)) || - __put_user (s->f_blocks, &(((struct statfs32 *)A(buf))->f_blocks)) || - __put_user (s->f_bfree, &(((struct statfs32 *)A(buf))->f_bfree)) || - __put_user (s->f_bavail, &(((struct statfs32 *)A(buf))->f_bavail)) || - __put_user (s->f_files, &(((struct statfs32 *)A(buf))->f_files)) || - __put_user (s->f_ffree, &(((struct statfs32 *)A(buf))->f_ffree)) || - __put_user (s->f_namelen, &(((struct statfs32 *)A(buf))->f_namelen)) || - __put_user (s->f_fsid.val[0], &(((struct statfs32 *)A(buf))->f_fsid.val[0])) || - __put_user (s->f_fsid.val[1], &(((struct statfs32 *)A(buf))->f_fsid.val[1]))) + if (put_user (kbuf->f_type, &ubuf->f_type) || + __put_user (kbuf->f_bsize, &ubuf->f_bsize) || + __put_user (kbuf->f_blocks, &ubuf->f_blocks) || + __put_user (kbuf->f_bfree, &ubuf->f_bfree) || + __put_user (kbuf->f_bavail, &ubuf->f_bavail) || + __put_user (kbuf->f_files, &ubuf->f_files) || + __put_user (kbuf->f_ffree, &ubuf->f_ffree) || + __put_user (kbuf->f_namelen, &ubuf->f_namelen) || + __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) || + __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1])) return -EFAULT; return 0; } +extern asmlinkage int sys_statfs(const char * path, struct statfs * buf); + asmlinkage int sys32_statfs(u32 path, u32 buf) { int ret; struct statfs s; unsigned long old_fs = get_fs(); + char *pth; - set_fs (KERNEL_DS); - ret = sys_statfs((const char *)A(path), &s); - set_fs (old_fs); - if (put_statfs(buf, &s)) return -EFAULT; + ret = getname32 (path, &pth); + if (!ret) { + set_fs (KERNEL_DS); + ret = sys_statfs((const char *)pth, &s); + set_fs (old_fs); + putname32 (pth); + if (put_statfs((struct statfs32 *)A(buf), &s)) + return -EFAULT; + } return ret; } +extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf); + asmlinkage int sys32_fstatfs(unsigned int fd, u32 buf) { int ret; @@ -739,20 +696,27 @@ asmlinkage int sys32_fstatfs(unsigned int fd, u32 buf) set_fs (KERNEL_DS); ret = sys_fstatfs(fd, &s); set_fs (old_fs); - if (put_statfs(buf, &s)) return -EFAULT; + if (put_statfs((struct statfs32 *)A(buf), &s)) + return -EFAULT; return ret; } +extern asmlinkage int sys_truncate(const char * path, unsigned long length); + asmlinkage int sys32_truncate(u32 path, u32 length) { return sys_truncate((const char *)A(path), (unsigned long)length); } +extern asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length); + asmlinkage int sys32_ftruncate(unsigned int fd, u32 length) { return sys_ftruncate(fd, (unsigned long)length); } +extern asmlinkage int sys_utime(char * filename, struct utimbuf * times); + asmlinkage int sys32_utime(u32 filename, u32 times) { struct utimbuf32 { __kernel_time_t32 actime, modtime; }; @@ -777,63 +741,91 @@ asmlinkage int sys32_utime(u32 filename, u32 times) return ret; } +extern asmlinkage int sys_utimes(char * filename, struct timeval * utimes); + asmlinkage int sys32_utimes(u32 filename, u32 utimes) { /* struct timeval is the same :)) */ return sys_utimes((char *)A(filename), (struct timeval *)A(utimes)); } +extern asmlinkage int sys_access(const char * filename, int mode); + asmlinkage int sys32_access(u32 filename, int mode) { return sys_access((const char *)A(filename), mode); } +extern asmlinkage int sys_chdir(const char * filename); + asmlinkage int sys32_chdir(u32 filename) { return sys_chdir((const char *)A(filename)); } +extern asmlinkage int sys_chroot(const char * filename); + asmlinkage int sys32_chroot(u32 filename) { return sys_chroot((const char *)A(filename)); } +extern asmlinkage int sys_chmod(const char * filename, mode_t mode); + asmlinkage int sys32_chmod(u32 filename, __kernel_mode_t32 mode) { return sys_chmod((const char *)A(filename), mode); } +extern asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group); + asmlinkage int sys32_chown(u32 filename, __kernel_uid_t32 user, __kernel_gid_t32 group) { return sys_chown((const char *)A(filename), user, group); } +extern asmlinkage int sys_open(const char * filename,int flags,int mode); + asmlinkage int sys32_open(u32 filename, int flags, int mode) { return sys_open((const char *)A(filename), flags, mode); } +extern asmlinkage int sys_creat(const char * pathname, int mode); + asmlinkage int sys32_creat(u32 pathname, int mode) { return sys_creat((const char *)A(pathname), mode); } +extern asmlinkage long sys_lseek(unsigned int fd, off_t offset, unsigned int origin); + asmlinkage long sys32_lseek(unsigned int fd, s32 offset, unsigned int origin) { return sys_lseek(fd, (off_t)offset, origin); } -asmlinkage int sys32_llseek(unsigned int fd, u32 offset_high, u32 offset_low, u32 result, unsigned int origin) +extern asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high, + unsigned long offset_low, + loff_t *result, unsigned int origin); + +asmlinkage int sys32_llseek(unsigned int fd, u32 offset_high, + u32 offset_low, u32 result, unsigned int origin) { /* loff_t is the same :)) */ - return sys_llseek(fd, (unsigned long)offset_high, (unsigned long)offset_low, (loff_t *)A(result), origin); + return sys_llseek(fd, (unsigned long)offset_high, (unsigned long)offset_low, + (loff_t *)A(result), origin); } +extern asmlinkage long sys_read(unsigned int fd, char * buf, unsigned long count); + asmlinkage long sys32_read(unsigned int fd, u32 buf, u32 count) { return sys_read(fd, (char *)A(buf), (unsigned long)count); } +extern asmlinkage long sys_write(unsigned int fd, const char * buf, unsigned long count); + asmlinkage long sys32_write(unsigned int fd, u32 buf, u32 count) { return sys_write(fd, (const char *)A(buf), (unsigned long)count); @@ -841,86 +833,146 @@ asmlinkage long sys32_write(unsigned int fd, u32 buf, u32 count) struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; }; -asmlinkage long sys32_readv(u32 fd, u32 vector, u32 count) +typedef long (*IO_fn_t)(struct inode *, struct file *, char *, unsigned long); + +static long do_readv_writev32(int type, struct inode *inode, struct file *file, + const struct iovec32 *vector, u32 count) { - struct iovec *v; - struct iovec vf[UIO_FASTIOV]; - u32 i; - long ret; - unsigned long old_fs; - - if (!count) return 0; if (count > UIO_MAXIOV) return -EINVAL; - if (count <= UIO_FASTIOV) - v = vf; - else { - lock_kernel (); - v = kmalloc (count * sizeof (struct iovec), GFP_KERNEL); - if (!v) { - ret = -ENOMEM; - goto out; - } + unsigned long tot_len; + struct iovec iovstack[UIO_FASTIOV]; + struct iovec *iov=iovstack, *ivp; + long retval, i; + IO_fn_t fn; + + /* First get the "struct iovec" from user memory and + * verify all the pointers + */ + if (!count) + return 0; + if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + return -EFAULT; + if (count > UIO_MAXIOV) + return -EINVAL; + if (count > UIO_FASTIOV) { + iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL); + if (!iov) + return -ENOMEM; } - for (i = 0; i < count; i++) { - if (__get_user ((unsigned long)(v[i].iov_base), &((((struct iovec32 *)A(vector))+i)->iov_base)) || - __get_user (v[i].iov_len, &((((struct iovec32 *)A(vector))+i)->iov_len))) { - ret = -EFAULT; - goto out; - } + + tot_len = 0; + i = count; + ivp = iov; + while(i > 0) { + u32 len; + u32 buf; + + __get_user(len, &vector->iov_len); + __get_user(buf, &vector->iov_base); + tot_len += len; + ivp->iov_base = (void *)A(buf); + ivp->iov_len = (__kernel_size_t) len; + vector++; + ivp++; + i--; } - old_fs = get_fs(); - set_fs (KERNEL_DS); - ret = sys_readv((unsigned long)fd, v, (unsigned long)count); - set_fs (old_fs); -out: - if (count > UIO_FASTIOV) { - kfree (v); - unlock_kernel (); + + retval = locks_verify_area((type == VERIFY_READ) ? + FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE, + inode, file, file->f_pos, tot_len); + if (retval) { + if (iov != iovstack) + kfree(iov); + return retval; } - return ret; -} -asmlinkage long sys32_writev(u32 fd, u32 vector, u32 count) -{ - struct iovec *v; - struct iovec vf[UIO_FASTIOV]; - u32 i; - long ret; - unsigned long old_fs; - - if (!count) return 0; if (count > UIO_MAXIOV) return -EINVAL; - if (count <= UIO_FASTIOV) - v = vf; - else { - lock_kernel (); - v = kmalloc (count * sizeof (struct iovec), GFP_KERNEL); - if (!v) { - ret = -ENOMEM; - goto out; - } + /* Then do the actual IO. Note that sockets need to be handled + * specially as they have atomicity guarantees and can handle + * iovec's natively + */ + if (inode->i_sock) { + int err; + err = sock_readv_writev(type, inode, file, iov, count, tot_len); + if (iov != iovstack) + kfree(iov); + return err; } - for (i = 0; i < count; i++) { - if (__get_user ((unsigned long)(v[i].iov_base), &((((struct iovec32 *)A(vector))+i)->iov_base)) || - __get_user (v[i].iov_len, &((((struct iovec32 *)A(vector))+i)->iov_len))) { - ret = -EFAULT; - goto out; - } + + if (!file->f_op) { + if (iov != iovstack) + kfree(iov); + return -EINVAL; } - old_fs = get_fs(); - set_fs (KERNEL_DS); - ret = sys_writev((unsigned long)fd, v, (unsigned long)count); - set_fs (old_fs); -out: - if (count > UIO_FASTIOV) { - kfree (v); - unlock_kernel (); + /* VERIFY_WRITE actually means a read, as we write to user space */ + fn = file->f_op->read; + if (type == VERIFY_READ) + fn = (IO_fn_t) file->f_op->write; + ivp = iov; + while (count > 0) { + void * base; + int len, nr; + + base = ivp->iov_base; + len = ivp->iov_len; + ivp++; + count--; + nr = fn(inode, file, base, len); + if (nr < 0) { + if (retval) + break; + retval = nr; + break; + } + retval += nr; + if (nr != len) + break; } - return ret; + if (iov != iovstack) + kfree(iov); + return retval; +} + +asmlinkage long sys32_readv(int fd, u32 vector, u32 count) +{ + struct file *file; + struct inode *inode; + long err = -EBADF; + + lock_kernel(); + if (fd >= NR_OPEN || !(file = current->files->fd[fd]) || !(inode=file->f_inode)) + goto out; + if (!(file->f_mode & 1)) + goto out; + err = do_readv_writev32(VERIFY_WRITE, inode, file, + (struct iovec32 *)A(vector), count); +out: + unlock_kernel(); + return err; +} + +asmlinkage long sys32_writev(int fd, u32 vector, u32 count) +{ + int error = -EBADF; + struct file *file; + struct inode *inode; + + lock_kernel(); + if (fd >= NR_OPEN || !(file = current->files->fd[fd]) || !(inode=file->f_inode)) + goto out; + if (!(file->f_mode & 2)) + goto out; + down(&inode->i_sem); + error = do_readv_writev32(VERIFY_READ, inode, file, + (struct iovec32 *)A(vector), count); + up(&inode->i_sem); +out: + unlock_kernel(); + return error; } /* readdir & getdents */ #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) -#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1)) +#define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1)) struct old_linux_dirent32 { u32 d_ino; @@ -934,7 +986,8 @@ struct readdir_callback32 { int count; }; -static int fillonedir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino) +static int fillonedir(void * __buf, const char * name, int namlen, + off_t offset, ino_t ino) { struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf; struct old_linux_dirent32 * dirent; @@ -963,7 +1016,8 @@ asmlinkage int old32_readdir(unsigned int fd, u32 dirent, unsigned int count) error = -ENOTDIR; if (!file->f_op || !file->f_op->readdir) goto out; - error = verify_area(VERIFY_WRITE, (void *)A(dirent), sizeof(struct old_linux_dirent32)); + error = verify_area(VERIFY_WRITE, (void *)A(dirent), + sizeof(struct old_linux_dirent32)); if (error) goto out; buf.count = 0; @@ -1052,84 +1106,124 @@ out: /* end of readdir & getdents */ +extern asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, + fd_set *exp, struct timeval *tvp); + asmlinkage int sys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp) { struct timeval kern_tv, *ktvp; unsigned long old_fs; char *p; - u32 *q; + u32 *q, *Inp, *Outp, *Exp; int i, ret = -EINVAL, nn; - u32 *Inp, *Outp, *Exp; - if (n < 0 || n > PAGE_SIZE*2) return -EINVAL; + if (n < 0 || n > PAGE_SIZE*2) + return -EINVAL; + lock_kernel (); p = (char *)__get_free_page (GFP_KERNEL); - if (!p) goto out; + if (!p) + goto out; + q = (u32 *)p; - nn = (n + 8 * sizeof(unsigned long) - 1) / (8 * sizeof (unsigned long)); - Inp = (u32 *)A(inp); Outp = (u32 *)A(outp); Exp = (u32 *)A(exp); + Inp = (u32 *)A(inp); + Outp = (u32 *)A(outp); + Exp = (u32 *)A(exp); + ret = -EFAULT; - for (i = 0; i < ret; i++, Inp += 2, Outp += 2, Exp += 2, q += 2) { - if (__get_user (q[1], Inp) || - __get_user (q[0], Inp+1) || - __get_user (q[1+PAGE_SIZE/4], Outp) || - __get_user (q[PAGE_SIZE/4], Outp+1) || - __get_user (q[1+PAGE_SIZE/2], Exp) || - __get_user (q[PAGE_SIZE/2], Exp+1)) + + nn = (n + (8 * sizeof(unsigned long)) - 1) / (8 * sizeof (unsigned long)); + for (i = 0; i < nn; i++, Inp += 2, Outp += 2, Exp += 2, q += 2) { + if(inp && (__get_user (q[1], Inp) || __get_user (q[0], Inp+1))) + goto out; + if(outp && (__get_user (q[1+(PAGE_SIZE/4/sizeof(u32))], Outp) || + __get_user (q[(PAGE_SIZE/4/sizeof(u32))], Outp+1))) + goto out; + if(exp && (__get_user (q[1+(PAGE_SIZE/2/sizeof(u32))], Exp) || + __get_user (q[(PAGE_SIZE/2/sizeof(u32))], Exp+1))) goto out; } + ktvp = NULL; if(tvp) { if(copy_from_user(&kern_tv, (struct timeval *)A(tvp), sizeof(*ktvp))) goto out; ktvp = &kern_tv; } + old_fs = get_fs (); set_fs (KERNEL_DS); - ret = sys_select(n, (fd_set *)p, (fd_set *)(p + PAGE_SIZE/4), (fd_set *)(p + PAGE_SIZE/2), ktvp); + q = (u32 *) p; + ret = sys_select(n, + inp ? (fd_set *)&q[0] : (fd_set *)0, + outp ? (fd_set *)&q[PAGE_SIZE/4/sizeof(u32)] : (fd_set *)0, + exp ? (fd_set *)&q[PAGE_SIZE/2/sizeof(u32)] : (fd_set *)0, + ktvp); set_fs (old_fs); + + if(tvp && !(current->personality & STICKY_TIMEOUTS)) + copy_to_user((struct timeval *)A(tvp), &kern_tv, sizeof(*ktvp)); + q = (u32 *)p; - Inp = (u32 *)A(inp); Outp = (u32 *)A(outp); Exp = (u32 *)A(exp); - for (i = 0; i < ret; i++, Inp += 2, Outp += 2, Exp += 2, q += 2) { - if (__put_user (q[1], Inp) || - __put_user (q[0], Inp+1) || - __put_user (q[1+PAGE_SIZE/4], Outp) || - __put_user (q[PAGE_SIZE/4], Outp+1) || - __put_user (q[1+PAGE_SIZE/2], Exp) || - __put_user (q[PAGE_SIZE/2], Exp+1)) { + Inp = (u32 *)A(inp); + Outp = (u32 *)A(outp); + Exp = (u32 *)A(exp); + + if(ret < 0) + goto out; + + for (i = 0; + i < nn; + i++, Inp += 2, Outp += 2, Exp += 2, q += 2) { + if(inp && (__put_user (q[1], Inp) || __put_user (q[0], Inp+1))) { + ret = -EFAULT; + goto out; + } + if(outp && (__put_user (q[1+(PAGE_SIZE/4/sizeof(u32))], Outp) || + __put_user (q[(PAGE_SIZE/4/sizeof(u32))], Outp+1))) { + ret = -EFAULT; + goto out; + } + if(exp && (__put_user (q[1+(PAGE_SIZE/2/sizeof(u32))], Exp) || + __put_user (q[(PAGE_SIZE/2/sizeof(u32))], Exp+1))) { ret = -EFAULT; goto out; } } out: free_page ((unsigned long)p); + unlock_kernel(); return ret; } +extern asmlinkage int sys_poll(struct pollfd * ufds, unsigned int nfds, int timeout); + asmlinkage int sys32_poll(u32 ufds, unsigned int nfds, int timeout) { return sys_poll((struct pollfd *)A(ufds), nfds, timeout); } -static inline int putstat(u32 statbuf, struct stat *s) -{ - if (put_user (s->st_dev, &(((struct stat32 *)A(statbuf))->st_dev)) || - __put_user (s->st_ino, &(((struct stat32 *)A(statbuf))->st_ino)) || - __put_user (s->st_mode, &(((struct stat32 *)A(statbuf))->st_mode)) || - __put_user (s->st_nlink, &(((struct stat32 *)A(statbuf))->st_nlink)) || - __put_user (s->st_uid, &(((struct stat32 *)A(statbuf))->st_uid)) || - __put_user (s->st_gid, &(((struct stat32 *)A(statbuf))->st_gid)) || - __put_user (s->st_rdev, &(((struct stat32 *)A(statbuf))->st_rdev)) || - __put_user (s->st_size, &(((struct stat32 *)A(statbuf))->st_size)) || - __put_user (s->st_atime, &(((struct stat32 *)A(statbuf))->st_atime)) || - __put_user (s->st_mtime, &(((struct stat32 *)A(statbuf))->st_mtime)) || - __put_user (s->st_ctime, &(((struct stat32 *)A(statbuf))->st_ctime)) || - __put_user (s->st_blksize, &(((struct stat32 *)A(statbuf))->st_blksize)) || - __put_user (s->st_blocks, &(((struct stat32 *)A(statbuf))->st_blocks))) +static inline int putstat(struct stat32 *ubuf, struct stat *kbuf) +{ + if (put_user (kbuf->st_dev, &ubuf->st_dev) || + __put_user (kbuf->st_ino, &ubuf->st_ino) || + __put_user (kbuf->st_mode, &ubuf->st_mode) || + __put_user (kbuf->st_nlink, &ubuf->st_nlink) || + __put_user (kbuf->st_uid, &ubuf->st_uid) || + __put_user (kbuf->st_gid, &ubuf->st_gid) || + __put_user (kbuf->st_rdev, &ubuf->st_rdev) || + __put_user (kbuf->st_size, &ubuf->st_size) || + __put_user (kbuf->st_atime, &ubuf->st_atime) || + __put_user (kbuf->st_mtime, &ubuf->st_mtime) || + __put_user (kbuf->st_ctime, &ubuf->st_ctime) || + __put_user (kbuf->st_blksize, &ubuf->st_blksize) || + __put_user (kbuf->st_blocks, &ubuf->st_blocks)) return -EFAULT; return 0; } +extern asmlinkage int sys_newstat(char * filename, struct stat * statbuf); + asmlinkage int sys32_newstat(u32 filename, u32 statbuf) { int ret; @@ -1143,11 +1237,14 @@ asmlinkage int sys32_newstat(u32 filename, u32 statbuf) ret = sys_newstat(filenam, &s); set_fs (old_fs); putname32 (filenam); - if (putstat (statbuf, &s)) return -EFAULT; + if (putstat ((struct stat32 *)A(statbuf), &s)) + return -EFAULT; } return ret; } +extern asmlinkage int sys_newlstat(char * filename, struct stat * statbuf); + asmlinkage int sys32_newlstat(u32 filename, u32 statbuf) { int ret; @@ -1161,11 +1258,14 @@ asmlinkage int sys32_newlstat(u32 filename, u32 statbuf) ret = sys_newlstat(filenam, &s); set_fs (old_fs); putname32 (filenam); - if (putstat (statbuf, &s)) return -EFAULT; + if (putstat ((struct stat32 *)A(statbuf), &s)) + return -EFAULT; } return ret; } +extern asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf); + asmlinkage int sys32_newfstat(unsigned int fd, u32 statbuf) { int ret; @@ -1175,15 +1275,20 @@ asmlinkage int sys32_newfstat(unsigned int fd, u32 statbuf) set_fs (KERNEL_DS); ret = sys_newfstat(fd, &s); set_fs (old_fs); - if (putstat (statbuf, &s)) return -EFAULT; + if (putstat ((struct stat32 *)A(statbuf), &s)) + return -EFAULT; return ret; } +extern asmlinkage int sys_readlink(const char * path, char * buf, int bufsiz); + asmlinkage int sys32_readlink(u32 path, u32 buf, int bufsiz) { return sys_readlink((const char *)A(path), (char *)A(buf), bufsiz); } +extern asmlinkage int sys_sysfs(int option, ...); + asmlinkage int sys32_sysfs(int option, ...) { va_list args; @@ -1207,28 +1312,39 @@ asmlinkage int sys32_sysfs(int option, ...) return ret; } +extern asmlinkage int sys_ustat(dev_t dev, struct ustat * ubuf); + asmlinkage int sys32_ustat(dev_t dev, u32 ubuf) { /* ustat is the same :)) */ return sys_ustat(dev, (struct ustat *)A(ubuf)); } +extern asmlinkage int sys_umount(char * name); + asmlinkage int sys32_umount(u32 name) { return sys_umount((char *)A(name)); } +extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, + unsigned long new_flags, void *data); + asmlinkage int sys32_mount(u32 dev_name, u32 dir_name, u32 type, u32 new_flags, u32 data) { return sys_mount((char *)A(dev_name), (char *)A(dir_name), (char *)A(type), (unsigned long)new_flags, (void *)A(data)); } +extern asmlinkage int sys_syslog(int type, char * bug, int count); + asmlinkage int sys32_syslog(int type, u32 bug, int count) { return sys_syslog(type, (char *)A(bug), count); } +extern asmlinkage int sys_personality(unsigned long personality); + asmlinkage int sys32_personality(u32 personality) { return sys_personality((unsigned long)personality); @@ -1277,6 +1393,9 @@ static int put_rusage (u32 ru, struct rusage *r) return 0; } +extern asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr, + int options, struct rusage * ru); + asmlinkage int sys32_wait4(__kernel_pid_t32 pid, u32 stat_addr, int options, u32 ru) { if (!ru) @@ -1284,16 +1403,21 @@ asmlinkage int sys32_wait4(__kernel_pid_t32 pid, u32 stat_addr, int options, u32 else { struct rusage r; int ret; + unsigned int status; unsigned long old_fs = get_fs(); set_fs (KERNEL_DS); - ret = sys_wait4(pid, (unsigned int *)A(stat_addr), options, &r); + ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r); set_fs (old_fs); if (put_rusage (ru, &r)) return -EFAULT; + if (stat_addr && put_user (status, (unsigned int *)A(stat_addr))) + return -EFAULT; return ret; } } +extern asmlinkage int sys_waitpid(pid_t pid,unsigned int * stat_addr, int options); + asmlinkage int sys32_waitpid(__kernel_pid_t32 pid, u32 stat_addr, int options) { return sys_waitpid(pid, (unsigned int *)A(stat_addr), options); @@ -1312,6 +1436,8 @@ struct sysinfo32 { char _f[22]; }; +extern asmlinkage int sys_sysinfo(struct sysinfo *info); + asmlinkage int sys32_sysinfo(u32 info) { struct sysinfo s; @@ -1336,28 +1462,41 @@ asmlinkage int sys32_sysinfo(u32 info) return ret; } +extern asmlinkage int sys_getitimer(int which, struct itimerval *value); + asmlinkage int sys32_getitimer(int which, u32 value) { /* itimerval is the same :)) */ return sys_getitimer(which, (struct itimerval *)A(value)); } +extern asmlinkage int sys_setitimer(int which, struct itimerval *value, + struct itimerval *ovalue); + asmlinkage int sys32_setitimer(int which, u32 value, u32 ovalue) { - return sys_setitimer(which, (struct itimerval *)A(value), (struct itimerval *)A(ovalue)); + return sys_setitimer(which, (struct itimerval *)A(value), + (struct itimerval *)A(ovalue)); } +extern asmlinkage int sys_sched_setscheduler(pid_t pid, int policy, + struct sched_param *param); + asmlinkage int sys32_sched_setscheduler(__kernel_pid_t32 pid, int policy, u32 param) { /* sched_param is the same :)) */ return sys_sched_setscheduler(pid, policy, (struct sched_param *)A(param)); } +extern asmlinkage int sys_sched_setparam(pid_t pid, struct sched_param *param); + asmlinkage int sys32_sched_setparam(__kernel_pid_t32 pid, u32 param) { return sys_sched_setparam(pid, (struct sched_param *)A(param)); } +extern asmlinkage int sys_sched_getparam(pid_t pid, struct sched_param *param); + asmlinkage int sys32_sched_getparam(__kernel_pid_t32 pid, u32 param) { return sys_sched_getparam(pid, (struct sched_param *)A(param)); @@ -1368,6 +1507,8 @@ struct timespec32 { s32 tv_nsec; }; +extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval); + asmlinkage int sys32_sched_rr_get_interval(__kernel_pid_t32 pid, u32 interval) { struct timespec t; @@ -1383,6 +1524,8 @@ asmlinkage int sys32_sched_rr_get_interval(__kernel_pid_t32 pid, u32 interval) return ret; } +extern asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp); + asmlinkage int sys32_nanosleep(u32 rqtp, u32 rmtp) { struct timespec t; @@ -1403,6 +1546,8 @@ asmlinkage int sys32_nanosleep(u32 rqtp, u32 rmtp) return ret; } +extern asmlinkage int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset); + asmlinkage int sys32_sigprocmask(int how, u32 set, u32 oset) { sigset_t s; @@ -1417,6 +1562,8 @@ asmlinkage int sys32_sigprocmask(int how, u32 set, u32 oset) return ret; } +extern asmlinkage int sys_sigpending(sigset_t *set); + asmlinkage int sys32_sigpending(u32 set) { sigset_t s; @@ -1430,21 +1577,29 @@ asmlinkage int sys32_sigpending(u32 set) return ret; } +extern asmlinkage unsigned long sys_signal(int signum, __sighandler_t handler); + asmlinkage unsigned long sys32_signal(int signum, u32 handler) { return sys_signal(signum, (__sighandler_t)A(handler)); } +extern asmlinkage int sys_reboot(int magic1, int magic2, int cmd, void * arg); + asmlinkage int sys32_reboot(int magic1, int magic2, int cmd, u32 arg) { return sys_reboot(magic1, magic2, cmd, (void *)A(arg)); } +extern asmlinkage int sys_acct(const char *name); + asmlinkage int sys32_acct(u32 name) { return sys_acct((const char *)A(name)); } +extern asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); + asmlinkage int sys32_getresuid(u32 ruid, u32 euid, u32 suid) { uid_t a, b, c; @@ -1468,6 +1623,8 @@ struct tms32 { __kernel_clock_t32 tms_cstime; }; +extern asmlinkage long sys_times(struct tms * tbuf); + asmlinkage long sys32_times(u32 tbuf) { struct tms t; @@ -1486,6 +1643,8 @@ asmlinkage long sys32_times(u32 tbuf) return ret; } +extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist); + asmlinkage int sys32_getgroups(int gidsetsize, u32 grouplist) { gid_t gl[NGROUPS]; @@ -1502,6 +1661,8 @@ asmlinkage int sys32_getgroups(int gidsetsize, u32 grouplist) return ret; } +extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist); + asmlinkage int sys32_setgroups(int gidsetsize, u32 grouplist) { gid_t gl[NGROUPS]; @@ -1519,27 +1680,37 @@ asmlinkage int sys32_setgroups(int gidsetsize, u32 grouplist) return ret; } +extern asmlinkage int sys_newuname(struct new_utsname * name); + asmlinkage int sys32_newuname(u32 name) { /* utsname is the same :)) */ return sys_newuname((struct new_utsname *)A(name)); } +extern asmlinkage int sys_olduname(struct oldold_utsname * name); + asmlinkage int sys32_olduname(u32 name) { return sys_olduname((struct oldold_utsname *)A(name)); } +extern asmlinkage int sys_sethostname(char *name, int len); + asmlinkage int sys32_sethostname(u32 name, int len) { return sys_sethostname((char *)A(name), len); } +extern asmlinkage int sys_gethostname(char *name, int len); + asmlinkage int sys32_gethostname(u32 name, int len) { return sys_gethostname((char *)A(name), len); } +extern asmlinkage int sys_setdomainname(char *name, int len); + asmlinkage int sys32_setdomainname(u32 name, int len) { return sys_setdomainname((char *)A(name), len); @@ -1550,6 +1721,8 @@ struct rlimit32 { s32 rlim_max; }; +extern asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim); + asmlinkage int sys32_getrlimit(unsigned int resource, u32 rlim) { struct rlimit r; @@ -1566,6 +1739,8 @@ asmlinkage int sys32_getrlimit(unsigned int resource, u32 rlim) return ret; } +extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim); + asmlinkage int sys32_setrlimit(unsigned int resource, u32 rlim) { struct rlimit r; @@ -1582,6 +1757,8 @@ asmlinkage int sys32_setrlimit(unsigned int resource, u32 rlim) return ret; } +extern asmlinkage int sys_getrusage(int who, struct rusage *ru); + asmlinkage int sys32_getrusage(int who, u32 ru) { struct rusage r; @@ -1595,17 +1772,23 @@ asmlinkage int sys32_getrusage(int who, u32 ru) return ret; } +extern asmlinkage int sys_time(int * tloc); + asmlinkage int sys32_time(u32 tloc) { return sys_time((int *)A(tloc)); } +extern asmlinkage int sys_gettimeofday(struct timeval *tv, struct timezone *tz); + asmlinkage int sys32_gettimeofday(u32 tv, u32 tz) { /* both timeval and timezone are ok :)) */ return sys_gettimeofday((struct timeval *)A(tv), (struct timezone *)A(tz)); } +extern asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz); + asmlinkage int sys32_settimeofday(u32 tv, u32 tz) { return sys_settimeofday((struct timeval *)A(tv), (struct timezone *)A(tz)); @@ -1636,6 +1819,8 @@ struct timex32 { int :32; int :32; int :32; int :32; }; +extern asmlinkage int sys_adjtimex(struct timex *txc_p); + asmlinkage int sys32_adjtimex(u32 txc_p) { struct timex t; @@ -1680,98 +1865,154 @@ asmlinkage int sys32_adjtimex(u32 txc_p) return ret; } +extern asmlinkage int sys_msync(unsigned long start, size_t len, int flags); + asmlinkage int sys32_msync(u32 start, __kernel_size_t32 len, int flags) { return sys_msync((unsigned long)start, (size_t)len, flags); } +extern asmlinkage int sys_mlock(unsigned long start, size_t len); + asmlinkage int sys32_mlock(u32 start, __kernel_size_t32 len) { return sys_mlock((unsigned long)start, (size_t)len); } +extern asmlinkage int sys_munlock(unsigned long start, size_t len); + asmlinkage int sys32_munlock(u32 start, __kernel_size_t32 len) { return sys_munlock((unsigned long)start, (size_t)len); } +extern asmlinkage unsigned long sys_brk(unsigned long brk); + asmlinkage unsigned long sparc32_brk(u32 brk) { return sys_brk((unsigned long)brk); } +extern asmlinkage int sys_munmap(unsigned long addr, size_t len); + asmlinkage int sys32_munmap(u32 addr, __kernel_size_t32 len) { return sys_munmap((unsigned long)addr, (size_t)len); } +extern asmlinkage int sys_mprotect(unsigned long start, size_t len, unsigned long prot); + asmlinkage int sys32_mprotect(u32 start, __kernel_size_t32 len, u32 prot) { return sys_mprotect((unsigned long)start, (size_t)len, (unsigned long)prot); } +extern asmlinkage unsigned long sys_mremap(unsigned long addr, unsigned long old_len, + unsigned long new_len, unsigned long flags); + asmlinkage unsigned long sys32_mremap(u32 addr, u32 old_len, u32 new_len, u32 flags) { - return sys_mremap((unsigned long)addr, (unsigned long)old_len, (unsigned long)new_len, (unsigned long)flags); + return sys_mremap((unsigned long)addr, (unsigned long)old_len, + (unsigned long)new_len, (unsigned long)flags); } +extern asmlinkage int sys_swapoff(const char * specialfile); + asmlinkage int sys32_swapoff(u32 specialfile) { return sys_swapoff((const char *)A(specialfile)); } +extern asmlinkage int sys_swapon(const char * specialfile, int swap_flags); + asmlinkage int sys32_swapon(u32 specialfile, int swap_flags) { return sys_swapon((const char *)A(specialfile), swap_flags); } -asmlinkage int sys32_bind(int fd, u32 umyaddr, int addrlen) +extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); + +asmlinkage inline int sys32_bind(int fd, u32 umyaddr, int addrlen) { /* sockaddr is the same :)) */ return sys_bind(fd, (struct sockaddr *)A(umyaddr), addrlen); } -asmlinkage int sys32_accept(int fd, u32 upeer_sockaddr, u32 upeer_addrlen) +extern asmlinkage int sys_accept(int fd, struct sockaddr *upeer_sockaddr, + int *upeer_addrlen); + +asmlinkage inline int sys32_accept(int fd, u32 upeer_sockaddr, u32 upeer_addrlen) { - return sys_accept(fd, (struct sockaddr *)A(upeer_sockaddr), (int *)A(upeer_addrlen)); + return sys_accept(fd, (struct sockaddr *)A(upeer_sockaddr), + (int *)A(upeer_addrlen)); } -asmlinkage int sys32_connect(int fd, u32 uservaddr, int addrlen) +extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen); + +asmlinkage inline int sys32_connect(int fd, u32 uservaddr, int addrlen) { return sys_connect(fd, (struct sockaddr *)A(uservaddr), addrlen); } +extern asmlinkage int sys_getsockname(int fd, struct sockaddr *usockaddr, + int *usockaddr_len); + asmlinkage int sys32_getsockname(int fd, u32 usockaddr, u32 usockaddr_len) { - return sys_getsockname(fd, (struct sockaddr *)A(usockaddr), (int *)A(usockaddr_len)); + return sys_getsockname(fd, (struct sockaddr *)A(usockaddr), + (int *)A(usockaddr_len)); } +extern asmlinkage int sys_getpeername(int fd, struct sockaddr *usockaddr, + int *usockaddr_len); + asmlinkage int sys32_getpeername(int fd, u32 usockaddr, u32 usockaddr_len) { - return sys_getpeername(fd, (struct sockaddr *)A(usockaddr), (int *)A(usockaddr_len)); + return sys_getpeername(fd, (struct sockaddr *)A(usockaddr), + (int *)A(usockaddr_len)); } -asmlinkage int sys32_send(int fd, u32 buff, __kernel_size_t32 len, unsigned flags) +extern asmlinkage int sys_send(int fd, void * buff, size_t len, unsigned flags); + +asmlinkage inline int sys32_send(int fd, u32 buff, + __kernel_size_t32 len, unsigned flags) { return sys_send(fd, (void *)A(buff), (size_t)len, flags); } -asmlinkage int sys32_sendto(int fd, u32 buff, __kernel_size_t32 len, unsigned flags, u32 addr, int addr_len) +extern asmlinkage int sys_sendto(int fd, void * buff, size_t len, unsigned flags, + struct sockaddr *addr, int addr_len); + +asmlinkage inline int sys32_sendto(int fd, u32 buff, __kernel_size_t32 len, + unsigned flags, u32 addr, int addr_len) { - return sys_sendto(fd, (void *)A(buff), (size_t)len, flags, (struct sockaddr *)A(addr), addr_len); + return sys_sendto(fd, (void *)A(buff), (size_t)len, flags, + (struct sockaddr *)A(addr), addr_len); } -asmlinkage int sys32_recv(int fd, u32 ubuf, __kernel_size_t32 size, unsigned flags) +extern asmlinkage int sys_recv(int fd, void * ubuf, size_t size, unsigned flags); + +asmlinkage inline int sys32_recv(int fd, u32 ubuf, + __kernel_size_t32 size, unsigned flags) { return sys_recv(fd, (void *)A(ubuf), (size_t)size, flags); } -asmlinkage int sys32_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size, unsigned flags, u32 addr, u32 addr_len) +extern asmlinkage int sys_recvfrom(int fd, void * ubuf, size_t size, unsigned flags, + struct sockaddr *addr, int *addr_len); + +asmlinkage inline int sys32_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size, + unsigned flags, u32 addr, u32 addr_len) { - return sys_recvfrom(fd, (void *)A(ubuf), (size_t)size, flags, (struct sockaddr *)A(addr), (int *)A(addr_len)); + return sys_recvfrom(fd, (void *)A(ubuf), (size_t)size, flags, + (struct sockaddr *)A(addr), (int *)A(addr_len)); } -asmlinkage int sys32_setsockopt(int fd, int level, int optname, u32 optval, int optlen) +extern asmlinkage int sys_setsockopt(int fd, int level, int optname, + char *optval, int optlen); + +asmlinkage inline int sys32_setsockopt(int fd, int level, int optname, + u32 optval, int optlen) { /* XXX handle ip_fw32->ip_fw conversion for IP firewalling and accounting. Do it using some macro in ip_sockglue.c @@ -1779,11 +2020,54 @@ asmlinkage int sys32_setsockopt(int fd, int level, int optname, u32 optval, int return sys_setsockopt(fd, level, optname, (char *)A(optval), optlen); } -asmlinkage int sys32_getsockopt(int fd, int level, int optname, u32 optval, u32 optlen) +extern asmlinkage int sys_getsockopt(int fd, int level, int optname, + char *optval, int *optlen); + +asmlinkage inline int sys32_getsockopt(int fd, int level, int optname, + u32 optval, u32 optlen) { return sys_getsockopt(fd, level, optname, (char *)A(optval), (int *)A(optlen)); } +/* XXX This really belongs in some header file... -DaveM */ +#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - + 16 for IP, 16 for IPX, + 24 for IPv6, + about 80 for AX.25 */ + +/* XXX These as well... */ +extern __inline__ struct socket *socki_lookup(struct inode *inode) +{ + return &inode->u.socket_i; +} + +extern __inline__ struct socket *sockfd_lookup(int fd, int *err) +{ + struct file *file; + struct inode *inode; + + if (!(file = fget(fd))) + { + *err = -EBADF; + return NULL; + } + + inode = file->f_inode; + if (!inode || !inode->i_sock || !socki_lookup(inode)) + { + *err = -ENOTSOCK; + fput(file,inode); + return NULL; + } + + return socki_lookup(inode); +} + +extern __inline__ void sockfd_put(struct socket *sock) +{ + fput(sock->file,sock->inode); +} + struct msghdr32 { u32 msg_name; int msg_namelen; @@ -1801,207 +2085,270 @@ struct cmsghdr32 { unsigned char cmsg_data[0]; }; -asmlinkage int sys32_sendmsg(int fd, u32 msg, unsigned flags) +static inline int iov_from_user32_to_kern(struct iovec *kiov, + struct iovec32 *uiov32, + int niov) { - struct msghdr m; - int count; - struct iovec *v; - struct iovec vf[UIO_FASTIOV]; - u32 i, vector; - long ret; - unsigned long old_fs; - - if (get_user ((long)m.msg_name, &(((struct msghdr32 *)A(msg))->msg_name)) || - __get_user (m.msg_namelen, &(((struct msghdr32 *)A(msg))->msg_namelen)) || - __get_user (vector, &(((struct msghdr32 *)A(msg))->msg_iov)) || - __get_user (m.msg_iovlen, &(((struct msghdr32 *)A(msg))->msg_iovlen)) || - __get_user ((long)m.msg_control, &(((struct msghdr32 *)A(msg))->msg_control)) || - __get_user (m.msg_controllen, &(((struct msghdr32 *)A(msg))->msg_controllen)) || - __get_user (m.msg_flags, &(((struct msghdr32 *)A(msg))->msg_flags))) - return -EFAULT; - - count = m.msg_iovlen; - if (!count) return 0; if (count > UIO_MAXIOV) return -EINVAL; - if (count <= UIO_FASTIOV) - v = vf; - else { - lock_kernel (); - v = kmalloc (count * sizeof (struct iovec), GFP_KERNEL); - if (!v) { - ret = -ENOMEM; - goto out; + int tot_len = 0; + + while(niov > 0) { + u32 len, buf; + + if(get_user(len, &uiov32->iov_len) || + get_user(buf, &uiov32->iov_base)) { + tot_len = -EFAULT; + break; } + tot_len += len; + kiov->iov_base = (void *)A(buf); + kiov->iov_len = (__kernel_size_t) len; + uiov32++; + kiov++; + niov--; } + return tot_len; +} - for (i = 0; i < count; i++) { - if (__get_user ((unsigned long)(v[i].iov_base), &((((struct iovec32 *)A(vector))+i)->iov_base)) || - __get_user (v[i].iov_len, &((((struct iovec32 *)A(vector))+i)->iov_len))) { - ret = -EFAULT; - goto out; +static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, + struct msghdr32 *umsg) +{ + u32 tmp1, tmp2, tmp3; + + if(get_user(tmp1, &umsg->msg_name) || + get_user(tmp2, &umsg->msg_iov) || + get_user(tmp3, &umsg->msg_control)) + return -EFAULT; + + kmsg->msg_name = (void *)A(tmp1); + kmsg->msg_iov = (struct iovec *)A(tmp2); + kmsg->msg_control = (void *)A(tmp3); + + if(get_user(kmsg->msg_namelen, &umsg->msg_namelen) || + get_user(kmsg->msg_controllen, &umsg->msg_controllen) || + get_user(kmsg->msg_flags, &umsg->msg_flags)) + return -EFAULT; + + return 0; +} + +/* I've named the args so it is easy to tell whose space the pointers are in. */ +static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, + char *kern_address, int mode) +{ + int tot_len; + + if(kern_msg->msg_namelen) { + if(mode==VERIFY_READ) { + int err = move_addr_to_kernel(kern_msg->msg_name, + kern_msg->msg_namelen, + kern_address); + if(err < 0) + return err; } + kern_msg->msg_name = kern_address; + } else + kern_msg->msg_name = NULL; + + if(kern_msg->msg_iovlen > UIO_FASTIOV) { + kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), + GFP_KERNEL); + if(!kern_iov) + return -ENOMEM; } - - m.msg_iov = v; - if (m.msg_controllen) { - /* XXX Handle msg_control stuff... Or should that go into ip_sockglue.c etc.? */ - } - old_fs = get_fs(); - set_fs (KERNEL_DS); - ret = sys_sendmsg(fd, &m, flags); - set_fs (old_fs); -out: - if (count > UIO_FASTIOV) { - kfree (v); - unlock_kernel (); - } - return ret; + tot_len = iov_from_user32_to_kern(kern_iov, + (struct iovec32 *)kern_msg->msg_iov, + kern_msg->msg_iovlen); + if(tot_len >= 0) + kern_msg->msg_iov = kern_iov; + else if(kern_msg->msg_iovlen > UIO_FASTIOV) + kfree(kern_iov); + + return tot_len; } -asmlinkage int sys32_recvmsg(int fd, u32 msg, unsigned int flags) +asmlinkage int sys32_sendmsg(int fd, u32 user_msg, unsigned user_flags) { - struct msghdr m; - int count; - struct iovec *v; - struct iovec vf[UIO_FASTIOV]; - u32 i, vector; - long ret; - unsigned long old_fs; - - if (get_user ((long)m.msg_name, &(((struct msghdr32 *)A(msg))->msg_name)) || - __get_user (m.msg_namelen, &(((struct msghdr32 *)A(msg))->msg_namelen)) || - __get_user (vector, &(((struct msghdr32 *)A(msg))->msg_iov)) || - __get_user (m.msg_iovlen, &(((struct msghdr32 *)A(msg))->msg_iovlen)) || - __get_user ((long)m.msg_control, &(((struct msghdr32 *)A(msg))->msg_control)) || - __get_user (m.msg_controllen, &(((struct msghdr32 *)A(msg))->msg_controllen)) || - __get_user (m.msg_flags, &(((struct msghdr32 *)A(msg))->msg_flags))) + struct socket *sock; + char address[MAX_SOCK_ADDR]; + struct iovec iov[UIO_FASTIOV]; + unsigned char ctl[sizeof(struct cmsghdr) + 20]; + struct msghdr kern_msg; + int err; + int total_len; + unsigned char *ctl_buf = ctl; + + if(msghdr_from_user32_to_kern(&kern_msg, (struct msghdr32 *)A(user_msg))) return -EFAULT; - - count = m.msg_iovlen; - if (!count) return 0; if (count > UIO_MAXIOV) return -EINVAL; - if (count <= UIO_FASTIOV) - v = vf; - else { - lock_kernel (); - v = kmalloc (count * sizeof (struct iovec), GFP_KERNEL); - if (!v) { - ret = -ENOMEM; - goto out; + if(kern_msg.msg_iovlen > UIO_MAXIOV) + return -EINVAL; + total_len = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); + if(total_len < 0) + return total_len; + if(kern_msg.msg_controllen) { + struct cmsghdr32 *ucmsg = (struct cmsghdr32 *)kern_msg.msg_control; + unsigned long *kcmsg; + __kernel_size_t32 cmlen; + + if(kern_msg.msg_controllen > sizeof(ctl) && + kern_msg.msg_controllen <= 256) { + ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL); + if(!ctl_buf) { + if(kern_msg.msg_iov != iov) + kfree(kern_msg.msg_iov); + return -ENOBUFS; + } } - } - - for (i = 0; i < count; i++) { - if (__get_user ((unsigned long)(v[i].iov_base), &((((struct iovec32 *)A(vector))+i)->iov_base)) || - __get_user (v[i].iov_len, &((((struct iovec32 *)A(vector))+i)->iov_len))) { - ret = -EFAULT; - goto out; + __get_user(cmlen, &ucmsg->cmsg_len); + kcmsg = (unsigned long *) ctl_buf; + *kcmsg++ = (unsigned long)cmlen; + if(copy_from_user(kcmsg, &ucmsg->cmsg_level, + kern_msg.msg_controllen - sizeof(__kernel_size_t32))) { + if(ctl_buf != ctl) + kfree_s(ctl_buf, kern_msg.msg_controllen); + if(kern_msg.msg_iov != iov) + kfree(kern_msg.msg_iov); + return -EFAULT; } + kern_msg.msg_control = ctl_buf; } - - m.msg_iov = v; + kern_msg.msg_flags = user_flags; - if (m.msg_controllen) { - /* XXX Handle msg_control stuff... Or should that go into ip_sockglue.c etc.? */ + lock_kernel(); + if(current->files->fd[fd]->f_flags & O_NONBLOCK) + kern_msg.msg_flags |= MSG_DONTWAIT; + if((sock = sockfd_lookup(fd, &err)) != NULL) { + err = sock_sendmsg(sock, &kern_msg, total_len); + sockfd_put(sock); } - old_fs = get_fs(); - set_fs (KERNEL_DS); - ret = sys_recvmsg(fd, &m, flags); - set_fs (old_fs); - if (ret >= 0) { - /* XXX Handle msg_control stuff... */ - if (put_user (m.msg_flags, &(((struct msghdr32 *)A(msg))->msg_flags)) || - __put_user (m.msg_controllen, &(((struct msghdr32 *)A(msg))->msg_controllen))) - return -EFAULT; + unlock_kernel(); + + if(ctl_buf != ctl) + kfree_s(ctl_buf, kern_msg.msg_controllen); + if(kern_msg.msg_iov != iov) + kfree(kern_msg.msg_iov); + return err; +} + +asmlinkage int sys32_recvmsg(int fd, u32 user_msg, unsigned int user_flags) +{ + struct iovec iovstack[UIO_FASTIOV]; + struct msghdr kern_msg; + char addr[MAX_SOCK_ADDR]; + struct socket *sock; + struct iovec *iov = iovstack; + struct sockaddr *uaddr; + int *uaddr_len; + unsigned long cmsg_ptr; + int err, total_len, len = 0; + + if(msghdr_from_user32_to_kern(&kern_msg, (struct msghdr32 *)A(user_msg))) + return -EFAULT; + if(kern_msg.msg_iovlen > UIO_MAXIOV) + return -EINVAL; + + uaddr = kern_msg.msg_name; + uaddr_len = &((struct msghdr32 *)A(user_msg))->msg_namelen; + err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); + if(err < 0) + return err; + total_len = err; + + cmsg_ptr = (unsigned long) kern_msg.msg_control; + kern_msg.msg_flags = 0; + + lock_kernel(); + if(current->files->fd[fd]->f_flags & O_NONBLOCK) + user_flags |= MSG_DONTWAIT; + if((sock = sockfd_lookup(fd, &err)) != NULL) { + err = sock_recvmsg(sock, &kern_msg, total_len, user_flags); + if(err >= 0) + len = err; + sockfd_put(sock); } -out: - if (count > UIO_FASTIOV) { - kfree (v); - unlock_kernel (); + unlock_kernel(); + + if(kern_msg.msg_iov != iov) + kfree(kern_msg.msg_iov); + if(uaddr != NULL && err >= 0) + err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); + if(err >= 0) { + err = __put_user(kern_msg.msg_flags, + &((struct msghdr32 *)A(user_msg))->msg_flags); + if(!err) { + /* XXX Convert cmsg back into userspace 32-bit format... */ + err = __put_user((unsigned long)kern_msg.msg_control - cmsg_ptr, + &((struct msghdr32 *)A(user_msg))->msg_controllen); + } } - return ret; + if(err < 0) + return err; + return len; } +/* Argument list sizes for sys_socketcall */ +#define AL(x) ((x) * sizeof(u32)) +static unsigned char nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), + AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), + AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; +#undef AL + +extern asmlinkage int sys_socket(int family, int type, int protocol); +extern asmlinkage int sys_socketpair(int family, int type, int protocol, + int usockvec[2]); +extern asmlinkage int sys_shutdown(int fd, int how); +extern asmlinkage int sys_listen(int fd, int backlog); + asmlinkage int sys32_socketcall(int call, u32 args) { - static unsigned char nargs[18]={0,3,3,3,2,3,3,3, - 4,4,4,6,6,2,5,5,3,3}; u32 a[6]; u32 a0,a1; - int err = -EINVAL; - int i; - lock_kernel(); - if(call<1||call>SYS_RECVMSG) - goto out; - err = -EFAULT; - - for (i = 0; i < nargs[call]; i++, args += sizeof (u32)) - if (get_user(a[i], (u32 *)A(args))) - goto out; - + if (call<SYS_SOCKET||call>SYS_RECVMSG) + return -EINVAL; + if (copy_from_user(a, (u32 *)A(args), nargs[call])) + return -EFAULT; a0=a[0]; a1=a[1]; switch(call) { case SYS_SOCKET: - err = sys_socket(a0, a1, a[2]); - break; + return sys_socket(a0, a1, a[2]); case SYS_BIND: - err = sys32_bind(a0, a1, a[2]); - break; + return sys32_bind(a0, a1, a[2]); case SYS_CONNECT: - err = sys32_connect(a0, a1, a[2]); - break; + return sys32_connect(a0, a1, a[2]); case SYS_LISTEN: - err = sys_listen(a0, a1); - break; + return sys_listen(a0, a1); case SYS_ACCEPT: - err = sys32_accept(a0, a1, a[2]); - break; + return sys32_accept(a0, a1, a[2]); case SYS_GETSOCKNAME: - err = sys32_getsockname(a0, a1, a[2]); - break; + return sys32_getsockname(a0, a1, a[2]); case SYS_GETPEERNAME: - err = sys32_getpeername(a0, a1, a[2]); - break; + return sys32_getpeername(a0, a1, a[2]); case SYS_SOCKETPAIR: - err = sys_socketpair(a0, a1, a[2], (int *)A(a[3])); - break; + return sys_socketpair(a0, a1, a[2], (int *)A(a[3])); case SYS_SEND: - err = sys32_send(a0, a1, a[2], a[3]); - break; + return sys32_send(a0, a1, a[2], a[3]); case SYS_SENDTO: - err = sys32_sendto(a0, a1, a[2], a[3], a[4], a[5]); - break; + return sys32_sendto(a0, a1, a[2], a[3], a[4], a[5]); case SYS_RECV: - err = sys32_recv(a0, a1, a[2], a[3]); - break; + return sys32_recv(a0, a1, a[2], a[3]); case SYS_RECVFROM: - err = sys32_recvfrom(a0, a1, a[2], a[3], a[4], a[5]); - break; + return sys32_recvfrom(a0, a1, a[2], a[3], a[4], a[5]); case SYS_SHUTDOWN: - err = sys_shutdown(a0,a1); - break; + return sys_shutdown(a0,a1); case SYS_SETSOCKOPT: - err = sys32_setsockopt(a0, a1, a[2], a[3], a[4]); - break; + return sys32_setsockopt(a0, a1, a[2], a[3], a[4]); case SYS_GETSOCKOPT: - err = sys32_getsockopt(a0, a1, a[2], a[3], a[4]); - break; + return sys32_getsockopt(a0, a1, a[2], a[3], a[4]); case SYS_SENDMSG: - err = sys32_sendmsg(a0, a1, a[2]); - break; + return sys32_sendmsg(a0, a1, a[2]); case SYS_RECVMSG: - err = sys32_recvmsg(a0, a1, a[2]); - break; - default: - err = -EINVAL; - break; + return sys32_recvmsg(a0, a1, a[2]); } -out: - unlock_kernel(); - return err; + return -EINVAL; } extern void check_pending(int signum); @@ -2060,6 +2407,8 @@ out: return err; } +extern asmlinkage int sys_nfsservctl(int cmd, void *argp, void *resp); + asmlinkage int sys32_nfsservctl(int cmd, u32 argp, u32 resp) { /* XXX handle argp and resp args */ @@ -2204,6 +2553,12 @@ asmlinkage int sparc32_execve(struct pt_regs *regs) return error; } +/* Modules will be supported with 64bit modutils only */ +asmlinkage int sys32_no_modules(void) +{ + return -ENOSYS; +} + struct ncp_mount_data32 { int version; unsigned int ncp_fd; diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index 02707186a..a74d0ffbd 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.11 1997/05/27 19:30:20 jj Exp $ +/* $Id: systbls.S,v 1.13 1997/06/04 13:05:29 jj Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -53,20 +53,20 @@ sys_call_table32: .xword sys32_quotactl, sys_nis_syscall, sys32_mount, sys32_ustat, sys_nis_syscall /*170*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents .xword sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall -/*180*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys_nis_syscall +/*180*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_no_modules .xword sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_newuname -/*190*/ .xword sys_nis_syscall, sys32_personality, sys_prof, sys_break, sys_lock +/*190*/ .xword sys32_no_modules, sys32_personality, sys_prof, sys_break, sys_lock .xword sys_mpx, sys_ulimit, sys_getppid, sparc32_sigaction, sys_sgetmask /*200*/ .xword sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys32_uselib, old32_readdir .xword sys_nis_syscall, sys32_socketcall, sys32_syslog, sys32_olduname, sys_nis_syscall /*210*/ .xword sys_idle, sys_nis_syscall, sys32_waitpid, sys32_swapoff, sys32_sysinfo .xword sys32_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex -/*220*/ .xword sys32_sigprocmask, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getpgid +/*220*/ .xword sys32_sigprocmask, sys32_no_modules, sys32_no_modules, sys32_no_modules, sys_getpgid .xword sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid /*230*/ .xword sys32_llseek, sys32_time, sys_nis_syscall, sys_stime, sys_nis_syscall .xword sys_nis_syscall, sys32_llseek, sys32_mlock, sys32_munlock, sys_mlockall /*240*/ .xword sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys_nis_syscall, sys_nis_syscall - .xword sys_nis_syscall, sys_sched_get_priority_max, sys_sched_get_priority_min, sys32_sched_rr_get_interval, sys_nanosleep + .xword sys_nis_syscall, sys_sched_get_priority_max, sys_sched_get_priority_min, sys32_sched_rr_get_interval, sys32_nanosleep /*250*/ .xword sys32_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl .xword sys_aplib, sys_nis_syscall diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 6f96408ad..824a3ddb4 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -1,7 +1,7 @@ -/* $Id: traps.c,v 1.13 1997/05/27 19:30:08 jj Exp $ +/* $Id: traps.c,v 1.19 1997/06/05 06:22:49 davem Exp $ * arch/sparc/kernel/traps.c * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ @@ -23,6 +23,7 @@ #include <asm/pgtable.h> #include <asm/unistd.h> #include <asm/uaccess.h> +#include <asm/fpumacro.h> /* #define SYSCALL_TRACING */ /* #define VERBOSE_SYSCALL_TRACING */ @@ -122,7 +123,8 @@ void syscall_trace_entry(unsigned long g1, struct pt_regs *regs) int i; #endif - printk("SYS[%s:%d]: <%d> ", current->comm, current->pid, (int)g1); + printk("SYS[%s:%d]: PC(%016lx) <%3d> ", + current->comm, current->pid, regs->tpc, (int)g1); #ifdef VERBOSE_SYSCALL_TRACING sdp = NULL; for(i = 0; i < NUM_SDESC_ENTRIES; i++) @@ -151,7 +153,7 @@ void syscall_trace_entry(unsigned long g1, struct pt_regs *regs) unsigned long syscall_trace_exit(unsigned long retval, struct pt_regs *regs) { - printk("ret[%08x]\n", (unsigned int) retval); + printk("ret[%016lx]\n", retval); return retval; } #endif /* SYSCALL_TRACING */ @@ -254,25 +256,143 @@ void do_iae(struct pt_regs *regs) barrier(); } +static unsigned long init_fsr = 0x0UL; +static unsigned int init_fregs[64] __attribute__ ((aligned (64))) = + { ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, + ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, + ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, + ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, + ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, + ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, + ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, + ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U }; + void do_fpdis(struct pt_regs *regs) { - printk("FPDIS: at %016lx\n", regs->tpc); - while(1) - barrier(); + lock_kernel(); + + regs->tstate |= TSTATE_PEF; + fprs_write(FPRS_FEF); + + /* This is allowed now because the V9 ABI varargs passes floating + * point args in floating point registers, so vsprintf() and sprintf() + * cause problems. Luckily we never actually pass floating point values + * to those routines in the kernel and the code generated just does + * stores of them to the stack. Therefore, for the moment this fix + * is sufficient. -DaveM + */ + if(regs->tstate & TSTATE_PRIV) + goto out; + +#ifndef __SMP__ + if(last_task_used_math == current) + goto out; + if(last_task_used_math) { + struct task_struct *fptask = last_task_used_math; + + if(fptask->tss.flags & SPARC_FLAG_32BIT) + fpsave32((unsigned long *)&fptask->tss.float_regs[0], + &fptask->tss.fsr); + else + fpsave((unsigned long *)&fptask->tss.float_regs[0], + &fptask->tss.fsr); + } + last_task_used_math = current; + if(current->used_math) { + if(current->tss.flags & SPARC_FLAG_32BIT) + fpload32(¤t->tss.float_regs[0], + ¤t->tss.fsr); + else + fpload(¤t->tss.float_regs[0], + ¤t->tss.fsr); + } else { + /* Set inital sane state. */ + fpload(&init_fregs[0], &init_fsr); + current->used_math = 1; + } +#else + if(!current->used_math) { + fpload(&init_fregs[0], &init_fsr); + current->used_math = 1; + } else { + if(current->tss.flags & SPARC_FLAG_32BIT) + fpload32(¤t->tss.float_regs[0], + ¤t->tss.fsr); + else + fpload(¤t->tss.float_regs[0], + ¤t->tss.fsr); + } + current->flags |= PF_USEDFPU; +#endif +#ifndef __SMP__ +out: +#endif + unlock_kernel(); +} + +static unsigned long fake_regs[32] __attribute__ ((aligned (8))); +static unsigned long fake_fsr; + +void do_fpe_common(struct pt_regs *regs) +{ + static int calls = 0; +#ifndef __SMP__ + struct task_struct *fpt = last_task_used_math; +#else + struct task_struct *fpt = current; +#endif + + lock_kernel(); + fprs_write(FPRS_FEF); + +#ifndef __SMP__ + if(!fpt) { +#else + if(!(fpt->flags & PF_USEDFPU)) { +#endif + fpsave(&fake_regs[0], &fake_fsr); + regs->tstate &= ~(TSTATE_PEF); + goto out; + } + if(fpt->tss.flags & SPARC_FLAG_32BIT) + fpsave32((unsigned long *)&fpt->tss.float_regs[0], &fpt->tss.fsr); + else + fpsave((unsigned long *)&fpt->tss.float_regs[0], &fpt->tss.fsr); + fpt->tss.sig_address = regs->tpc; + fpt->tss.sig_desc = SUBSIG_FPERROR; +#ifdef __SMP__ + fpt->flags &= ~PF_USEDFPU; +#endif + if(regs->tstate & TSTATE_PRIV) { + printk("WARNING: FPU exception from kernel mode. at pc=%016lx\n", + regs->tpc); + regs->tpc = regs->tnpc; + regs->tnpc += 4; + calls++; + if(calls > 2) + die_if_kernel("Too many Penguin-FPU traps from kernel mode", + regs); + goto out; + } + send_sig(SIGFPE, fpt, 1); +#ifndef __SMP__ + last_task_used_math = NULL; +#endif + regs->tstate &= ~TSTATE_PEF; + if(calls > 0) + calls = 0; +out: + unlock_kernel(); } void do_fpieee(struct pt_regs *regs) { - printk("FPIEEE: at %016lx\n", regs->tpc); - while(1) - barrier(); + do_fpe_common(regs); } void do_fpother(struct pt_regs *regs) { - printk("FPOTHER: at %016lx\n", regs->tpc); - while(1) - barrier(); + do_fpe_common(regs); } void do_tof(struct pt_regs *regs) @@ -352,23 +472,29 @@ void do_illegal_instruction(struct pt_regs *regs) printk("Ill instr. at pc=%016lx ", pc); get_user(insn, ((unsigned int *)pc)); printk("insn=[%08x]\n", insn); + show_regs(regs); } #endif current->tss.sig_address = pc; current->tss.sig_desc = SUBSIG_ILLINST; send_sig(SIGILL, current, 1); unlock_kernel(); - - while(1) - barrier(); } -void do_mna(struct pt_regs *regs) +void mem_address_unaligned(struct pt_regs *regs) { printk("AIEEE: do_mna at %016lx\n", regs->tpc); show_regs(regs); - while(1) - barrier(); + if(regs->tstate & TSTATE_PRIV) { + printk("MNA from kernel, spinning\n"); + sti(); + while(1) + barrier(); + } else { + current->tss.sig_address = regs->tpc; + current->tss.sig_desc = SUBSIG_PRIVINST; + send_sig(SIGBUS, current, 1); + } } void do_privop(struct pt_regs *regs) diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S index 326382c3f..8db708f07 100644 --- a/arch/sparc64/kernel/ttable.S +++ b/arch/sparc64/kernel/ttable.S @@ -1,4 +1,4 @@ -/* $Id: ttable.S,v 1.12 1997/05/17 08:22:30 davem Exp $ +/* $Id: ttable.S,v 1.13 1997/06/02 06:33:34 davem Exp $ * ttable.S: Sparc V9 Trap Table(s) with SpitFire extensions. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -30,7 +30,7 @@ tl0_dax: ACCESS_EXCEPTION_TRAP(data_access_exception) tl0_resv031: BTRAP(0x31) tl0_dae: TRAP(do_dae) tl0_resv033: BTRAP(0x33) -tl0_mna: TRAP(do_mna) +tl0_mna: TRAP_NOSAVE(do_mna) tl0_lddfmna: TRAP(do_lddfmna) tl0_stdfmna: TRAP(do_stdfmna) tl0_privact: TRAP(do_privact) @@ -163,7 +163,7 @@ tl1_dax: ACCESS_EXCEPTION_TRAPTL1(data_access_exception) tl1_resv031: BTRAPTL1(0x31) tl1_dae: TRAPTL1(do_dae_tl1) tl1_resv033: BTRAPTL1(0x33) -tl1_mna: TRAPTL1(do_mna_tl1) +tl1_mna: TRAP_NOSAVE(do_mna) tl1_lddfmna: TRAPTL1(do_lddfmna_tl1) tl1_stdfmna: TRAPTL1(do_stdfmna_tl1) tl1_privact: BTRAPTL1(0x37) diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S index a8293c453..2ac19a440 100644 --- a/arch/sparc64/kernel/winfixup.S +++ b/arch/sparc64/kernel/winfixup.S @@ -1,4 +1,4 @@ -/* $Id: winfixup.S,v 1.3 1997/05/18 22:52:26 davem Exp $ +/* $Id: winfixup.S,v 1.8 1997/06/02 06:33:35 davem Exp $ * * winfixup.S: Handle cases where user stack pointer is found to be bogus. * @@ -10,6 +10,7 @@ #include <asm/page.h> #include <asm/ptrace.h> #include <asm/processor.h> +#include <asm/spitfire.h> #include <asm/asm_offsets.h> .text @@ -28,74 +29,223 @@ */ .globl winfix_trampoline, fill_fixup, spill_fixup fill_fixup: - ba,pt %xcc, etrap - rd %pc, %g7 - mov %l5, %o4 - mov %l4, %o5 - srlx %l5, PAGE_SHIFT, %o3 - clr %o1 - sllx %o3, PAGE_SHIFT, %o3 - and %l4, 0x4, %o2 - - call do_sparc64_fault - add %sp, STACK_BIAS + REGWIN_SZ, %o0 - ba,a,pt %xcc, rtrap + rdpr %tstate, %g1 + andcc %g1, TSTATE_PRIV, %g0 + be,pt %xcc, window_scheisse_from_user_common + and %g1, TSTATE_CWP, %g1 + + /* This is the extremely complex case, but it does happen from + * time to time if things are just right. Essentially the restore + * done in rtrap right before going back to user mode, with tl=1 + * and that levels trap stack registers all setup, took a fill trap, + * the user stack was not mapped in the tlb, and tlb miss occurred, + * the pte found was not valid, and a simple ref bit watch update + * could not satisfy the miss, so we got here. + * + * We must carefully unwind the state so we get back to tl=0, preserve + * all the register values we were going to give to the user. Luckily + * most things are where they need to be, we also have the address + * which triggered the fault handy as well. + * + * First, get into the window where the original restore was executed. + */ + + rdpr %wstate, %g2 ! Grab user mode wstate. + wrpr %g1, %cwp ! Get into the right window. + sll %g2, 3, %g2 ! NORMAL-->OTHER + wrpr %g0, 0x0, %canrestore ! Standard etrap stuff. + + wrpr %g2, 0x0, %wstate ! This must be consistant. + wrpr %g0, 0x0, %otherwin ! We know this. + sethi %uhi(KERNBASE), %g2 ! Set this up + sllx %g2, 32, %g2 ! for the iflush + mov PRIMARY_CONTEXT, %g1 ! Change contexts... + stxa %g0, [%g1] ASI_DMMU ! Back into the nucleus. + flush %g2 ! Flush instruction buffers + rdpr %pstate, %l1 ! Prepare to change globals. + mov %g4, %o5 ! Setup args for + mov %g5, %o4 ! final call to do_sparc64_fault. + + wrpr %g0, 0x0, %tl ! Out of trap levels. + wrpr %l1, (PSTATE_IE | PSTATE_AG), %pstate + sethi %uhi(KERNBASE), %g4 ! Restore med-any global reg. + rd %pic, %g6 ! Get current as well. + b,pt %xcc, window_scheisse_merge ! And merge. + sllx %g4, 32, %g4 ! Finish med-any reg setup. + + /* Be very careful about usage of the alternate globals here. + * You cannot touch %g4/%g5 as that has the fault information + * should this be from usermode. Also be careful for the case + * where we get here from the save instruction in etrap.S when + * coming from either user or kernel (does not matter which, it + * is the same problem in both cases). Essentially this means + * do not touch %g7 or %g2 so we handle the two cases fine. + */ +spill_fixup: + rd %pic, %g1 + ldx [%g1 + AOFF_task_tss + AOFF_thread_flags], %g6 + andcc %g6, SPARC_FLAG_32BIT, %g0 + ldx [%g1 + AOFF_task_tss + AOFF_thread_w_saved], %g6 + sll %g6, 3, %g3 + add %g1, %g3, %g3 + stx %sp, [%g3 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs] + sll %g6, 7, %g3 + + bne,pt %xcc, 1f + add %g1, %g3, %g3 + stx %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00] + stx %l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08] + stx %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10] + stx %l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18] + stx %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20] + stx %l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28] + + stx %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30] + stx %l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38] + stx %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x40] + stx %i1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x48] + stx %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x50] + stx %i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x58] + stx %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x60] + stx %i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x68] + + stx %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x70] + stx %i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x78] + b,pt %xcc, 2f + add %g6, 1, %g6 +1: std %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00] + std %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08] + std %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10] + std %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18] + + std %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20] + std %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28] + std %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30] + std %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38] + add %g6, 1, %g6 +2: stx %g6, [%g1 + AOFF_task_tss + AOFF_thread_w_saved] + rdpr %tstate, %g1 + nop + + andcc %g1, TSTATE_PRIV, %g0 + saved + and %g1, TSTATE_CWP, %g1 + be,a,pn %xcc, window_scheisse_from_user_common + or %g4, 0x4, %g4 ! we know it was a write + retry +window_scheisse_from_user_common: nop + wrpr %g1, %cwp + + ba,pt %xcc, etrap + rd %pc, %g7 + mov %l5, %o4 + mov %l4, %o5 +window_scheisse_merge: + srlx %o4, PAGE_SHIFT, %o3 + clr %o1 + sllx %o3, PAGE_SHIFT, %o3 + and %o5, 0x4, %o2 + + call do_sparc64_fault + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + ba,pt %xcc, rtrap + clr %l6 winfix_trampoline: - andn %g5, 0x7f, %g5 - add %g5, 0x7c, %g5 - wrpr %g5, %tnpc + andn %g3, 0x7f, %g3 + add %g3, 0x7c, %g3 + wrpr %g3, %tnpc done -spill_fixup: - rd %pic, %g1 - ldx [%g1 + AOFF_task_tss + AOFF_thread_w_saved], %g2 - sll %g2, 3, %g5 - ldx [%g1 + AOFF_task_tss + AOFF_thread_flags], %g7 - add %g1, %g5, %g5 - andcc %g7, SPARC_FLAG_32BIT, %g0 - stx %sp, [%g5 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs] - sll %g2, 5, %g5 - - bne,pt %xcc, 1f - add %g1, %g5, %g5 - stx %l0, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x00] - stx %l1, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x08] - stx %l2, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x10] - stx %l3, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x18] - stx %l4, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x20] - stx %l5, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x28] - - stx %l6, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x30] - stx %l7, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x38] - stx %i0, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x40] - stx %i1, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x48] - stx %i2, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x50] - stx %i3, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x58] - stx %i4, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x60] - stx %i5, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x68] - - stx %i6, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x70] - stx %i7, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x78] - b,a,pt %xcc, 2f - add %g2, 1, %g2 -1: - std %l0, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x00] - std %l2, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x08] - std %l4, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x10] - std %l6, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x18] - - std %i0, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x20] - std %i2, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x28] - std %i4, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x30] - std %i6, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x38] - add %g2, 1, %g2 -2: - stx %g2, [%g1 + AOFF_task_tss + AOFF_thread_w_saved] - rdpr %tstate, %g1 + .globl winfix_mna, fill_fixup_mna, spill_fixup_mna +winfix_mna: + andn %g3, 0x7f, %g3 + add %g3, 0x78, %g3 + wrpr %g3, %tnpc + done +fill_fixup_mna: + rdpr %tstate, %g1 + andcc %g1, TSTATE_PRIV, %g0 + be,pt %xcc, window_mna_from_user_common + and %g1, TSTATE_CWP, %g1 + rdpr %wstate, %g2 ! Grab user mode wstate. + wrpr %g1, %cwp ! Get into the right window. + sll %g2, 3, %g2 ! NORMAL-->OTHER + wrpr %g0, 0x0, %canrestore ! Standard etrap stuff. + wrpr %g2, 0x0, %wstate ! This must be consistant. + wrpr %g0, 0x0, %otherwin ! We know this. + sethi %uhi(KERNBASE), %g2 ! Set this up + sllx %g2, 32, %g2 ! for the iflush + mov PRIMARY_CONTEXT, %g1 ! Change contexts... + stxa %g0, [%g1] ASI_DMMU ! Back into the nucleus. + flush %g2 ! Flush instruction buffers + rdpr %pstate, %l1 ! Prepare to change globals. + mov %g4, %o5 ! Setup args for + mov %g5, %o4 ! final call to do_sparc64_fault. + wrpr %g0, 0x0, %tl ! Out of trap levels. + wrpr %l1, (PSTATE_IE | PSTATE_AG), %pstate + sethi %uhi(KERNBASE), %g4 ! Restore med-any global reg. + rd %pic, %g6 ! Get current as well. + b,pt %xcc, window_mna_merge ! And merge. + sllx %g4, 32, %g4 ! Finish med-any reg setup. +spill_fixup_mna: + rd %pic, %g1 + ldx [%g1 + AOFF_task_tss + AOFF_thread_flags], %g6 + andcc %g6, SPARC_FLAG_32BIT, %g0 + ldx [%g1 + AOFF_task_tss + AOFF_thread_w_saved], %g6 + sll %g6, 3, %g3 + add %g1, %g3, %g3 + stx %sp, [%g3 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs] + sll %g6, 7, %g3 + + bne,pt %xcc, 1f + add %g1, %g3, %g3 + stx %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00] + stx %l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08] + stx %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10] + stx %l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18] + stx %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20] + stx %l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28] + + stx %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30] + stx %l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38] + stx %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x40] + stx %i1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x48] + stx %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x50] + stx %i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x58] + stx %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x60] + stx %i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x68] + + stx %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x70] + stx %i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x78] + b,pt %xcc, 2f + add %g6, 1, %g6 +1: std %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00] + std %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08] + std %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10] + std %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18] + + std %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20] + std %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28] + std %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30] + std %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38] + add %g6, 1, %g6 +2: stx %g6, [%g1 + AOFF_task_tss + AOFF_thread_w_saved] + rdpr %tstate, %g1 nop - andcc %g1, TSTATE_PRIV, %g0 - be,pn %xcc, fill_fixup - saved + andcc %g1, TSTATE_PRIV, %g0 + saved + be,pn %xcc, window_mna_from_user_common + and %g1, TSTATE_CWP, %g1 retry +window_mna_from_user_common: + wrpr %g1, %cwp + ba,pt %xcc, etrap + rd %pc, %g7 +window_mna_merge: + call mem_address_unaligned + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + ba,pt %xcc, rtrap + clr %l6 + diff --git a/arch/sparc64/lib/checksum.S b/arch/sparc64/lib/checksum.S index b63f0d6e8..10eebb8df 100644 --- a/arch/sparc64/lib/checksum.S +++ b/arch/sparc64/lib/checksum.S @@ -71,8 +71,9 @@ csum_partial_end_cruft: or %o5, %o4, %o4 ! coalese with hword (if any) 6: addcc %o4, %o2, %o2 ! add to sum 1: sllx %g4, 32, %g4 ! give gfp back + addc %g0, %o2, %o0 ! add final carry into retval retl ! get outta here - addc %g0, %o2, %o0 ! add final carry into retval + srl %o0, 0, %o0 /* Also do alignment out of band to get better cache patterns. */ csum_partial_fix_alignment: @@ -82,7 +83,9 @@ csum_partial_fix_alignment: */ .globl csum_partial csum_partial: /* %o0=buf, %o1=len, %o2=sum */ + srl %o1, 0, %o1 ! doof scheiss andcc %o0, 0x7, %g0 ! alignment problems? + srl %o2, 0, %o2 be,pt %icc, csum_partial_fix_aligned ! yep, handle it andn %o1, 0x7f, %o3 ! num loop iterations cmp %o1, 6 @@ -154,31 +157,31 @@ __csum_partial_copy_start: 99: ba,pt %xcc, 30f; \ a, b, %o3; \ .section __ex_table,z##alloc; \ - .align 4; \ - .word 98b, 99b; \ + .align 8; \ + .xword 98b, 99b; \ .text; \ .align 4 #define EX2(x,y,z) \ 98: x,y; \ .section __ex_table,z##alloc; \ - .align 4; \ - .word 98b, 30f; \ + .align 8; \ + .xword 98b, 30f; \ .text; \ .align 4 #define EX3(x,y,z) \ 98: x,y; \ .section __ex_table,z##alloc; \ - .align 4; \ - .word 98b, 96f; \ + .align 8; \ + .xword 98b, 96f; \ .text; \ .align 4 #define EXT(start,end,handler,z) \ .section __ex_table,z##alloc; \ - .align 4; \ - .word start, 0, end, handler; \ + .align 8; \ + .xword start, 0, end, handler; \ .text; \ .align 4 @@ -189,12 +192,12 @@ __csum_partial_copy_start: * please check the fixup code below as well. */ #define CSUMCOPY_BIGCHUNK_ALIGNED(src, dst, sum, off, t0, t1, t2, t3, t4, t5, t6, t7) \ - ldd [src + off + 0x00], t0; \ - ldd [src + off + 0x08], t2; \ + ldda [src + off + 0x00] %asi, t0; \ + ldda [src + off + 0x08] %asi, t2; \ addccc t0, sum, sum; \ - ldd [src + off + 0x10], t4; \ + ldda [src + off + 0x10] %asi, t4; \ addccc t1, sum, sum; \ - ldd [src + off + 0x18], t6; \ + ldda [src + off + 0x18] %asi, t6; \ addccc t2, sum, sum; \ std t0, [dst + off + 0x00]; \ addccc t3, sum, sum; \ @@ -211,10 +214,10 @@ __csum_partial_copy_start: * Viking MXCC into streaming mode. Ho hum... */ #define CSUMCOPY_BIGCHUNK(src, dst, sum, off, t0, t1, t2, t3, t4, t5, t6, t7) \ - ldd [src + off + 0x00], t0; \ - ldd [src + off + 0x08], t2; \ - ldd [src + off + 0x10], t4; \ - ldd [src + off + 0x18], t6; \ + ldda [src + off + 0x00] %asi, t0; \ + ldda [src + off + 0x08] %asi, t2; \ + ldda [src + off + 0x10] %asi, t4; \ + ldda [src + off + 0x18] %asi, t6; \ st t0, [dst + off + 0x00]; \ addccc t0, sum, sum; \ st t1, [dst + off + 0x04]; \ @@ -234,8 +237,8 @@ __csum_partial_copy_start: /* Yuck, 6 superscalar cycles... */ #define CSUMCOPY_LASTCHUNK(src, dst, sum, off, t0, t1, t2, t3) \ - ldd [src - off - 0x08], t0; \ - ldd [src - off - 0x00], t2; \ + ldda [src - off - 0x08] %asi, t0; \ + ldda [src - off - 0x00] %asi, t2; \ addccc t0, sum, sum; \ st t0, [dst - off - 0x08]; \ addccc t1, sum, sum; \ @@ -250,7 +253,7 @@ cc_end_cruft: andcc %o3, 8, %g0 ! begin checks for that code be,pn %icc, 1f and %o3, 4, %g5 - EX(ldd [%o0 + 0x00], %g2, and %o3, 0xf,#) + EX(ldda [%o0 + 0x00] %asi, %g2, and %o3, 0xf,#) add %o1, 8, %o1 addcc %g2, %g7, %g7 add %o0, 8, %o0 @@ -260,7 +263,7 @@ cc_end_cruft: EX2(st %g3, [%o1 - 0x04],#) 1: brz,pt %g5, 1f andcc %o3, 3, %o3 - EX(ld [%o0 + 0x00], %g2, add %o3, 4,#) + EX(lda [%o0 + 0x00] %asi, %g2, add %o3, 4,#) add %o1, 4, %o1 addcc %g2, %g7, %g7 EX2(st %g2, [%o1 - 0x04],#) @@ -272,20 +275,21 @@ cc_end_cruft: subcc %o3, 2, %o3 ba,pt %xcc, 4f clr %o4 -2: EX(lduh [%o0 + 0x00], %o4, add %o3, 2,#) +2: EX(lduha [%o0 + 0x00] %asi, %o4, add %o3, 2,#) add %o0, 2, %o0 EX2(sth %o4, [%o1 + 0x00],#) be,pn %icc, 6f add %o1, 2, %o1 sll %o4, 16, %o4 -4: EX(ldub [%o0 + 0x00], %o5, add %g0, 1,#) +4: EX(lduba [%o0 + 0x00] %asi, %o5, add %g0, 1,#) EX2(stb %o5, [%o1 + 0x00],#) sll %o5, 8, %o5 or %o5, %o4, %o4 6: addcc %o4, %g7, %g7 1: sllx %g4, 32, %g4 + addc %g0, %g7, %o0 retl - addc %g0, %g7, %o0 + srl %o0, 0, %o0 /* Sun, you just can't beat me, you just can't. Stop trying, * give up. I'm serious, I am going to kick the living shit @@ -295,7 +299,9 @@ cc_end_cruft: .globl __csum_partial_copy_sparc_generic __csum_partial_copy_sparc_generic: /* %o0=src, %o1=dest, %g1=len, %g7=sum */ + srl %g7, 0, %g7 ! you neve know... xor %o0, %o1, %o4 ! get changing bits + srl %g1, 0, %g1 ! doof scheiss andcc %o4, 3, %g0 ! check for mismatched alignment bne,pn %icc, ccslow ! better this than unaligned/fixups andcc %o0, 7, %g0 ! need to align things? @@ -309,7 +315,7 @@ __csum_partial_copy_sparc_generic: andcc %o0, 0x2, %g0 be,pn %icc, 1f andcc %o0, 0x4, %g0 - EX(lduh [%o0 + 0x00], %g4, add %g1, 0,#) + EX(lduha [%o0 + 0x00] %asi, %g4, add %g1, 0,#) sub %g1, 2, %g1 EX2(sth %g4, [%o1 + 0x00],#) add %o0, 2, %o0 @@ -325,7 +331,7 @@ __csum_partial_copy_sparc_generic: or %g3, %g7, %g7 1: be,pt %icc, 3f andn %g1, 0x7f, %g2 - EX(ld [%o0 + 0x00], %g4, add %g1, 0,#) + EX(lda [%o0 + 0x00] %asi, %g4, add %g1, 0,#) sub %g1, 4, %g1 EX2(st %g4, [%o1 + 0x00],#) add %o0, 4, %o0 @@ -372,8 +378,9 @@ cctbl: CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x68,%g2,%g3,%g4,%g5) ccte: bne,pn %icc, cc_end_cruft ! something left, handle it out of band sethi %uhi(KERNBASE), %g4 ! restore gfp mov %g7, %o0 ! give em the computed checksum + sllx %g4, 32, %g4 ! finish gfp restoration retl ! return - sllx %g4, 32, %g4 ! finish gfp restoration + srl %o0, 0, %o0 ccdbl: CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x00,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x20,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x40,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) @@ -394,7 +401,7 @@ ccslow: mov 0, %g5 be,a,pt %icc, 1f srl %g1, 1, %o3 sub %g1, 1, %g1 - EX(ldub [%o0], %g5, add %g1, 1,#) + EX(lduba [%o0] %asi, %g5, add %g1, 1,#) add %o0, 1, %o0 EX2(stb %g5, [%o1],#) srl %g1, 1, %o3 @@ -404,7 +411,7 @@ ccslow: mov 0, %g5 andcc %o0, 2, %g0 be,a,pt %icc, 1f srl %o3, 1, %o3 - EX(lduh [%o0], %o4, add %g1, 0,#) + EX(lduha [%o0] %asi, %o4, add %g1, 0,#) sub %g1, 2, %g1 srl %o4, 8, %g2 sub %o3, 1, %o3 @@ -416,7 +423,7 @@ ccslow: mov 0, %g5 add %o1, 2, %o1 1: brz,a,pn %o3, 2f andcc %g1, 2, %g0 - EX3(ld [%o0], %o4,#) + EX3(lda [%o0] %asi, %o4,#) 5: srl %o4, 24, %g2 srl %o4, 16, %g3 EX2(stb %g2, [%o1],#) @@ -430,7 +437,7 @@ ccslow: mov 0, %g5 add %o1, 4, %o1 ! is worthy). Maybe some day - with the sll/srl subcc %o3, 1, %o3 ! tricks bne,a,pt %icc, 5b - EX3(ld [%o0], %o4,#) + EX3(lda [%o0] %asi, %o4,#) sll %g5, 16, %g2 srl %g5, 16, %g5 srl %g2, 16, %g2 @@ -438,7 +445,7 @@ ccslow: mov 0, %g5 add %g2, %g5, %g5 2: be,a,pt %icc, 3f andcc %g1, 1, %g0 - EX(lduh [%o0], %o4, and %g1, 3,#) + EX(lduha [%o0] %asi, %o4, and %g1, 3,#) andcc %g1, 1, %g0 srl %o4, 8, %g2 add %o0, 2, %o0 @@ -448,7 +455,7 @@ ccslow: mov 0, %g5 add %o1, 2, %o1 3: be,a,pt %icc, 1f sll %g5, 16, %o4 - EX(ldub [%o0], %g2, add %g0, 1,#) + EX(lduba [%o0] %asi, %g2, add %g0, 1,#) sll %g2, 8, %o4 EX2(stb %g2, [%o1],#) add %g5, %o4, %g5 @@ -463,8 +470,9 @@ ccslow: mov 0, %g5 sll %g2, 8, %g2 or %g2, %o4, %g5 4: addcc %g7, %g5, %g7 + addc %g0, %g7, %o0 retl - addc %g0, %g7, %o0 + srl %o0, 0, %o0 __csum_partial_copy_end: .section .fixup,#alloc,#execinstr diff --git a/arch/sparc64/lib/copy_from_user.S b/arch/sparc64/lib/copy_from_user.S index 50ec7bb3d..196435aed 100644 --- a/arch/sparc64/lib/copy_from_user.S +++ b/arch/sparc64/lib/copy_from_user.S @@ -27,8 +27,8 @@ retl; \ a, b, %o0; \ .section __ex_table,z##alloc; \ - .align 4; \ - .word 98b, 99b; \ + .align 8; \ + .xword 98b, 99b; \ .text; \ .align 4 @@ -41,23 +41,23 @@ retl; \ a, b, %o0; \ .section __ex_table,z##alloc; \ - .align 4; \ - .word 98b, 99b; \ + .align 8; \ + .xword 98b, 99b; \ .text; \ .align 4 #define EXO2(x,y,z) \ 98: x,##y; \ .section __ex_table,z##alloc; \ - .align 4; \ - .word 98b, 97f; \ + .align 8; \ + .xword 98b, 97f; \ .text; \ .align 4 #define EXT(start,end,handler,z) \ .section __ex_table,z##alloc; \ - .align 4; \ - .word start, 0, end, handler; \ + .align 8; \ + .xword start, 0, end, handler; \ .text; \ .align 4 diff --git a/arch/sparc64/lib/copy_to_user.S b/arch/sparc64/lib/copy_to_user.S index 733953743..cc6db141f 100644 --- a/arch/sparc64/lib/copy_to_user.S +++ b/arch/sparc64/lib/copy_to_user.S @@ -27,8 +27,8 @@ retl; \ a, b, %o0; \ .section __ex_table,z##alloc; \ - .align 4; \ - .word 98b, 99b; \ + .align 8; \ + .xword 98b, 99b; \ .text; \ .align 4 @@ -41,23 +41,23 @@ retl; \ a, b, %o0; \ .section __ex_table,z##alloc; \ - .align 4; \ - .word 98b, 99b; \ + .align 8; \ + .xword 98b, 99b; \ .text; \ .align 4 #define EXO2(x,y,z) \ 98: x,##y; \ .section __ex_table,z##alloc; \ - .align 4; \ - .word 98b, 97f; \ + .align 8; \ + .xword 98b, 97f; \ .text; \ .align 4 #define EXT(start,end,handler,z) \ .section __ex_table,z##alloc; \ - .align 4; \ - .word start, 0, end, handler; \ + .align 8; \ + .xword start, 0, end, handler; \ .text; \ .align 4 diff --git a/arch/sparc64/lib/memset.S b/arch/sparc64/lib/memset.S index 55de4ea9d..713c78ca8 100644 --- a/arch/sparc64/lib/memset.S +++ b/arch/sparc64/lib/memset.S @@ -17,15 +17,15 @@ 99: ba,pt %xcc, 30f; \ a, b, %o0; \ .section __ex_table,z##alloc; \ - .align 4; \ - .word 98b, 99b; \ + .align 8; \ + .xword 98b, 99b; \ .text; \ .align 4 #define EXT(start,end,handler,z) \ .section __ex_table,z##alloc; \ - .align 4; \ - .word start, 0, end, handler; \ + .align 8; \ + .xword start, 0, end, handler; \ .text; \ .align 4 diff --git a/arch/sparc64/lib/strlen_user.S b/arch/sparc64/lib/strlen_user.S index 30beee3ff..4d57aed64 100644 --- a/arch/sparc64/lib/strlen_user.S +++ b/arch/sparc64/lib/strlen_user.S @@ -92,10 +92,10 @@ __strlen_user: clr %o0 .section __ex_table,#alloc - .align 4 + .align 8 - .word 10b, 30b - .word 11b, 30b - .word 12b, 30b - .word 13b, 30b - .word 14b, 30b + .xword 10b, 30b + .xword 11b, 30b + .xword 12b, 30b + .xword 13b, 30b + .xword 14b, 30b diff --git a/arch/sparc64/lib/strncpy_from_user.S b/arch/sparc64/lib/strncpy_from_user.S index e0fb0f09b..7a5dc768f 100644 --- a/arch/sparc64/lib/strncpy_from_user.S +++ b/arch/sparc64/lib/strncpy_from_user.S @@ -49,6 +49,6 @@ __strncpy_from_user: mov -EFAULT, %o0 .section __ex_table,#alloc - .align 4 - .word 10b, 4b - .word 11b, 4b + .align 8 + .xword 10b, 4b + .xword 11b, 4b diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index e23e736a9..6df923a4b 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.9 1997/05/19 05:58:54 davem Exp $ +/* $Id: fault.c,v 1.11 1997/06/01 05:46:15 davem Exp $ * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -135,6 +135,7 @@ asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc, } /* #define FAULT_TRACER */ +/* #define FAULT_TRACER_VERBOSE */ asmlinkage void do_sparc64_fault(struct pt_regs *regs, int text_fault, int write, unsigned long address, unsigned long tag, @@ -150,12 +151,23 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs, int text_fault, int write static unsigned long last_addr = 0; static int rcnt = 0; - printk("FAULT(PC[%016lx],t[%d],w[%d],addr[%016lx])\n", +#ifdef FAULT_TRACER_VERBOSE + printk("FAULT(PC[%016lx],t[%d],w[%d],addr[%016lx])...", regs->tpc, text_fault, write, address); - if(address == last_addr && rcnt++ > 5) { - printk("Wheee lotsa bogus faults, something wrong, spinning\n"); - while(1) - barrier(); +#else + printk("F[%016lx:%016lx:w(%d)", regs->tpc, address, write); +#endif + if(address == last_addr) { + if(rcnt++ > 15) { + printk("Wheee lotsa bogus faults, something wrong, spinning\n"); + __asm__ __volatile__("flushw"); + printk("o7[%016lx] i7[%016lx]\n", + regs->u_regs[UREG_I7], + ((struct reg_window *)(regs->u_regs[UREG_FP]+STACK_BIAS))->ins[7]); + sti(); + while(1) + barrier(); + } } else rcnt = 0; last_addr = address; #endif @@ -205,6 +217,13 @@ bad_area: goto out; } if(from_user) { +#if 1 + unsigned long cpc; + __asm__ __volatile__("mov %%i7, %0" : "=r" (cpc)); + printk("[%s:%d] SIGSEGV pc[%016lx] addr[%016lx] w[%d] sfsr[%016lx] " + "caller[%016lx]\n", current->comm, current->pid, regs->tpc, + address, write, sfsr, cpc); +#endif tsk->tss.sig_address = address; tsk->tss.sig_desc = SUBSIG_NOMAPPING; send_sig(SIGSEGV, tsk, 1); @@ -213,4 +232,12 @@ bad_area: unhandled_fault (address, tsk, regs); out: unlock_kernel(); +#ifdef FAULT_TRACER +#ifdef FAULT_TRACER_VERBOSE + printk(" done\n"); +#else + printk("]"); +#endif +#endif } + diff --git a/arch/sparc64/vmlinux.lds b/arch/sparc64/vmlinux.lds index f8ba23528..d2d0cac34 100644 --- a/arch/sparc64/vmlinux.lds +++ b/arch/sparc64/vmlinux.lds @@ -26,6 +26,7 @@ SECTIONS _edata = .; PROVIDE (edata = .); .fixup : { *(.fixup) } + . = ALIGN(16); __start___ex_table = .; __ex_table : { *(__ex_table) } __stop___ex_table = .; |