aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-12 21:47:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-12 21:47:41 -0400
commite225ca27057e70e7cbb14ae4c1e5f758973af645 (patch)
tree80a2de6cddda12d11b5379dca312e3fae507e225 /arch/sparc
parent54f7fc25e5736c39050454fe6b5a2bed027fbfab (diff)
parent55c2770e413e96871147b9406a9c41fe9bc5209c (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
Pull Sparc updates from David Miller: 1) Updated syscall tracing fix from Al Viro. 2) SUN4V error reporting was deficient in several areas. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc: sparc64: fix ptrace interaction with force_successful_syscall_return() sparc64: Fix deficiencies in sun4v error reporting.
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/include/asm/uaccess_64.h5
-rw-r--r--arch/sparc/kernel/syscalls.S32
-rw-r--r--arch/sparc/kernel/traps_64.c263
-rw-r--r--arch/sparc/mm/fault_64.c2
4 files changed, 221 insertions, 81 deletions
diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h
index 7c831d848b4e..73083e1d38d9 100644
--- a/arch/sparc/include/asm/uaccess_64.h
+++ b/arch/sparc/include/asm/uaccess_64.h
@@ -265,6 +265,11 @@ extern __must_check long strnlen_user(const char __user *str, long n);
265#define __copy_to_user_inatomic ___copy_to_user 265#define __copy_to_user_inatomic ___copy_to_user
266#define __copy_from_user_inatomic ___copy_from_user 266#define __copy_from_user_inatomic ___copy_from_user
267 267
268struct pt_regs;
269extern unsigned long compute_effective_address(struct pt_regs *,
270 unsigned int insn,
271 unsigned int rd);
272
268#endif /* __ASSEMBLY__ */ 273#endif /* __ASSEMBLY__ */
269 274
270#endif /* _ASM_UACCESS_H */ 275#endif /* _ASM_UACCESS_H */
diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S
index 1d7e274f3f2b..7f5f65d0b3fd 100644
--- a/arch/sparc/kernel/syscalls.S
+++ b/arch/sparc/kernel/syscalls.S
@@ -212,24 +212,20 @@ linux_sparc_syscall:
2123: stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] 2123: stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
213ret_sys_call: 213ret_sys_call:
214 ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3 214 ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
215 ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
216 sra %o0, 0, %o0 215 sra %o0, 0, %o0
217 mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2 216 mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
218 sllx %g2, 32, %g2 217 sllx %g2, 32, %g2
219 218
220 /* Check if force_successful_syscall_return()
221 * was invoked.
222 */
223 ldub [%g6 + TI_SYS_NOERROR], %l2
224 brnz,a,pn %l2, 80f
225 stb %g0, [%g6 + TI_SYS_NOERROR]
226
227 cmp %o0, -ERESTART_RESTARTBLOCK 219 cmp %o0, -ERESTART_RESTARTBLOCK
228 bgeu,pn %xcc, 1f 220 bgeu,pn %xcc, 1f
229 andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6 221 andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0
23080: 222 ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
223
2242:
225 stb %g0, [%g6 + TI_SYS_NOERROR]
231 /* System call success, clear Carry condition code. */ 226 /* System call success, clear Carry condition code. */
232 andn %g3, %g2, %g3 227 andn %g3, %g2, %g3
2283:
233 stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE] 229 stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
234 bne,pn %icc, linux_syscall_trace2 230 bne,pn %icc, linux_syscall_trace2
235 add %l1, 0x4, %l2 ! npc = npc+4 231 add %l1, 0x4, %l2 ! npc = npc+4
@@ -238,20 +234,20 @@ ret_sys_call:
238 stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] 234 stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
239 235
2401: 2361:
237 /* Check if force_successful_syscall_return()
238 * was invoked.
239 */
240 ldub [%g6 + TI_SYS_NOERROR], %l2
241 brnz,pn %l2, 2b
242 ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
241 /* System call failure, set Carry condition code. 243 /* System call failure, set Carry condition code.
242 * Also, get abs(errno) to return to the process. 244 * Also, get abs(errno) to return to the process.
243 */ 245 */
244 andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6
245 sub %g0, %o0, %o0 246 sub %g0, %o0, %o0
246 or %g3, %g2, %g3
247 stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] 247 stx %o0, [%sp + PTREGS_OFF + PT_V9_I0]
248 stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE] 248 ba,pt %xcc, 3b
249 bne,pn %icc, linux_syscall_trace2 249 or %g3, %g2, %g3
250 add %l1, 0x4, %l2 ! npc = npc+4
251 stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
252 250
253 b,pt %xcc, rtrap
254 stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
255linux_syscall_trace2: 251linux_syscall_trace2:
256 call syscall_trace_leave 252 call syscall_trace_leave
257 add %sp, PTREGS_OFF, %o0 253 add %sp, PTREGS_OFF, %o0
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c
index fa1f1d375ffc..b66a77968f35 100644
--- a/arch/sparc/kernel/traps_64.c
+++ b/arch/sparc/kernel/traps_64.c
@@ -1,6 +1,6 @@
1/* arch/sparc64/kernel/traps.c 1/* arch/sparc64/kernel/traps.c
2 * 2 *
3 * Copyright (C) 1995,1997,2008,2009 David S. Miller (davem@davemloft.net) 3 * Copyright (C) 1995,1997,2008,2009,2012 David S. Miller (davem@davemloft.net)
4 * Copyright (C) 1997,1999,2000 Jakub Jelinek (jakub@redhat.com) 4 * Copyright (C) 1997,1999,2000 Jakub Jelinek (jakub@redhat.com)
5 */ 5 */
6 6
@@ -18,6 +18,7 @@
18#include <linux/init.h> 18#include <linux/init.h>
19#include <linux/kdebug.h> 19#include <linux/kdebug.h>
20#include <linux/ftrace.h> 20#include <linux/ftrace.h>
21#include <linux/reboot.h>
21#include <linux/gfp.h> 22#include <linux/gfp.h>
22 23
23#include <asm/smp.h> 24#include <asm/smp.h>
@@ -1760,85 +1761,223 @@ void cheetah_plus_parity_error(int type, struct pt_regs *regs)
1760} 1761}
1761 1762
1762struct sun4v_error_entry { 1763struct sun4v_error_entry {
1763 u64 err_handle; 1764 /* Unique error handle */
1764 u64 err_stick; 1765/*0x00*/u64 err_handle;
1765 1766
1766 u32 err_type; 1767 /* %stick value at the time of the error */
1768/*0x08*/u64 err_stick;
1769
1770/*0x10*/u8 reserved_1[3];
1771
1772 /* Error type */
1773/*0x13*/u8 err_type;
1767#define SUN4V_ERR_TYPE_UNDEFINED 0 1774#define SUN4V_ERR_TYPE_UNDEFINED 0
1768#define SUN4V_ERR_TYPE_UNCORRECTED_RES 1 1775#define SUN4V_ERR_TYPE_UNCORRECTED_RES 1
1769#define SUN4V_ERR_TYPE_PRECISE_NONRES 2 1776#define SUN4V_ERR_TYPE_PRECISE_NONRES 2
1770#define SUN4V_ERR_TYPE_DEFERRED_NONRES 3 1777#define SUN4V_ERR_TYPE_DEFERRED_NONRES 3
1771#define SUN4V_ERR_TYPE_WARNING_RES 4 1778#define SUN4V_ERR_TYPE_SHUTDOWN_RQST 4
1779#define SUN4V_ERR_TYPE_DUMP_CORE 5
1780#define SUN4V_ERR_TYPE_SP_STATE_CHANGE 6
1781#define SUN4V_ERR_TYPE_NUM 7
1772 1782
1773 u32 err_attrs; 1783 /* Error attributes */
1784/*0x14*/u32 err_attrs;
1774#define SUN4V_ERR_ATTRS_PROCESSOR 0x00000001 1785#define SUN4V_ERR_ATTRS_PROCESSOR 0x00000001
1775#define SUN4V_ERR_ATTRS_MEMORY 0x00000002 1786#define SUN4V_ERR_ATTRS_MEMORY 0x00000002
1776#define SUN4V_ERR_ATTRS_PIO 0x00000004 1787#define SUN4V_ERR_ATTRS_PIO 0x00000004
1777#define SUN4V_ERR_ATTRS_INT_REGISTERS 0x00000008 1788#define SUN4V_ERR_ATTRS_INT_REGISTERS 0x00000008
1778#define SUN4V_ERR_ATTRS_FPU_REGISTERS 0x00000010 1789#define SUN4V_ERR_ATTRS_FPU_REGISTERS 0x00000010
1779#define SUN4V_ERR_ATTRS_USER_MODE 0x01000000 1790#define SUN4V_ERR_ATTRS_SHUTDOWN_RQST 0x00000020
1780#define SUN4V_ERR_ATTRS_PRIV_MODE 0x02000000 1791#define SUN4V_ERR_ATTRS_ASR 0x00000040
1792#define SUN4V_ERR_ATTRS_ASI 0x00000080
1793#define SUN4V_ERR_ATTRS_PRIV_REG 0x00000100
1794#define SUN4V_ERR_ATTRS_SPSTATE_MSK 0x00000600
1795#define SUN4V_ERR_ATTRS_SPSTATE_SHFT 9
1796#define SUN4V_ERR_ATTRS_MODE_MSK 0x03000000
1797#define SUN4V_ERR_ATTRS_MODE_SHFT 24
1781#define SUN4V_ERR_ATTRS_RES_QUEUE_FULL 0x80000000 1798#define SUN4V_ERR_ATTRS_RES_QUEUE_FULL 0x80000000
1782 1799
1783 u64 err_raddr; 1800#define SUN4V_ERR_SPSTATE_FAULTED 0
1784 u32 err_size; 1801#define SUN4V_ERR_SPSTATE_AVAILABLE 1
1785 u16 err_cpu; 1802#define SUN4V_ERR_SPSTATE_NOT_PRESENT 2
1786 u16 err_pad; 1803
1804#define SUN4V_ERR_MODE_USER 1
1805#define SUN4V_ERR_MODE_PRIV 2
1806
1807 /* Real address of the memory region or PIO transaction */
1808/*0x18*/u64 err_raddr;
1809
1810 /* Size of the operation triggering the error, in bytes */
1811/*0x20*/u32 err_size;
1812
1813 /* ID of the CPU */
1814/*0x24*/u16 err_cpu;
1815
1816 /* Grace periof for shutdown, in seconds */
1817/*0x26*/u16 err_secs;
1818
1819 /* Value of the %asi register */
1820/*0x28*/u8 err_asi;
1821
1822/*0x29*/u8 reserved_2;
1823
1824 /* Value of the ASR register number */
1825/*0x2a*/u16 err_asr;
1826#define SUN4V_ERR_ASR_VALID 0x8000
1827
1828/*0x2c*/u32 reserved_3;
1829/*0x30*/u64 reserved_4;
1830/*0x38*/u64 reserved_5;
1787}; 1831};
1788 1832
1789static atomic_t sun4v_resum_oflow_cnt = ATOMIC_INIT(0); 1833static atomic_t sun4v_resum_oflow_cnt = ATOMIC_INIT(0);
1790static atomic_t sun4v_nonresum_oflow_cnt = ATOMIC_INIT(0); 1834static atomic_t sun4v_nonresum_oflow_cnt = ATOMIC_INIT(0);
1791 1835
1792static const char *sun4v_err_type_to_str(u32 type) 1836static const char *sun4v_err_type_to_str(u8 type)
1793{ 1837{
1794 switch (type) { 1838 static const char *types[SUN4V_ERR_TYPE_NUM] = {
1795 case SUN4V_ERR_TYPE_UNDEFINED: 1839 "undefined",
1796 return "undefined"; 1840 "uncorrected resumable",
1797 case SUN4V_ERR_TYPE_UNCORRECTED_RES: 1841 "precise nonresumable",
1798 return "uncorrected resumable"; 1842 "deferred nonresumable",
1799 case SUN4V_ERR_TYPE_PRECISE_NONRES: 1843 "shutdown request",
1800 return "precise nonresumable"; 1844 "dump core",
1801 case SUN4V_ERR_TYPE_DEFERRED_NONRES: 1845 "SP state change",
1802 return "deferred nonresumable"; 1846 };
1803 case SUN4V_ERR_TYPE_WARNING_RES: 1847
1804 return "warning resumable"; 1848 if (type < SUN4V_ERR_TYPE_NUM)
1805 default: 1849 return types[type];
1806 return "unknown"; 1850
1851 return "unknown";
1852}
1853
1854static void sun4v_emit_err_attr_strings(u32 attrs)
1855{
1856 static const char *attr_names[] = {
1857 "processor",
1858 "memory",
1859 "PIO",
1860 "int-registers",
1861 "fpu-registers",
1862 "shutdown-request",
1863 "ASR",
1864 "ASI",
1865 "priv-reg",
1866 };
1867 static const char *sp_states[] = {
1868 "sp-faulted",
1869 "sp-available",
1870 "sp-not-present",
1871 "sp-state-reserved",
1872 };
1873 static const char *modes[] = {
1874 "mode-reserved0",
1875 "user",
1876 "priv",
1877 "mode-reserved1",
1878 };
1879 u32 sp_state, mode;
1880 int i;
1881
1882 for (i = 0; i < ARRAY_SIZE(attr_names); i++) {
1883 if (attrs & (1U << i)) {
1884 const char *s = attr_names[i];
1885
1886 pr_cont("%s ", s);
1887 }
1807 } 1888 }
1889
1890 sp_state = ((attrs & SUN4V_ERR_ATTRS_SPSTATE_MSK) >>
1891 SUN4V_ERR_ATTRS_SPSTATE_SHFT);
1892 pr_cont("%s ", sp_states[sp_state]);
1893
1894 mode = ((attrs & SUN4V_ERR_ATTRS_MODE_MSK) >>
1895 SUN4V_ERR_ATTRS_MODE_SHFT);
1896 pr_cont("%s ", modes[mode]);
1897
1898 if (attrs & SUN4V_ERR_ATTRS_RES_QUEUE_FULL)
1899 pr_cont("res-queue-full ");
1808} 1900}
1809 1901
1810static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent, int cpu, const char *pfx, atomic_t *ocnt) 1902/* When the report contains a real-address of "-1" it means that the
1903 * hardware did not provide the address. So we compute the effective
1904 * address of the load or store instruction at regs->tpc and report
1905 * that. Usually when this happens it's a PIO and in such a case we
1906 * are using physical addresses with bypass ASIs anyways, so what we
1907 * report here is exactly what we want.
1908 */
1909static void sun4v_report_real_raddr(const char *pfx, struct pt_regs *regs)
1811{ 1910{
1911 unsigned int insn;
1912 u64 addr;
1913
1914 if (!(regs->tstate & TSTATE_PRIV))
1915 return;
1916
1917 insn = *(unsigned int *) regs->tpc;
1918
1919 addr = compute_effective_address(regs, insn, 0);
1920
1921 printk("%s: insn effective address [0x%016llx]\n",
1922 pfx, addr);
1923}
1924
1925static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent,
1926 int cpu, const char *pfx, atomic_t *ocnt)
1927{
1928 u64 *raw_ptr = (u64 *) ent;
1929 u32 attrs;
1812 int cnt; 1930 int cnt;
1813 1931
1814 printk("%s: Reporting on cpu %d\n", pfx, cpu); 1932 printk("%s: Reporting on cpu %d\n", pfx, cpu);
1815 printk("%s: err_handle[%llx] err_stick[%llx] err_type[%08x:%s]\n", 1933 printk("%s: TPC [0x%016lx] <%pS>\n",
1816 pfx, 1934 pfx, regs->tpc, (void *) regs->tpc);
1817 ent->err_handle, ent->err_stick, 1935
1818 ent->err_type, 1936 printk("%s: RAW [%016llx:%016llx:%016llx:%016llx\n",
1819 sun4v_err_type_to_str(ent->err_type)); 1937 pfx, raw_ptr[0], raw_ptr[1], raw_ptr[2], raw_ptr[3]);
1820 printk("%s: err_attrs[%08x:%s %s %s %s %s %s %s %s]\n", 1938 printk("%s: %016llx:%016llx:%016llx:%016llx]\n",
1821 pfx, 1939 pfx, raw_ptr[4], raw_ptr[5], raw_ptr[6], raw_ptr[7]);
1822 ent->err_attrs, 1940
1823 ((ent->err_attrs & SUN4V_ERR_ATTRS_PROCESSOR) ? 1941 printk("%s: handle [0x%016llx] stick [0x%016llx]\n",
1824 "processor" : ""), 1942 pfx, ent->err_handle, ent->err_stick);
1825 ((ent->err_attrs & SUN4V_ERR_ATTRS_MEMORY) ? 1943
1826 "memory" : ""), 1944 printk("%s: type [%s]\n", pfx, sun4v_err_type_to_str(ent->err_type));
1827 ((ent->err_attrs & SUN4V_ERR_ATTRS_PIO) ? 1945
1828 "pio" : ""), 1946 attrs = ent->err_attrs;
1829 ((ent->err_attrs & SUN4V_ERR_ATTRS_INT_REGISTERS) ? 1947 printk("%s: attrs [0x%08x] < ", pfx, attrs);
1830 "integer-regs" : ""), 1948 sun4v_emit_err_attr_strings(attrs);
1831 ((ent->err_attrs & SUN4V_ERR_ATTRS_FPU_REGISTERS) ? 1949 pr_cont(">\n");
1832 "fpu-regs" : ""), 1950
1833 ((ent->err_attrs & SUN4V_ERR_ATTRS_USER_MODE) ? 1951 /* Various fields in the error report are only valid if
1834 "user" : ""), 1952 * certain attribute bits are set.
1835 ((ent->err_attrs & SUN4V_ERR_ATTRS_PRIV_MODE) ? 1953 */
1836 "privileged" : ""), 1954 if (attrs & (SUN4V_ERR_ATTRS_MEMORY |
1837 ((ent->err_attrs & SUN4V_ERR_ATTRS_RES_QUEUE_FULL) ? 1955 SUN4V_ERR_ATTRS_PIO |
1838 "queue-full" : "")); 1956 SUN4V_ERR_ATTRS_ASI)) {
1839 printk("%s: err_raddr[%016llx] err_size[%u] err_cpu[%u]\n", 1957 printk("%s: raddr [0x%016llx]\n", pfx, ent->err_raddr);
1840 pfx, 1958
1841 ent->err_raddr, ent->err_size, ent->err_cpu); 1959 if (ent->err_raddr == ~(u64)0)
1960 sun4v_report_real_raddr(pfx, regs);
1961 }
1962
1963 if (attrs & (SUN4V_ERR_ATTRS_MEMORY | SUN4V_ERR_ATTRS_ASI))
1964 printk("%s: size [0x%x]\n", pfx, ent->err_size);
1965
1966 if (attrs & (SUN4V_ERR_ATTRS_PROCESSOR |
1967 SUN4V_ERR_ATTRS_INT_REGISTERS |
1968 SUN4V_ERR_ATTRS_FPU_REGISTERS |
1969 SUN4V_ERR_ATTRS_PRIV_REG))
1970 printk("%s: cpu[%u]\n", pfx, ent->err_cpu);
1971
1972 if (attrs & SUN4V_ERR_ATTRS_ASI)
1973 printk("%s: asi [0x%02x]\n", pfx, ent->err_asi);
1974
1975 if ((attrs & (SUN4V_ERR_ATTRS_INT_REGISTERS |
1976 SUN4V_ERR_ATTRS_FPU_REGISTERS |
1977 SUN4V_ERR_ATTRS_PRIV_REG)) &&
1978 (ent->err_asr & SUN4V_ERR_ASR_VALID) != 0)
1979 printk("%s: reg [0x%04x]\n",
1980 pfx, ent->err_asr & ~SUN4V_ERR_ASR_VALID);
1842 1981
1843 show_regs(regs); 1982 show_regs(regs);
1844 1983
@@ -1874,13 +2013,15 @@ void sun4v_resum_error(struct pt_regs *regs, unsigned long offset)
1874 2013
1875 put_cpu(); 2014 put_cpu();
1876 2015
1877 if (ent->err_type == SUN4V_ERR_TYPE_WARNING_RES) { 2016 if (local_copy.err_type == SUN4V_ERR_TYPE_SHUTDOWN_RQST) {
1878 /* If err_type is 0x4, it's a powerdown request. Do 2017 /* We should really take the seconds field of
1879 * not do the usual resumable error log because that 2018 * the error report and use it for the shutdown
1880 * makes it look like some abnormal error. 2019 * invocation, but for now do the same thing we
2020 * do for a DS shutdown request.
1881 */ 2021 */
1882 printk(KERN_INFO "Power down request...\n"); 2022 pr_info("Shutdown request, %u seconds...\n",
1883 kill_cad_pid(SIGINT, 1); 2023 local_copy.err_secs);
2024 orderly_poweroff(true);
1884 return; 2025 return;
1885 } 2026 }
1886 2027
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
index 2976dba1ebaf..097aee763af3 100644
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -151,8 +151,6 @@ show_signal_msg(struct pt_regs *regs, int sig, int code,
151 printk(KERN_CONT "\n"); 151 printk(KERN_CONT "\n");
152} 152}
153 153
154extern unsigned long compute_effective_address(struct pt_regs *, unsigned int, unsigned int);
155
156static void do_fault_siginfo(int code, int sig, struct pt_regs *regs, 154static void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
157 unsigned int insn, int fault_code) 155 unsigned int insn, int fault_code)
158{ 156{