aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-10-10 20:19:32 -0400
committerDavid S. Miller <davem@davemloft.net>2012-10-10 20:19:32 -0400
commitf88620b9c5521e9cb9de88e56272bfec3d831513 (patch)
tree6d369a343c60d3100576b79d0d68b123eee0fbdd /arch/sparc
parent2474542f64432398f503373f53bdf620491bcfa8 (diff)
sparc64: Fix deficiencies in sun4v error reporting.
Missing error types, attributes, and report fields. Pad out to 64-bytes. Make string reporting cleaner and easier to extend in the future using "const char *" arrays that index by either bit position, or absolute field value. Report the raw 64-byte error report as a sequence of u64s before the annotated version. Only report fields which are valid, given the context and the attribute bits which are set. For shutdown requests, use the local copy of the error report not the one we just freed up back to the queue. Also, use orderly_poweroff() just like the Domain Services shutdown request code does. If the real-address reported is "-1" (unknown) try to disassemble the instruction to report the effective address of the access. Only do this in privileged mode. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/include/asm/uaccess_64.h5
-rw-r--r--arch/sparc/kernel/traps_64.c263
-rw-r--r--arch/sparc/mm/fault_64.c2
3 files changed, 207 insertions, 63 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/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{