Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1557693 > unrolled thread
| Started by | Tyler Baicar <tbaicar@codeaurora.org> |
|---|---|
| First post | 2017-01-12 19:20 +0100 |
| Last post | 2017-01-24 19:50 +0100 |
| Articles | 20 on this page of 29 — 5 participants |
Back to article view | Back to linux.kernel
[PATCH V7 00/10] Add UEFI 2.6 and ACPI 6.1 updates for RAS on ARM64 Tyler Baicar <tbaicar@codeaurora.org> - 2017-01-12 19:20 +0100
[PATCH V7 01/10] acpi: apei: read ack upon ghes record consumption Tyler Baicar <tbaicar@codeaurora.org> - 2017-01-12 19:20 +0100
[PATCH V7 04/10] arm64: exception: handle Synchronous External Abort Tyler Baicar <tbaicar@codeaurora.org> - 2017-01-12 19:20 +0100
Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort Will Deacon <will.deacon@arm.com> - 2017-01-16 13:00 +0100
Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort "Baicar, Tyler" <tbaicar@codeaurora.org> - 2017-01-16 21:20 +0100
Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort Will Deacon <will.deacon@arm.com> - 2017-01-17 11:30 +0100
Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort "Baicar, Tyler" <tbaicar@codeaurora.org> - 2017-01-19 00:10 +0100
Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort James Morse <james.morse@arm.com> - 2017-01-17 11:30 +0100
Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort "Baicar, Tyler" <tbaicar@codeaurora.org> - 2017-01-19 00:00 +0100
Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort James Morse <james.morse@arm.com> - 2017-01-17 11:40 +0100
Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort "Baicar, Tyler" <tbaicar@codeaurora.org> - 2017-01-19 00:30 +0100
Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort James Morse <james.morse@arm.com> - 2017-01-19 19:20 +0100
Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort "Baicar, Tyler" <tbaicar@codeaurora.org> - 2017-01-20 21:40 +0100
Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort James Morse <james.morse@arm.com> - 2017-01-23 11:10 +0100
Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort "Baicar, Tyler" <tbaicar@codeaurora.org> - 2017-01-24 19:50 +0100
[PATCH V7 10/10] arm/arm64: KVM: add guest SEA support Tyler Baicar <tbaicar@codeaurora.org> - 2017-01-12 19:30 +0100
Re: [PATCH V7 10/10] arm/arm64: KVM: add guest SEA support Marc Zyngier <marc.zyngier@arm.com> - 2017-01-16 13:00 +0100
Re: [PATCH V7 10/10] arm/arm64: KVM: add guest SEA support "Baicar, Tyler" <tbaicar@codeaurora.org> - 2017-01-16 21:20 +0100
[PATCH V7 08/10] ras: acpi / apei: generate trace event for unrecognized CPER section Tyler Baicar <tbaicar@codeaurora.org> - 2017-01-12 19:30 +0100
[PATCH V7 06/10] acpi: apei: panic OS with fatal error status block Tyler Baicar <tbaicar@codeaurora.org> - 2017-01-12 19:30 +0100
[PATCH V7 07/10] efi: print unrecognized CPER section Tyler Baicar <tbaicar@codeaurora.org> - 2017-01-12 19:30 +0100
[PATCH V7 09/10] trace, ras: add ARM processor error trace event Tyler Baicar <tbaicar@codeaurora.org> - 2017-01-12 19:30 +0100
[PATCH V7 05/10] acpi: apei: handle SEA notification type for ARMv8 Tyler Baicar <tbaicar@codeaurora.org> - 2017-01-12 19:30 +0100
Re: [PATCH V7 05/10] acpi: apei: handle SEA notification type for ARMv8 James Morse <james.morse@arm.com> - 2017-01-18 16:10 +0100
Re: [PATCH V7 05/10] acpi: apei: handle SEA notification type for ARMv8 "Baicar, Tyler" <tbaicar@codeaurora.org> - 2017-01-19 01:00 +0100
Re: [PATCH V7 05/10] acpi: apei: handle SEA notification type for ARMv8 James Morse <james.morse@arm.com> - 2017-01-19 19:10 +0100
Re: [PATCH V7 05/10] acpi: apei: handle SEA notification type for ARMv8 "Baicar, Tyler" <tbaicar@codeaurora.org> - 2017-01-20 22:00 +0100
Re: [PATCH V7 05/10] acpi: apei: handle SEA notification type for ARMv8 James Morse <james.morse@arm.com> - 2017-01-24 19:00 +0100
Re: [PATCH V7 05/10] acpi: apei: handle SEA notification type for ARMv8 "Baicar, Tyler" <tbaicar@codeaurora.org> - 2017-01-24 19:50 +0100
Page 1 of 2 [1] 2 Next page →
| From | Tyler Baicar <tbaicar@codeaurora.org> |
|---|---|
| Date | 2017-01-12 19:20 +0100 |
| Subject | [PATCH V7 00/10] Add UEFI 2.6 and ACPI 6.1 updates for RAS on ARM64 |
| Message-ID | <sYS8G-7eZ-5@gated-at.bofh.it> |
When a memory error, CPU error, PCIe error, or other type of hardware error
that's covered by RAS occurs, firmware should populate the shared GHES memory
location with the proper GHES structures to notify the OS of the error.
For example, platforms that implement firmware first handling may implement
separate GHES sources for corrected errors and uncorrected errors. If the
error is an uncorrectable error, then the firmware will notify the OS
immediately since the error needs to be handled ASAP. The OS will then be able
to take the appropriate action needed such as offlining a page. If the error
is a corrected error, then the firmware will not interrupt the OS immediately.
Instead, the OS will see and report the error the next time it's GHES timer
expires. The kernel will first parse the GHES structures and report the errors
through the kernel logs and then notify the user space through RAS trace
events. This allows user space applications such as RAS Daemon to see the
errors and report them however the user desires. This patchset extends the
kernel functionality for RAS errors based on updates in the UEFI 2.6 and
ACPI 6.1 specifications.
An example flow from firmware to user space could be:
+---------------+
+-------->| |
| | GHES polling |--+
+-------------+ | source | | +---------------+ +------------+
| | +---------------+ | | Kernel GHES | | |
| Firmware | +-->| CPER AER and |-->| RAS trace |
| | +---------------+ | | EDAC drivers | | event |
+-------------+ | | | +---------------+ +------------+
| | GHES sci |--+
+-------->| source |
+---------------+
Add support for Generic Hardware Error Source (GHES) v2, which introduces the
capability for the OS to acknowledge the consumption of the error record
generated by the Reliability, Availability and Serviceability (RAS) controller.
This eliminates potential race conditions between the OS and the RAS controller.
Add support for the timestamp field added to the Generic Error Data Entry v3,
allowing the OS to log the time that the error is generated by the firmware,
rather than the time the error is consumed. This improves the correctness of
event sequences when analyzing error logs. The timestamp is added in
ACPI 6.1, reference Table 18-343 Generic Error Data Entry.
Add support for ARMv8 Common Platform Error Record (CPER) per UEFI 2.6
specification. ARMv8 specific processor error information is reported as part of
the CPER records. This provides more detail on for processor error logs. This
can help describe ARMv8 cache, tlb, and bus errors.
Synchronous External Abort (SEA) represents a specific processor error condition
in ARM systems. A handler is added to recognize SEA errors, and a notifier is
added to parse and report the errors before the process is killed. Refer to
section N.2.1.1 in the Common Platform Error Record appendix of the UEFI 2.6
specification.
Currently the kernel ignores CPER records that are unrecognized.
On the other hand, UEFI spec allows for non-standard (eg. vendor
proprietary) error section type in CPER (Common Platform Error Record),
as defined in section N2.3 of UEFI version 2.5. Therefore, user
is not able to see hardware error data of non-standard section.
If section Type field of Generic Error Data Entry is unrecognized,
prints out the raw data in dmesg buffer, and also adds a tracepoint
for reporting such hardware errors.
Currently even if an error status block's severity is fatal, the kernel
does not honor the severity level and panic. With the firmware first
model, the platform could inform the OS about a fatal hardware error
through the non-NMI GHES notification type. The OS should panic when a
hardware error record is received with this severity.
Add support to handle SEAs that occur while a KVM guest kernel is
running. Currently these are unsupported by the guest abort handling.
V7: Update a couple prints for ARM processor errors
Add Print notifying if overflow occurred for ARM processor errors
Check for ARM configuration to allow the compiler to ignore ARM code
on non-ARM systems
Use SEA acronym instead of spelling it out
Update fault_info prints to be more clear
Add NMI locking to SEA notification
Remove error info structure from ARM trace event since there can be
a variable amount of these structures
V6: Change HEST_TYPE_GENERIC_V2 to IS_HEST_TYPE_GENERIC_V2 for readability
Move APEI helper defines from cper.h to ghes.h
Add data_len decrement back into print loop
Change references to ARMv8 to just ARM
Rewrite ARM processor context info parsing
Check valid bit of ARM error info field before printing it
Add include of linux/uuid.h in ghes.c
V5: Fix GHES goto logic for error conditions
Change ghes_do_read_ack to ghes_ack_error
Make sure data version check is >= 3
Use CPER helper functions in print functions
Make handle_guest_sea() dummy function static for arm
Add arm to subject line for KVM patch
V4: Add bit offset left shift to read_ack_write value
Make HEST generic and generic_v2 structures a union in the ghes structure
Move gdata v3 helper functions into ghes.h to avoid duplication
Reorder the timestamp print and avoid memcpy
Add helper functions for gdata size checking
Rename the SEA functions
Add helper function for GHES panics
Set fru_id to NULL UUID at variable declaration
Limit ARM trace event parameters to the needed structures
Reorder the ARM trace event variables to save space
Add comment for why we don't pass SEAs to the guest when it aborts
Move ARM trace event call into GHES driver instead of CPER
V3: Fix unmapped address to the read_ack_register in ghes.c
Add helper function to get the proper payload based on generic data entry
version
Move timestamp print to avoid changing function calls in cper.c
Remove patch "arm64: exception: handle instruction abort at current EL"
since the el1_ia handler is already added in 4.8
Add EFI and ARM64 dependencies for HAVE_ACPI_APEI_SEA
Add a new trace event for ARM type errors
Add support to handle KVM guest SEAs
V2: Add PSCI state print for the ARMv8 error type.
Separate timestamp year into year and century using BCD format.
Rebase on top of ACPICA 20160318 release and remove header file changes
in include/acpi/actbl1.h.
Add panic OS with fatal error status block patch.
Add processing of unrecognized CPER error section patches with updates
from previous comments. Original patches: https://lkml.org/lkml/2015/9/8/646
V1: https://lkml.org/lkml/2016/2/5/544
Jonathan (Zhixiong) Zhang (1):
acpi: apei: panic OS with fatal error status block
Tyler Baicar (9):
acpi: apei: read ack upon ghes record consumption
ras: acpi/apei: cper: generic error data entry v3 per ACPI 6.1
efi: parse ARM processor error
arm64: exception: handle Synchronous External Abort
acpi: apei: handle SEA notification type for ARMv8
efi: print unrecognized CPER section
ras: acpi / apei: generate trace event for unrecognized CPER section
trace, ras: add ARM processor error trace event
arm/arm64: KVM: add guest SEA support
arch/arm/include/asm/kvm_arm.h | 1 +
arch/arm/include/asm/system_misc.h | 5 +
arch/arm/kvm/mmu.c | 18 ++-
arch/arm64/Kconfig | 2 +
arch/arm64/include/asm/kvm_arm.h | 1 +
arch/arm64/include/asm/system_misc.h | 15 +++
arch/arm64/mm/fault.c | 71 ++++++++++--
drivers/acpi/apei/Kconfig | 14 +++
drivers/acpi/apei/ghes.c | 188 ++++++++++++++++++++++++++++---
drivers/acpi/apei/hest.c | 7 +-
drivers/firmware/efi/cper.c | 209 ++++++++++++++++++++++++++++++++---
drivers/ras/ras.c | 2 +
include/acpi/ghes.h | 27 ++++-
include/linux/cper.h | 54 +++++++++
include/ras/ras_event.h | 79 +++++++++++++
15 files changed, 649 insertions(+), 44 deletions(-)
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
[toc] | [next] | [standalone]
| From | Tyler Baicar <tbaicar@codeaurora.org> |
|---|---|
| Date | 2017-01-12 19:20 +0100 |
| Subject | [PATCH V7 01/10] acpi: apei: read ack upon ghes record consumption |
| Message-ID | <sYS8H-7eZ-29@gated-at.bofh.it> |
| In reply to | #1557693 |
A RAS (Reliability, Availability, Serviceability) controller
may be a separate processor running in parallel with OS
execution, and may generate error records for consumption by
the OS. If the RAS controller produces multiple error records,
then they may be overwritten before the OS has consumed them.
The Generic Hardware Error Source (GHES) v2 structure
introduces the capability for the OS to acknowledge the
consumption of the error record generated by the RAS
controller. A RAS controller supporting GHESv2 shall wait for
the acknowledgment before writing a new error record, thus
eliminating the race condition.
Add support for parsing of GHESv2 sub-tables as well.
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Signed-off-by: Richard Ruigrok <rruigrok@codeaurora.org>
Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
Reviewed-by: James Morse <james.morse@arm.com>
---
drivers/acpi/apei/ghes.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---
drivers/acpi/apei/hest.c | 7 +++++--
include/acpi/ghes.h | 5 ++++-
3 files changed, 55 insertions(+), 6 deletions(-)
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 60746ef..b23160d 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -45,6 +45,7 @@
#include <linux/aer.h>
#include <linux/nmi.h>
+#include <acpi/actbl1.h>
#include <acpi/ghes.h>
#include <acpi/apei.h>
#include <asm/tlbflush.h>
@@ -79,6 +80,10 @@
((struct acpi_hest_generic_status *) \
((struct ghes_estatus_node *)(estatus_node) + 1))
+#define IS_HEST_TYPE_GENERIC_V2(ghes) \
+ ((struct acpi_hest_header *)ghes->generic)->type == \
+ ACPI_HEST_TYPE_GENERIC_ERROR_V2
+
/*
* This driver isn't really modular, however for the time being,
* continuing to use module_param is the easiest way to remain
@@ -248,10 +253,18 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
ghes = kzalloc(sizeof(*ghes), GFP_KERNEL);
if (!ghes)
return ERR_PTR(-ENOMEM);
+
ghes->generic = generic;
+ if (IS_HEST_TYPE_GENERIC_V2(ghes)) {
+ rc = apei_map_generic_address(
+ &ghes->generic_v2->read_ack_register);
+ if (rc)
+ goto err_free;
+ }
+
rc = apei_map_generic_address(&generic->error_status_address);
if (rc)
- goto err_free;
+ goto err_unmap_read_ack_addr;
error_block_length = generic->error_block_length;
if (error_block_length > GHES_ESTATUS_MAX_SIZE) {
pr_warning(FW_WARN GHES_PFX
@@ -263,13 +276,17 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
ghes->estatus = kmalloc(error_block_length, GFP_KERNEL);
if (!ghes->estatus) {
rc = -ENOMEM;
- goto err_unmap;
+ goto err_unmap_status_addr;
}
return ghes;
-err_unmap:
+err_unmap_status_addr:
apei_unmap_generic_address(&generic->error_status_address);
+err_unmap_read_ack_addr:
+ if (IS_HEST_TYPE_GENERIC_V2(ghes))
+ apei_unmap_generic_address(
+ &ghes->generic_v2->read_ack_register);
err_free:
kfree(ghes);
return ERR_PTR(rc);
@@ -279,6 +296,9 @@ static void ghes_fini(struct ghes *ghes)
{
kfree(ghes->estatus);
apei_unmap_generic_address(&ghes->generic->error_status_address);
+ if (IS_HEST_TYPE_GENERIC_V2(ghes))
+ apei_unmap_generic_address(
+ &ghes->generic_v2->read_ack_register);
}
static inline int ghes_severity(int severity)
@@ -648,6 +668,23 @@ static void ghes_estatus_cache_add(
rcu_read_unlock();
}
+static int ghes_ack_error(struct acpi_hest_generic_v2 *generic_v2)
+{
+ int rc;
+ u64 val = 0;
+
+ rc = apei_read(&val, &generic_v2->read_ack_register);
+ if (rc)
+ return rc;
+ val &= generic_v2->read_ack_preserve <<
+ generic_v2->read_ack_register.bit_offset;
+ val |= generic_v2->read_ack_write <<
+ generic_v2->read_ack_register.bit_offset;
+ rc = apei_write(val, &generic_v2->read_ack_register);
+
+ return rc;
+}
+
static int ghes_proc(struct ghes *ghes)
{
int rc;
@@ -660,6 +697,12 @@ static int ghes_proc(struct ghes *ghes)
ghes_estatus_cache_add(ghes->generic, ghes->estatus);
}
ghes_do_proc(ghes, ghes->estatus);
+
+ if (IS_HEST_TYPE_GENERIC_V2(ghes)) {
+ rc = ghes_ack_error(ghes->generic_v2);
+ if (rc)
+ return rc;
+ }
out:
ghes_clear_estatus(ghes);
return 0;
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
index 792a0d9..ef725a9 100644
--- a/drivers/acpi/apei/hest.c
+++ b/drivers/acpi/apei/hest.c
@@ -52,6 +52,7 @@ static const int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = {
[ACPI_HEST_TYPE_AER_ENDPOINT] = sizeof(struct acpi_hest_aer),
[ACPI_HEST_TYPE_AER_BRIDGE] = sizeof(struct acpi_hest_aer_bridge),
[ACPI_HEST_TYPE_GENERIC_ERROR] = sizeof(struct acpi_hest_generic),
+ [ACPI_HEST_TYPE_GENERIC_ERROR_V2] = sizeof(struct acpi_hest_generic_v2),
};
static int hest_esrc_len(struct acpi_hest_header *hest_hdr)
@@ -146,7 +147,8 @@ static int __init hest_parse_ghes_count(struct acpi_hest_header *hest_hdr, void
{
int *count = data;
- if (hest_hdr->type == ACPI_HEST_TYPE_GENERIC_ERROR)
+ if (hest_hdr->type == ACPI_HEST_TYPE_GENERIC_ERROR ||
+ hest_hdr->type == ACPI_HEST_TYPE_GENERIC_ERROR_V2)
(*count)++;
return 0;
}
@@ -157,7 +159,8 @@ static int __init hest_parse_ghes(struct acpi_hest_header *hest_hdr, void *data)
struct ghes_arr *ghes_arr = data;
int rc, i;
- if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR)
+ if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR &&
+ hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR_V2)
return 0;
if (!((struct acpi_hest_generic *)hest_hdr)->enabled)
diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h
index 720446c..68f088a 100644
--- a/include/acpi/ghes.h
+++ b/include/acpi/ghes.h
@@ -13,7 +13,10 @@
#define GHES_EXITING 0x0002
struct ghes {
- struct acpi_hest_generic *generic;
+ union {
+ struct acpi_hest_generic *generic;
+ struct acpi_hest_generic_v2 *generic_v2;
+ };
struct acpi_hest_generic_status *estatus;
u64 buffer_paddr;
unsigned long flags;
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
[toc] | [prev] | [next] | [standalone]
| From | Tyler Baicar <tbaicar@codeaurora.org> |
|---|---|
| Date | 2017-01-12 19:20 +0100 |
| Subject | [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort |
| Message-ID | <sYS8H-7eZ-31@gated-at.bofh.it> |
| In reply to | #1557693 |
SEA exceptions are often caused by an uncorrected hardware
error, and are handled when data abort and instruction abort
exception classes have specific values for their Fault Status
Code.
When SEA occurs, before killing the process, go through
the handlers registered in the notification list.
Update fault_info[] with specific SEA faults so that the
new SEA handler is used.
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
---
arch/arm64/include/asm/system_misc.h | 13 ++++++++
arch/arm64/mm/fault.c | 58 +++++++++++++++++++++++++++++-------
2 files changed, 61 insertions(+), 10 deletions(-)
diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
index 57f110b..e7f3440 100644
--- a/arch/arm64/include/asm/system_misc.h
+++ b/arch/arm64/include/asm/system_misc.h
@@ -64,4 +64,17 @@ extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
#endif /* __ASSEMBLY__ */
+/*
+ * The functions below are used to register and unregister callbacks
+ * that are to be invoked when a Synchronous External Abort (SEA)
+ * occurs. An SEA is raised by certain fault status codes that have
+ * either data or instruction abort as the exception class, and
+ * callbacks may be registered to parse or handle such hardware errors.
+ *
+ * Registered callbacks are run in an interrupt/atomic context. They
+ * are not allowed to block or sleep.
+ */
+int register_sea_notifier(struct notifier_block *nb);
+void unregister_sea_notifier(struct notifier_block *nb);
+
#endif /* __ASM_SYSTEM_MISC_H */
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 05d2bd7..81039c7 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -39,6 +39,22 @@
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
+/*
+ * GHES SEA handler code may register a notifier call here to
+ * handle HW error record passed from platform.
+ */
+static ATOMIC_NOTIFIER_HEAD(sea_handler_chain);
+
+int register_sea_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&sea_handler_chain, nb);
+}
+
+void unregister_sea_notifier(struct notifier_block *nb)
+{
+ atomic_notifier_chain_unregister(&sea_handler_chain, nb);
+}
+
static const char *fault_name(unsigned int esr);
#ifdef CONFIG_KPROBES
@@ -480,6 +496,28 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
return 1;
}
+/*
+ * This abort handler deals with Synchronous External Abort.
+ * It calls notifiers, and then returns "fault".
+ */
+static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
+{
+ struct siginfo info;
+
+ atomic_notifier_call_chain(&sea_handler_chain, 0, NULL);
+
+ pr_err("Synchronous External Abort: %s (0x%08x) at 0x%016lx\n",
+ fault_name(esr), esr, addr);
+
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = 0;
+ info.si_addr = (void __user *)addr;
+ arm64_notify_die("", regs, &info, esr);
+
+ return 0;
+}
+
static const struct fault_info {
int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs);
int sig;
@@ -502,22 +540,22 @@ static const struct fault_info {
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" },
{ do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" },
- { do_bad, SIGBUS, 0, "synchronous external abort" },
+ { do_sea, SIGBUS, 0, "synchronous external abort" },
{ do_bad, SIGBUS, 0, "unknown 17" },
{ do_bad, SIGBUS, 0, "unknown 18" },
{ do_bad, SIGBUS, 0, "unknown 19" },
- { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
- { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
- { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
- { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
- { do_bad, SIGBUS, 0, "synchronous parity error" },
+ { do_sea, SIGBUS, 0, "level 0 SEA (translation table walk)" },
+ { do_sea, SIGBUS, 0, "level 1 SEA (translation table walk)" },
+ { do_sea, SIGBUS, 0, "level 2 SEA (translation table walk)" },
+ { do_sea, SIGBUS, 0, "level 3 SEA (translation table walk)" },
+ { do_sea, SIGBUS, 0, "synchronous parity or ECC err" },
{ do_bad, SIGBUS, 0, "unknown 25" },
{ do_bad, SIGBUS, 0, "unknown 26" },
{ do_bad, SIGBUS, 0, "unknown 27" },
- { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk)" },
- { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk)" },
- { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk)" },
- { do_bad, SIGBUS, 0, "synchronous parity error (translation table walk)" },
+ { do_sea, SIGBUS, 0, "level 0 synchronous parity error (translation table walk)" },
+ { do_sea, SIGBUS, 0, "level 1 synchronous parity error (translation table walk)" },
+ { do_sea, SIGBUS, 0, "level 2 synchronous parity error (translation table walk)" },
+ { do_sea, SIGBUS, 0, "level 3 synchronous parity error (translation table walk)" },
{ do_bad, SIGBUS, 0, "unknown 32" },
{ do_alignment_fault, SIGBUS, BUS_ADRALN, "alignment fault" },
{ do_bad, SIGBUS, 0, "unknown 34" },
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
[toc] | [prev] | [next] | [standalone]
| From | Will Deacon <will.deacon@arm.com> |
|---|---|
| Date | 2017-01-16 13:00 +0100 |
| Subject | Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort |
| Message-ID | <t0e77-8ky-15@gated-at.bofh.it> |
| In reply to | #1557698 |
On Thu, Jan 12, 2017 at 11:15:18AM -0700, Tyler Baicar wrote:
> SEA exceptions are often caused by an uncorrected hardware
> error, and are handled when data abort and instruction abort
> exception classes have specific values for their Fault Status
> Code.
> When SEA occurs, before killing the process, go through
> the handlers registered in the notification list.
> Update fault_info[] with specific SEA faults so that the
> new SEA handler is used.
>
> Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
> Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
> Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
> ---
> arch/arm64/include/asm/system_misc.h | 13 ++++++++
> arch/arm64/mm/fault.c | 58 +++++++++++++++++++++++++++++-------
> 2 files changed, 61 insertions(+), 10 deletions(-)
>
> diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
> index 57f110b..e7f3440 100644
> --- a/arch/arm64/include/asm/system_misc.h
> +++ b/arch/arm64/include/asm/system_misc.h
> @@ -64,4 +64,17 @@ extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
>
> #endif /* __ASSEMBLY__ */
>
> +/*
> + * The functions below are used to register and unregister callbacks
> + * that are to be invoked when a Synchronous External Abort (SEA)
> + * occurs. An SEA is raised by certain fault status codes that have
> + * either data or instruction abort as the exception class, and
> + * callbacks may be registered to parse or handle such hardware errors.
> + *
> + * Registered callbacks are run in an interrupt/atomic context. They
> + * are not allowed to block or sleep.
> + */
> +int register_sea_notifier(struct notifier_block *nb);
> +void unregister_sea_notifier(struct notifier_block *nb);
I still don't understand why you need notifiers for this. You register
precisely one hook in the series.
> #endif /* __ASM_SYSTEM_MISC_H */
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index 05d2bd7..81039c7 100644
> --- a/arch/arm64/mm/fault.c
> +++ b/arch/arm64/mm/fault.c
> @@ -39,6 +39,22 @@
> #include <asm/pgtable.h>
> #include <asm/tlbflush.h>
>
> +/*
> + * GHES SEA handler code may register a notifier call here to
> + * handle HW error record passed from platform.
> + */
> +static ATOMIC_NOTIFIER_HEAD(sea_handler_chain);
> +
> +int register_sea_notifier(struct notifier_block *nb)
> +{
> + return atomic_notifier_chain_register(&sea_handler_chain, nb);
> +}
> +
> +void unregister_sea_notifier(struct notifier_block *nb)
> +{
> + atomic_notifier_chain_unregister(&sea_handler_chain, nb);
> +}
> +
> static const char *fault_name(unsigned int esr);
>
> #ifdef CONFIG_KPROBES
> @@ -480,6 +496,28 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
> return 1;
> }
>
> +/*
> + * This abort handler deals with Synchronous External Abort.
> + * It calls notifiers, and then returns "fault".
> + */
> +static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
> +{
> + struct siginfo info;
> +
> + atomic_notifier_call_chain(&sea_handler_chain, 0, NULL);
> +
> + pr_err("Synchronous External Abort: %s (0x%08x) at 0x%016lx\n",
> + fault_name(esr), esr, addr);
> +
> + info.si_signo = SIGBUS;
> + info.si_errno = 0;
> + info.si_code = 0;
> + info.si_addr = (void __user *)addr;
> + arm64_notify_die("", regs, &info, esr);
> +
> + return 0;
> +}
> +
> static const struct fault_info {
> int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs);
> int sig;
> @@ -502,22 +540,22 @@ static const struct fault_info {
> { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" },
> { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" },
> { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" },
> - { do_bad, SIGBUS, 0, "synchronous external abort" },
> + { do_sea, SIGBUS, 0, "synchronous external abort" },
> { do_bad, SIGBUS, 0, "unknown 17" },
> { do_bad, SIGBUS, 0, "unknown 18" },
> { do_bad, SIGBUS, 0, "unknown 19" },
> - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
> - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
> - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
> - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
> - { do_bad, SIGBUS, 0, "synchronous parity error" },
> + { do_sea, SIGBUS, 0, "level 0 SEA (translation table walk)" },
> + { do_sea, SIGBUS, 0, "level 1 SEA (translation table walk)" },
> + { do_sea, SIGBUS, 0, "level 2 SEA (translation table walk)" },
> + { do_sea, SIGBUS, 0, "level 3 SEA (translation table walk)" },
Perhaps I wasn't clear enough in my previous review, but please expand the
acronym for strings and comments.
> + { do_sea, SIGBUS, 0, "synchronous parity or ECC err" },
s/err/error/
Will
[toc] | [prev] | [next] | [standalone]
| From | "Baicar, Tyler" <tbaicar@codeaurora.org> |
|---|---|
| Date | 2017-01-16 21:20 +0100 |
| Subject | Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort |
| Message-ID | <t0lV0-5Di-23@gated-at.bofh.it> |
| In reply to | #1559667 |
Hello Will,
On 1/16/2017 4:53 AM, Will Deacon wrote:
> On Thu, Jan 12, 2017 at 11:15:18AM -0700, Tyler Baicar wrote:
>> SEA exceptions are often caused by an uncorrected hardware
>> error, and are handled when data abort and instruction abort
>> exception classes have specific values for their Fault Status
>> Code.
>> When SEA occurs, before killing the process, go through
>> the handlers registered in the notification list.
>> Update fault_info[] with specific SEA faults so that the
>> new SEA handler is used.
>>
>> Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
>> Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
>> Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
>> ---
>> arch/arm64/include/asm/system_misc.h | 13 ++++++++
>> arch/arm64/mm/fault.c | 58 +++++++++++++++++++++++++++++-------
>> 2 files changed, 61 insertions(+), 10 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
>> index 57f110b..e7f3440 100644
>> --- a/arch/arm64/include/asm/system_misc.h
>> +++ b/arch/arm64/include/asm/system_misc.h
>> @@ -64,4 +64,17 @@ extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
>>
>> #endif /* __ASSEMBLY__ */
>>
>> +/*
>> + * The functions below are used to register and unregister callbacks
>> + * that are to be invoked when a Synchronous External Abort (SEA)
>> + * occurs. An SEA is raised by certain fault status codes that have
>> + * either data or instruction abort as the exception class, and
>> + * callbacks may be registered to parse or handle such hardware errors.
>> + *
>> + * Registered callbacks are run in an interrupt/atomic context. They
>> + * are not allowed to block or sleep.
>> + */
>> +int register_sea_notifier(struct notifier_block *nb);
>> +void unregister_sea_notifier(struct notifier_block *nb);
> I still don't understand why you need notifiers for this. You register
> precisely one hook in the series.
I didn't see a response to my last comment on the previous series so I
just left it in for this series.
The notifier usage is consistent with the GHES code for SCI errors which
are also only used a single
time in the code. If you think making the call directly is a better
option I will remove the notifiers.
>> #endif /* __ASM_SYSTEM_MISC_H */
>> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
>> index 05d2bd7..81039c7 100644
>> --- a/arch/arm64/mm/fault.c
>> +++ b/arch/arm64/mm/fault.c
>> @@ -39,6 +39,22 @@
>> #include <asm/pgtable.h>
>> #include <asm/tlbflush.h>
>>
>> +/*
>> + * GHES SEA handler code may register a notifier call here to
>> + * handle HW error record passed from platform.
>> + */
>> +static ATOMIC_NOTIFIER_HEAD(sea_handler_chain);
>> +
>> +int register_sea_notifier(struct notifier_block *nb)
>> +{
>> + return atomic_notifier_chain_register(&sea_handler_chain, nb);
>> +}
>> +
>> +void unregister_sea_notifier(struct notifier_block *nb)
>> +{
>> + atomic_notifier_chain_unregister(&sea_handler_chain, nb);
>> +}
>> +
>> static const char *fault_name(unsigned int esr);
>>
>> #ifdef CONFIG_KPROBES
>> @@ -480,6 +496,28 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
>> return 1;
>> }
>>
>> +/*
>> + * This abort handler deals with Synchronous External Abort.
>> + * It calls notifiers, and then returns "fault".
>> + */
>> +static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
>> +{
>> + struct siginfo info;
>> +
>> + atomic_notifier_call_chain(&sea_handler_chain, 0, NULL);
>> +
>> + pr_err("Synchronous External Abort: %s (0x%08x) at 0x%016lx\n",
>> + fault_name(esr), esr, addr);
>> +
>> + info.si_signo = SIGBUS;
>> + info.si_errno = 0;
>> + info.si_code = 0;
>> + info.si_addr = (void __user *)addr;
>> + arm64_notify_die("", regs, &info, esr);
>> +
>> + return 0;
>> +}
>> +
>> static const struct fault_info {
>> int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs);
>> int sig;
>> @@ -502,22 +540,22 @@ static const struct fault_info {
>> { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" },
>> { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" },
>> { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" },
>> - { do_bad, SIGBUS, 0, "synchronous external abort" },
>> + { do_sea, SIGBUS, 0, "synchronous external abort" },
>> { do_bad, SIGBUS, 0, "unknown 17" },
>> { do_bad, SIGBUS, 0, "unknown 18" },
>> { do_bad, SIGBUS, 0, "unknown 19" },
>> - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
>> - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
>> - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
>> - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
>> - { do_bad, SIGBUS, 0, "synchronous parity error" },
>> + { do_sea, SIGBUS, 0, "level 0 SEA (translation table walk)" },
>> + { do_sea, SIGBUS, 0, "level 1 SEA (translation table walk)" },
>> + { do_sea, SIGBUS, 0, "level 2 SEA (translation table walk)" },
>> + { do_sea, SIGBUS, 0, "level 3 SEA (translation table walk)" },
> Perhaps I wasn't clear enough in my previous review, but please expand the
> acronym for strings and comments.
Sorry, I will expand these.
>> + { do_sea, SIGBUS, 0, "synchronous parity or ECC err" },
> s/err/error/
>
> Will
Thanks,
Tyler
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
[toc] | [prev] | [next] | [standalone]
| From | Will Deacon <will.deacon@arm.com> |
|---|---|
| Date | 2017-01-17 11:30 +0100 |
| Subject | Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort |
| Message-ID | <t0zbz-5Tg-9@gated-at.bofh.it> |
| In reply to | #1560037 |
On Mon, Jan 16, 2017 at 01:09:22PM -0700, Baicar, Tyler wrote: > On 1/16/2017 4:53 AM, Will Deacon wrote: > >On Thu, Jan 12, 2017 at 11:15:18AM -0700, Tyler Baicar wrote: > >>SEA exceptions are often caused by an uncorrected hardware > >>error, and are handled when data abort and instruction abort > >>exception classes have specific values for their Fault Status > >>Code. > >>When SEA occurs, before killing the process, go through > >>the handlers registered in the notification list. > >>Update fault_info[] with specific SEA faults so that the > >>new SEA handler is used. > >> > >>Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org> > >>Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org> > >>Signed-off-by: Naveen Kaje <nkaje@codeaurora.org> > >>--- > >> arch/arm64/include/asm/system_misc.h | 13 ++++++++ > >> arch/arm64/mm/fault.c | 58 +++++++++++++++++++++++++++++------- > >> 2 files changed, 61 insertions(+), 10 deletions(-) > >> > >>diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h > >>index 57f110b..e7f3440 100644 > >>--- a/arch/arm64/include/asm/system_misc.h > >>+++ b/arch/arm64/include/asm/system_misc.h > >>@@ -64,4 +64,17 @@ extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd); > >> #endif /* __ASSEMBLY__ */ > >>+/* > >>+ * The functions below are used to register and unregister callbacks > >>+ * that are to be invoked when a Synchronous External Abort (SEA) > >>+ * occurs. An SEA is raised by certain fault status codes that have > >>+ * either data or instruction abort as the exception class, and > >>+ * callbacks may be registered to parse or handle such hardware errors. > >>+ * > >>+ * Registered callbacks are run in an interrupt/atomic context. They > >>+ * are not allowed to block or sleep. > >>+ */ > >>+int register_sea_notifier(struct notifier_block *nb); > >>+void unregister_sea_notifier(struct notifier_block *nb); > >I still don't understand why you need notifiers for this. You register > >precisely one hook in the series. > I didn't see a response to my last comment on the previous series so I just > left it in for this series. > The notifier usage is consistent with the GHES code for SCI errors which are > also only used a single > time in the code. If you think making the call directly is a better option I > will remove the notifiers. Yes, please. It's easy to add the notifier infrastructure back if/when it's actually needed and I don't see why the low-level fault dispatching needs to be consistent with the GHES/SCI code. Will
[toc] | [prev] | [next] | [standalone]
| From | "Baicar, Tyler" <tbaicar@codeaurora.org> |
|---|---|
| Date | 2017-01-19 00:10 +0100 |
| Subject | Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort |
| Message-ID | <t17wD-1Zz-35@gated-at.bofh.it> |
| In reply to | #1560435 |
On 1/17/2017 3:27 AM, Will Deacon wrote: > On Mon, Jan 16, 2017 at 01:09:22PM -0700, Baicar, Tyler wrote: >> On 1/16/2017 4:53 AM, Will Deacon wrote: >>> On Thu, Jan 12, 2017 at 11:15:18AM -0700, Tyler Baicar wrote: >>>> SEA exceptions are often caused by an uncorrected hardware >>>> error, and are handled when data abort and instruction abort >>>> exception classes have specific values for their Fault Status >>>> Code. >>>> When SEA occurs, before killing the process, go through >>>> the handlers registered in the notification list. >>>> Update fault_info[] with specific SEA faults so that the >>>> new SEA handler is used. >>>> >>>> Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org> >>>> Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org> >>>> Signed-off-by: Naveen Kaje <nkaje@codeaurora.org> >>>> --- >>>> arch/arm64/include/asm/system_misc.h | 13 ++++++++ >>>> arch/arm64/mm/fault.c | 58 +++++++++++++++++++++++++++++------- >>>> 2 files changed, 61 insertions(+), 10 deletions(-) >>>> >>>> diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h >>>> index 57f110b..e7f3440 100644 >>>> --- a/arch/arm64/include/asm/system_misc.h >>>> +++ b/arch/arm64/include/asm/system_misc.h >>>> @@ -64,4 +64,17 @@ extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd); >>>> #endif /* __ASSEMBLY__ */ >>>> +/* >>>> + * The functions below are used to register and unregister callbacks >>>> + * that are to be invoked when a Synchronous External Abort (SEA) >>>> + * occurs. An SEA is raised by certain fault status codes that have >>>> + * either data or instruction abort as the exception class, and >>>> + * callbacks may be registered to parse or handle such hardware errors. >>>> + * >>>> + * Registered callbacks are run in an interrupt/atomic context. They >>>> + * are not allowed to block or sleep. >>>> + */ >>>> +int register_sea_notifier(struct notifier_block *nb); >>>> +void unregister_sea_notifier(struct notifier_block *nb); >>> I still don't understand why you need notifiers for this. You register >>> precisely one hook in the series. >> I didn't see a response to my last comment on the previous series so I just >> left it in for this series. >> The notifier usage is consistent with the GHES code for SCI errors which are >> also only used a single >> time in the code. If you think making the call directly is a better option I >> will remove the notifiers. > Yes, please. It's easy to add the notifier infrastructure back if/when it's > actually needed and I don't see why the low-level fault dispatching needs to > be consistent with the GHES/SCI code. > > Will Sounds good, I will remove the notifier in the next patchset. Thanks, Tyler -- Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc. Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.
[toc] | [prev] | [next] | [standalone]
| From | James Morse <james.morse@arm.com> |
|---|---|
| Date | 2017-01-17 11:30 +0100 |
| Subject | Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort |
| Message-ID | <t0zbB-5Tg-43@gated-at.bofh.it> |
| In reply to | #1559667 |
Hi Tyler,
On 16/01/17 11:53, Will Deacon wrote:
> On Thu, Jan 12, 2017 at 11:15:18AM -0700, Tyler Baicar wrote:
>> SEA exceptions are often caused by an uncorrected hardware
>> error, and are handled when data abort and instruction abort
>> exception classes have specific values for their Fault Status
>> Code.
>> When SEA occurs, before killing the process, go through
>> the handlers registered in the notification list.
>> Update fault_info[] with specific SEA faults so that the
>> new SEA handler is used.
>> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
>> index 05d2bd7..81039c7 100644
>> --- a/arch/arm64/mm/fault.c
>> +++ b/arch/arm64/mm/fault.c
>> @@ -480,6 +496,28 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
>> return 1;
>> }
>>
>> +/*
>> + * This abort handler deals with Synchronous External Abort.
>> + * It calls notifiers, and then returns "fault".
>> + */
>> +static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
>> +{
>> + struct siginfo info;
>> +
>> + atomic_notifier_call_chain(&sea_handler_chain, 0, NULL);
>> +
>> + pr_err("Synchronous External Abort: %s (0x%08x) at 0x%016lx\n",
>> + fault_name(esr), esr, addr);
>> +
>> + info.si_signo = SIGBUS;
>> + info.si_errno = 0;
>> + info.si_code = 0;
>> + info.si_addr = (void __user *)addr;
>> + arm64_notify_die("", regs, &info, esr);
>> +
>> + return 0;
>> +}
>> +
>> static const struct fault_info {
>> int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs);
>> int sig;
>> @@ -502,22 +540,22 @@ static const struct fault_info {
>> { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" },
>> { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" },
>> { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" },
>> - { do_bad, SIGBUS, 0, "synchronous external abort" },
>> + { do_sea, SIGBUS, 0, "synchronous external abort" },
>> { do_bad, SIGBUS, 0, "unknown 17" },
>> { do_bad, SIGBUS, 0, "unknown 18" },
>> { do_bad, SIGBUS, 0, "unknown 19" },
>> - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
>> - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
>> - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
>> - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
>> - { do_bad, SIGBUS, 0, "synchronous parity error" },
>> + { do_sea, SIGBUS, 0, "level 0 SEA (translation table walk)" },
>> + { do_sea, SIGBUS, 0, "level 1 SEA (translation table walk)" },
>> + { do_sea, SIGBUS, 0, "level 2 SEA (translation table walk)" },
>> + { do_sea, SIGBUS, 0, "level 3 SEA (translation table walk)" },
>
> Perhaps I wasn't clear enough in my previous review, but please expand the
> acronym for strings and comments.
The 'SEA' in this user-string doesn't add anything. Now that these use do_sea()
instead of do_bad(), when they are printed won't it be:
> Synchronous External Abort: level 3 SEA (translation table walk) (...) at ....
Thanks,
James
[toc] | [prev] | [next] | [standalone]
| From | "Baicar, Tyler" <tbaicar@codeaurora.org> |
|---|---|
| Date | 2017-01-19 00:00 +0100 |
| Subject | Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort |
| Message-ID | <t17mW-1Gi-15@gated-at.bofh.it> |
| In reply to | #1560446 |
On 1/17/2017 3:23 AM, James Morse wrote:
> Hi Tyler,
>
> On 16/01/17 11:53, Will Deacon wrote:
>> On Thu, Jan 12, 2017 at 11:15:18AM -0700, Tyler Baicar wrote:
>>> SEA exceptions are often caused by an uncorrected hardware
>>> error, and are handled when data abort and instruction abort
>>> exception classes have specific values for their Fault Status
>>> Code.
>>> When SEA occurs, before killing the process, go through
>>> the handlers registered in the notification list.
>>> Update fault_info[] with specific SEA faults so that the
>>> new SEA handler is used.
>>> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
>>> index 05d2bd7..81039c7 100644
>>> --- a/arch/arm64/mm/fault.c
>>> +++ b/arch/arm64/mm/fault.c
>>> @@ -480,6 +496,28 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
>>> return 1;
>>> }
>>>
>>> +/*
>>> + * This abort handler deals with Synchronous External Abort.
>>> + * It calls notifiers, and then returns "fault".
>>> + */
>>> +static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
>>> +{
>>> + struct siginfo info;
>>> +
>>> + atomic_notifier_call_chain(&sea_handler_chain, 0, NULL);
>>> +
>>> + pr_err("Synchronous External Abort: %s (0x%08x) at 0x%016lx\n",
>>> + fault_name(esr), esr, addr);
>>> +
>>> + info.si_signo = SIGBUS;
>>> + info.si_errno = 0;
>>> + info.si_code = 0;
>>> + info.si_addr = (void __user *)addr;
>>> + arm64_notify_die("", regs, &info, esr);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static const struct fault_info {
>>> int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs);
>>> int sig;
>>> @@ -502,22 +540,22 @@ static const struct fault_info {
>>> { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 1 permission fault" },
>>> { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 2 permission fault" },
>>> { do_page_fault, SIGSEGV, SEGV_ACCERR, "level 3 permission fault" },
>>> - { do_bad, SIGBUS, 0, "synchronous external abort" },
>>> + { do_sea, SIGBUS, 0, "synchronous external abort" },
>>> { do_bad, SIGBUS, 0, "unknown 17" },
>>> { do_bad, SIGBUS, 0, "unknown 18" },
>>> { do_bad, SIGBUS, 0, "unknown 19" },
>>> - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
>>> - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
>>> - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
>>> - { do_bad, SIGBUS, 0, "synchronous abort (translation table walk)" },
>>> - { do_bad, SIGBUS, 0, "synchronous parity error" },
>>> + { do_sea, SIGBUS, 0, "level 0 SEA (translation table walk)" },
>>> + { do_sea, SIGBUS, 0, "level 1 SEA (translation table walk)" },
>>> + { do_sea, SIGBUS, 0, "level 2 SEA (translation table walk)" },
>>> + { do_sea, SIGBUS, 0, "level 3 SEA (translation table walk)" },
>> Perhaps I wasn't clear enough in my previous review, but please expand the
>> acronym for strings and comments.
>
> The 'SEA' in this user-string doesn't add anything. Now that these use do_sea()
> instead of do_bad(), when they are printed won't it be:
>> Synchronous External Abort: level 3 SEA (translation table walk) (...) at ....
Good point, yes they will:
+ pr_err("Synchronous External Abort: %s (0x%08x) at 0x%016lx\n",
+ fault_name(esr), esr, addr);
I can just remove SEA here then.
Thanks,
Tyler
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
[toc] | [prev] | [next] | [standalone]
| From | James Morse <james.morse@arm.com> |
|---|---|
| Date | 2017-01-17 11:40 +0100 |
| Subject | Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort |
| Message-ID | <t0zlg-5WC-23@gated-at.bofh.it> |
| In reply to | #1557698 |
Hi Tyler,
On 12/01/17 18:15, Tyler Baicar wrote:
> SEA exceptions are often caused by an uncorrected hardware
> error, and are handled when data abort and instruction abort
> exception classes have specific values for their Fault Status
> Code.
> When SEA occurs, before killing the process, go through
> the handlers registered in the notification list.
> Update fault_info[] with specific SEA faults so that the
> new SEA handler is used.
> @@ -480,6 +496,28 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
> return 1;
> }
>
> +/*
> + * This abort handler deals with Synchronous External Abort.
> + * It calls notifiers, and then returns "fault".
> + */
> +static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
> +{
> + struct siginfo info;
> +
> + atomic_notifier_call_chain(&sea_handler_chain, 0, NULL);
> +
> + pr_err("Synchronous External Abort: %s (0x%08x) at 0x%016lx\n",
> + fault_name(esr), esr, addr);
> +
> + info.si_signo = SIGBUS;
> + info.si_errno = 0;
> + info.si_code = 0;
Half of the other do_*() functions in this file read the signo and code from the
fault_info table.
> + info.si_addr = (void __user *)addr;
addr here was read from FAR_EL1, but for some of the classes of exception you
have listed below this register isn't updated with the faulting address.
The ARM-ARM version 'k' in D1.10.5 "Summary of registers on faults taken to an
Exception level that is using Aarch64" has:
> The architecture permits that the FAR_ELx is UNKNOWN for Synchronous External
> Aborts other than Synchronous External Aborts on Translation Table Walks. In
> this case, the ISS.FnV bit returned in ESR_ELx indicates whether FAR_ELx is
> valid.
This is a problem if we get 'synchronous external abort' or 'synchronous parity
error' while a user space process was running.
> + arm64_notify_die("", regs, &info, esr);
> +
> + return 0;
> +}
> +
> static const struct fault_info {
> int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs);
> int sig;
Thanks,
James
[toc] | [prev] | [next] | [standalone]
| From | "Baicar, Tyler" <tbaicar@codeaurora.org> |
|---|---|
| Date | 2017-01-19 00:30 +0100 |
| Subject | Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort |
| Message-ID | <t17PY-26r-13@gated-at.bofh.it> |
| In reply to | #1560463 |
Hello James,
On 1/17/2017 3:31 AM, James Morse wrote:
> Hi Tyler,
>
> On 12/01/17 18:15, Tyler Baicar wrote:
>> SEA exceptions are often caused by an uncorrected hardware
>> error, and are handled when data abort and instruction abort
>> exception classes have specific values for their Fault Status
>> Code.
>> When SEA occurs, before killing the process, go through
>> the handlers registered in the notification list.
>> Update fault_info[] with specific SEA faults so that the
>> new SEA handler is used.
>> @@ -480,6 +496,28 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
>> return 1;
>> }
>>
>> +/*
>> + * This abort handler deals with Synchronous External Abort.
>> + * It calls notifiers, and then returns "fault".
>> + */
>> +static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
>> +{
>> + struct siginfo info;
>> +
>> + atomic_notifier_call_chain(&sea_handler_chain, 0, NULL);
>> +
>> + pr_err("Synchronous External Abort: %s (0x%08x) at 0x%016lx\n",
>> + fault_name(esr), esr, addr);
>> +
>> + info.si_signo = SIGBUS;
>> + info.si_errno = 0;
>> + info.si_code = 0;
> Half of the other do_*() functions in this file read the signo and code from the
> fault_info table.
>
>
>> + info.si_addr = (void __user *)addr;
> addr here was read from FAR_EL1, but for some of the classes of exception you
> have listed below this register isn't updated with the faulting address.
>
> The ARM-ARM version 'k' in D1.10.5 "Summary of registers on faults taken to an
> Exception level that is using Aarch64" has:
>> The architecture permits that the FAR_ELx is UNKNOWN for Synchronous External
>> Aborts other than Synchronous External Aborts on Translation Table Walks. In
>> this case, the ISS.FnV bit returned in ESR_ELx indicates whether FAR_ELx is
>> valid.
> This is a problem if we get 'synchronous external abort' or 'synchronous parity
> error' while a user space process was running.
It looks like this would just cause an incorrect address to be printed
in the above pr_err.
Unless I'm missing something, I don't see arm64_notify_die or anything
that gets called from
there using the info.si_addr variable.
What do you suggest I do here? The firmware should be reporting the
physical and virtual
address information if it is available in the HEST entry that the kernel
will parse. So should I
just remove the use of the addr parameter in do_sea?
Thanks,
Tyler
>> + arm64_notify_die("", regs, &info, esr);
>> +
>> + return 0;
>> +}
>> +
>> static const struct fault_info {
>> int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs);
>> int sig;
>
> Thanks,
>
> James
>
>
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
[toc] | [prev] | [next] | [standalone]
| From | James Morse <james.morse@arm.com> |
|---|---|
| Date | 2017-01-19 19:20 +0100 |
| Subject | Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort |
| Message-ID | <t1ptw-4XW-3@gated-at.bofh.it> |
| In reply to | #1562280 |
Hi Tyler,
On 18/01/17 23:26, Baicar, Tyler wrote:
> On 1/17/2017 3:31 AM, James Morse wrote:
>> On 12/01/17 18:15, Tyler Baicar wrote:
>>> SEA exceptions are often caused by an uncorrected hardware
>>> error, and are handled when data abort and instruction abort
>>> exception classes have specific values for their Fault Status
>>> Code.
>>> When SEA occurs, before killing the process, go through
>>> the handlers registered in the notification list.
>>> Update fault_info[] with specific SEA faults so that the
>>> new SEA handler is used.
>>> @@ -480,6 +496,28 @@ static int do_bad(unsigned long addr, unsigned int esr,
>>> struct pt_regs *regs)
>>> return 1;
>>> }
>>> +/*
>>> + * This abort handler deals with Synchronous External Abort.
>>> + * It calls notifiers, and then returns "fault".
>>> + */
>>> +static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
>>> +{
>>> + struct siginfo info;
>>> +
>>> + atomic_notifier_call_chain(&sea_handler_chain, 0, NULL);
>>> +
>>> + pr_err("Synchronous External Abort: %s (0x%08x) at 0x%016lx\n",
>>> + fault_name(esr), esr, addr);
>>> +
>>> + info.si_signo = SIGBUS;
>>> + info.si_errno = 0;
>>> + info.si_code = 0;
>> Half of the other do_*() functions in this file read the signo and code from the
>> fault_info table.
>>
>>
>>> + info.si_addr = (void __user *)addr;
>> addr here was read from FAR_EL1, but for some of the classes of exception you
>> have listed below this register isn't updated with the faulting address.
>>
>> The ARM-ARM version 'k' in D1.10.5 "Summary of registers on faults taken to an
>> Exception level that is using Aarch64" has:
>>> The architecture permits that the FAR_ELx is UNKNOWN for Synchronous External
>>> Aborts other than Synchronous External Aborts on Translation Table Walks. In
>>> this case, the ISS.FnV bit returned in ESR_ELx indicates whether FAR_ELx is
>>> valid.
>> This is a problem if we get 'synchronous external abort' or 'synchronous parity
>> error' while a user space process was running.
> It looks like this would just cause an incorrect address to be printed in the
> above pr_err.
> Unless I'm missing something, I don't see arm64_notify_die or anything that gets
> called from
> there using the info.si_addr variable.
I may be misreading something here...
This patch has:
> info.si_addr = (void __user *)addr;
> arm64_notify_die("", regs, &info, esr);
From arch/arm64/kernel/traps.c:arm64_notify_die():
> if (user_mode(regs)) {
> current->thread.fault_address = 0;
> current->thread.fault_code = err;
> force_sig_info(info->si_signo, info, current);
> }
So if the SEA interrupted userspace, we put maybe-unknown addr into
force_sig_info() to deliver a signal to user space. User-space then gets a copy
of the info struct containing the maybe-unknown addr.
I think this is an existing bug, but if we are separating the synchronous
external aborts from the generic do_bad handler, we should probably check the
FnV bit. (I think we should still print it out)
> What do you suggest I do here? The firmware should be reporting the physical and
> virtual
> address information if it is available in the HEST entry that the kernel will
> parse.
Its not just firmware that may trigger this, other SoCs may use it for parity or
ECC errors, and they may not always have a valid address in FAR_EL1.
I think we should check the FnV bit in the esr variable and set info.si_addr to
0 if the addr we have isn't valid:
'For some implementations, the value of si_addr may be inaccurate.' [0]
Thanks,
James
[0] http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html
[toc] | [prev] | [next] | [standalone]
| From | "Baicar, Tyler" <tbaicar@codeaurora.org> |
|---|---|
| Date | 2017-01-20 21:40 +0100 |
| Subject | Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort |
| Message-ID | <t1O8y-3uV-23@gated-at.bofh.it> |
| In reply to | #1562985 |
On 1/19/2017 10:55 AM, James Morse wrote:
> Hi Tyler,
>
> On 18/01/17 23:26, Baicar, Tyler wrote:
>> On 1/17/2017 3:31 AM, James Morse wrote:
>>> On 12/01/17 18:15, Tyler Baicar wrote:
>>>> SEA exceptions are often caused by an uncorrected hardware
>>>> error, and are handled when data abort and instruction abort
>>>> exception classes have specific values for their Fault Status
>>>> Code.
>>>> When SEA occurs, before killing the process, go through
>>>> the handlers registered in the notification list.
>>>> Update fault_info[] with specific SEA faults so that the
>>>> new SEA handler is used.
>>>> @@ -480,6 +496,28 @@ static int do_bad(unsigned long addr, unsigned int esr,
>>>> struct pt_regs *regs)
>>>> return 1;
>>>> }
>>>> +/*
>>>> + * This abort handler deals with Synchronous External Abort.
>>>> + * It calls notifiers, and then returns "fault".
>>>> + */
>>>> +static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
>>>> +{
>>>> + struct siginfo info;
>>>> +
>>>> + atomic_notifier_call_chain(&sea_handler_chain, 0, NULL);
>>>> +
>>>> + pr_err("Synchronous External Abort: %s (0x%08x) at 0x%016lx\n",
>>>> + fault_name(esr), esr, addr);
>>>> +
>>>> + info.si_signo = SIGBUS;
>>>> + info.si_errno = 0;
>>>> + info.si_code = 0;
>>> Half of the other do_*() functions in this file read the signo and code from the
>>> fault_info table.
>>>
>>>
>>>> + info.si_addr = (void __user *)addr;
>>> addr here was read from FAR_EL1, but for some of the classes of exception you
>>> have listed below this register isn't updated with the faulting address.
>>>
>>> The ARM-ARM version 'k' in D1.10.5 "Summary of registers on faults taken to an
>>> Exception level that is using Aarch64" has:
>>>> The architecture permits that the FAR_ELx is UNKNOWN for Synchronous External
>>>> Aborts other than Synchronous External Aborts on Translation Table Walks. In
>>>> this case, the ISS.FnV bit returned in ESR_ELx indicates whether FAR_ELx is
>>>> valid.
>>> This is a problem if we get 'synchronous external abort' or 'synchronous parity
>>> error' while a user space process was running.
>> It looks like this would just cause an incorrect address to be printed in the
>> above pr_err.
>> Unless I'm missing something, I don't see arm64_notify_die or anything that gets
>> called from
>> there using the info.si_addr variable.
> I may be misreading something here...
>
> This patch has:
>> info.si_addr = (void __user *)addr;
>> arm64_notify_die("", regs, &info, esr);
> From arch/arm64/kernel/traps.c:arm64_notify_die():
>> if (user_mode(regs)) {
>> current->thread.fault_address = 0;
>> current->thread.fault_code = err;
>> force_sig_info(info->si_signo, info, current);
>> }
> So if the SEA interrupted userspace, we put maybe-unknown addr into
> force_sig_info() to deliver a signal to user space. User-space then gets a copy
> of the info struct containing the maybe-unknown addr.
>
> I think this is an existing bug, but if we are separating the synchronous
> external aborts from the generic do_bad handler, we should probably check the
> FnV bit. (I think we should still print it out)
>
>
>> What do you suggest I do here? The firmware should be reporting the physical and
>> virtual
>> address information if it is available in the HEST entry that the kernel will
>> parse.
> Its not just firmware that may trigger this, other SoCs may use it for parity or
> ECC errors, and they may not always have a valid address in FAR_EL1.
>
> I think we should check the FnV bit in the esr variable and set info.si_addr to
> 0 if the addr we have isn't valid:
> 'For some implementations, the value of si_addr may be inaccurate.' [0]
>
>
> Thanks,
>
> James
>
>
> [0] http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html
Hello James,
Okay, that makes sense, we don't want userspace to be notified with an
incorrect address.
I will add the check to verify it's valid. Which bit in the ESR is the
FnV bit? I'm not finding
the bit breakdown of the ISS that shows it.
Thanks,
Tyler
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
[toc] | [prev] | [next] | [standalone]
| From | James Morse <james.morse@arm.com> |
|---|---|
| Date | 2017-01-23 11:10 +0100 |
| Subject | Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort |
| Message-ID | <t2JJw-56E-41@gated-at.bofh.it> |
| In reply to | #1563904 |
Hi Tyler,
On 20/01/17 20:35, Baicar, Tyler wrote:
> On 1/19/2017 10:55 AM, James Morse wrote:
>> On 18/01/17 23:26, Baicar, Tyler wrote:
>>> On 1/17/2017 3:31 AM, James Morse wrote:
>>>> On 12/01/17 18:15, Tyler Baicar wrote:
>>>>> + info.si_addr = (void __user *)addr;
>>>> addr here was read from FAR_EL1, but for some of the classes of exception you
>>>> have listed below this register isn't updated with the faulting address.
>>>>
>>>> The ARM-ARM version 'k' in D1.10.5 "Summary of registers on faults taken to an
>>>> Exception level that is using Aarch64" has:
>>>>> The architecture permits that the FAR_ELx is UNKNOWN for Synchronous External
>>>>> Aborts other than Synchronous External Aborts on Translation Table Walks. In
>>>>> this case, the ISS.FnV bit returned in ESR_ELx indicates whether FAR_ELx is
>>>>> valid.
>>>> This is a problem if we get 'synchronous external abort' or 'synchronous parity
>>>> error' while a user space process was running.
>>> It looks like this would just cause an incorrect address to be printed in the
>>> above pr_err.
>>> Unless I'm missing something, I don't see arm64_notify_die or anything that gets
>>> called from
>>> there using the info.si_addr variable.
>> I may be misreading something here...
>>
>> This patch has:
>>> info.si_addr = (void __user *)addr;
>>> arm64_notify_die("", regs, &info, esr);
>> From arch/arm64/kernel/traps.c:arm64_notify_die():
>>> if (user_mode(regs)) {
>>> current->thread.fault_address = 0;
>>> current->thread.fault_code = err;
>>> force_sig_info(info->si_signo, info, current);
>>> }
>> So if the SEA interrupted userspace, we put maybe-unknown addr into
>> force_sig_info() to deliver a signal to user space. User-space then gets a copy
>> of the info struct containing the maybe-unknown addr.
>>
>> I think this is an existing bug, but if we are separating the synchronous
>> external aborts from the generic do_bad handler, we should probably check the
>> FnV bit. (I think we should still print it out)
>>
>>
>>> What do you suggest I do here? The firmware should be reporting the physical and
>>> virtual
>>> address information if it is available in the HEST entry that the kernel will
>>> parse.
>> Its not just firmware that may trigger this, other SoCs may use it for parity or
>> ECC errors, and they may not always have a valid address in FAR_EL1.
>>
>> I think we should check the FnV bit in the esr variable and set info.si_addr to
>> 0 if the addr we have isn't valid:
>> 'For some implementations, the value of si_addr may be inaccurate.' [0]
> Okay, that makes sense, we don't want userspace to be notified with an incorrect
> address.
> I will add the check to verify it's valid. Which bit in the ESR is the FnV bit?
> I'm not finding
> the bit breakdown of the ISS that shows it.
The bits in ISS vary depending on the EC, so a little digging is required.
"D7.2.27 ESR_ELx, Exception Syndrome Register (ELx)" lists the EC values, from
there 'Instruction Abort' and 'Data Abort' both list FnV as bit 10. Version 'k'
of the ARM-ARM has this on pages D7-1953 to D7-1956.
Thanks,
James
[toc] | [prev] | [next] | [standalone]
| From | "Baicar, Tyler" <tbaicar@codeaurora.org> |
|---|---|
| Date | 2017-01-24 19:50 +0100 |
| Subject | Re: [PATCH V7 04/10] arm64: exception: handle Synchronous External Abort |
| Message-ID | <t3ekh-7Q2-3@gated-at.bofh.it> |
| In reply to | #1564843 |
On 1/23/2017 3:01 AM, James Morse wrote:
> Hi Tyler,
>
> On 20/01/17 20:35, Baicar, Tyler wrote:
>> On 1/19/2017 10:55 AM, James Morse wrote:
>>> On 18/01/17 23:26, Baicar, Tyler wrote:
>>>> On 1/17/2017 3:31 AM, James Morse wrote:
>>>>> On 12/01/17 18:15, Tyler Baicar wrote:
>>>>>> + info.si_addr = (void __user *)addr;
>>>>> addr here was read from FAR_EL1, but for some of the classes of exception you
>>>>> have listed below this register isn't updated with the faulting address.
>>>>>
>>>>> The ARM-ARM version 'k' in D1.10.5 "Summary of registers on faults taken to an
>>>>> Exception level that is using Aarch64" has:
>>>>>> The architecture permits that the FAR_ELx is UNKNOWN for Synchronous External
>>>>>> Aborts other than Synchronous External Aborts on Translation Table Walks. In
>>>>>> this case, the ISS.FnV bit returned in ESR_ELx indicates whether FAR_ELx is
>>>>>> valid.
>>>>> This is a problem if we get 'synchronous external abort' or 'synchronous parity
>>>>> error' while a user space process was running.
>>>> It looks like this would just cause an incorrect address to be printed in the
>>>> above pr_err.
>>>> Unless I'm missing something, I don't see arm64_notify_die or anything that gets
>>>> called from
>>>> there using the info.si_addr variable.
>>> I may be misreading something here...
>>>
>>> This patch has:
>>>> info.si_addr = (void __user *)addr;
>>>> arm64_notify_die("", regs, &info, esr);
>>> From arch/arm64/kernel/traps.c:arm64_notify_die():
>>>> if (user_mode(regs)) {
>>>> current->thread.fault_address = 0;
>>>> current->thread.fault_code = err;
>>>> force_sig_info(info->si_signo, info, current);
>>>> }
>>> So if the SEA interrupted userspace, we put maybe-unknown addr into
>>> force_sig_info() to deliver a signal to user space. User-space then gets a copy
>>> of the info struct containing the maybe-unknown addr.
>>>
>>> I think this is an existing bug, but if we are separating the synchronous
>>> external aborts from the generic do_bad handler, we should probably check the
>>> FnV bit. (I think we should still print it out)
>>>
>>>
>>>> What do you suggest I do here? The firmware should be reporting the physical and
>>>> virtual
>>>> address information if it is available in the HEST entry that the kernel will
>>>> parse.
>>> Its not just firmware that may trigger this, other SoCs may use it for parity or
>>> ECC errors, and they may not always have a valid address in FAR_EL1.
>>>
>>> I think we should check the FnV bit in the esr variable and set info.si_addr to
>>> 0 if the addr we have isn't valid:
>>> 'For some implementations, the value of si_addr may be inaccurate.' [0]
>> Okay, that makes sense, we don't want userspace to be notified with an incorrect
>> address.
>> I will add the check to verify it's valid. Which bit in the ESR is the FnV bit?
>> I'm not finding
>> the bit breakdown of the ISS that shows it.
> The bits in ISS vary depending on the EC, so a little digging is required.
> "D7.2.27 ESR_ELx, Exception Syndrome Register (ELx)" lists the EC values, from
> there 'Instruction Abort' and 'Data Abort' both list FnV as bit 10. Version 'k'
> of the ARM-ARM has this on pages D7-1953 to D7-1956.
Got it! I'll add the check for this in my next patchset.
Thanks,
Tyler
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
[toc] | [prev] | [next] | [standalone]
| From | Tyler Baicar <tbaicar@codeaurora.org> |
|---|---|
| Date | 2017-01-12 19:30 +0100 |
| Subject | [PATCH V7 10/10] arm/arm64: KVM: add guest SEA support |
| Message-ID | <sYSim-7i7-13@gated-at.bofh.it> |
| In reply to | #1557693 |
Currently external aborts are unsupported by the guest abort
handling. Add handling for SEAs so that the host kernel reports
SEAs which occur in the guest kernel.
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
---
arch/arm/include/asm/kvm_arm.h | 1 +
arch/arm/include/asm/system_misc.h | 5 +++++
arch/arm/kvm/mmu.c | 18 ++++++++++++++++--
arch/arm64/include/asm/kvm_arm.h | 1 +
arch/arm64/include/asm/system_misc.h | 2 ++
arch/arm64/mm/fault.c | 13 +++++++++++++
6 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
index e22089f..33a77509 100644
--- a/arch/arm/include/asm/kvm_arm.h
+++ b/arch/arm/include/asm/kvm_arm.h
@@ -187,6 +187,7 @@
#define FSC_FAULT (0x04)
#define FSC_ACCESS (0x08)
#define FSC_PERM (0x0c)
+#define FSC_EXTABT (0x10)
/* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
#define HPFAR_MASK (~0xf)
diff --git a/arch/arm/include/asm/system_misc.h b/arch/arm/include/asm/system_misc.h
index a3d61ad..ea45d94 100644
--- a/arch/arm/include/asm/system_misc.h
+++ b/arch/arm/include/asm/system_misc.h
@@ -24,4 +24,9 @@ extern unsigned int user_debug;
#endif /* !__ASSEMBLY__ */
+static inline int handle_guest_sea(unsigned long addr, unsigned int esr)
+{
+ return -1;
+}
+
#endif /* __ASM_ARM_SYSTEM_MISC_H */
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index e9a5c0e..1152966 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -29,6 +29,7 @@
#include <asm/kvm_asm.h>
#include <asm/kvm_emulate.h>
#include <asm/virt.h>
+#include <asm/system_misc.h>
#include "trace.h"
@@ -1441,8 +1442,21 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
/* Check the stage-2 fault is trans. fault or write fault */
fault_status = kvm_vcpu_trap_get_fault_type(vcpu);
- if (fault_status != FSC_FAULT && fault_status != FSC_PERM &&
- fault_status != FSC_ACCESS) {
+
+ /* The host kernel will handle the synchronous external abort. There
+ * is no need to pass the error into the guest.
+ */
+ if (fault_status == FSC_EXTABT) {
+ if(handle_guest_sea((unsigned long)fault_ipa,
+ kvm_vcpu_get_hsr(vcpu))) {
+ kvm_err("Failed to handle guest SEA, FSC: EC=%#x xFSC=%#lx ESR_EL2=%#lx\n",
+ kvm_vcpu_trap_get_class(vcpu),
+ (unsigned long)kvm_vcpu_trap_get_fault(vcpu),
+ (unsigned long)kvm_vcpu_get_hsr(vcpu));
+ return -EFAULT;
+ }
+ } else if (fault_status != FSC_FAULT && fault_status != FSC_PERM &&
+ fault_status != FSC_ACCESS) {
kvm_err("Unsupported FSC: EC=%#x xFSC=%#lx ESR_EL2=%#lx\n",
kvm_vcpu_trap_get_class(vcpu),
(unsigned long)kvm_vcpu_trap_get_fault(vcpu),
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 4b5c977..be0efb6 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -201,6 +201,7 @@
#define FSC_FAULT ESR_ELx_FSC_FAULT
#define FSC_ACCESS ESR_ELx_FSC_ACCESS
#define FSC_PERM ESR_ELx_FSC_PERM
+#define FSC_EXTABT ESR_ELx_FSC_EXTABT
/* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
#define HPFAR_MASK (~UL(0xf))
diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
index e7f3440..27816cb 100644
--- a/arch/arm64/include/asm/system_misc.h
+++ b/arch/arm64/include/asm/system_misc.h
@@ -77,4 +77,6 @@ extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
int register_sea_notifier(struct notifier_block *nb);
void unregister_sea_notifier(struct notifier_block *nb);
+int handle_guest_sea(unsigned long addr, unsigned int esr);
+
#endif /* __ASM_SYSTEM_MISC_H */
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 81039c7..fa8d4d7 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -597,6 +597,19 @@ static const char *fault_name(unsigned int esr)
}
/*
+ * Handle Synchronous External Aborts that occur in a guest kernel.
+ */
+int handle_guest_sea(unsigned long addr, unsigned int esr)
+{
+ atomic_notifier_call_chain(&sea_handler_chain, 0, NULL);
+
+ pr_err("Synchronous External Abort: %s (0x%08x) at 0x%016lx\n",
+ fault_name(esr), esr, addr);
+
+ return 0;
+}
+
+/*
* Dispatch a data abort to the relevant handler.
*/
asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
[toc] | [prev] | [next] | [standalone]
| From | Marc Zyngier <marc.zyngier@arm.com> |
|---|---|
| Date | 2017-01-16 13:00 +0100 |
| Subject | Re: [PATCH V7 10/10] arm/arm64: KVM: add guest SEA support |
| Message-ID | <t0e77-8ky-1@gated-at.bofh.it> |
| In reply to | #1557699 |
Hi Tyler,
On 12/01/17 18:15, Tyler Baicar wrote:
> Currently external aborts are unsupported by the guest abort
> handling. Add handling for SEAs so that the host kernel reports
> SEAs which occur in the guest kernel.
>
> Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
> ---
> arch/arm/include/asm/kvm_arm.h | 1 +
> arch/arm/include/asm/system_misc.h | 5 +++++
> arch/arm/kvm/mmu.c | 18 ++++++++++++++++--
> arch/arm64/include/asm/kvm_arm.h | 1 +
> arch/arm64/include/asm/system_misc.h | 2 ++
> arch/arm64/mm/fault.c | 13 +++++++++++++
> 6 files changed, 38 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
> index e22089f..33a77509 100644
> --- a/arch/arm/include/asm/kvm_arm.h
> +++ b/arch/arm/include/asm/kvm_arm.h
> @@ -187,6 +187,7 @@
> #define FSC_FAULT (0x04)
> #define FSC_ACCESS (0x08)
> #define FSC_PERM (0x0c)
> +#define FSC_EXTABT (0x10)
>
> /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
> #define HPFAR_MASK (~0xf)
> diff --git a/arch/arm/include/asm/system_misc.h b/arch/arm/include/asm/system_misc.h
> index a3d61ad..ea45d94 100644
> --- a/arch/arm/include/asm/system_misc.h
> +++ b/arch/arm/include/asm/system_misc.h
> @@ -24,4 +24,9 @@ extern unsigned int user_debug;
>
> #endif /* !__ASSEMBLY__ */
>
> +static inline int handle_guest_sea(unsigned long addr, unsigned int esr)
> +{
> + return -1;
> +}
> +
> #endif /* __ASM_ARM_SYSTEM_MISC_H */
> diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
> index e9a5c0e..1152966 100644
> --- a/arch/arm/kvm/mmu.c
> +++ b/arch/arm/kvm/mmu.c
> @@ -29,6 +29,7 @@
> #include <asm/kvm_asm.h>
> #include <asm/kvm_emulate.h>
> #include <asm/virt.h>
> +#include <asm/system_misc.h>
>
> #include "trace.h"
>
> @@ -1441,8 +1442,21 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
>
> /* Check the stage-2 fault is trans. fault or write fault */
> fault_status = kvm_vcpu_trap_get_fault_type(vcpu);
> - if (fault_status != FSC_FAULT && fault_status != FSC_PERM &&
> - fault_status != FSC_ACCESS) {
> +
> + /* The host kernel will handle the synchronous external abort. There
> + * is no need to pass the error into the guest.
> + */
> + if (fault_status == FSC_EXTABT) {
> + if(handle_guest_sea((unsigned long)fault_ipa,
> + kvm_vcpu_get_hsr(vcpu))) {
> + kvm_err("Failed to handle guest SEA, FSC: EC=%#x xFSC=%#lx ESR_EL2=%#lx\n",
> + kvm_vcpu_trap_get_class(vcpu),
> + (unsigned long)kvm_vcpu_trap_get_fault(vcpu),
> + (unsigned long)kvm_vcpu_get_hsr(vcpu));
So there's one thing I don't like here, which is that we just gave the
guest a very nice way to pollute the host's kernel log with spurious
messages. So I'd rather make it silent, or at the very least rate limited.
> + return -EFAULT;
> + }
> + } else if (fault_status != FSC_FAULT && fault_status != FSC_PERM &&
> + fault_status != FSC_ACCESS) {
> kvm_err("Unsupported FSC: EC=%#x xFSC=%#lx ESR_EL2=%#lx\n",
> kvm_vcpu_trap_get_class(vcpu),
> (unsigned long)kvm_vcpu_trap_get_fault(vcpu),
> diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
> index 4b5c977..be0efb6 100644
> --- a/arch/arm64/include/asm/kvm_arm.h
> +++ b/arch/arm64/include/asm/kvm_arm.h
> @@ -201,6 +201,7 @@
> #define FSC_FAULT ESR_ELx_FSC_FAULT
> #define FSC_ACCESS ESR_ELx_FSC_ACCESS
> #define FSC_PERM ESR_ELx_FSC_PERM
> +#define FSC_EXTABT ESR_ELx_FSC_EXTABT
>
> /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
> #define HPFAR_MASK (~UL(0xf))
> diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
> index e7f3440..27816cb 100644
> --- a/arch/arm64/include/asm/system_misc.h
> +++ b/arch/arm64/include/asm/system_misc.h
> @@ -77,4 +77,6 @@ extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
> int register_sea_notifier(struct notifier_block *nb);
> void unregister_sea_notifier(struct notifier_block *nb);
>
> +int handle_guest_sea(unsigned long addr, unsigned int esr);
> +
> #endif /* __ASM_SYSTEM_MISC_H */
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index 81039c7..fa8d4d7 100644
> --- a/arch/arm64/mm/fault.c
> +++ b/arch/arm64/mm/fault.c
> @@ -597,6 +597,19 @@ static const char *fault_name(unsigned int esr)
> }
>
> /*
> + * Handle Synchronous External Aborts that occur in a guest kernel.
> + */
> +int handle_guest_sea(unsigned long addr, unsigned int esr)
> +{
> + atomic_notifier_call_chain(&sea_handler_chain, 0, NULL);
> +
> + pr_err("Synchronous External Abort: %s (0x%08x) at 0x%016lx\n",
> + fault_name(esr), esr, addr);
Same here.
> +
> + return 0;
> +}
> +
> +/*
> * Dispatch a data abort to the relevant handler.
> */
> asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
>
Thanks,
M.
--
Jazz is not dead. It just smells funny...
[toc] | [prev] | [next] | [standalone]
| From | "Baicar, Tyler" <tbaicar@codeaurora.org> |
|---|---|
| Date | 2017-01-16 21:20 +0100 |
| Subject | Re: [PATCH V7 10/10] arm/arm64: KVM: add guest SEA support |
| Message-ID | <t0lUZ-5Di-1@gated-at.bofh.it> |
| In reply to | #1559666 |
Hello Marc,
On 1/16/2017 4:58 AM, Marc Zyngier wrote:
> Hi Tyler,
>
> On 12/01/17 18:15, Tyler Baicar wrote:
>> Currently external aborts are unsupported by the guest abort
>> handling. Add handling for SEAs so that the host kernel reports
>> SEAs which occur in the guest kernel.
>>
>> Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
>> ---
>> arch/arm/include/asm/kvm_arm.h | 1 +
>> arch/arm/include/asm/system_misc.h | 5 +++++
>> arch/arm/kvm/mmu.c | 18 ++++++++++++++++--
>> arch/arm64/include/asm/kvm_arm.h | 1 +
>> arch/arm64/include/asm/system_misc.h | 2 ++
>> arch/arm64/mm/fault.c | 13 +++++++++++++
>> 6 files changed, 38 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
>> index e22089f..33a77509 100644
>> --- a/arch/arm/include/asm/kvm_arm.h
>> +++ b/arch/arm/include/asm/kvm_arm.h
>> @@ -187,6 +187,7 @@
>> #define FSC_FAULT (0x04)
>> #define FSC_ACCESS (0x08)
>> #define FSC_PERM (0x0c)
>> +#define FSC_EXTABT (0x10)
>>
>> /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
>> #define HPFAR_MASK (~0xf)
>> diff --git a/arch/arm/include/asm/system_misc.h b/arch/arm/include/asm/system_misc.h
>> index a3d61ad..ea45d94 100644
>> --- a/arch/arm/include/asm/system_misc.h
>> +++ b/arch/arm/include/asm/system_misc.h
>> @@ -24,4 +24,9 @@ extern unsigned int user_debug;
>>
>> #endif /* !__ASSEMBLY__ */
>>
>> +static inline int handle_guest_sea(unsigned long addr, unsigned int esr)
>> +{
>> + return -1;
>> +}
>> +
>> #endif /* __ASM_ARM_SYSTEM_MISC_H */
>> diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
>> index e9a5c0e..1152966 100644
>> --- a/arch/arm/kvm/mmu.c
>> +++ b/arch/arm/kvm/mmu.c
>> @@ -29,6 +29,7 @@
>> #include <asm/kvm_asm.h>
>> #include <asm/kvm_emulate.h>
>> #include <asm/virt.h>
>> +#include <asm/system_misc.h>
>>
>> #include "trace.h"
>>
>> @@ -1441,8 +1442,21 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
>>
>> /* Check the stage-2 fault is trans. fault or write fault */
>> fault_status = kvm_vcpu_trap_get_fault_type(vcpu);
>> - if (fault_status != FSC_FAULT && fault_status != FSC_PERM &&
>> - fault_status != FSC_ACCESS) {
>> +
>> + /* The host kernel will handle the synchronous external abort. There
>> + * is no need to pass the error into the guest.
>> + */
>> + if (fault_status == FSC_EXTABT) {
>> + if(handle_guest_sea((unsigned long)fault_ipa,
>> + kvm_vcpu_get_hsr(vcpu))) {
>> + kvm_err("Failed to handle guest SEA, FSC: EC=%#x xFSC=%#lx ESR_EL2=%#lx\n",
>> + kvm_vcpu_trap_get_class(vcpu),
>> + (unsigned long)kvm_vcpu_trap_get_fault(vcpu),
>> + (unsigned long)kvm_vcpu_get_hsr(vcpu));
> So there's one thing I don't like here, which is that we just gave the
> guest a very nice way to pollute the host's kernel log with spurious
> messages. So I'd rather make it silent, or at the very least rate limited.
Before this patch, if a guest exits with FSC_EXTABT, then the below
print for
"Unsupported FSC..." would happen. So this print isn't really adding any
noise
that isn't already there. Also, this print would only happen if
handle_guest_sea
fails. If you still think this print should be removed then I will
remove it though.
>> + return -EFAULT;
>> + }
>> + } else if (fault_status != FSC_FAULT && fault_status != FSC_PERM &&
>> + fault_status != FSC_ACCESS) {
>> kvm_err("Unsupported FSC: EC=%#x xFSC=%#lx ESR_EL2=%#lx\n",
>> kvm_vcpu_trap_get_class(vcpu),
>> (unsigned long)kvm_vcpu_trap_get_fault(vcpu),
>> diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
>> index 4b5c977..be0efb6 100644
>> --- a/arch/arm64/include/asm/kvm_arm.h
>> +++ b/arch/arm64/include/asm/kvm_arm.h
>> @@ -201,6 +201,7 @@
>> #define FSC_FAULT ESR_ELx_FSC_FAULT
>> #define FSC_ACCESS ESR_ELx_FSC_ACCESS
>> #define FSC_PERM ESR_ELx_FSC_PERM
>> +#define FSC_EXTABT ESR_ELx_FSC_EXTABT
>>
>> /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
>> #define HPFAR_MASK (~UL(0xf))
>> diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
>> index e7f3440..27816cb 100644
>> --- a/arch/arm64/include/asm/system_misc.h
>> +++ b/arch/arm64/include/asm/system_misc.h
>> @@ -77,4 +77,6 @@ extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
>> int register_sea_notifier(struct notifier_block *nb);
>> void unregister_sea_notifier(struct notifier_block *nb);
>>
>> +int handle_guest_sea(unsigned long addr, unsigned int esr);
>> +
>> #endif /* __ASM_SYSTEM_MISC_H */
>> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
>> index 81039c7..fa8d4d7 100644
>> --- a/arch/arm64/mm/fault.c
>> +++ b/arch/arm64/mm/fault.c
>> @@ -597,6 +597,19 @@ static const char *fault_name(unsigned int esr)
>> }
>>
>> /*
>> + * Handle Synchronous External Aborts that occur in a guest kernel.
>> + */
>> +int handle_guest_sea(unsigned long addr, unsigned int esr)
>> +{
>> + atomic_notifier_call_chain(&sea_handler_chain, 0, NULL);
>> +
>> + pr_err("Synchronous External Abort: %s (0x%08x) at 0x%016lx\n",
>> + fault_name(esr), esr, addr);
> Same here.
I will remove this print.
>> +
>> + return 0;
>> +}
>> +
>> +/*
>> * Dispatch a data abort to the relevant handler.
>> */
>> asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
>>
> Thanks,
>
> M.
Thanks,
Tyler
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
[toc] | [prev] | [next] | [standalone]
| From | Tyler Baicar <tbaicar@codeaurora.org> |
|---|---|
| Date | 2017-01-12 19:30 +0100 |
| Subject | [PATCH V7 08/10] ras: acpi / apei: generate trace event for unrecognized CPER section |
| Message-ID | <sYSim-7i7-7@gated-at.bofh.it> |
| In reply to | #1557693 |
UEFI spec allows for non-standard section in Common Platform Error
Record. This is defined in section N.2.3 of UEFI version 2.5.
Currently if the CPER section's type (UUID) does not match with
any section type that the kernel knows how to parse, trace event
is not generated for such section. And thus user is not able to know
happening of such hardware error, including error record of
non-standard section.
This commit generates a trace event which contains raw error data
for unrecognized CPER section.
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
---
drivers/acpi/apei/ghes.c | 22 ++++++++++++++++++++--
drivers/ras/ras.c | 1 +
include/ras/ras_event.h | 45 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 66 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 4e9a20d..a32c1b1 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -45,11 +45,13 @@
#include <linux/aer.h>
#include <linux/nmi.h>
#include <linux/hardirq.h>
+#include <linux/uuid.h>
#include <acpi/actbl1.h>
#include <acpi/ghes.h>
#include <acpi/apei.h>
#include <asm/tlbflush.h>
+#include <ras/ras_event.h>
#ifdef CONFIG_HAVE_ACPI_APEI_SEA
#include <asm/system_misc.h>
@@ -458,11 +460,21 @@ static void ghes_do_proc(struct ghes *ghes,
{
int sev, sec_sev;
struct acpi_hest_generic_data *gdata;
+ uuid_le sec_type;
+ uuid_le *fru_id = &NULL_UUID_LE;
+ char *fru_text = "";
sev = ghes_severity(estatus->error_severity);
apei_estatus_for_each_section(estatus, gdata) {
sec_sev = ghes_severity(gdata->error_severity);
- if (!uuid_le_cmp(*(uuid_le *)gdata->section_type,
+ sec_type = *(uuid_le *)gdata->section_type;
+
+ if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID)
+ fru_id = (uuid_le *)gdata->fru_id;
+ if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT)
+ fru_text = gdata->fru_text;
+
+ if (!uuid_le_cmp(sec_type,
CPER_SEC_PLATFORM_MEM)) {
struct cper_sec_mem_err *mem_err;
@@ -473,7 +485,7 @@ static void ghes_do_proc(struct ghes *ghes,
ghes_handle_memory_failure(gdata, sev);
}
#ifdef CONFIG_ACPI_APEI_PCIEAER
- else if (!uuid_le_cmp(*(uuid_le *)gdata->section_type,
+ else if (!uuid_le_cmp(sec_type,
CPER_SEC_PCIE)) {
struct cper_sec_pcie *pcie_err;
@@ -506,6 +518,12 @@ static void ghes_do_proc(struct ghes *ghes,
}
#endif
+ else {
+ void *unknown_err = acpi_hest_generic_data_payload(gdata);
+ trace_unknown_sec_event(&sec_type,
+ fru_id, fru_text, sec_sev,
+ unknown_err, gdata->error_data_length);
+ }
}
}
diff --git a/drivers/ras/ras.c b/drivers/ras/ras.c
index b67dd36..fb2500b 100644
--- a/drivers/ras/ras.c
+++ b/drivers/ras/ras.c
@@ -27,3 +27,4 @@ subsys_initcall(ras_init);
EXPORT_TRACEPOINT_SYMBOL_GPL(extlog_mem_event);
#endif
EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event);
+EXPORT_TRACEPOINT_SYMBOL_GPL(unknown_sec_event);
diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
index 1791a12..5861b6f 100644
--- a/include/ras/ras_event.h
+++ b/include/ras/ras_event.h
@@ -162,6 +162,51 @@ TRACE_EVENT(mc_event,
);
/*
+ * Unknown Section Report
+ *
+ * This event is generated when hardware detected a hardware
+ * error event, which may be of non-standard section as defined
+ * in UEFI spec appendix "Common Platform Error Record", or may
+ * be of sections for which TRACE_EVENT is not defined.
+ *
+ */
+TRACE_EVENT(unknown_sec_event,
+
+ TP_PROTO(const uuid_le *sec_type,
+ const uuid_le *fru_id,
+ const char *fru_text,
+ const u8 sev,
+ const u8 *err,
+ const u32 len),
+
+ TP_ARGS(sec_type, fru_id, fru_text, sev, err, len),
+
+ TP_STRUCT__entry(
+ __array(char, sec_type, 16)
+ __array(char, fru_id, 16)
+ __string(fru_text, fru_text)
+ __field(u8, sev)
+ __field(u32, len)
+ __dynamic_array(u8, buf, len)
+ ),
+
+ TP_fast_assign(
+ memcpy(__entry->sec_type, sec_type, sizeof(uuid_le));
+ memcpy(__entry->fru_id, fru_id, sizeof(uuid_le));
+ __assign_str(fru_text, fru_text);
+ __entry->sev = sev;
+ __entry->len = len;
+ memcpy(__get_dynamic_array(buf), err, len);
+ ),
+
+ TP_printk("severity: %d; sec type:%pU; FRU: %pU %s; data len:%d; raw data:%s",
+ __entry->sev, __entry->sec_type,
+ __entry->fru_id, __get_str(fru_text),
+ __entry->len,
+ __print_hex(__get_dynamic_array(buf), __entry->len))
+);
+
+/*
* PCIe AER Trace event
*
* These events are generated when hardware detects a corrected or
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
[toc] | [prev] | [next] | [standalone]
| From | Tyler Baicar <tbaicar@codeaurora.org> |
|---|---|
| Date | 2017-01-12 19:30 +0100 |
| Subject | [PATCH V7 06/10] acpi: apei: panic OS with fatal error status block |
| Message-ID | <sYSim-7i7-5@gated-at.bofh.it> |
| In reply to | #1557693 |
From: "Jonathan (Zhixiong) Zhang" <zjzhang@codeaurora.org>
Even if an error status block's severity is fatal, the kernel does not
honor the severity level and panic.
With the firmware first model, the platform could inform the OS about a
fatal hardware error through the non-NMI GHES notification type. The OS
should panic when a hardware error record is received with this
severity.
Call panic() after CPER data in error status block is printed if
severity is fatal, before each error section is handled.
Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
---
drivers/acpi/apei/ghes.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 87efe26..4e9a20d 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -142,6 +142,8 @@ static unsigned long ghes_estatus_pool_size_request;
static struct ghes_estatus_cache *ghes_estatus_caches[GHES_ESTATUS_CACHES_SIZE];
static atomic_t ghes_estatus_cache_alloced;
+static int ghes_panic_timeout __read_mostly = 30;
+
static int ghes_ioremap_init(void)
{
ghes_ioremap_area = __get_vm_area(PAGE_SIZE * GHES_IOREMAP_PAGES,
@@ -693,6 +695,13 @@ static int ghes_ack_error(struct acpi_hest_generic_v2 *generic_v2)
return rc;
}
+static void __ghes_call_panic(void)
+{
+ if (panic_timeout == 0)
+ panic_timeout = ghes_panic_timeout;
+ panic("Fatal hardware error!");
+}
+
static int ghes_proc(struct ghes *ghes)
{
int rc;
@@ -704,6 +713,10 @@ static int ghes_proc(struct ghes *ghes)
if (ghes_print_estatus(NULL, ghes->generic, ghes->estatus))
ghes_estatus_cache_add(ghes->generic, ghes->estatus);
}
+ if (ghes_severity(ghes->estatus->error_severity) >= GHES_SEV_PANIC) {
+ __ghes_call_panic();
+ }
+
ghes_do_proc(ghes, ghes->estatus);
if (IS_HEST_TYPE_GENERIC_V2(ghes)) {
@@ -848,8 +861,6 @@ static atomic_t ghes_in_nmi = ATOMIC_INIT(0);
static LIST_HEAD(ghes_nmi);
-static int ghes_panic_timeout __read_mostly = 30;
-
static void ghes_proc_in_irq(struct irq_work *irq_work)
{
struct llist_node *llnode, *next;
@@ -942,9 +953,7 @@ static void __ghes_panic(struct ghes *ghes)
__ghes_print_estatus(KERN_EMERG, ghes->generic, ghes->estatus);
/* reboot to log the error! */
- if (panic_timeout == 0)
- panic_timeout = ghes_panic_timeout;
- panic("Fatal hardware error!");
+ __ghes_call_panic();
}
static int ghes_notify_nmi(unsigned int cmd, struct pt_regs *regs)
--
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | linux.kernel
csiph-web