diff options
| -rw-r--r-- | arch/sparc64/Kconfig | 8 | ||||
| -rw-r--r-- | arch/sparc64/kernel/Makefile | 1 | ||||
| -rw-r--r-- | arch/sparc64/kernel/binfmt_elf32.c | 134 | ||||
| -rw-r--r-- | arch/sparc64/kernel/ptrace.c | 266 | ||||
| -rw-r--r-- | arch/sparc64/kernel/systbls.S | 2 | ||||
| -rw-r--r-- | include/asm-sparc64/elf.h | 59 | ||||
| -rw-r--r-- | include/asm-sparc64/ptrace.h | 2 |
7 files changed, 163 insertions, 309 deletions
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 5023b815e522..b810f2b7526a 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig | |||
| @@ -383,13 +383,7 @@ config COMPAT | |||
| 383 | bool | 383 | bool |
| 384 | depends on SPARC32_COMPAT | 384 | depends on SPARC32_COMPAT |
| 385 | default y | 385 | default y |
| 386 | 386 | select COMPAT_BINFMT_ELF | |
| 387 | config BINFMT_ELF32 | ||
| 388 | bool "Kernel support for 32-bit ELF binaries" | ||
| 389 | depends on SPARC32_COMPAT | ||
| 390 | help | ||
| 391 | This allows you to run 32-bit Linux/ELF binaries on your Ultra. | ||
| 392 | Everybody wants this; say Y. | ||
| 393 | 387 | ||
| 394 | config BINFMT_AOUT32 | 388 | config BINFMT_AOUT32 |
| 395 | bool "Kernel support for 32-bit (ie. SunOS) a.out binaries" | 389 | bool "Kernel support for 32-bit (ie. SunOS) a.out binaries" |
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 4b78b24ef413..1bf5b187de49 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile | |||
| @@ -21,7 +21,6 @@ obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o \ | |||
| 21 | obj-$(CONFIG_PCI_MSI) += pci_msi.o | 21 | obj-$(CONFIG_PCI_MSI) += pci_msi.o |
| 22 | obj-$(CONFIG_SMP) += smp.o trampoline.o hvtramp.o | 22 | obj-$(CONFIG_SMP) += smp.o trampoline.o hvtramp.o |
| 23 | obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o | 23 | obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o |
| 24 | obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o | ||
| 25 | obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o | 24 | obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o |
| 26 | obj-$(CONFIG_MODULES) += module.o | 25 | obj-$(CONFIG_MODULES) += module.o |
| 27 | obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o | 26 | obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o |
diff --git a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c deleted file mode 100644 index a0718dc950f4..000000000000 --- a/arch/sparc64/kernel/binfmt_elf32.c +++ /dev/null | |||
| @@ -1,134 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * binfmt_elf32.c: Support 32-bit Sparc ELF binaries on Ultra. | ||
| 3 | * | ||
| 4 | * Copyright (C) 1995, 1996, 1997, 1998, 2008 David S. Miller (davem@davemloft.net) | ||
| 5 | * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz) | ||
| 6 | */ | ||
| 7 | |||
| 8 | #define ELF_ARCH EM_SPARC | ||
| 9 | #define ELF_CLASS ELFCLASS32 | ||
| 10 | #define ELF_DATA ELFDATA2MSB; | ||
| 11 | |||
| 12 | /* Format is: | ||
| 13 | * G0 --> G7 | ||
| 14 | * O0 --> O7 | ||
| 15 | * L0 --> L7 | ||
| 16 | * I0 --> I7 | ||
| 17 | * PSR, PC, nPC, Y, WIM, TBR | ||
| 18 | */ | ||
| 19 | typedef unsigned int elf_greg_t; | ||
| 20 | #define ELF_NGREG 38 | ||
| 21 | typedef elf_greg_t elf_gregset_t[ELF_NGREG]; | ||
| 22 | |||
| 23 | typedef struct { | ||
| 24 | union { | ||
| 25 | unsigned int pr_regs[32]; | ||
| 26 | unsigned long pr_dregs[16]; | ||
| 27 | } pr_fr; | ||
| 28 | unsigned int __unused; | ||
| 29 | unsigned int pr_fsr; | ||
| 30 | unsigned char pr_qcnt; | ||
| 31 | unsigned char pr_q_entrysize; | ||
| 32 | unsigned char pr_en; | ||
| 33 | unsigned int pr_q[64]; | ||
| 34 | } elf_fpregset_t; | ||
| 35 | |||
| 36 | /* UltraSparc extensions. Still unused, but will be eventually. */ | ||
| 37 | typedef struct { | ||
| 38 | unsigned int pr_type; | ||
| 39 | unsigned int pr_align; | ||
| 40 | union { | ||
| 41 | struct { | ||
| 42 | union { | ||
| 43 | unsigned int pr_regs[32]; | ||
| 44 | unsigned long pr_dregs[16]; | ||
| 45 | long double pr_qregs[8]; | ||
| 46 | } pr_xfr; | ||
| 47 | } pr_v8p; | ||
| 48 | unsigned int pr_xfsr; | ||
| 49 | unsigned int pr_fprs; | ||
| 50 | unsigned int pr_xg[8]; | ||
| 51 | unsigned int pr_xo[8]; | ||
| 52 | unsigned long pr_tstate; | ||
| 53 | unsigned int pr_filler[8]; | ||
| 54 | } pr_un; | ||
| 55 | } elf_xregset_t; | ||
| 56 | |||
| 57 | #define elf_check_arch(x) (((x)->e_machine == EM_SPARC) || ((x)->e_machine == EM_SPARC32PLUS)) | ||
| 58 | |||
| 59 | #define ELF_ET_DYN_BASE 0x70000000 | ||
| 60 | |||
| 61 | |||
| 62 | #include <asm/processor.h> | ||
| 63 | #include <linux/module.h> | ||
| 64 | #include <linux/elfcore.h> | ||
| 65 | #include <linux/compat.h> | ||
| 66 | |||
| 67 | #define elf_prstatus elf_prstatus32 | ||
| 68 | struct elf_prstatus32 | ||
| 69 | { | ||
| 70 | struct elf_siginfo pr_info; /* Info associated with signal */ | ||
| 71 | short pr_cursig; /* Current signal */ | ||
| 72 | unsigned int pr_sigpend; /* Set of pending signals */ | ||
| 73 | unsigned int pr_sighold; /* Set of held signals */ | ||
| 74 | pid_t pr_pid; | ||
| 75 | pid_t pr_ppid; | ||
| 76 | pid_t pr_pgrp; | ||
| 77 | pid_t pr_sid; | ||
| 78 | struct compat_timeval pr_utime; /* User time */ | ||
| 79 | struct compat_timeval pr_stime; /* System time */ | ||
| 80 | struct compat_timeval pr_cutime; /* Cumulative user time */ | ||
| 81 | struct compat_timeval pr_cstime; /* Cumulative system time */ | ||
| 82 | elf_gregset_t pr_reg; /* GP registers */ | ||
| 83 | int pr_fpvalid; /* True if math co-processor being used. */ | ||
| 84 | }; | ||
| 85 | |||
| 86 | #define elf_prpsinfo elf_prpsinfo32 | ||
| 87 | struct elf_prpsinfo32 | ||
| 88 | { | ||
| 89 | char pr_state; /* numeric process state */ | ||
| 90 | char pr_sname; /* char for pr_state */ | ||
| 91 | char pr_zomb; /* zombie */ | ||
| 92 | char pr_nice; /* nice val */ | ||
| 93 | unsigned int pr_flag; /* flags */ | ||
| 94 | u16 pr_uid; | ||
| 95 | u16 pr_gid; | ||
| 96 | pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; | ||
| 97 | /* Lots missing */ | ||
| 98 | char pr_fname[16]; /* filename of executable */ | ||
| 99 | char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ | ||
| 100 | }; | ||
| 101 | |||
| 102 | #include <linux/highuid.h> | ||
| 103 | |||
| 104 | #undef NEW_TO_OLD_UID | ||
| 105 | #undef NEW_TO_OLD_GID | ||
| 106 | #define NEW_TO_OLD_UID(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid) | ||
| 107 | #define NEW_TO_OLD_GID(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid) | ||
| 108 | |||
| 109 | #include <linux/time.h> | ||
| 110 | |||
| 111 | #undef cputime_to_timeval | ||
| 112 | #define cputime_to_timeval cputime_to_compat_timeval | ||
| 113 | static inline void | ||
| 114 | cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value) | ||
| 115 | { | ||
| 116 | unsigned long jiffies = cputime_to_jiffies(cputime); | ||
| 117 | value->tv_usec = (jiffies % HZ) * (1000000L / HZ); | ||
| 118 | value->tv_sec = jiffies / HZ; | ||
| 119 | } | ||
| 120 | |||
| 121 | #undef start_thread | ||
| 122 | #define start_thread start_thread32 | ||
| 123 | #define init_elf_binfmt init_elf32_binfmt | ||
| 124 | |||
| 125 | MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit SparcLinux binaries on the Ultra"); | ||
| 126 | MODULE_AUTHOR("Eric Youngdale, David S. Miller, Jakub Jelinek"); | ||
| 127 | |||
| 128 | #undef MODULE_DESCRIPTION | ||
| 129 | #undef MODULE_AUTHOR | ||
| 130 | |||
| 131 | #undef TASK_SIZE | ||
| 132 | #define TASK_SIZE STACK_TOP32 | ||
| 133 | |||
| 134 | #include "../../../fs/binfmt_elf.c" | ||
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index 51f012410f9d..9a1ba1fe859d 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c | |||
| @@ -684,72 +684,39 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) | |||
| 684 | return &user_sparc64_view; | 684 | return &user_sparc64_view; |
| 685 | } | 685 | } |
| 686 | 686 | ||
| 687 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 687 | struct compat_fps { |
| 688 | unsigned int regs[32]; | ||
| 689 | unsigned int fsr; | ||
| 690 | unsigned int flags; | ||
| 691 | unsigned int extra; | ||
| 692 | unsigned int fpqd; | ||
| 693 | struct compat_fq { | ||
| 694 | unsigned int insnaddr; | ||
| 695 | unsigned int insn; | ||
| 696 | } fpq[16]; | ||
| 697 | }; | ||
| 698 | |||
| 699 | long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | ||
| 700 | compat_ulong_t caddr, compat_ulong_t cdata) | ||
| 688 | { | 701 | { |
| 689 | long addr2 = task_pt_regs(current)->u_regs[UREG_I4]; | 702 | const struct user_regset_view *view = task_user_regset_view(child); |
| 690 | const struct user_regset_view *view; | 703 | compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4]; |
| 704 | struct pt_regs32 __user *pregs; | ||
| 705 | struct compat_fps __user *fps; | ||
| 706 | unsigned long addr2 = caddr2; | ||
| 707 | unsigned long addr = caddr; | ||
| 708 | unsigned long data = cdata; | ||
| 691 | int ret; | 709 | int ret; |
| 692 | 710 | ||
| 693 | if (test_thread_flag(TIF_32BIT)) | 711 | pregs = (struct pt_regs32 __user *) addr; |
| 694 | addr2 &= 0xffffffffUL; | 712 | fps = (struct compat_fps __user *) addr; |
| 695 | 713 | ||
| 696 | view = task_user_regset_view(child); | 714 | switch (request) { |
| 697 | |||
| 698 | switch(request) { | ||
| 699 | case PTRACE_PEEKUSR: | 715 | case PTRACE_PEEKUSR: |
| 700 | ret = (addr != 0) ? -EIO : 0; | 716 | ret = (addr != 0) ? -EIO : 0; |
| 701 | break; | 717 | break; |
| 702 | 718 | ||
| 703 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 719 | case PTRACE_GETREGS: |
| 704 | case PTRACE_PEEKDATA: { | ||
| 705 | unsigned long tmp64; | ||
| 706 | unsigned int tmp32; | ||
| 707 | int copied; | ||
| 708 | |||
| 709 | ret = -EIO; | ||
| 710 | if (test_thread_flag(TIF_32BIT)) { | ||
| 711 | copied = access_process_vm(child, addr, | ||
| 712 | &tmp32, sizeof(tmp32), 0); | ||
| 713 | if (copied == sizeof(tmp32)) | ||
| 714 | ret = put_user(tmp32, | ||
| 715 | (unsigned int __user *) data); | ||
| 716 | } else { | ||
| 717 | copied = access_process_vm(child, addr, | ||
| 718 | &tmp64, sizeof(tmp64), 0); | ||
| 719 | if (copied == sizeof(tmp64)) | ||
| 720 | ret = put_user(tmp64, | ||
| 721 | (unsigned long __user *) data); | ||
| 722 | } | ||
| 723 | break; | ||
| 724 | } | ||
| 725 | |||
| 726 | case PTRACE_POKETEXT: /* write the word at location addr. */ | ||
| 727 | case PTRACE_POKEDATA: { | ||
| 728 | unsigned long tmp64; | ||
| 729 | unsigned int tmp32; | ||
| 730 | int copied; | ||
| 731 | |||
| 732 | ret = -EIO; | ||
| 733 | if (test_thread_flag(TIF_32BIT)) { | ||
| 734 | tmp32 = data; | ||
| 735 | copied = access_process_vm(child, addr, | ||
| 736 | &tmp32, sizeof(tmp32), 1); | ||
| 737 | if (copied == sizeof(tmp32)) | ||
| 738 | ret = 0; | ||
| 739 | } else { | ||
| 740 | tmp64 = data; | ||
| 741 | copied = access_process_vm(child, addr, | ||
| 742 | &tmp64, sizeof(tmp64), 1); | ||
| 743 | if (copied == sizeof(tmp64)) | ||
| 744 | ret = 0; | ||
| 745 | } | ||
| 746 | break; | ||
| 747 | } | ||
| 748 | |||
| 749 | case PTRACE_GETREGS: { | ||
| 750 | struct pt_regs32 __user *pregs = | ||
| 751 | (struct pt_regs32 __user *) addr; | ||
| 752 | |||
| 753 | ret = copy_regset_to_user(child, view, REGSET_GENERAL, | 720 | ret = copy_regset_to_user(child, view, REGSET_GENERAL, |
| 754 | 32 * sizeof(u32), | 721 | 32 * sizeof(u32), |
| 755 | 4 * sizeof(u32), | 722 | 4 * sizeof(u32), |
| @@ -760,29 +727,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 760 | 15 * sizeof(u32), | 727 | 15 * sizeof(u32), |
| 761 | &pregs->u_regs[0]); | 728 | &pregs->u_regs[0]); |
| 762 | break; | 729 | break; |
| 763 | } | ||
| 764 | |||
| 765 | case PTRACE_GETREGS64: { | ||
| 766 | struct pt_regs __user *pregs = (struct pt_regs __user *) addr; | ||
| 767 | |||
| 768 | ret = copy_regset_to_user(child, view, REGSET_GENERAL, | ||
| 769 | 1 * sizeof(u64), | ||
| 770 | 15 * sizeof(u64), | ||
| 771 | &pregs->u_regs[0]); | ||
| 772 | if (!ret) { | ||
| 773 | /* XXX doesn't handle 'y' register correctly XXX */ | ||
| 774 | ret = copy_regset_to_user(child, view, REGSET_GENERAL, | ||
| 775 | 32 * sizeof(u64), | ||
| 776 | 4 * sizeof(u64), | ||
| 777 | &pregs->tstate); | ||
| 778 | } | ||
| 779 | break; | ||
| 780 | } | ||
| 781 | |||
| 782 | case PTRACE_SETREGS: { | ||
| 783 | struct pt_regs32 __user *pregs = | ||
| 784 | (struct pt_regs32 __user *) addr; | ||
| 785 | 730 | ||
| 731 | case PTRACE_SETREGS: | ||
| 786 | ret = copy_regset_from_user(child, view, REGSET_GENERAL, | 732 | ret = copy_regset_from_user(child, view, REGSET_GENERAL, |
| 787 | 32 * sizeof(u32), | 733 | 32 * sizeof(u32), |
| 788 | 4 * sizeof(u32), | 734 | 4 * sizeof(u32), |
| @@ -793,39 +739,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 793 | 15 * sizeof(u32), | 739 | 15 * sizeof(u32), |
| 794 | &pregs->u_regs[0]); | 740 | &pregs->u_regs[0]); |
| 795 | break; | 741 | break; |
| 796 | } | ||
| 797 | |||
| 798 | case PTRACE_SETREGS64: { | ||
| 799 | struct pt_regs __user *pregs = (struct pt_regs __user *) addr; | ||
| 800 | |||
| 801 | ret = copy_regset_from_user(child, view, REGSET_GENERAL, | ||
| 802 | 1 * sizeof(u64), | ||
| 803 | 15 * sizeof(u64), | ||
| 804 | &pregs->u_regs[0]); | ||
| 805 | if (!ret) { | ||
| 806 | /* XXX doesn't handle 'y' register correctly XXX */ | ||
| 807 | ret = copy_regset_from_user(child, view, REGSET_GENERAL, | ||
| 808 | 32 * sizeof(u64), | ||
| 809 | 4 * sizeof(u64), | ||
| 810 | &pregs->tstate); | ||
| 811 | } | ||
| 812 | break; | ||
| 813 | } | ||
| 814 | |||
| 815 | case PTRACE_GETFPREGS: { | ||
| 816 | struct fps { | ||
| 817 | unsigned int regs[32]; | ||
| 818 | unsigned int fsr; | ||
| 819 | unsigned int flags; | ||
| 820 | unsigned int extra; | ||
| 821 | unsigned int fpqd; | ||
| 822 | struct fq { | ||
| 823 | unsigned int insnaddr; | ||
| 824 | unsigned int insn; | ||
| 825 | } fpq[16]; | ||
| 826 | }; | ||
| 827 | struct fps __user *fps = (struct fps __user *) addr; | ||
| 828 | 742 | ||
| 743 | case PTRACE_GETFPREGS: | ||
| 829 | ret = copy_regset_to_user(child, view, REGSET_FP, | 744 | ret = copy_regset_to_user(child, view, REGSET_FP, |
| 830 | 0 * sizeof(u32), | 745 | 0 * sizeof(u32), |
| 831 | 32 * sizeof(u32), | 746 | 32 * sizeof(u32), |
| @@ -843,36 +758,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 843 | ret = -EFAULT; | 758 | ret = -EFAULT; |
| 844 | } | 759 | } |
| 845 | break; | 760 | break; |
| 846 | } | ||
| 847 | |||
| 848 | case PTRACE_GETFPREGS64: { | ||
| 849 | struct fps { | ||
| 850 | unsigned int regs[64]; | ||
| 851 | unsigned long fsr; | ||
| 852 | }; | ||
| 853 | struct fps __user *fps = (struct fps __user *) addr; | ||
| 854 | |||
| 855 | ret = copy_regset_to_user(child, view, REGSET_FP, | ||
| 856 | 0 * sizeof(u64), | ||
| 857 | 33 * sizeof(u64), | ||
| 858 | fps); | ||
| 859 | break; | ||
| 860 | } | ||
| 861 | |||
| 862 | case PTRACE_SETFPREGS: { | ||
| 863 | struct fps { | ||
| 864 | unsigned int regs[32]; | ||
| 865 | unsigned int fsr; | ||
| 866 | unsigned int flags; | ||
| 867 | unsigned int extra; | ||
| 868 | unsigned int fpqd; | ||
| 869 | struct fq { | ||
| 870 | unsigned int insnaddr; | ||
| 871 | unsigned int insn; | ||
| 872 | } fpq[16]; | ||
| 873 | }; | ||
| 874 | struct fps __user *fps = (struct fps __user *) addr; | ||
| 875 | 761 | ||
| 762 | case PTRACE_SETFPREGS: | ||
| 876 | ret = copy_regset_from_user(child, view, REGSET_FP, | 763 | ret = copy_regset_from_user(child, view, REGSET_FP, |
| 877 | 0 * sizeof(u32), | 764 | 0 * sizeof(u32), |
| 878 | 32 * sizeof(u32), | 765 | 32 * sizeof(u32), |
| @@ -883,21 +770,94 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 883 | 1 * sizeof(u32), | 770 | 1 * sizeof(u32), |
| 884 | &fps->fsr); | 771 | &fps->fsr); |
| 885 | break; | 772 | break; |
| 773 | |||
| 774 | case PTRACE_READTEXT: | ||
| 775 | case PTRACE_READDATA: | ||
| 776 | ret = ptrace_readdata(child, addr, | ||
| 777 | (char __user *)addr2, data); | ||
| 778 | if (ret == data) | ||
| 779 | ret = 0; | ||
| 780 | else if (ret >= 0) | ||
| 781 | ret = -EIO; | ||
| 782 | break; | ||
| 783 | |||
| 784 | case PTRACE_WRITETEXT: | ||
| 785 | case PTRACE_WRITEDATA: | ||
| 786 | ret = ptrace_writedata(child, (char __user *) addr2, | ||
| 787 | addr, data); | ||
| 788 | if (ret == data) | ||
| 789 | ret = 0; | ||
| 790 | else if (ret >= 0) | ||
| 791 | ret = -EIO; | ||
| 792 | break; | ||
| 793 | |||
| 794 | default: | ||
| 795 | ret = compat_ptrace_request(child, request, addr, data); | ||
| 796 | break; | ||
| 886 | } | 797 | } |
| 887 | 798 | ||
| 888 | case PTRACE_SETFPREGS64: { | 799 | return ret; |
| 889 | struct fps { | 800 | } |
| 890 | unsigned int regs[64]; | 801 | |
| 891 | unsigned long fsr; | 802 | struct fps { |
| 892 | }; | 803 | unsigned int regs[64]; |
| 893 | struct fps __user *fps = (struct fps __user *) addr; | 804 | unsigned long fsr; |
| 805 | }; | ||
| 806 | |||
| 807 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | ||
| 808 | { | ||
| 809 | const struct user_regset_view *view = task_user_regset_view(child); | ||
| 810 | struct pt_regs __user *pregs = (struct pt_regs __user *) addr; | ||
| 811 | unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4]; | ||
| 812 | struct fps __user *fps = (struct fps __user *) addr; | ||
| 813 | int ret; | ||
| 814 | |||
| 815 | switch (request) { | ||
| 816 | case PTRACE_PEEKUSR: | ||
| 817 | ret = (addr != 0) ? -EIO : 0; | ||
| 818 | break; | ||
| 894 | 819 | ||
| 820 | case PTRACE_GETREGS64: | ||
| 821 | ret = copy_regset_to_user(child, view, REGSET_GENERAL, | ||
| 822 | 1 * sizeof(u64), | ||
| 823 | 15 * sizeof(u64), | ||
| 824 | &pregs->u_regs[0]); | ||
| 825 | if (!ret) { | ||
| 826 | /* XXX doesn't handle 'y' register correctly XXX */ | ||
| 827 | ret = copy_regset_to_user(child, view, REGSET_GENERAL, | ||
| 828 | 32 * sizeof(u64), | ||
| 829 | 4 * sizeof(u64), | ||
| 830 | &pregs->tstate); | ||
| 831 | } | ||
| 832 | break; | ||
| 833 | |||
| 834 | case PTRACE_SETREGS64: | ||
| 835 | ret = copy_regset_from_user(child, view, REGSET_GENERAL, | ||
| 836 | 1 * sizeof(u64), | ||
| 837 | 15 * sizeof(u64), | ||
| 838 | &pregs->u_regs[0]); | ||
| 839 | if (!ret) { | ||
| 840 | /* XXX doesn't handle 'y' register correctly XXX */ | ||
| 841 | ret = copy_regset_from_user(child, view, REGSET_GENERAL, | ||
| 842 | 32 * sizeof(u64), | ||
| 843 | 4 * sizeof(u64), | ||
| 844 | &pregs->tstate); | ||
| 845 | } | ||
| 846 | break; | ||
| 847 | |||
| 848 | case PTRACE_GETFPREGS64: | ||
| 849 | ret = copy_regset_to_user(child, view, REGSET_FP, | ||
| 850 | 0 * sizeof(u64), | ||
| 851 | 33 * sizeof(u64), | ||
| 852 | fps); | ||
| 853 | break; | ||
| 854 | |||
| 855 | case PTRACE_SETFPREGS64: | ||
| 895 | ret = copy_regset_to_user(child, view, REGSET_FP, | 856 | ret = copy_regset_to_user(child, view, REGSET_FP, |
| 896 | 0 * sizeof(u64), | 857 | 0 * sizeof(u64), |
| 897 | 33 * sizeof(u64), | 858 | 33 * sizeof(u64), |
| 898 | fps); | 859 | fps); |
| 899 | break; | 860 | break; |
| 900 | } | ||
| 901 | 861 | ||
| 902 | case PTRACE_READTEXT: | 862 | case PTRACE_READTEXT: |
| 903 | case PTRACE_READDATA: | 863 | case PTRACE_READDATA: |
| @@ -919,16 +879,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 919 | ret = -EIO; | 879 | ret = -EIO; |
| 920 | break; | 880 | break; |
| 921 | 881 | ||
| 922 | case PTRACE_GETEVENTMSG: { | ||
| 923 | if (test_thread_flag(TIF_32BIT)) | ||
| 924 | ret = put_user(child->ptrace_message, | ||
| 925 | (unsigned int __user *) data); | ||
| 926 | else | ||
| 927 | ret = put_user(child->ptrace_message, | ||
| 928 | (unsigned long __user *) data); | ||
| 929 | break; | ||
| 930 | } | ||
| 931 | |||
| 932 | default: | 882 | default: |
| 933 | ret = ptrace_request(child, request, addr, data); | 883 | ret = ptrace_request(child, request, addr, data); |
| 934 | break; | 884 | break; |
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index adc62f490f36..6b9b718e24af 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S | |||
| @@ -23,7 +23,7 @@ sys_call_table32: | |||
| 23 | /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys32_chown16, sys32_mknod | 23 | /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys32_chown16, sys32_mknod |
| 24 | /*15*/ .word sys_chmod, sys32_lchown16, sparc_brk, sys32_perfctr, sys32_lseek | 24 | /*15*/ .word sys_chmod, sys32_lchown16, sparc_brk, sys32_perfctr, sys32_lseek |
| 25 | /*20*/ .word sys_getpid, sys_capget, sys_capset, sys32_setuid16, sys32_getuid16 | 25 | /*20*/ .word sys_getpid, sys_capget, sys_capset, sys32_setuid16, sys32_getuid16 |
| 26 | /*25*/ .word sys32_vmsplice, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause | 26 | /*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause |
| 27 | /*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice | 27 | /*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice |
| 28 | .word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile | 28 | .word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile |
| 29 | /*40*/ .word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid | 29 | /*40*/ .word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid |
diff --git a/include/asm-sparc64/elf.h b/include/asm-sparc64/elf.h index 272a65873f2e..11c8e68d712a 100644 --- a/include/asm-sparc64/elf.h +++ b/include/asm-sparc64/elf.h | |||
| @@ -75,7 +75,6 @@ | |||
| 75 | /* | 75 | /* |
| 76 | * These are used to set parameters in the core dumps. | 76 | * These are used to set parameters in the core dumps. |
| 77 | */ | 77 | */ |
| 78 | #ifndef ELF_ARCH | ||
| 79 | #define ELF_ARCH EM_SPARCV9 | 78 | #define ELF_ARCH EM_SPARCV9 |
| 80 | #define ELF_CLASS ELFCLASS64 | 79 | #define ELF_CLASS ELFCLASS64 |
| 81 | #define ELF_DATA ELFDATA2MSB | 80 | #define ELF_DATA ELFDATA2MSB |
| @@ -100,14 +99,59 @@ typedef struct { | |||
| 100 | unsigned long pr_gsr; | 99 | unsigned long pr_gsr; |
| 101 | unsigned long pr_fprs; | 100 | unsigned long pr_fprs; |
| 102 | } elf_fpregset_t; | 101 | } elf_fpregset_t; |
| 103 | #endif | 102 | |
| 103 | /* Format of 32-bit elf_gregset_t is: | ||
| 104 | * G0 --> G7 | ||
| 105 | * O0 --> O7 | ||
| 106 | * L0 --> L7 | ||
| 107 | * I0 --> I7 | ||
| 108 | * PSR, PC, nPC, Y, WIM, TBR | ||
| 109 | */ | ||
| 110 | typedef unsigned int compat_elf_greg_t; | ||
| 111 | #define COMPAT_ELF_NGREG 38 | ||
| 112 | typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG]; | ||
| 113 | |||
| 114 | typedef struct { | ||
| 115 | union { | ||
| 116 | unsigned int pr_regs[32]; | ||
| 117 | unsigned long pr_dregs[16]; | ||
| 118 | } pr_fr; | ||
| 119 | unsigned int __unused; | ||
| 120 | unsigned int pr_fsr; | ||
| 121 | unsigned char pr_qcnt; | ||
| 122 | unsigned char pr_q_entrysize; | ||
| 123 | unsigned char pr_en; | ||
| 124 | unsigned int pr_q[64]; | ||
| 125 | } compat_elf_fpregset_t; | ||
| 126 | |||
| 127 | /* UltraSparc extensions. Still unused, but will be eventually. */ | ||
| 128 | typedef struct { | ||
| 129 | unsigned int pr_type; | ||
| 130 | unsigned int pr_align; | ||
| 131 | union { | ||
| 132 | struct { | ||
| 133 | union { | ||
| 134 | unsigned int pr_regs[32]; | ||
| 135 | unsigned long pr_dregs[16]; | ||
| 136 | long double pr_qregs[8]; | ||
| 137 | } pr_xfr; | ||
| 138 | } pr_v8p; | ||
| 139 | unsigned int pr_xfsr; | ||
| 140 | unsigned int pr_fprs; | ||
| 141 | unsigned int pr_xg[8]; | ||
| 142 | unsigned int pr_xo[8]; | ||
| 143 | unsigned long pr_tstate; | ||
| 144 | unsigned int pr_filler[8]; | ||
| 145 | } pr_un; | ||
| 146 | } elf_xregset_t; | ||
| 104 | 147 | ||
| 105 | /* | 148 | /* |
| 106 | * This is used to ensure we don't load something for the wrong architecture. | 149 | * This is used to ensure we don't load something for the wrong architecture. |
| 107 | */ | 150 | */ |
| 108 | #ifndef elf_check_arch | 151 | #define elf_check_arch(x) ((x)->e_machine == ELF_ARCH) |
| 109 | #define elf_check_arch(x) ((x)->e_machine == ELF_ARCH) /* Might be EM_SPARCV9 or EM_SPARC */ | 152 | #define compat_elf_check_arch(x) ((x)->e_machine == EM_SPARC || \ |
| 110 | #endif | 153 | (x)->e_machine == EM_SPARC32PLUS) |
| 154 | #define compat_start_thread start_thread32 | ||
| 111 | 155 | ||
| 112 | #define USE_ELF_CORE_DUMP | 156 | #define USE_ELF_CORE_DUMP |
| 113 | #define ELF_EXEC_PAGESIZE PAGE_SIZE | 157 | #define ELF_EXEC_PAGESIZE PAGE_SIZE |
| @@ -117,9 +161,8 @@ typedef struct { | |||
| 117 | the loader. We need to make sure that it is out of the way of the program | 161 | the loader. We need to make sure that it is out of the way of the program |
| 118 | that it will "exec", and that there is sufficient room for the brk. */ | 162 | that it will "exec", and that there is sufficient room for the brk. */ |
| 119 | 163 | ||
| 120 | #ifndef ELF_ET_DYN_BASE | 164 | #define ELF_ET_DYN_BASE 0x0000010000000000UL |
| 121 | #define ELF_ET_DYN_BASE 0x0000010000000000UL | 165 | #define COMPAT_ELF_ET_DYN_BASE 0x0000000070000000UL |
| 122 | #endif | ||
| 123 | 166 | ||
| 124 | 167 | ||
| 125 | /* This yields a mask that user programs can use to figure out what | 168 | /* This yields a mask that user programs can use to figure out what |
diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h index 734a767f0a4e..8617c3a5143b 100644 --- a/include/asm-sparc64/ptrace.h +++ b/include/asm-sparc64/ptrace.h | |||
| @@ -95,6 +95,8 @@ struct sparc_trapf { | |||
| 95 | 95 | ||
| 96 | #ifdef __KERNEL__ | 96 | #ifdef __KERNEL__ |
| 97 | 97 | ||
| 98 | #define __ARCH_WANT_COMPAT_SYS_PTRACE | ||
| 99 | |||
| 98 | #define force_successful_syscall_return() \ | 100 | #define force_successful_syscall_return() \ |
| 99 | do { current_thread_info()->syscall_noerror = 1; \ | 101 | do { current_thread_info()->syscall_noerror = 1; \ |
| 100 | } while (0) | 102 | } while (0) |
