Skip to content
This repository has been archived by the owner on Jul 16, 2024. It is now read-only.

Commit

Permalink
BACKPORT: arm64: acpi: Make apei_claim_sea() synchronise with APEI's …
Browse files Browse the repository at this point in the history
…irq work

APEI is unable to do all of its error handling work in nmi-context, so
it defers non-fatal work onto the irq_work queue. arch_irq_work_raise()
sends an IPI to the calling cpu, but this is not guaranteed to be taken
before returning to user-space.

Unless the exception interrupted a context with irqs-masked,
irq_work_run() can run immediately. Otherwise return -EINPROGRESS to
indicate ghes_notify_sea() found some work to do, but it hasn't
finished yet.

With this apei_claim_sea() returning '0' means this external-abort was
also notification of a firmware-first RAS error, and that APEI has
processed the CPER records.

This patch is needed because Quicksilver firmware-first error handling
uses the SDEI notification type for communication between trusted
firmware and the OS. This adds needed NMI and SDEI functionality so
that the SDEI path in the kernel through APEI acts as an NMI and is
properly wired up to the APEI interfaces.

Backported from: https://patchwork.kernel.org/patch/10786985/

Signed-off-by: James Morse <[email protected]>
Reviewed-by: Punit Agrawal <[email protected]>
Tested-by: Tyler Baicar <[email protected]>
Acked-by: Catalin Marinas <[email protected]>
CC: Xie XiuQi <[email protected]>
CC: gengdongjiu <[email protected]>
Reviewed-by: Julien Thierry <[email protected]>
Signed-off-by: Tyler Baicar <[email protected]>
  • Loading branch information
James Morse authored and tphan-ampere committed Apr 21, 2020
1 parent ac5d13a commit 76f72cb
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 5 deletions.
23 changes: 23 additions & 0 deletions arch/arm64/kernel/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/irq_work.h>
#include <linux/memblock.h>
#include <linux/of_fdt.h>
#include <linux/smp.h>
Expand Down Expand Up @@ -269,12 +270,17 @@ pgprot_t __acpi_get_mem_attribute(phys_addr_t addr)
int apei_claim_sea(struct pt_regs *regs)
{
int err = -ENOENT;
bool return_to_irqs_enabled;
unsigned long current_flags;

if (!IS_ENABLED(CONFIG_ACPI_APEI_GHES))
return err;

current_flags = arch_local_save_flags();
return_to_irqs_enabled = !irqs_disabled_flags(current_flags);

if (regs)
return_to_irqs_enabled = interrupts_enabled(regs);

/*
* SEA can interrupt SError, mask it and describe this as an NMI so
Expand All @@ -284,6 +290,23 @@ int apei_claim_sea(struct pt_regs *regs)
nmi_enter();
err = ghes_notify_sea();
nmi_exit();

/*
* APEI NMI-like notifications are deferred to irq_work. Unless
* we interrupted irqs-masked code, we can do that now.
*/
if (!err) {
if (return_to_irqs_enabled) {
local_daif_restore(DAIF_PROCCTX_NOIRQ);
__irq_enter();
irq_work_run();
__irq_exit();
} else {
pr_warn("APEI work queued but not completed");
err = -EINPROGRESS;
}
}

local_daif_restore(current_flags);

return err;
Expand Down
9 changes: 4 additions & 5 deletions arch/arm64/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -630,11 +630,10 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)

inf = esr_to_fault_info(esr);

/*
* Return value ignored as we rely on signal merging.
* Future patches will make this more robust.
*/
apei_claim_sea();
if (apei_claim_sea(regs) == 0) {
/* APEI claimed this as a firmware-first notification */
return 0;
}

clear_siginfo(&info);
info.si_signo = inf->sig;
Expand Down

0 comments on commit 76f72cb

Please sign in to comment.