aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKhalid Aziz <khalid.aziz@oracle.com>2018-02-21 12:15:47 -0500
committerDavid S. Miller <davem@davemloft.net>2018-03-18 10:38:46 -0400
commit94addb3530bb81e7ffde2c5c50a88310f734c365 (patch)
tree211fabfdde558501c50ab3501594e3a292659252
parent52df948d1bff7954f416085a821e299a188424b8 (diff)
sparc64: Add handler for "Memory Corruption Detected" trap
M7 and newer processors add a "Memory corruption Detected" trap with the addition of ADI feature. This trap is vectored into kernel by HV through resumable error trap with error attribute for the resumable error set to 0x00000800. Signed-off-by: Khalid Aziz <khalid.aziz@oracle.com> Cc: Khalid Aziz <khalid@gonehiking.org> Reviewed-by: Anthony Yznaga <anthony.yznaga@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc/kernel/traps_64.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c
index d273a65a0a10..f36a40217f6c 100644
--- a/arch/sparc/kernel/traps_64.c
+++ b/arch/sparc/kernel/traps_64.c
@@ -1870,6 +1870,7 @@ struct sun4v_error_entry {
1870#define SUN4V_ERR_ATTRS_ASI 0x00000080 1870#define SUN4V_ERR_ATTRS_ASI 0x00000080
1871#define SUN4V_ERR_ATTRS_PRIV_REG 0x00000100 1871#define SUN4V_ERR_ATTRS_PRIV_REG 0x00000100
1872#define SUN4V_ERR_ATTRS_SPSTATE_MSK 0x00000600 1872#define SUN4V_ERR_ATTRS_SPSTATE_MSK 0x00000600
1873#define SUN4V_ERR_ATTRS_MCD 0x00000800
1873#define SUN4V_ERR_ATTRS_SPSTATE_SHFT 9 1874#define SUN4V_ERR_ATTRS_SPSTATE_SHFT 9
1874#define SUN4V_ERR_ATTRS_MODE_MSK 0x03000000 1875#define SUN4V_ERR_ATTRS_MODE_MSK 0x03000000
1875#define SUN4V_ERR_ATTRS_MODE_SHFT 24 1876#define SUN4V_ERR_ATTRS_MODE_SHFT 24
@@ -2067,6 +2068,56 @@ static void sun4v_log_error(struct pt_regs *regs, struct sun4v_error_entry *ent,
2067 } 2068 }
2068} 2069}
2069 2070
2071/* Handle memory corruption detected error which is vectored in
2072 * through resumable error trap.
2073 */
2074void do_mcd_err(struct pt_regs *regs, struct sun4v_error_entry ent)
2075{
2076 siginfo_t info;
2077
2078 if (notify_die(DIE_TRAP, "MCD error", regs, 0, 0x34,
2079 SIGSEGV) == NOTIFY_STOP)
2080 return;
2081
2082 if (regs->tstate & TSTATE_PRIV) {
2083 /* MCD exception could happen because the task was
2084 * running a system call with MCD enabled and passed a
2085 * non-versioned pointer or pointer with bad version
2086 * tag to the system call. In such cases, hypervisor
2087 * places the address of offending instruction in the
2088 * resumable error report. This is a deferred error,
2089 * so the read/write that caused the trap was potentially
2090 * retired long time back and we may have no choice
2091 * but to send SIGSEGV to the process.
2092 */
2093 const struct exception_table_entry *entry;
2094
2095 entry = search_exception_tables(regs->tpc);
2096 if (entry) {
2097 /* Looks like a bad syscall parameter */
2098#ifdef DEBUG_EXCEPTIONS
2099 pr_emerg("Exception: PC<%016lx> faddr<UNKNOWN>\n",
2100 regs->tpc);
2101 pr_emerg("EX_TABLE: insn<%016lx> fixup<%016lx>\n",
2102 ent.err_raddr, entry->fixup);
2103#endif
2104 regs->tpc = entry->fixup;
2105 regs->tnpc = regs->tpc + 4;
2106 return;
2107 }
2108 }
2109
2110 /* Send SIGSEGV to the userspace process with the right signal
2111 * code
2112 */
2113 info.si_signo = SIGSEGV;
2114 info.si_errno = 0;
2115 info.si_code = SEGV_ADIDERR;
2116 info.si_addr = (void __user *)ent.err_raddr;
2117 info.si_trapno = 0;
2118 force_sig_info(SIGSEGV, &info, current);
2119}
2120
2070/* We run with %pil set to PIL_NORMAL_MAX and PSTATE_IE enabled in %pstate. 2121/* We run with %pil set to PIL_NORMAL_MAX and PSTATE_IE enabled in %pstate.
2071 * Log the event and clear the first word of the entry. 2122 * Log the event and clear the first word of the entry.
2072 */ 2123 */
@@ -2104,6 +2155,14 @@ void sun4v_resum_error(struct pt_regs *regs, unsigned long offset)
2104 goto out; 2155 goto out;
2105 } 2156 }
2106 2157
2158 /* If this is a memory corruption detected error vectored in
2159 * by HV through resumable error trap, call the handler
2160 */
2161 if (local_copy.err_attrs & SUN4V_ERR_ATTRS_MCD) {
2162 do_mcd_err(regs, local_copy);
2163 return;
2164 }
2165
2107 sun4v_log_error(regs, &local_copy, cpu, 2166 sun4v_log_error(regs, &local_copy, cpu,
2108 KERN_ERR "RESUMABLE ERROR", 2167 KERN_ERR "RESUMABLE ERROR",
2109 &sun4v_resum_oflow_cnt); 2168 &sun4v_resum_oflow_cnt);