Commit f3aafa6c authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6:
  [SPARC64]: Make use of the new fs/compat_binfmt_elf.c
  [SPARC64]: Make use of compat_sys_ptrace()

Manually fixed trivial delete/modift conflict in arch/sparc64/kernel/binfmt_elf32.c
parents 3668805a 48c946a4
...@@ -383,13 +383,7 @@ config COMPAT ...@@ -383,13 +383,7 @@ config COMPAT
bool bool
depends on SPARC32_COMPAT depends on SPARC32_COMPAT
default y default y
select COMPAT_BINFMT_ELF
config BINFMT_ELF32
bool "Kernel support for 32-bit ELF binaries"
depends on SPARC32_COMPAT
help
This allows you to run 32-bit Linux/ELF binaries on your Ultra.
Everybody wants this; say Y.
config BINFMT_AOUT32 config BINFMT_AOUT32
bool "Kernel support for 32-bit (ie. SunOS) a.out binaries" bool "Kernel support for 32-bit (ie. SunOS) a.out binaries"
......
...@@ -21,7 +21,6 @@ obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o \ ...@@ -21,7 +21,6 @@ obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o \
obj-$(CONFIG_PCI_MSI) += pci_msi.o obj-$(CONFIG_PCI_MSI) += pci_msi.o
obj-$(CONFIG_SMP) += smp.o trampoline.o hvtramp.o obj-$(CONFIG_SMP) += smp.o trampoline.o hvtramp.o
obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o
obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o
obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o
obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o
......
/*
* binfmt_elf32.c: Support 32-bit Sparc ELF binaries on Ultra.
*
* Copyright (C) 1995, 1996, 1997, 1998, 2008 David S. Miller (davem@davemloft.net)
* Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz)
*/
#define ELF_ARCH EM_SPARC
#define ELF_CLASS ELFCLASS32
#define ELF_DATA ELFDATA2MSB;
/* Format is:
* G0 --> G7
* O0 --> O7
* L0 --> L7
* I0 --> I7
* PSR, PC, nPC, Y, WIM, TBR
*/
typedef unsigned int elf_greg_t;
#define ELF_NGREG 38
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
typedef struct {
union {
unsigned int pr_regs[32];
unsigned long pr_dregs[16];
} pr_fr;
unsigned int __unused;
unsigned int pr_fsr;
unsigned char pr_qcnt;
unsigned char pr_q_entrysize;
unsigned char pr_en;
unsigned int pr_q[64];
} elf_fpregset_t;
/* UltraSparc extensions. Still unused, but will be eventually. */
typedef struct {
unsigned int pr_type;
unsigned int pr_align;
union {
struct {
union {
unsigned int pr_regs[32];
unsigned long pr_dregs[16];
long double pr_qregs[8];
} pr_xfr;
} pr_v8p;
unsigned int pr_xfsr;
unsigned int pr_fprs;
unsigned int pr_xg[8];
unsigned int pr_xo[8];
unsigned long pr_tstate;
unsigned int pr_filler[8];
} pr_un;
} elf_xregset_t;
#define elf_check_arch(x) (((x)->e_machine == EM_SPARC) || ((x)->e_machine == EM_SPARC32PLUS))
#define ELF_ET_DYN_BASE 0x70000000
#include <asm/processor.h>
#include <linux/module.h>
#include <linux/elfcore.h>
#include <linux/compat.h>
#define elf_prstatus elf_prstatus32
struct elf_prstatus32
{
struct elf_siginfo pr_info; /* Info associated with signal */
short pr_cursig; /* Current signal */
unsigned int pr_sigpend; /* Set of pending signals */
unsigned int pr_sighold; /* Set of held signals */
pid_t pr_pid;
pid_t pr_ppid;
pid_t pr_pgrp;
pid_t pr_sid;
struct compat_timeval pr_utime; /* User time */
struct compat_timeval pr_stime; /* System time */
struct compat_timeval pr_cutime; /* Cumulative user time */
struct compat_timeval pr_cstime; /* Cumulative system time */
elf_gregset_t pr_reg; /* GP registers */
int pr_fpvalid; /* True if math co-processor being used. */
};
#define elf_prpsinfo elf_prpsinfo32
struct elf_prpsinfo32
{
char pr_state; /* numeric process state */
char pr_sname; /* char for pr_state */
char pr_zomb; /* zombie */
char pr_nice; /* nice val */
unsigned int pr_flag; /* flags */
u16 pr_uid;
u16 pr_gid;
pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
/* Lots missing */
char pr_fname[16]; /* filename of executable */
char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
};
#include <linux/highuid.h>
#undef NEW_TO_OLD_UID
#undef NEW_TO_OLD_GID
#define NEW_TO_OLD_UID(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)
#define NEW_TO_OLD_GID(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)
#include <linux/time.h>
#undef cputime_to_timeval
#define cputime_to_timeval cputime_to_compat_timeval
static inline void
cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
{
unsigned long jiffies = cputime_to_jiffies(cputime);
value->tv_usec = (jiffies % HZ) * (1000000L / HZ);
value->tv_sec = jiffies / HZ;
}
#undef start_thread
#define start_thread start_thread32
#define init_elf_binfmt init_elf32_binfmt
MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit SparcLinux binaries on the Ultra");
MODULE_AUTHOR("Eric Youngdale, David S. Miller, Jakub Jelinek");
#undef MODULE_DESCRIPTION
#undef MODULE_AUTHOR
#undef TASK_SIZE
#define TASK_SIZE STACK_TOP32
#include "../../../fs/binfmt_elf.c"
...@@ -684,72 +684,39 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) ...@@ -684,72 +684,39 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
return &user_sparc64_view; return &user_sparc64_view;
} }
long arch_ptrace(struct task_struct *child, long request, long addr, long data) struct compat_fps {
unsigned int regs[32];
unsigned int fsr;
unsigned int flags;
unsigned int extra;
unsigned int fpqd;
struct compat_fq {
unsigned int insnaddr;
unsigned int insn;
} fpq[16];
};
long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
compat_ulong_t caddr, compat_ulong_t cdata)
{ {
long addr2 = task_pt_regs(current)->u_regs[UREG_I4]; const struct user_regset_view *view = task_user_regset_view(child);
const struct user_regset_view *view; compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4];
struct pt_regs32 __user *pregs;
struct compat_fps __user *fps;
unsigned long addr2 = caddr2;
unsigned long addr = caddr;
unsigned long data = cdata;
int ret; int ret;
if (test_thread_flag(TIF_32BIT)) pregs = (struct pt_regs32 __user *) addr;
addr2 &= 0xffffffffUL; fps = (struct compat_fps __user *) addr;
view = task_user_regset_view(child); switch (request) {
switch(request) {
case PTRACE_PEEKUSR: case PTRACE_PEEKUSR:
ret = (addr != 0) ? -EIO : 0; ret = (addr != 0) ? -EIO : 0;
break; break;
case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_GETREGS:
case PTRACE_PEEKDATA: {
unsigned long tmp64;
unsigned int tmp32;
int copied;
ret = -EIO;
if (test_thread_flag(TIF_32BIT)) {
copied = access_process_vm(child, addr,
&tmp32, sizeof(tmp32), 0);
if (copied == sizeof(tmp32))
ret = put_user(tmp32,
(unsigned int __user *) data);
} else {
copied = access_process_vm(child, addr,
&tmp64, sizeof(tmp64), 0);
if (copied == sizeof(tmp64))
ret = put_user(tmp64,
(unsigned long __user *) data);
}
break;
}
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA: {
unsigned long tmp64;
unsigned int tmp32;
int copied;
ret = -EIO;
if (test_thread_flag(TIF_32BIT)) {
tmp32 = data;
copied = access_process_vm(child, addr,
&tmp32, sizeof(tmp32), 1);
if (copied == sizeof(tmp32))
ret = 0;
} else {
tmp64 = data;
copied = access_process_vm(child, addr,
&tmp64, sizeof(tmp64), 1);
if (copied == sizeof(tmp64))
ret = 0;
}
break;
}
case PTRACE_GETREGS: {
struct pt_regs32 __user *pregs =
(struct pt_regs32 __user *) addr;
ret = copy_regset_to_user(child, view, REGSET_GENERAL, ret = copy_regset_to_user(child, view, REGSET_GENERAL,
32 * sizeof(u32), 32 * sizeof(u32),
4 * sizeof(u32), 4 * sizeof(u32),
...@@ -760,29 +727,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -760,29 +727,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
15 * sizeof(u32), 15 * sizeof(u32),
&pregs->u_regs[0]); &pregs->u_regs[0]);
break; break;
}
case PTRACE_GETREGS64: {
struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
ret = copy_regset_to_user(child, view, REGSET_GENERAL,
1 * sizeof(u64),
15 * sizeof(u64),
&pregs->u_regs[0]);
if (!ret) {
/* XXX doesn't handle 'y' register correctly XXX */
ret = copy_regset_to_user(child, view, REGSET_GENERAL,
32 * sizeof(u64),
4 * sizeof(u64),
&pregs->tstate);
}
break;
}
case PTRACE_SETREGS: {
struct pt_regs32 __user *pregs =
(struct pt_regs32 __user *) addr;
case PTRACE_SETREGS:
ret = copy_regset_from_user(child, view, REGSET_GENERAL, ret = copy_regset_from_user(child, view, REGSET_GENERAL,
32 * sizeof(u32), 32 * sizeof(u32),
4 * sizeof(u32), 4 * sizeof(u32),
...@@ -793,39 +739,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -793,39 +739,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
15 * sizeof(u32), 15 * sizeof(u32),
&pregs->u_regs[0]); &pregs->u_regs[0]);
break; break;
}
case PTRACE_SETREGS64: {
struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
ret = copy_regset_from_user(child, view, REGSET_GENERAL,
1 * sizeof(u64),
15 * sizeof(u64),
&pregs->u_regs[0]);
if (!ret) {
/* XXX doesn't handle 'y' register correctly XXX */
ret = copy_regset_from_user(child, view, REGSET_GENERAL,
32 * sizeof(u64),
4 * sizeof(u64),
&pregs->tstate);
}
break;
}
case PTRACE_GETFPREGS: {
struct fps {
unsigned int regs[32];
unsigned int fsr;
unsigned int flags;
unsigned int extra;
unsigned int fpqd;
struct fq {
unsigned int insnaddr;
unsigned int insn;
} fpq[16];
};
struct fps __user *fps = (struct fps __user *) addr;
case PTRACE_GETFPREGS:
ret = copy_regset_to_user(child, view, REGSET_FP, ret = copy_regset_to_user(child, view, REGSET_FP,
0 * sizeof(u32), 0 * sizeof(u32),
32 * sizeof(u32), 32 * sizeof(u32),
...@@ -843,36 +758,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -843,36 +758,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = -EFAULT; ret = -EFAULT;
} }
break; break;
}
case PTRACE_GETFPREGS64: {
struct fps {
unsigned int regs[64];
unsigned long fsr;
};
struct fps __user *fps = (struct fps __user *) addr;
ret = copy_regset_to_user(child, view, REGSET_FP,
0 * sizeof(u64),
33 * sizeof(u64),
fps);
break;
}
case PTRACE_SETFPREGS: {
struct fps {
unsigned int regs[32];
unsigned int fsr;
unsigned int flags;
unsigned int extra;
unsigned int fpqd;
struct fq {
unsigned int insnaddr;
unsigned int insn;
} fpq[16];
};
struct fps __user *fps = (struct fps __user *) addr;
case PTRACE_SETFPREGS:
ret = copy_regset_from_user(child, view, REGSET_FP, ret = copy_regset_from_user(child, view, REGSET_FP,
0 * sizeof(u32), 0 * sizeof(u32),
32 * sizeof(u32), 32 * sizeof(u32),
...@@ -883,21 +770,94 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -883,21 +770,94 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
1 * sizeof(u32), 1 * sizeof(u32),
&fps->fsr); &fps->fsr);
break; break;
case PTRACE_READTEXT:
case PTRACE_READDATA:
ret = ptrace_readdata(child, addr,
(char __user *)addr2, data);
if (ret == data)
ret = 0;
else if (ret >= 0)
ret = -EIO;
break;
case PTRACE_WRITETEXT:
case PTRACE_WRITEDATA:
ret = ptrace_writedata(child, (char __user *) addr2,
addr, data);
if (ret == data)
ret = 0;
else if (ret >= 0)
ret = -EIO;
break;
default:
ret = compat_ptrace_request(child, request, addr, data);
break;
} }
case PTRACE_SETFPREGS64: { return ret;
struct fps { }
unsigned int regs[64];
unsigned long fsr; struct fps {
}; unsigned int regs[64];
struct fps __user *fps = (struct fps __user *) addr; unsigned long fsr;
};
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
const struct user_regset_view *view = task_user_regset_view(child);
struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
struct fps __user *fps = (struct fps __user *) addr;
int ret;
switch (request) {
case PTRACE_PEEKUSR:
ret = (addr != 0) ? -EIO : 0;
break;
case PTRACE_GETREGS64:
ret = copy_regset_to_user(child, view, REGSET_GENERAL,
1 * sizeof(u64),
15 * sizeof(u64),
&pregs->u_regs[0]);
if (!ret) {
/* XXX doesn't handle 'y' register correctly XXX */
ret = copy_regset_to_user(child, view, REGSET_GENERAL,
32 * sizeof(u64),
4 * sizeof(u64),
&pregs->tstate);
}
break;
case PTRACE_SETREGS64:
ret = copy_regset_from_user(child, view, REGSET_GENERAL,
1 * sizeof(u64),
15 * sizeof(u64),
&pregs->u_regs[0]);
if (!ret) {
/* XXX doesn't handle 'y' register correctly XXX */
ret = copy_regset_from_user(child, view, REGSET_GENERAL,
32 * sizeof(u64),
4 * sizeof(u64),
&pregs->tstate);
}
break;
case PTRACE_GETFPREGS64:
ret = copy_regset_to_user(child, view, REGSET_FP,
0 * sizeof(u64),
33 * sizeof(u64),
fps);
break;
case PTRACE_SETFPREGS64:
ret = copy_regset_to_user(child, view, REGSET_FP, ret = copy_regset_to_user(child, view, REGSET_FP,
0 * sizeof(u64), 0 * sizeof(u64),
33 * sizeof(u64), 33 * sizeof(u64),
fps); fps);
break; break;
}
case PTRACE_READTEXT: case PTRACE_READTEXT:
case PTRACE_READDATA: case PTRACE_READDATA:
...@@ -919,16 +879,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -919,16 +879,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = -EIO; ret = -EIO;
break; break;
case PTRACE_GETEVENTMSG: {
if (test_thread_flag(TIF_32BIT))
ret = put_user(child->ptrace_message,
(unsigned int __user *) data);
else
ret = put_user(child->ptrace_message,
(unsigned long __user *) data);
break;
}
default: default:
ret = ptrace_request(child, request, addr, data); ret = ptrace_request(child, request, addr, data);
break; break;
......
...@@ -23,7 +23,7 @@ sys_call_table32: ...@@ -23,7 +23,7 @@ sys_call_table32:
/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys32_chown16, sys32_mknod /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys32_chown16, sys32_mknod
/*15*/ .word sys_chmod, sys32_lchown16, sparc_brk, sys32_perfctr, sys32_lseek /*15*/ .word sys_chmod, sys32_lchown16, sparc_brk, sys32_perfctr, sys32_lseek
/*20*/ .word sys_getpid, sys_capget, sys_capset, sys32_setuid16, sys32_getuid16 /*20*/ .word sys_getpid, sys_capget, sys_capset, sys32_setuid16, sys32_getuid16
/*25*/ .word sys32_vmsplice, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause /*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause
/*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice /*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice
.word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile .word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile
/*40*/ .word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid /*40*/ .word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid
......
...@@ -75,7 +75,6 @@ ...@@ -75,7 +75,6 @@
/* /*
* These are used to set parameters in the core dumps. * These are used to set parameters in the core dumps.
*/ */
#ifndef ELF_ARCH
#define ELF_ARCH EM_SPARCV9 #define ELF_ARCH EM_SPARCV9
#define ELF_CLASS ELFCLASS64 #define ELF_CLASS ELFCLASS64
#define ELF_DATA ELFDATA2MSB #define ELF_DATA ELFDATA2MSB
...@@ -100,14 +99,59 @@ typedef struct { ...@@ -100,14 +99,59 @@ typedef struct {
unsigned long pr_gsr; unsigned long pr_gsr;
unsigned long pr_fprs; unsigned long pr_fprs;
} elf_fpregset_t; } elf_fpregset_t;
#endif
/* Format of 32-bit elf_gregset_t is:
* G0 --> G7
* O0 --> O7
* L0 --> L7
* I0 --> I7
* PSR, PC, nPC, Y, WIM, TBR
*/
typedef unsigned int compat_elf_greg_t;
#define COMPAT_ELF_NGREG 38
typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG];
typedef struct {
union {
unsigned int pr_regs[32];
unsigned long pr_dregs[16];
} pr_fr;
unsigned int __unused;
unsigned int pr_fsr;
unsigned char pr_qcnt;
unsigned char pr_q_entrysize;
unsigned char pr_en;
unsigned int pr_q[64];
} compat_elf_fpregset_t;
/* UltraSparc extensions. Still unused, but will be eventually. */
typedef struct {
unsigned int pr_type;
unsigned int pr_align;
union {
struct {
union {
unsigned int pr_regs[32];
unsigned long pr_dregs[16];
long double pr_qregs[8];
} pr_xfr;
} pr_v8p;
unsigned int pr_xfsr;
unsigned int pr_fprs;
unsigned int pr_xg[8];
unsigned int pr_xo[8];
unsigned long pr_tstate;
unsigned int pr_filler[8];
} pr_un;
} elf_xregset_t;
/* /*
* This is used to ensure we don't load something for the wrong architecture. * This is used to ensure we don't load something for the wrong architecture.
*/ */
#ifndef elf_check_arch #define elf_check_arch(x) ((x)->e_machine == ELF_ARCH)
#define elf_check_arch(x) ((x)->e_machine == ELF_ARCH) /* Might be EM_SPARCV9 or EM_SPARC */ #define compat_elf_check_arch(x) ((x)->e_machine == EM_SPARC || \
#endif (x)->e_machine == EM_SPARC32PLUS)
#define compat_start_thread start_thread32
#define USE_ELF_CORE_DUMP #define USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE PAGE_SIZE #define ELF_EXEC_PAGESIZE PAGE_SIZE
...@@ -117,9 +161,8 @@ typedef struct { ...@@ -117,9 +161,8 @@ typedef struct {
the loader. We need to make sure that it is out of the way of the program the loader. We need to make sure that it is out of the way of the program
that it will "exec", and that there is sufficient room for the brk. */ that it will "exec", and that there is sufficient room for the brk. */
#ifndef ELF_ET_DYN_BASE #define ELF_ET_DYN_BASE 0x0000010000000000UL
#define ELF_ET_DYN_BASE 0x0000010000000000UL #define COMPAT_ELF_ET_DYN_BASE 0x0000000070000000UL
#endif
/* This yields a mask that user programs can use to figure out what /* This yields a mask that user programs can use to figure out what
......
...@@ -95,6 +95,8 @@ struct sparc_trapf { ...@@ -95,6 +95,8 @@ struct sparc_trapf {
#ifdef __KERNEL__ #ifdef __KERNEL__
#define __ARCH_WANT_COMPAT_SYS_PTRACE
#define force_successful_syscall_return() \ #define force_successful_syscall_return() \
do { current_thread_info()->syscall_noerror = 1; \ do { current_thread_info()->syscall_noerror = 1; \
} while (0) } while (0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment