diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-06-17 13:25:08 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-06-17 13:25:08 +0000 |
commit | 59223edaa18759982db0a8aced0e77457d10c68e (patch) | |
tree | 89354903b01fa0a447bffeefe00df3044495db2e /arch/sparc64/kernel | |
parent | db7d4daea91e105e3859cf461d7e53b9b77454b2 (diff) |
Merge with Linux 2.3.6. Sorry, this isn't tested on silicon, I don't
have a MIPS box at hand.
Diffstat (limited to 'arch/sparc64/kernel')
-rw-r--r-- | arch/sparc64/kernel/binfmt_aout32.c | 39 | ||||
-rw-r--r-- | arch/sparc64/kernel/etrap.S | 10 | ||||
-rw-r--r-- | arch/sparc64/kernel/head.S | 3 | ||||
-rw-r--r-- | arch/sparc64/kernel/init_task.c | 6 | ||||
-rw-r--r-- | arch/sparc64/kernel/ioctl32.c | 24 | ||||
-rw-r--r-- | arch/sparc64/kernel/process.c | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/ptrace.c | 21 | ||||
-rw-r--r-- | arch/sparc64/kernel/rtrap.S | 3 | ||||
-rw-r--r-- | arch/sparc64/kernel/setup.c | 4 | ||||
-rw-r--r-- | arch/sparc64/kernel/signal.c | 68 | ||||
-rw-r--r-- | arch/sparc64/kernel/smp.c | 19 | ||||
-rw-r--r-- | arch/sparc64/kernel/sys_sparc.c | 35 | ||||
-rw-r--r-- | arch/sparc64/kernel/sys_sparc32.c | 177 | ||||
-rw-r--r-- | arch/sparc64/kernel/sys_sunos32.c | 10 | ||||
-rw-r--r-- | arch/sparc64/kernel/systbls.S | 4 | ||||
-rw-r--r-- | arch/sparc64/kernel/trampoline.S | 4 | ||||
-rw-r--r-- | arch/sparc64/kernel/traps.c | 48 | ||||
-rw-r--r-- | arch/sparc64/kernel/unaligned.c | 13 |
18 files changed, 270 insertions, 220 deletions
diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c index 450451ac0..e852ca8f8 100644 --- a/arch/sparc64/kernel/binfmt_aout32.c +++ b/arch/sparc64/kernel/binfmt_aout32.c @@ -48,9 +48,7 @@ static void set_brk(unsigned long start, unsigned long end) end = PAGE_ALIGN(end); if (end <= start) return; - do_mmap(NULL, start, end - start, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_FIXED | MAP_PRIVATE, 0); + do_brk(start, end - start); } /* @@ -284,24 +282,18 @@ static inline int do_load_aout32_binary(struct linux_binprm * bprm, current->flags &= ~PF_FORKNOEXEC; if (N_MAGIC(ex) == NMAGIC) { /* Fuck me plenty... */ - error = do_mmap(NULL, N_TXTADDR(ex), ex.a_text, - PROT_READ|PROT_WRITE|PROT_EXEC, - MAP_FIXED|MAP_PRIVATE, 0); + error = do_brk(N_TXTADDR(ex), ex.a_text); read_exec(bprm->dentry, fd_offset, (char *) N_TXTADDR(ex), ex.a_text, 0); - error = do_mmap(NULL, N_DATADDR(ex), ex.a_data, - PROT_READ|PROT_WRITE|PROT_EXEC, - MAP_FIXED|MAP_PRIVATE, 0); + error = do_brk(N_DATADDR(ex), ex.a_data); read_exec(bprm->dentry, fd_offset + ex.a_text, (char *) N_DATADDR(ex), ex.a_data, 0); goto beyond_if; } if (N_MAGIC(ex) == OMAGIC) { - do_mmap(NULL, N_TXTADDR(ex) & PAGE_MASK, - ex.a_text+ex.a_data + PAGE_SIZE - 1, - PROT_READ|PROT_WRITE|PROT_EXEC, - MAP_FIXED|MAP_PRIVATE, 0); + do_brk(N_TXTADDR(ex) & PAGE_MASK, + ex.a_text+ex.a_data + PAGE_SIZE - 1); read_exec(bprm->dentry, fd_offset, (char *) N_TXTADDR(ex), ex.a_text+ex.a_data, 0); } else { @@ -316,9 +308,7 @@ static inline int do_load_aout32_binary(struct linux_binprm * bprm, if (!file->f_op || !file->f_op->mmap) { sys_close(fd); - do_mmap(NULL, 0, ex.a_text+ex.a_data, - PROT_READ|PROT_WRITE|PROT_EXEC, - MAP_FIXED|MAP_PRIVATE, 0); + do_brk(0, ex.a_text+ex.a_data); read_exec(bprm->dentry, fd_offset, (char *) N_TXTADDR(ex), ex.a_text+ex.a_data, 0); goto beyond_if; @@ -359,11 +349,16 @@ beyond_if: set_brk(current->mm->start_brk, current->mm->brk); - p = setup_arg_pages(p, bprm); + retval = setup_arg_pages(bprm); + if (retval < 0) { + /* Someone check-me: is this error path enough? */ + send_sig(SIGKILL, current, 0); + return retval; + } - p = (unsigned long) create_aout32_tables((char *)p, bprm); - current->mm->start_stack = p; - start_thread32(regs, ex.a_entry, p); + current->mm->start_stack = + (unsigned long) create_aout32_tables((char *)bprm->p, bprm); + start_thread32(regs, ex.a_entry, current->mm->start_stack); if (current->flags & PF_PTRACED) send_sig(SIGTRAP, current, 0); return 0; @@ -442,9 +437,7 @@ do_load_aout32_library(int fd) len = PAGE_ALIGN(ex.a_text + ex.a_data); bss = ex.a_text + ex.a_data + ex.a_bss; if (bss > len) { - error = do_mmap(NULL, start_addr + len, bss - len, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_FIXED, 0); + error = do_brk(start_addr + len, bss - len); retval = error; if (error != start_addr + len) goto out_putf; diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S index 1b6a1e2b0..6a94cf3ab 100644 --- a/arch/sparc64/kernel/etrap.S +++ b/arch/sparc64/kernel/etrap.S @@ -1,8 +1,8 @@ -/* $Id: etrap.S,v 1.40 1998/06/12 14:54:03 jj Exp $ +/* $Id: etrap.S,v 1.41 1999/05/25 16:53:09 jj Exp $ * etrap.S: Preparing for entry into the kernel on Sparc V9. * * Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1997, 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 1997, 1998, 1999 Jakub Jelinek (jj@ultra.linux.cz) */ #include <asm/asi.h> @@ -59,10 +59,9 @@ etrap_irq: rdpr %tstate, %g1 ! Single Group stb %l5, [%l6 + AOFF_task_tss + AOFF_thread_fpdepth] ! Store wrpr %g3, 0, %otherwin ! Single Group+4bubbles wrpr %g2, 0, %wstate ! Single Group+4bubbles - ldxa [%l4] ASI_DMMU, %g2 ! Load Group stxa %g0, [%l4] ASI_DMMU ! Store Group - stxa %g2, [%l4 + %l4] ASI_DMMU ! Store Group flush %l6 ! Single Group+9bubbles + wr %g0, ASI_AIUS, %asi ! Single Group+4bubbles 2: wrpr %g0, 0x0, %tl ! Single Group+4bubbles andn %g1, PSTATE_MM, %l1 ! IEU0 Group mov %g4, %l4 ! IEU1 @@ -135,10 +134,9 @@ scetrap: rdpr %pil, %g2 ! Single Group sll %g2, 3, %g2 ! IEU0 Group wrpr %g3, 0, %otherwin ! Single Group+4bubbles wrpr %g2, 0, %wstate ! Single Group+4bubbles - ldxa [%l4] ASI_DMMU, %g2 ! Load Group stxa %g0, [%l4] ASI_DMMU ! Store Group - stxa %g2, [%l4 + %l4] ASI_DMMU ! Store Group flush %l6 ! Single Group+9bubbles + wr %g0, ASI_AIUS, %asi ! Single Group+4bubbles 2: wrpr %g0, 0x0, %tl ! Single Group+4bubbles andn %g1, PSTATE_MM, %l1 ! IEU0 Group mov %g4, %l4 ! IEU1 diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 21c1872a8..ad863a71d 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.60 1999/04/12 08:08:21 davem Exp $ +/* $Id: head.S,v 1.61 1999/05/25 16:53:10 jj Exp $ * head.S: Initial boot code for the Sparc64 port of Linux. * * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -286,6 +286,7 @@ sun4u_init: wr %g6, 0x0, %pic #endif + wr %g0, ASI_P, %asi mov 1, %g5 sllx %g5, (PAGE_SHIFT + 1), %g5 sub %g5, (REGWIN_SZ + STACK_BIAS), %g5 diff --git a/arch/sparc64/kernel/init_task.c b/arch/sparc64/kernel/init_task.c index 86b6c3dd6..66869404d 100644 --- a/arch/sparc64/kernel/init_task.c +++ b/arch/sparc64/kernel/init_task.c @@ -9,11 +9,13 @@ static struct fs_struct init_fs = INIT_FS; static struct file * init_fd_array[NR_OPEN] = { NULL, }; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS; -struct mm_struct init_mm = INIT_MM; +struct mm_struct init_mm = INIT_MM(init_mm); /* .text section in head.S is aligned at 2 page boundry and this gets linked * right after that so that the init_task_union is aligned properly as well. * We really don't need this special alignment like the Intel does, but * I do it anyways for completeness. */ -union task_union init_task_union __attribute__((__section__(".text"))) = { INIT_TASK }; +union task_union init_task_union + __attribute__((__section__(".text"))) = + { INIT_TASK(init_task_union.task) }; diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 84d4de363..6759f74d4 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.62 1999/05/01 09:17:44 davem Exp $ +/* $Id: ioctl32.c,v 1.63 1999/06/09 04:56:14 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -37,6 +37,7 @@ #include <linux/fb.h> #include <linux/ext2_fs.h> #include <linux/videodev.h> +#include <linux/netdevice.h> #include <scsi/scsi.h> /* Ugly hack. */ @@ -417,6 +418,23 @@ struct ifconf32 { __kernel_caddr_t32 ifcbuf; }; +static int dev_ifname32(unsigned int fd, unsigned long arg) +{ + struct device *dev; + struct ifreq32 ifr32; + int err; + + if (copy_from_user(&ifr32, (struct ifreq32 *)arg, sizeof(struct ifreq32))) + return -EFAULT; + + dev = dev_get_by_index(ifr32.ifr_ifindex); + if (!dev) + return -ENODEV; + + err = copy_to_user((struct ifreq32 *)arg, &ifr32, sizeof(struct ifreq32)); + return (err ? -EFAULT : 0); +} + static inline int dev_ifconf(unsigned int fd, unsigned long arg) { struct ifconf32 ifc32; @@ -1687,6 +1705,10 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) goto out; } switch (cmd) { + case SIOCGIFNAME: + error = dev_ifname32(fd, arg); + goto out; + case SIOCGIFCONF: error = dev_ifconf(fd, arg); goto out; diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 0d4871132..1abe767e9 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.92 1999/05/08 23:04:48 davem Exp $ +/* $Id: process.c,v 1.94 1999/05/27 04:49:30 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index 4dd9651b3..00340d6d5 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -204,26 +204,6 @@ static inline void put_int(struct task_struct * tsk, struct vm_area_struct * vma flush_tlb_page(vma, addr); } -static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, - unsigned long addr) -{ - struct vm_area_struct * vma; - - addr &= PAGE_MASK; - vma = find_vma(tsk->mm,addr); - if (!vma) - return NULL; - if (vma->vm_start <= addr) - return vma; - if (!(vma->vm_flags & VM_GROWSDOWN)) - return NULL; - if (vma->vm_end - addr > tsk->rlim[RLIMIT_STACK].rlim_cur) - return NULL; - vma->vm_offset -= vma->vm_start - addr; - vma->vm_start = addr; - return vma; -} - /* * This routine checks the page boundaries, and that the offset is * within the task area. It then calls get_long() to read a long. @@ -603,6 +583,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) if((!child->dumpable || (current->uid != child->euid) || (current->uid != child->uid) || + (current->uid != child->suid) || (current->gid != child->egid) || (current->gid != child->sgid) || (!cap_issubset(child->cap_permitted, current->cap_permitted)) || diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S index a3137ee50..8444bc966 100644 --- a/arch/sparc64/kernel/rtrap.S +++ b/arch/sparc64/kernel/rtrap.S @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.45 1998/11/09 15:33:29 davem Exp $ +/* $Id: rtrap.S,v 1.46 1999/05/25 16:53:20 jj Exp $ * rtrap.S: Preparing for return from trap on Sparc V9. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -106,7 +106,6 @@ rt_continue: lduh [%g6 + AOFF_task_tss + AOFF_thread_ctx], %l0 brnz,pn %l3, kern_rtt mov PRIMARY_CONTEXT, %l7 stxa %l0, [%l7] ASI_DMMU - stxa %l0, [%l7 + %l7] ASI_DMMU flush %o5 rdpr %wstate, %l1 diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index caa1d99ef..d5e980ebf 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.43 1999/04/12 08:08:24 davem Exp $ +/* $Id: setup.c,v 1.44 1999/05/28 02:17:29 davem Exp $ * linux/arch/sparc64/kernel/setup.c * * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) @@ -550,7 +550,9 @@ __initfunc(void setup_arch(char **cmdline_p, ic_servaddr = sv; if (gw) ic_gateway = gw; +#if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP) ic_proto_enabled = 0; +#endif } } #endif diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index 91dc7224d..e0ba8aa1e 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.38 1998/10/16 03:19:04 davem Exp $ +/* $Id: signal.c,v 1.40 1999/06/02 19:19:52 jj Exp $ * arch/sparc64/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -491,7 +491,7 @@ segv: /* Checks if the fp is valid */ static int invalid_frame_pointer(void *fp, int fplen) { - if ((((unsigned long) fp) & 7) || ((unsigned long)fp) > 0x80000000000ULL - fplen) + if (((unsigned long) fp) & 7) return 1; return 0; } @@ -554,8 +554,10 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs, goto sigill; if (current->tss.w_saved != 0) { +#ifdef DEBUG_SIGNALS printk ("%s[%d]: Invalid user stack frame for " "signal delivery.\n", current->comm, current->pid); +#endif goto sigill; } @@ -590,35 +592,7 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs, regs->tnpc = (regs->tpc + 4); /* 4. return to kernel instructions */ - if (ka->ka_restorer) - regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; - else { - /* Flush instruction space. */ - unsigned long address = ((unsigned long)&(sf->insns[0])); - pgd_t *pgdp = pgd_offset(current->mm, address); - pmd_t *pmdp = pmd_offset(pgdp, address); - pte_t *ptep = pte_offset(pmdp, address); - - regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); - - /* mov __NR_sigreturn, %g1 */ - err |= __put_user(0x821020d8, &sf->insns[0]); - - /* t 0x6d */ - err |= __put_user(0x91d0206d, &sf->insns[1]); - if (err) - goto sigsegv; - - if(pte_present(*ptep)) { - unsigned long page = pte_page(*ptep); - - __asm__ __volatile__(" - membar #StoreStore - flush %0 + %1" - : : "r" (page), "r" (address & (PAGE_SIZE - 1)) - : "memory"); - } - } + regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; return; sigill: @@ -650,8 +624,10 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, goto sigill; if (current->tss.w_saved != 0) { +#ifdef DEBUG_SIGNALS printk ("%s[%d]: Invalid user stack frame for " "signal delivery.\n", current->comm, current->pid); +#endif goto sigill; } @@ -690,35 +666,7 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, regs->tnpc = (regs->tpc + 4); /* 4. return to kernel instructions */ - if (ka->ka_restorer) - regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; - else { - /* Flush instruction space. */ - unsigned long address = ((unsigned long)&(sf->insns[0])); - pgd_t *pgdp = pgd_offset(current->mm, address); - pmd_t *pmdp = pmd_offset(pgdp, address); - pte_t *ptep = pte_offset(pmdp, address); - - regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2); - - /* mov __NR_rt_sigreturn, %g1 */ - err |= __put_user(0x82102065, &sf->insns[0]); - - /* t 0x6d */ - err |= __put_user(0x91d0206d, &sf->insns[1]); - if (err) - goto sigsegv; - - if(pte_present(*ptep)) { - unsigned long page = pte_page(*ptep); - - __asm__ __volatile__(" - membar #StoreStore - flush %0 + %1" - : : "r" (page), "r" (address & (PAGE_SIZE - 1)) - : "memory"); - } - } + regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; return; sigill: diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 27344f4b6..b0e92d50b 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -272,25 +272,26 @@ __initfunc(void smp_boot_cpus(void)) static inline void xcall_deliver(u64 data0, u64 data1, u64 data2, u64 pstate, unsigned long cpu) { u64 result, target = (cpu << 14) | 0x70; - int stuck; + int stuck, tmp; #ifdef XCALL_DEBUG printk("CPU[%d]: xcall(data[%016lx:%016lx:%016lx],tgt[%016lx])\n", smp_processor_id(), data0, data1, data2, target); #endif again: + tmp = 0x40; __asm__ __volatile__(" - wrpr %0, %1, %%pstate - wr %%g0, %2, %%asi - stxa %3, [0x40] %%asi - stxa %4, [0x50] %%asi - stxa %5, [0x60] %%asi + wrpr %1, %2, %%pstate + stxa %4, [%0] %3 + stxa %5, [%0+%8] %3 + add %0, %8, %0 + stxa %6, [%0+%8] %3 membar #Sync - stxa %%g0, [%6] %%asi + stxa %%g0, [%7] %3 membar #Sync" - : /* No outputs */ + : "=r" (tmp) : "r" (pstate), "i" (PSTATE_IE), "i" (ASI_UDB_INTR_W), - "r" (data0), "r" (data1), "r" (data2), "r" (target)); + "r" (data0), "r" (data1), "r" (data2), "r" (target), "r" (0x10), "0" (tmp)); /* NOTE: PSTATE_IE is still clear. */ stuck = 100000; diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c index 8d11f10b8..4906cea93 100644 --- a/arch/sparc64/kernel/sys_sparc.c +++ b/arch/sparc64/kernel/sys_sparc.c @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.26 1999/01/07 19:07:01 jj Exp $ +/* $Id: sys_sparc.c,v 1.27 1999/06/02 12:06:34 jj Exp $ * linux/arch/sparc64/kernel/sys_sparc.c * * This file contains various random system calls that @@ -328,39 +328,6 @@ long sparc_memory_ordering(unsigned long model, struct pt_regs *regs) } asmlinkage int -sys_sigaction(int sig, const struct old_sigaction *act, - struct old_sigaction *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - if (act) { - old_sigset_t mask; - if (verify_area(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) - return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); - siginitset(&new_ka.sa.sa_mask, mask); - new_ka.ka_restorer = NULL; - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } - - return ret; -} - -asmlinkage int sys_rt_sigaction(int sig, const struct sigaction *act, struct sigaction *oact, void *restorer, size_t sigsetsize) { diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index a7f85ca58..79ce3db45 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.107 1999/03/05 13:21:02 davem Exp $ +/* $Id: sys_sparc32.c,v 1.109 1999/06/03 07:11:31 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -2363,6 +2363,94 @@ static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) __scm_destroy(scm); } +/* In these cases we (currently) can just copy to data over verbatim + * because all CMSGs created by the kernel have well defined types which + * have the same layout in both the 32-bit and 64-bit API. One must add + * some special cased conversions here if we start sending control messages + * with incompatible types. + * + * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after + * we do our work. The remaining cases are: + * + * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean + * IP_TTL int 32-bit clean + * IP_TOS __u8 32-bit clean + * IP_RECVOPTS variable length 32-bit clean + * IP_RETOPTS variable length 32-bit clean + * (these last two are clean because the types are defined + * by the IPv4 protocol) + * IP_RECVERR struct sock_extended_err + + * struct sockaddr_in 32-bit clean + * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + + * struct sockaddr_in6 32-bit clean + * IPV6_PKTINFO struct in6_pktinfo 32-bit clean + * IPV6_HOPLIMIT int 32-bit clean + * IPV6_FLOWINFO u32 32-bit clean + * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean + * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean + * IPV6_RTHDR ipv6 routing exthdr 32-bit clean + * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean + */ +static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) +{ + unsigned char *workbuf, *wp; + unsigned long bufsz, space_avail; + struct cmsghdr *ucmsg; + + bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; + space_avail = kmsg->msg_controllen + bufsz; + wp = workbuf = kmalloc(bufsz, GFP_KERNEL); + if(workbuf == NULL) + goto fail; + + /* To make this more sane we assume the kernel sends back properly + * formatted control messages. Because of how the kernel will truncate + * the cmsg_len for MSG_TRUNC cases, we need not check that case either. + */ + ucmsg = (struct cmsghdr *) orig_cmsg_uptr; + while(((unsigned long)ucmsg) < ((unsigned long)kmsg->msg_control)) { + struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; + int clen64, clen32; + + /* UCMSG is the 64-bit format CMSG entry in user-space. + * KCMSG32 is within the kernel space temporary buffer + * we use to convert into a 32-bit style CMSG. + */ + __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); + __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); + __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); + + clen64 = kcmsg32->cmsg_len; + copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), + clen64 - CMSG_ALIGN(sizeof(*ucmsg))); + clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + + CMSG32_ALIGN(sizeof(struct cmsghdr32))); + kcmsg32->cmsg_len = clen32; + + ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); + wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); + } + + /* Copy back fixed up data, and adjust pointers. */ + bufsz = (wp - workbuf); + copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); + + kmsg->msg_control = (struct cmsghdr *) + (((char *)orig_cmsg_uptr) + bufsz); + kmsg->msg_controllen = space_avail - bufsz; + + kfree(workbuf); + return; + +fail: + /* If we leave the 64-bit format CMSG chunks in there, + * the application could get confused and crash. So to + * ensure greater recovery, we report no CMSGs. + */ + kmsg->msg_controllen += bufsz; + kmsg->msg_control = (void *) orig_cmsg_uptr; +} + asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags) { struct socket *sock; @@ -2455,6 +2543,14 @@ asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int use if(scm.fp) __scm_destroy(&scm); } else { + /* If recvmsg processing itself placed some + * control messages into user space, it's is + * using 64-bit CMSG processing, so we need + * to fix it up before we tack on more stuff. + */ + if((unsigned long) kern_msg.msg_control != cmsg_ptr) + cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); + /* Wheee... */ if(sock->passcred) put_cmsg32(&kern_msg, @@ -2471,9 +2567,9 @@ asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int use if(uaddr != NULL && err >= 0) err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); if(cmsg_ptr != 0 && err >= 0) { - u32 ucmsg_ptr = ((u32)(unsigned long)kern_msg.msg_control); - err = __put_user(ucmsg_ptr, &user_msg->msg_control); - err |= __put_user(kern_msg.msg_controllen, &user_msg->msg_controllen); + unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); + __kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr - cmsg_ptr); + err |= __put_user(uclen, &user_msg->msg_controllen); } if(err >= 0) err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); @@ -2680,42 +2776,46 @@ static int count32(u32 * argv) * memory to free pages in kernel mem. These are in a format ready * to be put directly into the top of new user memory. */ -static unsigned long -copy_strings32(int argc,u32 * argv,unsigned long *page, - unsigned long p) +static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm) { - u32 str; - - if (!p) return 0; /* bullet-proofing */ while (argc-- > 0) { + u32 str; int len; unsigned long pos; - get_user(str, argv+argc); - if (!str) panic("VFS: argc is wrong"); - len = strlen_user((char *)A(str)); /* includes the '\0' */ - if (p < len) /* this shouldn't happen - 128kB */ - return 0; - p -= len; pos = p; + if (get_user(str, argv + argc) || + !str || + !(len = strlen_user((char *)A(str)))) + return -EFAULT; + if (bprm->p < len) + return -E2BIG; + + bprm->p -= len; + + pos = bprm->p; while (len) { char *pag; int offset, bytes_to_copy; offset = pos % PAGE_SIZE; - if (!(pag = (char *) page[pos/PAGE_SIZE]) && - !(pag = (char *) page[pos/PAGE_SIZE] = + if (!(pag = (char *) bprm->page[pos/PAGE_SIZE]) && + !(pag = (char *) bprm->page[pos/PAGE_SIZE] = (unsigned long *) get_free_page(GFP_USER))) - return 0; + return -ENOMEM; + bytes_to_copy = PAGE_SIZE - offset; if (bytes_to_copy > len) bytes_to_copy = len; - copy_from_user(pag + offset, (char *)A(str), bytes_to_copy); + + if (copy_from_user(pag + offset, (char *)A(str), bytes_to_copy)) + return -EFAULT; + pos += bytes_to_copy; str += bytes_to_copy; len -= bytes_to_copy; } } - return p; + return 0; } /* @@ -2754,29 +2854,36 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) } retval = prepare_binprm(&bprm); + if (retval < 0) + goto out; - if(retval>=0) { - bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p, 2); - bprm.exec = bprm.p; - bprm.p = copy_strings32(bprm.envc,envp,bprm.page,bprm.p); - bprm.p = copy_strings32(bprm.argc,argv,bprm.page,bprm.p); - if (!bprm.p) - retval = -E2BIG; - } - - if(retval>=0) - retval = search_binary_handler(&bprm,regs); - if(retval>=0) + retval = copy_strings_kernel(1, &bprm.filename, &bprm); + if (retval < 0) + goto out; + + bprm.exec = bprm.p; + retval = copy_strings32(bprm.envc, envp, &bprm); + if (retval < 0) + goto out; + + retval = copy_strings32(bprm.argc, argv, &bprm); + if (retval < 0) + goto out; + + retval = search_binary_handler(&bprm, regs); + if (retval >= 0) /* execve success */ return retval; +out: /* Something went wrong, return the inode and free the argument pages*/ - if(bprm.dentry) + if (bprm.dentry) dput(bprm.dentry); for (i=0 ; i<MAX_ARG_PAGES ; i++) free_page(bprm.page[i]); - return(retval); + + return retval; } /* diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c index 82701cc9e..99e010e78 100644 --- a/arch/sparc64/kernel/sys_sunos32.c +++ b/arch/sparc64/kernel/sys_sunos32.c @@ -1,4 +1,4 @@ -/* $Id: sys_sunos32.c,v 1.22 1998/10/26 20:01:13 davem Exp $ +/* $Id: sys_sunos32.c,v 1.26 1999/06/09 08:23:54 davem Exp $ * sys_sunos32.c: SunOS binary compatability layer on sparc64. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -134,7 +134,6 @@ asmlinkage int sunos_brk(u32 baddr) unsigned long newbrk, oldbrk, brk = (unsigned long) baddr; down(¤t->mm->mmap_sem); - lock_kernel(); if (brk < current->mm->end_code) goto out; newbrk = PAGE_ALIGN(brk); @@ -175,12 +174,9 @@ asmlinkage int sunos_brk(u32 baddr) goto out; /* Ok, we have probably got enough memory - let it rip. */ current->mm->brk = brk; - do_mmap(NULL, oldbrk, newbrk-oldbrk, - PROT_READ|PROT_WRITE|PROT_EXEC, - MAP_FIXED|MAP_PRIVATE, 0); + do_brk(oldbrk, newbrk-oldbrk); retval = 0; out: - unlock_kernel(); up(¤t->mm->mmap_sem); return retval; } @@ -1347,7 +1343,7 @@ asmlinkage int sunos_readv(u32 fd, u32 vector, s32 count) lock_kernel(); ret = check_nonblock(sys32_readv(fd, vector, count), fd); - lock_kernel(); + unlock_kernel(); return ret; } diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index d2a75033a..e99ae0532 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.53 1999/04/07 17:14:11 davem Exp $ +/* $Id: systbls.S,v 1.54 1999/06/02 12:06:31 jj Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -115,7 +115,7 @@ sys_call_table: /*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname /*190*/ .word sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall - .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_sigaction, sys_sgetmask + .word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask /*200*/ .word sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, sys_nis_syscall .word sys_nis_syscall, sys_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall /*210*/ .word sys_idle, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S index 2c19cc39d..0dd40b538 100644 --- a/arch/sparc64/kernel/trampoline.S +++ b/arch/sparc64/kernel/trampoline.S @@ -1,4 +1,4 @@ -/* $Id: trampoline.S,v 1.8 1998/12/09 21:01:15 davem Exp $ +/* $Id: trampoline.S,v 1.9 1999/05/25 16:53:12 jj Exp $ * trampoline.S: Jump start slave processors on sparc64. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -130,6 +130,8 @@ sparc64_cpu_startup: nop bounce: + wr %g0, ASI_P, %asi + mov PRIMARY_CONTEXT, %g7 stxa %g0, [%g7] ASI_DMMU membar #Sync diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 5f7049822..86ee5b661 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.58 1999/03/29 12:38:10 jj Exp $ +/* $Id: traps.c,v 1.60 1999/06/02 19:19:55 jj Exp $ * arch/sparc64/kernel/traps.c * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -282,11 +282,16 @@ void instruction_access_exception (struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) { lock_kernel(); + if (regs->tstate & TSTATE_PRIV) { #if 1 - printk("instruction_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n", - sfsr, sfar); + printk("instruction_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n", + sfsr, sfar); #endif - die_if_kernel("Iax", regs); + die_if_kernel("Iax", regs); + } + current->tss.sig_desc = SUBSIG_ILLINST; + current->tss.sig_address = regs->tpc; + force_sig(SIGILL, current); unlock_kernel(); } @@ -452,15 +457,35 @@ void instruction_dump (unsigned int *pc) if((((unsigned long) pc) & 3)) return; + printk("Instruction DUMP:"); for(i = -3; i < 6; i++) printk("%c%08x%c",i?' ':'<',pc[i],i?' ':'>'); printk("\n"); } +void user_instruction_dump (unsigned int *pc) +{ + int i; + unsigned int buf[9]; + + if((((unsigned long) pc) & 3)) + return; + + if(copy_from_user(buf, pc - 3, sizeof(buf))) + return; + + printk("Instruction DUMP:"); + for(i = 0; i < 9; i++) + printk("%c%08x%c",i==3?' ':'<',buf[i],i==3?' ':'>'); + printk("\n"); +} + void die_if_kernel(char *str, struct pt_regs *regs) { extern void __show_regs(struct pt_regs * regs); extern void smp_report_regs(void); + int count = 0; + struct reg_window *lastrw; /* Amuse the user. */ printk( @@ -472,25 +497,28 @@ void die_if_kernel(char *str, struct pt_regs *regs) printk("%s(%d): %s\n", current->comm, current->pid, str); __asm__ __volatile__("flushw"); __show_regs(regs); - { + if(regs->tstate & TSTATE_PRIV) { struct reg_window *rw = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS); /* Stop the back trace when we hit userland or we * find some badly aligned kernel stack. */ + lastrw = (struct reg_window *)current; while(rw && - (((unsigned long) rw) >= PAGE_OFFSET) && + count++ < 30 && + rw >= lastrw && + (char *) rw < ((char *) current) + + sizeof (union task_union) && !(((unsigned long) rw) & 0x7)) { printk("Caller[%016lx]\n", rw->ins[7]); + lastrw = rw; rw = (struct reg_window *) (rw->ins[6] + STACK_BIAS); } - } - if(regs->tstate & TSTATE_PRIV) { - printk("Instruction DUMP:"); instruction_dump ((unsigned int *) regs->tpc); - } + } else + user_instruction_dump ((unsigned int *) regs->tpc); #ifdef __SMP__ smp_report_regs(); #endif diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c index f4599bbdb..3b813f415 100644 --- a/arch/sparc64/kernel/unaligned.c +++ b/arch/sparc64/kernel/unaligned.c @@ -1,4 +1,4 @@ -/* $Id: unaligned.c,v 1.15 1999/04/03 11:36:21 anton Exp $ +/* $Id: unaligned.c,v 1.16 1999/05/25 16:53:15 jj Exp $ * unaligned.c: Unaligned load/store trap handling with special * cases for the kernel to do them more quickly. * @@ -228,7 +228,8 @@ __asm__ __volatile__ ( \ "sra %%g7, 0, %%g7\n\t" \ "stx %%l1, [%0]\n\t" \ "stx %%g7, [%0 + 8]\n" \ -"0:\n\n\t" \ +"0:\n\t" \ + "wr %%g0, %5, %%asi\n\n\t" \ ".section __ex_table\n\t" \ ".word 4b, " #errh "\n\t" \ ".word 5b, " #errh "\n\t" \ @@ -244,7 +245,8 @@ __asm__ __volatile__ ( \ ".word 15b, " #errh "\n\t" \ ".word 16b, " #errh "\n\n\t" \ ".previous\n\t" \ - : : "r" (dest_reg), "r" (size), "r" (saddr), "r" (is_signed), "r" (asi) \ + : : "r" (dest_reg), "r" (size), "r" (saddr), "r" (is_signed), \ + "r" (asi), "i" (ASI_AIUS) \ : "l1", "l2", "g7", "g1", "cc"); \ }) @@ -282,7 +284,8 @@ __asm__ __volatile__ ( \ "2:\t" "srl %%l1, 8, %%l2\n" \ "16:\t" "stba %%l2, [%0] %%asi\n" \ "17:\t" "stba %%l1, [%0 + 1] %%asi\n" \ -"0:\n\n\t" \ +"0:\n\t" \ + "wr %%g0, %4, %%asi\n\n\t" \ ".section __ex_table\n\t" \ ".word 4b, " #errh "\n\t" \ ".word 5b, " #errh "\n\t" \ @@ -299,7 +302,7 @@ __asm__ __volatile__ ( \ ".word 16b, " #errh "\n\t" \ ".word 17b, " #errh "\n\n\t" \ ".previous\n\t" \ - : : "r" (dst_addr), "r" (size), "r" (src_val), "r" (asi) \ + : : "r" (dst_addr), "r" (size), "r" (src_val), "r" (asi), "i" (ASI_AIUS)\ : "l1", "l2", "g7", "g1", "cc"); \ }) |