summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-06-17 13:25:08 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-06-17 13:25:08 +0000
commit59223edaa18759982db0a8aced0e77457d10c68e (patch)
tree89354903b01fa0a447bffeefe00df3044495db2e /arch/sparc64/kernel
parentdb7d4daea91e105e3859cf461d7e53b9b77454b2 (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.c39
-rw-r--r--arch/sparc64/kernel/etrap.S10
-rw-r--r--arch/sparc64/kernel/head.S3
-rw-r--r--arch/sparc64/kernel/init_task.c6
-rw-r--r--arch/sparc64/kernel/ioctl32.c24
-rw-r--r--arch/sparc64/kernel/process.c2
-rw-r--r--arch/sparc64/kernel/ptrace.c21
-rw-r--r--arch/sparc64/kernel/rtrap.S3
-rw-r--r--arch/sparc64/kernel/setup.c4
-rw-r--r--arch/sparc64/kernel/signal.c68
-rw-r--r--arch/sparc64/kernel/smp.c19
-rw-r--r--arch/sparc64/kernel/sys_sparc.c35
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c177
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c10
-rw-r--r--arch/sparc64/kernel/systbls.S4
-rw-r--r--arch/sparc64/kernel/trampoline.S4
-rw-r--r--arch/sparc64/kernel/traps.c48
-rw-r--r--arch/sparc64/kernel/unaligned.c13
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(&current->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(&current->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"); \
})