lkml.org 
[lkml]   [2017]   [Jul]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 051/172] sparc64: Handle PIO & MEM non-resumable errors.
    Date
    4.9-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: "Liam R. Howlett" <Liam.Howlett@Oracle.com>


    [ Upstream commit 047487241ff59374fded8c477f21453681f5995c ]

    User processes trying to access an invalid memory address via PIO will
    receive a SIGBUS signal instead of causing a panic. Memory errors will
    receive a SIGKILL since a SIGBUS may result in a coredump which may
    attempt to repeat the faulting access.

    Signed-off-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    arch/sparc/kernel/traps_64.c | 73 +++++++++++++++++++++++++++++++++++++++++++
    1 file changed, 73 insertions(+)

    --- a/arch/sparc/kernel/traps_64.c
    +++ b/arch/sparc/kernel/traps_64.c
    @@ -2051,6 +2051,73 @@ void sun4v_resum_overflow(struct pt_regs
    atomic_inc(&sun4v_resum_oflow_cnt);
    }

    +/* Given a set of registers, get the virtual addressi that was being accessed
    + * by the faulting instructions at tpc.
    + */
    +static unsigned long sun4v_get_vaddr(struct pt_regs *regs)
    +{
    + unsigned int insn;
    +
    + if (!copy_from_user(&insn, (void __user *)regs->tpc, 4)) {
    + return compute_effective_address(regs, insn,
    + (insn >> 25) & 0x1f);
    + }
    + return 0;
    +}
    +
    +/* Attempt to handle non-resumable errors generated from userspace.
    + * Returns true if the signal was handled, false otherwise.
    + */
    +bool sun4v_nonresum_error_user_handled(struct pt_regs *regs,
    + struct sun4v_error_entry *ent) {
    +
    + unsigned int attrs = ent->err_attrs;
    +
    + if (attrs & SUN4V_ERR_ATTRS_MEMORY) {
    + unsigned long addr = ent->err_raddr;
    + siginfo_t info;
    +
    + if (addr == ~(u64)0) {
    + /* This seems highly unlikely to ever occur */
    + pr_emerg("SUN4V NON-RECOVERABLE ERROR: Memory error detected in unknown location!\n");
    + } else {
    + unsigned long page_cnt = DIV_ROUND_UP(ent->err_size,
    + PAGE_SIZE);
    +
    + /* Break the unfortunate news. */
    + pr_emerg("SUN4V NON-RECOVERABLE ERROR: Memory failed at %016lX\n",
    + addr);
    + pr_emerg("SUN4V NON-RECOVERABLE ERROR: Claiming %lu ages.\n",
    + page_cnt);
    +
    + while (page_cnt-- > 0) {
    + if (pfn_valid(addr >> PAGE_SHIFT))
    + get_page(pfn_to_page(addr >> PAGE_SHIFT));
    + addr += PAGE_SIZE;
    + }
    + }
    + info.si_signo = SIGKILL;
    + info.si_errno = 0;
    + info.si_trapno = 0;
    + force_sig_info(info.si_signo, &info, current);
    +
    + return true;
    + }
    + if (attrs & SUN4V_ERR_ATTRS_PIO) {
    + siginfo_t info;
    +
    + info.si_signo = SIGBUS;
    + info.si_code = BUS_ADRERR;
    + info.si_addr = (void __user *)sun4v_get_vaddr(regs);
    + force_sig_info(info.si_signo, &info, current);
    +
    + return true;
    + }
    +
    + /* Default to doing nothing */
    + return false;
    +}
    +
    /* We run with %pil set to PIL_NORMAL_MAX and PSTATE_IE enabled in %pstate.
    * Log the event, clear the first word of the entry, and die.
    */
    @@ -2075,6 +2142,12 @@ void sun4v_nonresum_error(struct pt_regs

    put_cpu();

    + if (!(regs->tstate & TSTATE_PRIV) &&
    + sun4v_nonresum_error_user_handled(regs, &local_copy)) {
    + /* DON'T PANIC: This userspace error was handled. */
    + return;
    + }
    +
    #ifdef CONFIG_PCI
    /* Check for the special PCI poke sequence. */
    if (pci_poke_in_progress && pci_poke_cpu == cpu) {

    \
     
     \ /
      Last update: 2017-07-03 16:34    [W:4.995 / U:0.124 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site