* [PATCH v4] Adding missing features of Coresight PTM components
From: Mathieu Poirier @ 2016-10-07 21:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <0b570076-08cb-c63a-7240-8c81d34fc383@centralesupelec.fr>
On 7 October 2016 at 06:16, Muhammad Abdul WAHAB
<muhammadabdul.wahab@centralesupelec.fr> wrote:
> In the current driver for Coresight components, two features of PTM
> components are missing:
>
> 1. Branch Broadcasting (present also in ETM but called Branch Output)
> 2. Return Stack (only present in PTM v1.0 and PTMv1.1)
>
> These features can be added simply to the code using `mode` field of
> `etm_config` struct.
>
> 1. **Branch Broadcast** : The branch broadcast feature is present in ETM
> components as well and is called Branch output. It allows to retrieve
> addresses for direct branch addresses alongside the indirect branch
> addresses. For example, it could be useful in cases when tracing without
> source code.
> 2. **Return Stack** : The return stack option allows to retrieve the return
> addresses of function calls. It can be useful to avoid CRA
> (Code Reuse Attacks) by keeping a shadowstack.
>
> Signed-off-by: Muhammad Abdul Wahab <muhammadabdul.wahab@centralesupelec.fr>
> ---
> change(s) in v4 :
> - syntax error correction (sorry did not compile after 1st version
> but did compile it before sending it this time)
>
> drivers/hwtracing/coresight/coresight-etm.h | 5 +++++
> drivers/hwtracing/coresight/coresight-etm3x-sysfs.c | 10 ++++++++++
> 2 files changed, 15 insertions(+)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm.h
> b/drivers/hwtracing/coresight/coresight-etm.h
> index 4a18ee4..ad063d7 100644
> --- a/drivers/hwtracing/coresight/coresight-etm.h
> +++ b/drivers/hwtracing/coresight/coresight-etm.h
> @@ -89,11 +89,13 @@
> /* ETMCR - 0x00 */
> #define ETMCR_PWD_DWN BIT(0)
> #define ETMCR_STALL_MODE BIT(7)
> +#define ETMCR_BRANCH_BROADCAST BIT(8)
> #define ETMCR_ETM_PRG BIT(10)
> #define ETMCR_ETM_EN BIT(11)
> #define ETMCR_CYC_ACC BIT(12)
> #define ETMCR_CTXID_SIZE (BIT(14)|BIT(15))
> #define ETMCR_TIMESTAMP_EN BIT(28)
> +#define ETMCR_RETURN_STACK BIT(29)
> /* ETMCCR - 0x04 */
> #define ETMCCR_FIFOFULL BIT(23)
> /* ETMPDCR - 0x310 */
> @@ -110,8 +112,11 @@
> #define ETM_MODE_STALL BIT(2)
> #define ETM_MODE_TIMESTAMP BIT(3)
> #define ETM_MODE_CTXID BIT(4)
> +#define ETM_MODE_BBROAD BIT(5)
> +#define ETM_MODE_RET_STACK BIT(6)
> #define ETM_MODE_ALL (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC | \
> ETM_MODE_STALL | ETM_MODE_TIMESTAMP | \
> + ETM_MODE_BBROAD | ETM_MODE_RET_STACK | \
> ETM_MODE_CTXID | ETM_MODE_EXCL_KERN | \
> ETM_MODE_EXCL_USER)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
> b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
> index e9b0719..7308304 100644
> --- a/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
> +++ b/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
> @@ -164,6 +164,16 @@ static ssize_t mode_store(struct device *dev,
> else
> config->ctrl &= ~ETMCR_CTXID_SIZE;
>
> + if (config->mode & ETM_MODE_BBROAD)
> + config->ctrl |= ETMCR_BRANCH_BROADCAST;
> + else
> + config->ctrl &= ~ETMCR_BRANCH_BROADCAST;
> +
> + if (config->mode & ETM_MODE_RET_STACK)
> + config->ctrl |= ETMCR_RETURN_STACK;
> + else
> + config->ctrl &= ~ETMCR_RETURN_STACK;
> +
> if (config->mode & (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER))
> etm_config_trace_mode(config);
Applied.
Thanks,
Mathieu
>
> --
> 1.9.1
^ permalink raw reply
* [PATCH V3 09/10] trace, ras: add ARM processor error trace event
From: Steven Rostedt @ 2016-10-07 21:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475875882-2604-10-git-send-email-tbaicar@codeaurora.org>
On Fri, 7 Oct 2016 15:31:21 -0600
Tyler Baicar <tbaicar@codeaurora.org> wrote:
> Currently there are trace events for the various RAS
> errors with the exception of ARM processor type errors.
> Add a new trace event for such errors so that the user
> will know when they occur. These trace events are
> consistent with the ARM processor error section type
> defined in UEFI 2.6 spec section N.2.4.4.
>
> Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
> ---
> drivers/firmware/efi/cper.c | 9 ++++++
> drivers/ras/ras.c | 1 +
> include/ras/ras_event.h | 67 +++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 77 insertions(+)
>
> diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
> index f9ffba6..21b8a6f 100644
> --- a/drivers/firmware/efi/cper.c
> +++ b/drivers/firmware/efi/cper.c
> @@ -34,6 +34,7 @@
> #include <linux/aer.h>
> #include <linux/printk.h>
> #include <linux/bcd.h>
> +#include <ras/ras_event.h>
>
> #define INDENT_SP " "
>
> @@ -256,6 +257,14 @@ static void cper_print_proc_armv8(const char *pfx,
> CPER_ARMV8_INFO_VALID_PHYSICAL_ADDR)
> printk("%sphysical fault address: 0x%016llx\n",
> newpfx, err_info->physical_fault_addr);
> + trace_arm_event(proc->affinity_level, proc->mpidr, proc->midr,
> + proc->running_state, proc->psci_state,
> + err_info->version, err_info->type,
> + err_info->multiple_error,
> + err_info->validation_bits,
> + err_info->error_info,
> + err_info->virt_fault_addr,
> + err_info->physical_fault_addr);
Why waste all the effort into passing each individual field. Why not
just pass the structure in and sort it out in the TP_fast_assign()?
> err_info += 1;
> }
>
> diff --git a/drivers/ras/ras.c b/drivers/ras/ras.c
> index fb2500b..8ba5a94 100644
> --- a/drivers/ras/ras.c
> +++ b/drivers/ras/ras.c
> @@ -28,3 +28,4 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(extlog_mem_event);
> #endif
> EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event);
> EXPORT_TRACEPOINT_SYMBOL_GPL(unknown_sec_event);
> +EXPORT_TRACEPOINT_SYMBOL_GPL(arm_event);
> diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
> index 5861b6f..eb2719a 100644
> --- a/include/ras/ras_event.h
> +++ b/include/ras/ras_event.h
> @@ -162,6 +162,73 @@ TRACE_EVENT(mc_event,
> );
>
> /*
> + * ARM Processor Events Report
> + *
> + * This event is generated when hardware detects an ARM processor error
> + * has occurred. UEFI 2.6 spec section N.2.4.4.
> + */
> +TRACE_EVENT(arm_event,
> +
> + TP_PROTO(const u8 affinity,
> + const u64 mpidr,
> + const u64 midr,
> + const u32 running_state,
> + const u32 psci_state,
> + const u8 version,
> + const u8 type,
> + const u16 err_count,
> + const u8 flags,
> + const u64 info,
> + const u64 virt_fault_addr,
> + const u64 phys_fault_addr),
> +
> + TP_ARGS(affinity, mpidr, midr, running_state, psci_state,
> + version, type, err_count, flags, info, virt_fault_addr,
> + phys_fault_addr),
> +
> + TP_STRUCT__entry(
> + __field(u8, affinity)
> + __field(u64, mpidr)
> + __field(u64, midr)
> + __field(u32, running_state)
> + __field(u32, psci_state)
> + __field(u8, version)
> + __field(u8, type)
> + __field(u16, err_count)
> + __field(u8, flags)
> + __field(u64, info)
> + __field(u64, virt_fault_addr)
> + __field(u64, phys_fault_addr)
The above creates a structure with lots of holes in it. Pack it better.
You want something like:
__field(u64, mpidr)
__field(u64, midr)
__field(u64, info)
__field(u64, virt_fault_addr)
__field(u64, phys_fault_addr)
__field(u32, running_state)
__field(u32, psci_state)
__field(u16, err_count)
__field(u8, affinity)
__field(u8, version)
__field(u8, type)
__field(u8, flags)
The above is a total of 54 bytes. Your original was at a minimum, 64
bytes.
-- Steve
> + ),
> +
> + TP_fast_assign(
> + __entry->affinity = affinity;
> + __entry->mpidr = mpidr;
> + __entry->midr = midr;
> + __entry->running_state = running_state;
> + __entry->psci_state = psci_state;
> + __entry->version = version;
> + __entry->type = type;
> + __entry->err_count = err_count;
> + __entry->flags = flags;
> + __entry->info = info;
> + __entry->virt_fault_addr = virt_fault_addr;
> + __entry->phys_fault_addr = phys_fault_addr;
> + ),
> +
> + TP_printk("affinity level: %d; MPIDR: %016llx; MIDR: %016llx; "
> + "running state: %d; PSCI state: %d; version: %d; type: %d; "
> + "error count: 0x%04x; flags: 0x%02x; info: %016llx; "
> + "virtual fault address: %016llx; "
> + "physical fault address: %016llx",
> + __entry->affinity, __entry->mpidr, __entry->midr,
> + __entry->running_state, __entry->psci_state, __entry->version,
> + __entry->type, __entry->err_count, __entry->flags,
> + __entry->info, __entry->virt_fault_addr,
> + __entry->phys_fault_addr)
> +);
> +
> +/*
> * Unknown Section Report
> *
> * This event is generated when hardware detected a hardware
^ permalink raw reply
* [PATCH V3 10/10] arm64: KVM: add guest SEA support
From: Tyler Baicar @ 2016-10-07 21:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475875882-2604-1-git-send-email-tbaicar@codeaurora.org>
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 | 15 +++++++++++++--
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, 35 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..86e1faa 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__ */
+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..24cde84 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,18 @@ 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) {
+
+ 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 90daf4a..8522fff 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 sea_register_handler_chain(struct notifier_block *nb);
void sea_unregister_handler_chain(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 81cb7ad..d714432 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.
^ permalink raw reply related
* [PATCH V3 09/10] trace, ras: add ARM processor error trace event
From: Tyler Baicar @ 2016-10-07 21:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475875882-2604-1-git-send-email-tbaicar@codeaurora.org>
Currently there are trace events for the various RAS
errors with the exception of ARM processor type errors.
Add a new trace event for such errors so that the user
will know when they occur. These trace events are
consistent with the ARM processor error section type
defined in UEFI 2.6 spec section N.2.4.4.
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
---
drivers/firmware/efi/cper.c | 9 ++++++
drivers/ras/ras.c | 1 +
include/ras/ras_event.h | 67 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 77 insertions(+)
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index f9ffba6..21b8a6f 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -34,6 +34,7 @@
#include <linux/aer.h>
#include <linux/printk.h>
#include <linux/bcd.h>
+#include <ras/ras_event.h>
#define INDENT_SP " "
@@ -256,6 +257,14 @@ static void cper_print_proc_armv8(const char *pfx,
CPER_ARMV8_INFO_VALID_PHYSICAL_ADDR)
printk("%sphysical fault address: 0x%016llx\n",
newpfx, err_info->physical_fault_addr);
+ trace_arm_event(proc->affinity_level, proc->mpidr, proc->midr,
+ proc->running_state, proc->psci_state,
+ err_info->version, err_info->type,
+ err_info->multiple_error,
+ err_info->validation_bits,
+ err_info->error_info,
+ err_info->virt_fault_addr,
+ err_info->physical_fault_addr);
err_info += 1;
}
diff --git a/drivers/ras/ras.c b/drivers/ras/ras.c
index fb2500b..8ba5a94 100644
--- a/drivers/ras/ras.c
+++ b/drivers/ras/ras.c
@@ -28,3 +28,4 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(extlog_mem_event);
#endif
EXPORT_TRACEPOINT_SYMBOL_GPL(mc_event);
EXPORT_TRACEPOINT_SYMBOL_GPL(unknown_sec_event);
+EXPORT_TRACEPOINT_SYMBOL_GPL(arm_event);
diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
index 5861b6f..eb2719a 100644
--- a/include/ras/ras_event.h
+++ b/include/ras/ras_event.h
@@ -162,6 +162,73 @@ TRACE_EVENT(mc_event,
);
/*
+ * ARM Processor Events Report
+ *
+ * This event is generated when hardware detects an ARM processor error
+ * has occurred. UEFI 2.6 spec section N.2.4.4.
+ */
+TRACE_EVENT(arm_event,
+
+ TP_PROTO(const u8 affinity,
+ const u64 mpidr,
+ const u64 midr,
+ const u32 running_state,
+ const u32 psci_state,
+ const u8 version,
+ const u8 type,
+ const u16 err_count,
+ const u8 flags,
+ const u64 info,
+ const u64 virt_fault_addr,
+ const u64 phys_fault_addr),
+
+ TP_ARGS(affinity, mpidr, midr, running_state, psci_state,
+ version, type, err_count, flags, info, virt_fault_addr,
+ phys_fault_addr),
+
+ TP_STRUCT__entry(
+ __field(u8, affinity)
+ __field(u64, mpidr)
+ __field(u64, midr)
+ __field(u32, running_state)
+ __field(u32, psci_state)
+ __field(u8, version)
+ __field(u8, type)
+ __field(u16, err_count)
+ __field(u8, flags)
+ __field(u64, info)
+ __field(u64, virt_fault_addr)
+ __field(u64, phys_fault_addr)
+ ),
+
+ TP_fast_assign(
+ __entry->affinity = affinity;
+ __entry->mpidr = mpidr;
+ __entry->midr = midr;
+ __entry->running_state = running_state;
+ __entry->psci_state = psci_state;
+ __entry->version = version;
+ __entry->type = type;
+ __entry->err_count = err_count;
+ __entry->flags = flags;
+ __entry->info = info;
+ __entry->virt_fault_addr = virt_fault_addr;
+ __entry->phys_fault_addr = phys_fault_addr;
+ ),
+
+ TP_printk("affinity level: %d; MPIDR: %016llx; MIDR: %016llx; "
+ "running state: %d; PSCI state: %d; version: %d; type: %d; "
+ "error count: 0x%04x; flags: 0x%02x; info: %016llx; "
+ "virtual fault address: %016llx; "
+ "physical fault address: %016llx",
+ __entry->affinity, __entry->mpidr, __entry->midr,
+ __entry->running_state, __entry->psci_state, __entry->version,
+ __entry->type, __entry->err_count, __entry->flags,
+ __entry->info, __entry->virt_fault_addr,
+ __entry->phys_fault_addr)
+);
+
+/*
* Unknown Section Report
*
* This event is generated when hardware detected a hardware
--
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.
^ permalink raw reply related
* [PATCH V3 08/10] ras: acpi / apei: generate trace event for unrecognized CPER section
From: Tyler Baicar @ 2016-10-07 21:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475875882-2604-1-git-send-email-tbaicar@codeaurora.org>
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: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
---
drivers/acpi/apei/ghes.c | 18 +++++++++++++++++-
drivers/ras/ras.c | 1 +
include/ras/ras_event.h | 45 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 36894c8..cb4c7f4 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -49,6 +49,7 @@
#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>
@@ -468,12 +469,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;
+ char *fru_text = "";
sev = ghes_severity(estatus->error_severity);
apei_estatus_for_each_section(estatus, gdata) {
sec_sev = ghes_severity(gdata->error_severity);
sec_type = *(uuid_le *)gdata->section_type;
+ if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID)
+ fru_id = (uuid_le *)gdata->fru_id;
+ else
+ fru_id = &NULL_UUID_LE;
+ 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;
@@ -485,7 +495,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;
@@ -518,6 +528,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.
^ permalink raw reply related
* [PATCH V3 07/10] efi: print unrecognized CPER section
From: Tyler Baicar @ 2016-10-07 21:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475875882-2604-1-git-send-email-tbaicar@codeaurora.org>
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
one of the section types that the kernel knows how to parse, the
section is skipped. Therefore, user is not able to see
such CPER data, for instance, error record of non-standard section.
For above mentioned case, this change prints out the raw data in
hex in dmesg buffer. Data length is taken from Error Data length
field of Generic Error Data Entry.
Following is a sample output from dmesg:
[ 115.771702] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
[ 115.779042] {1}[Hardware Error]: It has been corrected by h/w and requires no further action
[ 115.787456] {1}[Hardware Error]: event severity: corrected
[ 115.792927] {1}[Hardware Error]: Error 0, type: corrected
[ 115.798415] {1}[Hardware Error]: fru_id: 00000000-0000-0000-0000-000000000000
[ 115.805596] {1}[Hardware Error]: fru_text:
[ 115.816105] {1}[Hardware Error]: section type: d2e2621c-f936-468d-0d84-15a4ed015c8b
[ 115.823880] {1}[Hardware Error]: section length: 88
[ 115.828779] {1}[Hardware Error]: 00000000: 01000001 00000002 5f434345 525f4543
[ 115.836153] {1}[Hardware Error]: 00000010: 0000574d 00000000 00000000 00000000
[ 115.843531] {1}[Hardware Error]: 00000020: 00000000 00000000 00000000 00000000
[ 115.850908] {1}[Hardware Error]: 00000030: 00000000 00000000 00000000 00000000
[ 115.858288] {1}[Hardware Error]: 00000040: fe800000 00000000 00000004 5f434345
[ 115.865665] {1}[Hardware Error]: 00000050: 525f4543 0000574d
Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
---
drivers/firmware/efi/cper.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 2594245..f9ffba6 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -605,8 +605,16 @@ static void cper_estatus_print_section(
cper_print_proc_armv8(newpfx, armv8_err);
else
goto err_section_too_small;
- } else
- printk("%s""section type: unknown, %pUl\n", newpfx, sec_type);
+ } else {
+ const void *unknown_err;
+
+ unknown_err = acpi_hest_generic_data_payload(gdata);
+ printk("%ssection type: %pUl\n", newpfx, sec_type);
+ printk("%ssection length: %d\n", newpfx,
+ gdata->error_data_length);
+ print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4,
+ unknown_err, gdata->error_data_length, 0);
+ }
return;
--
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.
^ permalink raw reply related
* [PATCH V3 06/10] acpi: apei: panic OS with fatal error status block
From: Tyler Baicar @ 2016-10-07 21:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475875882-2604-1-git-send-email-tbaicar@codeaurora.org>
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>
---
drivers/acpi/apei/ghes.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 28d5a09..36894c8 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -141,6 +141,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,
@@ -715,6 +717,12 @@ 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) {
+ if (panic_timeout == 0)
+ panic_timeout = ghes_panic_timeout;
+ panic("Fatal hardware error!");
+ }
+
ghes_do_proc(ghes, ghes->estatus);
if (ghes->generic_v2) {
@@ -859,8 +867,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;
--
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.
^ permalink raw reply related
* [PATCH V3 05/10] acpi: apei: handle SEA notification type for ARMv8
From: Tyler Baicar @ 2016-10-07 21:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475875882-2604-1-git-send-email-tbaicar@codeaurora.org>
ARM APEI extension proposal added SEA (Synchrounous External
Abort) notification type for ARMv8.
Add a new GHES error source handling function for SEA. If an error
source's notification type is SEA, then this function can be registered
into the SEA exception handler. That way GHES will parse and report
SEA exceptions when they occur.
Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
---
arch/arm64/Kconfig | 1 +
drivers/acpi/apei/Kconfig | 15 +++++++++
drivers/acpi/apei/ghes.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 99 insertions(+)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b380c87..ae34349 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -53,6 +53,7 @@ config ARM64
select HANDLE_DOMAIN_IRQ
select HARDIRQS_SW_RESEND
select HAVE_ACPI_APEI if (ACPI && EFI)
+ select HAVE_ACPI_APEI_SEA if (ACPI && EFI)
select HAVE_ALIGNED_STRUCT_PAGE if SLUB
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_BITREVERSE
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
index b0140c8..fb99c1c 100644
--- a/drivers/acpi/apei/Kconfig
+++ b/drivers/acpi/apei/Kconfig
@@ -4,6 +4,21 @@ config HAVE_ACPI_APEI
config HAVE_ACPI_APEI_NMI
bool
+config HAVE_ACPI_APEI_SEA
+ bool "APEI Synchronous External Abort logging/recovering support"
+ depends on ARM64
+ help
+ This option should be enabled if the system supports
+ firmware first handling of SEA (Synchronous External Abort).
+ SEA happens with certain faults of data abort or instruction
+ abort synchronous exceptions on ARMv8 systems. If a system
+ supports firmware first handling of SEA, the platform analyzes
+ and handles hardware error notifications with SEA, and it may then
+ form a HW error record for the OS to parse and handle. This
+ option allows the OS to look for such HW error record, and
+ take appropriate action.
+
config ACPI_APEI
bool "ACPI Platform Error Interface (APEI)"
select MISC_FILESYSTEMS
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index c8488f1..28d5a09 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -50,6 +50,10 @@
#include <acpi/apei.h>
#include <asm/tlbflush.h>
+#ifdef CONFIG_HAVE_ACPI_APEI_SEA
+#include <asm/system_misc.h>
+#endif
+
#include "apei-internal.h"
#define GHES_PFX "GHES: "
@@ -779,6 +783,62 @@ static struct notifier_block ghes_notifier_sci = {
.notifier_call = ghes_notify_sci,
};
+#ifdef CONFIG_HAVE_ACPI_APEI_SEA
+static LIST_HEAD(ghes_sea);
+
+static int ghes_notify_sea(struct notifier_block *this,
+ unsigned long event, void *data)
+{
+ struct ghes *ghes;
+ int ret = NOTIFY_DONE;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(ghes, &ghes_sea, list) {
+ if (!ghes_proc(ghes))
+ ret = NOTIFY_OK;
+ }
+ rcu_read_unlock();
+
+ return ret;
+}
+
+static struct notifier_block ghes_notifier_sea = {
+ .notifier_call = ghes_notify_sea,
+};
+
+static int ghes_sea_add(struct ghes *ghes)
+{
+ mutex_lock(&ghes_list_mutex);
+ if (list_empty(&ghes_sea))
+ sea_register_handler_chain(&ghes_notifier_sea);
+ list_add_rcu(&ghes->list, &ghes_sea);
+ mutex_unlock(&ghes_list_mutex);
+ return 0;
+}
+
+static void ghes_sea_remove(struct ghes *ghes)
+{
+ mutex_lock(&ghes_list_mutex);
+ list_del_rcu(&ghes->list);
+ if (list_empty(&ghes_sea))
+ sea_unregister_handler_chain(&ghes_notifier_sea);
+ mutex_unlock(&ghes_list_mutex);
+}
+#else /* CONFIG_HAVE_ACPI_APEI_SEA */
+static inline int ghes_sea_add(struct ghes *ghes)
+{
+ pr_err(GHES_PFX "ID: %d, trying to add SEA notification which is not supported\n",
+ ghes->generic->header.source_id);
+ return -ENOTSUPP;
+}
+
+static inline void ghes_sea_remove(struct ghes *ghes)
+{
+ pr_err(GHES_PFX "ID: %d, trying to remove SEA notification which is not supported\n",
+ ghes->generic->header.source_id);
+}
+#endif /* CONFIG_HAVE_ACPI_APEI_SEA */
+
#ifdef CONFIG_HAVE_ACPI_APEI_NMI
/*
* printk is not safe in NMI context. So in NMI handler, we allocate
@@ -1023,6 +1083,14 @@ static int ghes_probe(struct platform_device *ghes_dev)
case ACPI_HEST_NOTIFY_EXTERNAL:
case ACPI_HEST_NOTIFY_SCI:
break;
+ case ACPI_HEST_NOTIFY_SEA:
+ if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_SEA)) {
+ pr_warn(GHES_PFX "Generic hardware error source: %d notified via SEA is not supported\n",
+ generic->header.source_id);
+ rc = -ENOTSUPP;
+ goto err;
+ }
+ break;
case ACPI_HEST_NOTIFY_NMI:
if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_NMI)) {
pr_warn(GHES_PFX "Generic hardware error source: %d notified via NMI interrupt is not supported!\n",
@@ -1034,6 +1102,13 @@ static int ghes_probe(struct platform_device *ghes_dev)
pr_warning(GHES_PFX "Generic hardware error source: %d notified via local interrupt is not supported!\n",
generic->header.source_id);
goto err;
+ case ACPI_HEST_NOTIFY_GPIO:
+ case ACPI_HEST_NOTIFY_SEI:
+ case ACPI_HEST_NOTIFY_GSIV:
+ pr_warn(GHES_PFX "Generic hardware error source: %d notified via notification type %u is not supported\n",
+ generic->header.source_id, generic->header.source_id);
+ rc = -ENOTSUPP;
+ goto err;
default:
pr_warning(FW_WARN GHES_PFX "Unknown notification type: %u for generic hardware error source: %d\n",
generic->notify.type, generic->header.source_id);
@@ -1088,6 +1163,11 @@ static int ghes_probe(struct platform_device *ghes_dev)
list_add_rcu(&ghes->list, &ghes_sci);
mutex_unlock(&ghes_list_mutex);
break;
+ case ACPI_HEST_NOTIFY_SEA:
+ rc = ghes_sea_add(ghes);
+ if (rc)
+ goto err_edac_unreg;
+ break;
case ACPI_HEST_NOTIFY_NMI:
ghes_nmi_add(ghes);
break;
@@ -1130,6 +1210,9 @@ static int ghes_remove(struct platform_device *ghes_dev)
unregister_acpi_hed_notifier(&ghes_notifier_sci);
mutex_unlock(&ghes_list_mutex);
break;
+ case ACPI_HEST_NOTIFY_SEA:
+ ghes_sea_remove(ghes);
+ break;
case ACPI_HEST_NOTIFY_NMI:
ghes_nmi_remove(ghes);
break;
--
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.
^ permalink raw reply related
* [PATCH V3 04/10] arm64: exception: handle Synchronous External Abort
From: Tyler Baicar @ 2016-10-07 21:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475875882-2604-1-git-send-email-tbaicar@codeaurora.org>
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: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Signed-off-by: Tyler Baicar <tbaicar@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..90daf4a 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 sea_register_handler_chain(struct notifier_block *nb);
+void sea_unregister_handler_chain(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..81cb7ad 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 sea_register_handler_chain(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&sea_handler_chain, nb);
+}
+
+void sea_unregister_handler_chain(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 (trans tbl walk)" },
+ { do_sea, SIGBUS, 0, "level 1 SEA (trans tbl walk)" },
+ { do_sea, SIGBUS, 0, "level 2 SEA (trans tbl walk)" },
+ { do_sea, SIGBUS, 0, "level 3 SEA (trans tbl 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 synch parity error" },
+ { do_sea, SIGBUS, 0, "level 1 synch parity error" },
+ { do_sea, SIGBUS, 0, "level 2 synch parity error" },
+ { do_sea, SIGBUS, 0, "level 3 synch parity error" },
{ 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.
^ permalink raw reply related
* [PATCH V3 03/10] efi: parse ARMv8 processor error
From: Tyler Baicar @ 2016-10-07 21:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475875882-2604-1-git-send-email-tbaicar@codeaurora.org>
Add support for ARMv8 Common Platform Error Record (CPER).
UEFI 2.6 specification adds support for ARMv8 specific
processor error information to be reported as part of the
CPER records. This provides more detail on for processor error logs.
Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
---
drivers/firmware/efi/cper.c | 135 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/cper.h | 72 +++++++++++++++++++++++
2 files changed, 207 insertions(+)
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 9fa1317..2594245 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -112,12 +112,15 @@ void cper_print_bits(const char *pfx, unsigned int bits,
static const char * const proc_type_strs[] = {
"IA32/X64",
"IA64",
+ "ARMv8",
};
static const char * const proc_isa_strs[] = {
"IA32",
"IA64",
"X64",
+ "ARM A32/T32",
+ "ARM A64",
};
static const char * const proc_error_type_strs[] = {
@@ -186,6 +189,129 @@ static void cper_print_proc_generic(const char *pfx,
printk("%s""IP: 0x%016llx\n", pfx, proc->ip);
}
+static void cper_print_proc_armv8(const char *pfx,
+ const struct cper_sec_proc_armv8 *proc)
+{
+ int i, len;
+ struct cper_armv8_err_info *err_info;
+ __u64 *qword = NULL;
+ char newpfx[64];
+
+ printk("%ssection length: %d\n", pfx, proc->section_length);
+ printk("%sMIDR: 0x%016llx\n", pfx, proc->midr);
+
+ len = proc->section_length - (sizeof(*proc) +
+ proc->err_info_num * (sizeof(*err_info)));
+ if (len < 0) {
+ printk("%ssection length is too small.\n", pfx);
+ printk("%sERR_INFO_NUM is %d.\n", pfx, proc->err_info_num);
+ return;
+ }
+
+ if (proc->validation_bits & CPER_ARMV8_VALID_MPIDR)
+ printk("%sMPIDR: 0x%016llx\n", pfx, proc->mpidr);
+ if (proc->validation_bits & CPER_ARMV8_VALID_AFFINITY_LEVEL)
+ printk("%serror affinity level: %d\n", pfx,
+ proc->affinity_level);
+ if (proc->validation_bits & CPER_ARMV8_VALID_RUNNING_STATE) {
+ printk("%srunning state: %d\n", pfx, proc->running_state);
+ printk("%sPSCI state: %d\n", pfx, proc->psci_state);
+ }
+
+ snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
+
+ err_info = (struct cper_armv8_err_info *)(proc + 1);
+ for (i = 0; i < proc->err_info_num; i++) {
+ printk("%sError info structure %d:\n", pfx, i);
+ printk("%sversion:%d\n", newpfx, err_info->version);
+ printk("%slength:%d\n", newpfx, err_info->length);
+ if (err_info->validation_bits &
+ CPER_ARMV8_INFO_VALID_MULTI_ERR) {
+ if (err_info->multiple_error == 0)
+ printk("%ssingle error.\n", newpfx);
+ else if (err_info->multiple_error == 1)
+ printk("%smultiple errors.\n", newpfx);
+ else
+ printk("%smultiple errors count:%d.\n",
+ newpfx, err_info->multiple_error);
+ }
+ if (err_info->validation_bits & CPER_ARMV8_INFO_VALID_FLAGS) {
+ if (err_info->flags & CPER_ARMV8_INFO_FLAGS_FIRST)
+ printk("%sfirst error captured.\n", newpfx);
+ if (err_info->flags & CPER_ARMV8_INFO_FLAGS_LAST)
+ printk("%slast error captured.\n", newpfx);
+ if (err_info->flags & CPER_ARMV8_INFO_FLAGS_PROPAGATED)
+ printk("%spropagated error captured.\n",
+ newpfx);
+ }
+ printk("%serror_type: %d, %s\n", newpfx, err_info->type,
+ err_info->type < ARRAY_SIZE(proc_error_type_strs) ?
+ proc_error_type_strs[err_info->type] : "unknown");
+ printk("%serror_info: 0x%016llx\n", newpfx,
+ err_info->error_info);
+ if (err_info->validation_bits & CPER_ARMV8_INFO_VALID_VIRT_ADDR)
+ printk("%svirtual fault address: 0x%016llx\n",
+ newpfx, err_info->virt_fault_addr);
+ if (err_info->validation_bits &
+ CPER_ARMV8_INFO_VALID_PHYSICAL_ADDR)
+ printk("%sphysical fault address: 0x%016llx\n",
+ newpfx, err_info->physical_fault_addr);
+ err_info += 1;
+ }
+
+ if (len < sizeof(*qword) && proc->context_info_num > 0) {
+ printk("%ssection length is too small.\n", pfx);
+ printk("%sCTX_INFO_NUM is %d.\n", pfx, proc->context_info_num);
+ return;
+ }
+ for (i = 0; i < proc->context_info_num; i++) {
+ qword = (__u64 *)err_info;
+ printk("%sProcessor context info structure %d:\n", pfx, i);
+ printk("%sException level %d.\n", newpfx,
+ (int)((*qword & CPER_ARMV8_CTX_EL_MASK)
+ >> CPER_ARMV8_CTX_EL_SHIFT));
+ printk("%sSecure bit: %d.\n", newpfx,
+ (int)((*qword & CPER_ARMV8_CTX_NS_MASK)
+ >> CPER_ARMV8_CTX_NS_SHIFT));
+ if ((*qword & CPER_ARMV8_CTX_TYPE_MASK) == 0) {
+ if (len < CPER_AARCH32_CTX_LEN) {
+ printk("%ssection length is too small.\n", pfx);
+ printk("%sremaining length is %d.\n", pfx, len);
+ return;
+ }
+ printk("%sAArch32 execution context.\n", newpfx);
+ qword++;
+ print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4,
+ qword, CPER_AARCH32_CTX_LEN - sizeof(*qword),
+ 0);
+ len -= CPER_AARCH32_CTX_LEN;
+ } else if ((*qword & CPER_ARMV8_CTX_TYPE_MASK) == 1) {
+ if (len < CPER_AARCH64_CTX_LEN) {
+ printk("%ssection length is too small.\n", pfx);
+ printk("%sremaining length is %d.\n", pfx, len);
+ return;
+ }
+ printk("%sAArch64 execution context.\n", newpfx);
+ qword++;
+ print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4,
+ qword, CPER_AARCH64_CTX_LEN - sizeof(*qword),
+ 0);
+ len -= CPER_AARCH64_CTX_LEN;
+ } else {
+ printk("%scontext type is incorrect 0x%016llx.\n",
+ pfx, *qword);
+ return;
+ }
+ }
+
+ if (len > 0) {
+ printk("%sVendor specific error info has %d bytes.\n", pfx,
+ len);
+ print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, qword, len,
+ 0);
+ }
+}
+
static const char * const mem_err_type_strs[] = {
"unknown",
"no error",
@@ -470,6 +596,15 @@ static void cper_estatus_print_section(
cper_print_pcie(newpfx, pcie, gdata);
else
goto err_section_too_small;
+ } else if (!uuid_le_cmp(*sec_type, CPER_SEC_PROC_ARMV8)) {
+ struct cper_sec_proc_armv8 *armv8_err;
+
+ armv8_err = acpi_hest_generic_data_payload(gdata);
+ printk("%ssection_type: ARMv8 processor error\n", newpfx);
+ if (gdata->error_data_length >= sizeof(*armv8_err))
+ cper_print_proc_armv8(newpfx, armv8_err);
+ else
+ goto err_section_too_small;
} else
printk("%s""section type: unknown, %pUl\n", newpfx, sec_type);
diff --git a/include/linux/cper.h b/include/linux/cper.h
index dcacb1a..d1efbef 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -162,6 +162,11 @@ enum {
* corrective action before the data is consumed
*/
#define CPER_SEC_LATENT_ERROR 0x0020
+/*
+ * If set, the section contains an error that is propagated. The error
+ * did not originate from the hardware associated with this section.
+ */
+#define CPER_SEC_PROPAGATED 0x0040
/*
* Section type definitions, used in section_type field in struct
@@ -180,6 +185,10 @@ enum {
#define CPER_SEC_PROC_IPF \
UUID_LE(0xE429FAF1, 0x3CB7, 0x11D4, 0x0B, 0xCA, 0x07, 0x00, \
0x80, 0xC7, 0x3C, 0x88, 0x81)
+/* Processor Specific: ARMv8 */
+#define CPER_SEC_PROC_ARMV8 \
+ UUID_LE(0xE19E3D16, 0xBC11, 0x11E4, 0x9C, 0xAA, 0xC2, 0x05, \
+ 0x1D, 0x5D, 0x46, 0xB0)
/* Platform Memory */
#define CPER_SEC_PLATFORM_MEM \
UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \
@@ -255,6 +264,34 @@ enum {
#define CPER_PCIE_SLOT_SHIFT 3
+#define CPER_ARMV8_ERR_INFO_NUM_MASK 0x00000000000000FF
+#define CPER_ARMV8_CTX_INFO_NUM_MASK 0x0000000000FFFF00
+#define CPER_ARMV8_CTX_INFO_NUM_SHIFT 8
+
+#define CPER_ARMV8_VALID_MPIDR 0x00000001
+#define CPER_ARMV8_VALID_AFFINITY_LEVEL 0x00000002
+#define CPER_ARMV8_VALID_RUNNING_STATE 0x00000004
+#define CPER_ARMV8_VALID_VENDOR_INFO 0x00000008
+
+#define CPER_ARMV8_INFO_VALID_MULTI_ERR 0x0001
+#define CPER_ARMV8_INFO_VALID_FLAGS 0x0002
+#define CPER_ARMV8_INFO_VALID_ERR_INFO 0x0004
+#define CPER_ARMV8_INFO_VALID_VIRT_ADDR 0x0008
+#define CPER_ARMV8_INFO_VALID_PHYSICAL_ADDR 0x0010
+
+#define CPER_ARMV8_INFO_FLAGS_FIRST 0x0001
+#define CPER_ARMV8_INFO_FLAGS_LAST 0x0002
+#define CPER_ARMV8_INFO_FLAGS_PROPAGATED 0x0004
+
+#define CPER_AARCH64_CTX_LEN 368
+#define CPER_AARCH32_CTX_LEN 256
+
+#define CPER_ARMV8_CTX_TYPE_MASK 0x000000000000000F
+#define CPER_ARMV8_CTX_EL_MASK 0x0000000000000070
+#define CPER_ARMV8_CTX_NS_MASK 0x0000000000000080
+#define CPER_ARMV8_CTX_EL_SHIFT 4
+#define CPER_ARMV8_CTX_NS_SHIFT 7
+
/*
* All tables and structs must be byte-packed to match CPER
* specification, since the tables are provided by the system BIOS
@@ -340,6 +377,41 @@ struct cper_ia_proc_ctx {
__u64 mm_reg_addr;
};
+/* ARMv8 Processor Error Section */
+struct cper_sec_proc_armv8 {
+ __u32 validation_bits;
+ __u16 err_info_num; /* Number of Processor Error Info */
+ __u16 context_info_num; /* Number of Processor Context Info Records*/
+ __u32 section_length;
+ __u8 affinity_level;
+ __u8 reserved[3]; /* must be zero */
+ __u64 mpidr;
+ __u64 midr;
+ __u32 running_state; /* Bit 0 set - Processor running. PSCI = 0 */
+ __u32 psci_state;
+};
+
+/* ARMv8 Processor Error Information Structure */
+struct cper_armv8_err_info {
+ __u8 version;
+ __u8 length;
+ __u16 validation_bits;
+ __u8 type;
+ __u16 multiple_error;
+ __u8 flags;
+ __u64 error_info;
+ __u64 virt_fault_addr;
+ __u64 physical_fault_addr;
+};
+
+/* ARMv8 AARCH64 Processor Context Information Structure */
+struct cper_armv8_aarch64_ctx {
+ __u8 type_el_ns;
+ __u8 reserved[7]; /* must be zero */
+ __u8 gpr[288];
+ __u8 spr[68];
+};
+
/* Old Memory Error Section UEFI 2.1, 2.2 */
struct cper_sec_mem_err_old {
__u64 validation_bits;
--
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.
^ permalink raw reply related
* [PATCH V3 02/10] ras: acpi/apei: cper: generic error data entry v3 per ACPI 6.1
From: Tyler Baicar @ 2016-10-07 21:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475875882-2604-1-git-send-email-tbaicar@codeaurora.org>
Currently when a RAS error is reported it is not timestamped.
The ACPI 6.1 spec adds the timestamp field to the generic error
data entry v3 structure. The timestamp of when the firmware
generated the error is now being reported.
Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Signed-off-by: Richard Ruigrok <rruigrok@codeaurora.org>
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
---
drivers/acpi/apei/ghes.c | 25 ++++++++++--
drivers/firmware/efi/cper.c | 97 +++++++++++++++++++++++++++++++++++++++------
2 files changed, 105 insertions(+), 17 deletions(-)
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 3021f0e..c8488f1 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -80,6 +80,10 @@
((struct acpi_hest_generic_status *) \
((struct ghes_estatus_node *)(estatus_node) + 1))
+#define acpi_hest_generic_data_version(gdata) \
+ (gdata->revision >> 8)
+
+
/*
* This driver isn't really modular, however for the time being,
* continuing to use module_param is the easiest way to remain
@@ -412,6 +416,13 @@ static void ghes_clear_estatus(struct ghes *ghes)
ghes->flags &= ~GHES_TO_CLEAR;
}
+inline void *acpi_hest_generic_data_payload(struct acpi_hest_generic_data *gdata)
+{
+ return acpi_hest_generic_data_version(gdata) >= 3 ?
+ (void *)(((struct acpi_hest_generic_data_v300 *)(gdata)) + 1) :
+ gdata + 1;
+}
+
static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int sev)
{
#ifdef CONFIG_ACPI_APEI_MEMORY_FAILURE
@@ -419,7 +430,8 @@ static void ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, int
int flags = -1;
int sec_sev = ghes_severity(gdata->error_severity);
struct cper_sec_mem_err *mem_err;
- mem_err = (struct cper_sec_mem_err *)(gdata + 1);
+
+ mem_err = acpi_hest_generic_data_payload(gdata);
if (!(mem_err->validation_bits & CPER_MEM_VALID_PA))
return;
@@ -449,14 +461,18 @@ static void ghes_do_proc(struct ghes *ghes,
{
int sev, sec_sev;
struct acpi_hest_generic_data *gdata;
+ uuid_le sec_type;
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 (!uuid_le_cmp(sec_type,
CPER_SEC_PLATFORM_MEM)) {
struct cper_sec_mem_err *mem_err;
- mem_err = (struct cper_sec_mem_err *)(gdata+1);
+
+ mem_err = acpi_hest_generic_data_payload(gdata);
ghes_edac_report_mem_error(ghes, sev, mem_err);
arch_apei_report_mem_error(sev, mem_err);
@@ -466,7 +482,8 @@ static void ghes_do_proc(struct ghes *ghes,
else if (!uuid_le_cmp(*(uuid_le *)gdata->section_type,
CPER_SEC_PCIE)) {
struct cper_sec_pcie *pcie_err;
- pcie_err = (struct cper_sec_pcie *)(gdata+1);
+
+ pcie_err = acpi_hest_generic_data_payload(gdata);
if (sev == GHES_SEV_RECOVERABLE &&
sec_sev == GHES_SEV_RECOVERABLE &&
pcie_err->validation_bits & CPER_PCIE_VALID_DEVICE_ID &&
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index d425374..9fa1317 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -32,9 +32,14 @@
#include <linux/acpi.h>
#include <linux/pci.h>
#include <linux/aer.h>
+#include <linux/printk.h>
+#include <linux/bcd.h>
#define INDENT_SP " "
+#define acpi_hest_generic_data_version(gdata) \
+ (gdata->revision >> 8)
+
static char rcd_decode_str[CPER_REC_LEN];
/*
@@ -386,13 +391,47 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
pfx, pcie->bridge.secondary_status, pcie->bridge.control);
}
+static inline void *acpi_hest_generic_data_payload(struct acpi_hest_generic_data *gdata)
+{
+ return acpi_hest_generic_data_version(gdata) >= 3 ?
+ (void *)(((struct acpi_hest_generic_data_v300 *)(gdata)) + 1) :
+ gdata + 1;
+}
+
+static void cper_estatus_print_section_v300(const char *pfx,
+ const struct acpi_hest_generic_data_v300 *gdata)
+{
+ __u8 hour, min, sec, day, mon, year, century, *timestamp;
+
+ if (gdata->validation_bits & ACPI_HEST_GEN_VALID_TIMESTAMP) {
+ timestamp = (__u8 *)&(gdata->time_stamp);
+ memcpy(&sec, timestamp, 1);
+ memcpy(&min, timestamp + 1, 1);
+ memcpy(&hour, timestamp + 2, 1);
+ memcpy(&day, timestamp + 4, 1);
+ memcpy(&mon, timestamp + 5, 1);
+ memcpy(&year, timestamp + 6, 1);
+ memcpy(¢ury, timestamp + 7, 1);
+ printk("%stime: ", pfx);
+ printk("%7s", 0x01 & *(timestamp + 3) ? "precise" : "");
+ printk(" %02d:%02d:%02d %02d%02d-%02d-%02d\n",
+ bcd2bin(hour), bcd2bin(min), bcd2bin(sec),
+ bcd2bin(century), bcd2bin(year), bcd2bin(mon),
+ bcd2bin(day));
+ }
+}
+
static void cper_estatus_print_section(
- const char *pfx, const struct acpi_hest_generic_data *gdata, int sec_no)
+ const char *pfx, struct acpi_hest_generic_data *gdata, int sec_no)
{
uuid_le *sec_type = (uuid_le *)gdata->section_type;
__u16 severity;
char newpfx[64];
+ if ((gdata->revision >> 8) >= 0x03)
+ cper_estatus_print_section_v300(pfx,
+ (const struct acpi_hest_generic_data_v300 *)gdata);
+
severity = gdata->error_severity;
printk("%s""Error %d, type: %s\n", pfx, sec_no,
cper_severity_str(severity));
@@ -403,14 +442,18 @@ static void cper_estatus_print_section(
snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
if (!uuid_le_cmp(*sec_type, CPER_SEC_PROC_GENERIC)) {
- struct cper_sec_proc_generic *proc_err = (void *)(gdata + 1);
+ struct cper_sec_proc_generic *proc_err;
+
+ proc_err = acpi_hest_generic_data_payload(gdata);
printk("%s""section_type: general processor error\n", newpfx);
if (gdata->error_data_length >= sizeof(*proc_err))
cper_print_proc_generic(newpfx, proc_err);
else
goto err_section_too_small;
} else if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) {
- struct cper_sec_mem_err *mem_err = (void *)(gdata + 1);
+ struct cper_sec_mem_err *mem_err;
+
+ mem_err = acpi_hest_generic_data_payload(gdata);
printk("%s""section_type: memory error\n", newpfx);
if (gdata->error_data_length >=
sizeof(struct cper_sec_mem_err_old))
@@ -419,7 +462,9 @@ static void cper_estatus_print_section(
else
goto err_section_too_small;
} else if (!uuid_le_cmp(*sec_type, CPER_SEC_PCIE)) {
- struct cper_sec_pcie *pcie = (void *)(gdata + 1);
+ struct cper_sec_pcie *pcie;
+
+ pcie = acpi_hest_generic_data_payload(gdata);
printk("%s""section_type: PCIe error\n", newpfx);
if (gdata->error_data_length >= sizeof(*pcie))
cper_print_pcie(newpfx, pcie, gdata);
@@ -438,6 +483,7 @@ void cper_estatus_print(const char *pfx,
const struct acpi_hest_generic_status *estatus)
{
struct acpi_hest_generic_data *gdata;
+ struct acpi_hest_generic_data_v300 *gdata_v3 = NULL;
unsigned int data_len, gedata_len;
int sec_no = 0;
char newpfx[64];
@@ -451,12 +497,22 @@ void cper_estatus_print(const char *pfx,
printk("%s""event severity: %s\n", pfx, cper_severity_str(severity));
data_len = estatus->data_length;
gdata = (struct acpi_hest_generic_data *)(estatus + 1);
+ if ((gdata->revision >> 8) >= 0x03)
+ gdata_v3 = (struct acpi_hest_generic_data_v300 *)gdata;
+
snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
+
while (data_len >= sizeof(*gdata)) {
gedata_len = gdata->error_data_length;
cper_estatus_print_section(newpfx, gdata, sec_no);
- data_len -= gedata_len + sizeof(*gdata);
- gdata = (void *)(gdata + 1) + gedata_len;
+ if(gdata_v3) {
+ data_len -= gedata_len + sizeof(*gdata_v3);
+ gdata_v3 = (void *)(gdata_v3 + 1) + gedata_len;
+ gdata = (struct acpi_hest_generic_data *)gdata_v3;
+ } else {
+ data_len -= gedata_len + sizeof(*gdata);
+ gdata = (void *)(gdata + 1) + gedata_len;
+ }
sec_no++;
}
}
@@ -478,6 +534,7 @@ EXPORT_SYMBOL_GPL(cper_estatus_check_header);
int cper_estatus_check(const struct acpi_hest_generic_status *estatus)
{
struct acpi_hest_generic_data *gdata;
+ struct acpi_hest_generic_data_v300 *gdata_v3 = NULL;
unsigned int data_len, gedata_len;
int rc;
@@ -486,15 +543,29 @@ int cper_estatus_check(const struct acpi_hest_generic_status *estatus)
return rc;
data_len = estatus->data_length;
gdata = (struct acpi_hest_generic_data *)(estatus + 1);
- while (data_len >= sizeof(*gdata)) {
- gedata_len = gdata->error_data_length;
- if (gedata_len > data_len - sizeof(*gdata))
+
+ if ((gdata->revision >> 8) >= 0x03) {
+ gdata_v3 = (struct acpi_hest_generic_data_v300 *)gdata;
+ while (data_len >= sizeof(*gdata_v3)) {
+ gedata_len = gdata_v3->error_data_length;
+ if (gedata_len > data_len - sizeof(*gdata_v3))
+ return -EINVAL;
+ data_len -= gedata_len + sizeof(*gdata_v3);
+ gdata_v3 = (void *)(gdata_v3 + 1) + gedata_len;
+ }
+ if (data_len)
+ return -EINVAL;
+ } else {
+ while (data_len >= sizeof(*gdata)) {
+ gedata_len = gdata->error_data_length;
+ if (gedata_len > data_len - sizeof(*gdata))
+ return -EINVAL;
+ data_len -= gedata_len + sizeof(*gdata);
+ gdata = (void *)(gdata + 1) + gedata_len;
+ }
+ if (data_len)
return -EINVAL;
- data_len -= gedata_len + sizeof(*gdata);
- gdata = (void *)(gdata + 1) + gedata_len;
}
- if (data_len)
- return -EINVAL;
return 0;
}
--
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.
^ permalink raw reply related
* [PATCH V3 01/10] acpi: apei: read ack upon ghes record consumption
From: Tyler Baicar @ 2016-10-07 21:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475875882-2604-1-git-send-email-tbaicar@codeaurora.org>
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.
Signed-off-by: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
Signed-off-by: Richard Ruigrok <rruigrok@codeaurora.org>
Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
---
drivers/acpi/apei/ghes.c | 41 +++++++++++++++++++++++++++++++++++++++++
drivers/acpi/apei/hest.c | 7 +++++--
include/acpi/ghes.h | 1 +
3 files changed, 47 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 60746ef..3021f0e 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>
@@ -244,10 +245,22 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
struct ghes *ghes;
unsigned int error_block_length;
int rc;
+ struct acpi_hest_header *hest_hdr;
ghes = kzalloc(sizeof(*ghes), GFP_KERNEL);
if (!ghes)
return ERR_PTR(-ENOMEM);
+
+ hest_hdr = (struct acpi_hest_header *)generic;
+ if (hest_hdr->type == ACPI_HEST_TYPE_GENERIC_ERROR_V2) {
+ ghes->generic_v2 = (struct acpi_hest_generic_v2 *)generic;
+ rc = apei_map_generic_address(
+ &ghes->generic_v2->read_ack_register);
+ if (rc)
+ goto err_unmap;
+ } else
+ ghes->generic_v2 = NULL;
+
ghes->generic = generic;
rc = apei_map_generic_address(&generic->error_status_address);
if (rc)
@@ -270,6 +283,9 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
err_unmap:
apei_unmap_generic_address(&generic->error_status_address);
+ if (ghes->generic_v2)
+ apei_unmap_generic_address(
+ &ghes->generic_v2->read_ack_register);
err_free:
kfree(ghes);
return ERR_PTR(rc);
@@ -279,6 +295,9 @@ static void ghes_fini(struct ghes *ghes)
{
kfree(ghes->estatus);
apei_unmap_generic_address(&ghes->generic->error_status_address);
+ if (ghes->generic_v2)
+ apei_unmap_generic_address(
+ &ghes->generic_v2->read_ack_register);
}
static inline int ghes_severity(int severity)
@@ -648,6 +667,22 @@ static void ghes_estatus_cache_add(
rcu_read_unlock();
}
+static int ghes_do_read_ack(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;
+ rc = apei_write(val, &generic_v2->read_ack_register);
+
+ return rc;
+}
+
static int ghes_proc(struct ghes *ghes)
{
int rc;
@@ -660,6 +695,12 @@ static int ghes_proc(struct ghes *ghes)
ghes_estatus_cache_add(ghes->generic, ghes->estatus);
}
ghes_do_proc(ghes, ghes->estatus);
+
+ if (ghes->generic_v2) {
+ rc = ghes_do_read_ack(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..d0108b6 100644
--- a/include/acpi/ghes.h
+++ b/include/acpi/ghes.h
@@ -14,6 +14,7 @@
struct ghes {
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.
^ permalink raw reply related
* [PATCH V3 00/10] Add UEFI 2.6 and ACPI 6.1 updates for RAS on ARM64
From: Tyler Baicar @ 2016-10-07 21:31 UTC (permalink / raw)
To: linux-arm-kernel
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.
Depends on: [PATCH v14] acpi, apei, arm64: APEI initial support for aarch64.
https://lkml.org/lkml/2016/8/10/231
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 ARMv8 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
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 | 15 ++-
arch/arm64/Kconfig | 1 +
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 | 15 +++
drivers/acpi/apei/ghes.c | 177 +++++++++++++++++++++++-
drivers/acpi/apei/hest.c | 7 +-
drivers/firmware/efi/cper.c | 252 ++++++++++++++++++++++++++++++++---
drivers/ras/ras.c | 2 +
include/acpi/ghes.h | 1 +
include/linux/cper.h | 72 ++++++++++
include/ras/ras_event.h | 112 ++++++++++++++++
15 files changed, 711 insertions(+), 36 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.
^ permalink raw reply
* [PATCH] arm64: dts: rename ns2.txt to brcm,ns2.txt
From: Scott Branden @ 2016-10-07 21:29 UTC (permalink / raw)
To: linux-arm-kernel
Rename ns2.txt to brcm,ns2.txt to match naming convention followed
by rest of Broadcom binding documentation.
Signed-off-by: Scott Branden <scott.branden@broadcom.com>
---
Documentation/devicetree/bindings/arm/bcm/brcm,ns2.txt | 9 +++++++++
Documentation/devicetree/bindings/arm/bcm/ns2.txt | 9 ---------
2 files changed, 9 insertions(+), 9 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/bcm/brcm,ns2.txt
delete mode 100644 Documentation/devicetree/bindings/arm/bcm/ns2.txt
diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,ns2.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,ns2.txt
new file mode 100644
index 0000000..35f056f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/bcm/brcm,ns2.txt
@@ -0,0 +1,9 @@
+Broadcom North Star 2 (NS2) device tree bindings
+------------------------------------------------
+
+Boards with NS2 shall have the following properties:
+
+Required root node property:
+
+NS2 SVK board
+compatible = "brcm,ns2-svk", "brcm,ns2";
diff --git a/Documentation/devicetree/bindings/arm/bcm/ns2.txt b/Documentation/devicetree/bindings/arm/bcm/ns2.txt
deleted file mode 100644
index 35f056f..0000000
--- a/Documentation/devicetree/bindings/arm/bcm/ns2.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-Broadcom North Star 2 (NS2) device tree bindings
-------------------------------------------------
-
-Boards with NS2 shall have the following properties:
-
-Required root node property:
-
-NS2 SVK board
-compatible = "brcm,ns2-svk", "brcm,ns2";
--
2.5.0
^ permalink raw reply related
* [PATCH] arm64: defconfig: enable EEPROM_AT25 config option
From: Scott Branden @ 2016-10-07 21:23 UTC (permalink / raw)
To: linux-arm-kernel
Enable support for on board SPI EEPROM by turning on
CONFIG_EEPROM_AT25.
Signed-off-by: Scott Branden <scott.branden@broadcom.com>
---
arch/arm64/configs/defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index eadf485..9955ee1 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -136,6 +136,7 @@ CONFIG_MTD_SPI_NOR=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=m
CONFIG_VIRTIO_BLK=y
+CONFIG_EEPROM_AT25=y
CONFIG_SRAM=y
# CONFIG_SCSI_PROC_FS is not set
CONFIG_BLK_DEV_SD=y
--
2.5.0
^ permalink raw reply related
* [PATCH] coresight: reset "enable_sink" flag when need be
From: Mathieu Poirier @ 2016-10-07 21:10 UTC (permalink / raw)
To: linux-arm-kernel
When using coresight from the perf interface sinks are specified
as part of the perf command line. As such the sink needs to be
disabled once it has been acknowledged by the coresight framework.
Otherwise the sink stays enabled, which may interfere with other
sessions.
This patch removes the sink selection check from the build path
process and make it a function on it's own. The function is
then used when operating from sysFS or perf to determine what
sink has been selected.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
drivers/hwtracing/coresight/coresight-etm-perf.c | 31 ++++++------
drivers/hwtracing/coresight/coresight-priv.h | 4 +-
drivers/hwtracing/coresight/coresight.c | 62 +++++++++++++++++++++---
3 files changed, 75 insertions(+), 22 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index 2cd7c718198a..1103073b2640 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -202,6 +202,21 @@ static void *etm_setup_aux(int event_cpu, void **pages,
if (!event_data)
return NULL;
+ /*
+ * In theory nothing prevent tracers in a trace session from being
+ * associated with different sinks, nor having a sink per tracer. But
+ * until we have HW with this kind of topolog we need to assume tracers
+ * in a trace session are using the same sink. Therefore go through
+ * the coresight bus and pick the first enabled sink.
+ *
+ * When operated from sysFS users are responsible to enable the sink
+ * while from perf, the perf tools will do it based on the choice made
+ * on the cmd line. As such the "enable_sink" flag in sysFS is reset.
+ */
+ sink = coresight_get_enabled_sink(true);
+ if (!sink)
+ return NULL;
+
INIT_WORK(&event_data->work, free_event_data);
mask = &event_data->mask;
@@ -219,25 +234,11 @@ static void *etm_setup_aux(int event_cpu, void **pages,
* list of devices from source to sink that can be
* referenced later when the path is actually needed.
*/
- event_data->path[cpu] = coresight_build_path(csdev);
+ event_data->path[cpu] = coresight_build_path(csdev, sink);
if (IS_ERR(event_data->path[cpu]))
goto err;
}
- /*
- * In theory nothing prevent tracers in a trace session from being
- * associated with different sinks, nor having a sink per tracer. But
- * until we have HW with this kind of topology and a way to convey
- * sink assignement from the perf cmd line we need to assume tracers
- * in a trace session are using the same sink. Therefore pick the sink
- * found at the end of the first available path.
- */
- cpu = cpumask_first(mask);
- /* Grab the sink at the end of the path */
- sink = coresight_get_sink(event_data->path[cpu]);
- if (!sink)
- goto err;
-
if (!sink_ops(sink)->alloc_buffer)
goto err;
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 196a14be4b3d..ef9d8e93e3b2 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -111,7 +111,9 @@ static inline void CS_UNLOCK(void __iomem *addr)
void coresight_disable_path(struct list_head *path);
int coresight_enable_path(struct list_head *path, u32 mode);
struct coresight_device *coresight_get_sink(struct list_head *path);
-struct list_head *coresight_build_path(struct coresight_device *csdev);
+struct coresight_device *coresight_get_enabled_sink(bool reset);
+struct list_head *coresight_build_path(struct coresight_device *csdev,
+ struct coresight_device *sink);
void coresight_release_path(struct list_head *path);
#ifdef CONFIG_CORESIGHT_SOURCE_ETM3X
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 7bf00a0beb6f..40ede643d553 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -368,6 +368,40 @@ struct coresight_device *coresight_get_sink(struct list_head *path)
return csdev;
}
+static int coresight_enabled_sink(struct device *dev, void *data)
+{
+ bool *reset = data;
+ struct coresight_device *csdev = to_coresight_device(dev);
+
+ if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
+ csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) &&
+ csdev->activated) {
+ /*
+ * Now that we have a handle on the sink for this session,
+ * disable the sysFS "enable_sink" flag so that possible
+ * concurrent perf session that wish to use another sink don't
+ * trip on it. Doing so has no ramification for the current
+ * session.
+ */
+ if (*reset)
+ csdev->activated = false;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+struct coresight_device *coresight_get_enabled_sink(bool reset)
+{
+ struct device *dev = NULL;
+
+ dev = bus_find_device(&coresight_bustype, NULL, &reset,
+ coresight_enabled_sink);
+
+ return dev ? to_coresight_device(dev) : NULL;
+}
+
/**
* _coresight_build_path - recursively build a path from a @csdev to a sink.
* @csdev: The device to start from.
@@ -380,6 +414,7 @@ struct coresight_device *coresight_get_sink(struct list_head *path)
* last one.
*/
static int _coresight_build_path(struct coresight_device *csdev,
+ struct coresight_device *sink,
struct list_head *path)
{
int i;
@@ -387,15 +422,15 @@ static int _coresight_build_path(struct coresight_device *csdev,
struct coresight_node *node;
/* An activated sink has been found. Enqueue the element */
- if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
- csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) && csdev->activated)
+ if (csdev == sink)
goto out;
/* Not a sink - recursively explore each port found on this element */
for (i = 0; i < csdev->nr_outport; i++) {
struct coresight_device *child_dev = csdev->conns[i].child_dev;
- if (child_dev && _coresight_build_path(child_dev, path) == 0) {
+ if (child_dev &&
+ _coresight_build_path(child_dev, sink, path) == 0) {
found = true;
break;
}
@@ -422,18 +457,22 @@ out:
return 0;
}
-struct list_head *coresight_build_path(struct coresight_device *csdev)
+struct list_head *coresight_build_path(struct coresight_device *source,
+ struct coresight_device *sink)
{
struct list_head *path;
int rc;
+ if (!sink)
+ return ERR_PTR(-EINVAL);
+
path = kzalloc(sizeof(struct list_head), GFP_KERNEL);
if (!path)
return ERR_PTR(-ENOMEM);
INIT_LIST_HEAD(path);
- rc = _coresight_build_path(csdev, path);
+ rc = _coresight_build_path(source, sink, path);
if (rc) {
kfree(path);
return ERR_PTR(rc);
@@ -497,6 +536,7 @@ static int coresight_validate_source(struct coresight_device *csdev,
int coresight_enable(struct coresight_device *csdev)
{
int cpu, ret = 0;
+ struct coresight_device *sink;
struct list_head *path;
mutex_lock(&coresight_mutex);
@@ -508,7 +548,17 @@ int coresight_enable(struct coresight_device *csdev)
if (csdev->enable)
goto out;
- path = coresight_build_path(csdev);
+ /*
+ * Search for a valid sink for this session but don't reset the
+ * "enable_sink" flag in sysFS. Users get to do that explicitly.
+ */
+ sink = coresight_get_enabled_sink(false);
+ if (!sink) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ path = coresight_build_path(csdev, sink);
if (IS_ERR(path)) {
pr_err("building path(s) failed\n");
ret = PTR_ERR(path);
--
2.7.4
^ permalink raw reply related
* [PATCH 1/3] fpga manager: Add cyclonespi driver for Altera fpgas
From: Joshua Clayton @ 2016-10-07 20:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.02.1610071248320.32627@linuxheads99>
On 10/07/2016 11:21 AM, atull wrote:
> On Fri, 7 Oct 2016, Moritz Fischer wrote:
>
>>> +static inline u32 revbit8x4(u32 n)
>>> +{
>>> + n = ((n & 0xF0F0F0F0UL) >> 4) | ((n & 0x0F0F0F0FUL) << 4);
>>> + n = ((n & 0xCCCCCCCCUL) >> 2) | ((n & 0x33333333UL) << 2);
>>> + n = ((n & 0xAAAAAAAAUL) >> 1) | ((n & 0x55555555UL) << 1);
>>> + return n;
>>> +}
The real issue is that The FPGA wants lsb first, and my SPI driver
doesn't support it.
What I really wanted to do here was to get generic support for lsb-first
SPI into the SPI subsystem.
>> During the Zynq FPGA manager reviews we decided that manipulating the bitstream
>> to be consumable by the driver is userland's job.
> Moritz, Can you remind me what that issue was there (or point me to
> that email, I can't find it)? I don't think I had a problem with that
> in your case. In general I think if these drivers can take the
> bitstream that comes from the manufacturer's tools and stuff it into
> the FPGA, then we are accomplishing what we want. So I am OK with
> this here. The intent of the driver is to load a standard rbf, same
> as the other Altera FPGA drivers.
> There is a problem here though it will be easy to fix. This call to
> revbit8x4 should happen in cyclonespi_write(), not in
> cyclonespi_write_init(). The reason for that is that write_init() may
> just get the first chunk of the image (the header) and that write()
> will be called multiple times for the remaining chunks. The current
> FPGA manager API won't show this problem since you have to give
> fpga_mgr_buf_load the whole image buffer at once. But it is easy to
> imagine that some time in the future we may want to expand the FPGA
> manager API to support streaming where we don't have the whole buffer.
OK.
If generic lsb first support for SPI is too high a bar (which it may be),
I will move the bit reversing code into the write function.
> Thanks for submitting, Joshua. Will be looking at this over the
> next several days.
>
> Alan
Thanks for the quick response!
I'll be looking forward to your review,
Joshua Clayton
^ permalink raw reply
* [PATCH v13 12/15] vfio: Allow reserved msi iova registration
From: Alex Williamson @ 2016-10-07 20:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <27e4db66-7df2-16b4-c3d9-982d6ea845b0@redhat.com>
On Fri, 7 Oct 2016 19:11:43 +0200
Auger Eric <eric.auger@redhat.com> wrote:
> Hi Alex,
>
> On 06/10/2016 22:19, Alex Williamson wrote:
> > On Thu, 6 Oct 2016 08:45:28 +0000
> > Eric Auger <eric.auger@redhat.com> wrote:
> >
> >> The user is allowed to register a reserved MSI IOVA range by using the
> >> DMA MAP API and setting the new flag: VFIO_DMA_MAP_FLAG_MSI_RESERVED_IOVA.
> >> This region is stored in the vfio_dma rb tree. At that point the iova
> >> range is not mapped to any target address yet. The host kernel will use
> >> those iova when needed, typically when MSIs are allocated.
> >>
> >> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> >> Signed-off-by: Bharat Bhushan <Bharat.Bhushan@freescale.com>
> >>
> >> ---
> >> v12 -> v13:
> >> - use iommu_get_dma_msi_region_cookie
> >>
> >> v9 -> v10
> >> - use VFIO_IOVA_RESERVED_MSI enum value
> >>
> >> v7 -> v8:
> >> - use iommu_msi_set_aperture function. There is no notion of
> >> unregistration anymore since the reserved msi slot remains
> >> until the container gets closed.
> >>
> >> v6 -> v7:
> >> - use iommu_free_reserved_iova_domain
> >> - convey prot attributes downto dma-reserved-iommu iova domain creation
> >> - reserved bindings teardown now performed on iommu domain destruction
> >> - rename VFIO_DMA_MAP_FLAG_MSI_RESERVED_IOVA into
> >> VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA
> >> - change title
> >> - pass the protection attribute to dma-reserved-iommu API
> >>
> >> v3 -> v4:
> >> - use iommu_alloc/free_reserved_iova_domain exported by dma-reserved-iommu
> >> - protect vfio_register_reserved_iova_range implementation with
> >> CONFIG_IOMMU_DMA_RESERVED
> >> - handle unregistration by user-space and on vfio_iommu_type1 release
> >>
> >> v1 -> v2:
> >> - set returned value according to alloc_reserved_iova_domain result
> >> - free the iova domains in case any error occurs
> >>
> >> RFC v1 -> v1:
> >> - takes into account Alex comments, based on
> >> [RFC PATCH 1/6] vfio: Add interface for add/del reserved iova region:
> >> - use the existing dma map/unmap ioctl interface with a flag to register
> >> a reserved IOVA range. A single reserved iova region is allowed.
> >> ---
> >> drivers/vfio/vfio_iommu_type1.c | 77 ++++++++++++++++++++++++++++++++++++++++-
> >> include/uapi/linux/vfio.h | 10 +++++-
> >> 2 files changed, 85 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> >> index 5bc5fc9..c2f8bd9 100644
> >> --- a/drivers/vfio/vfio_iommu_type1.c
> >> +++ b/drivers/vfio/vfio_iommu_type1.c
> >> @@ -442,6 +442,20 @@ static void vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma)
> >> vfio_lock_acct(-unlocked);
> >> }
> >>
> >> +static int vfio_set_msi_aperture(struct vfio_iommu *iommu,
> >> + dma_addr_t iova, size_t size)
> >> +{
> >> + struct vfio_domain *d;
> >> + int ret = 0;
> >> +
> >> + list_for_each_entry(d, &iommu->domain_list, next) {
> >> + ret = iommu_get_dma_msi_region_cookie(d->domain, iova, size);
> >> + if (ret)
> >> + break;
> >> + }
> >> + return ret;
> >
> > Doesn't this need an unwind on failure loop?
> At the moment the de-allocation is done by the smmu driver, on
> domain_free ops, which calls iommu_put_dma_cookie. In case,
> iommu_get_dma_msi_region_cookie fails on a given VFIO domain currently
> there is no other way but destroying all VFIO domains and redo everything.
>
> So yes I plan to unfold everything, ie call iommu_put_dma_cookie for
> each domain.
That's a pretty harsh user experience isn't it? They potentially have
some domains where the cookie is setup and others without and they have
no means to recover except to tear it all down and start over? Thanks,
Alex
^ permalink raw reply
* [PATCH 4/10] MAINTAINERS: add entry for Marvell Xenon MMC Host Controller drivers
From: Joe Perches @ 2016-10-07 20:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <86b237c01d9767d4e0edf6d41194ab959838e5c0.1475853198.git-series.gregory.clement@free-electrons.com>
On Fri, 2016-10-07 at 17:22 +0200, Gregory CLEMENT wrote:
> Add maintainer entry for Marvell Xenon eMMC/SD/SDIO Host
> Controller drivers.
[]
> diff --git a/MAINTAINERS b/MAINTAINERS
[]
> @@ -7578,6 +7578,11 @@ M: Nicolas Pitre <nico@fluxnic.net>
> S: Odd Fixes
> F: drivers/mmc/host/mvsdio.*
>
> +MARVELL XENON MMC/SD/SDIO HOST CONTROLLER DRIVER
> +M: Ziji Hu <huziji@marvell.com>
> +L: linux-mmc at vger.kernel.org
> +S: Supported
You should really add F: file patterns here
^ permalink raw reply
* [PATCH 2/3] doc: dt: add cyclone-spi binding document
From: Joshua Clayton @ 2016-10-07 20:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAAtXAHeZLBT-y8xTKgG4PnZA6DH1z5=FoaM4ipC3pTEVU9KR+Q@mail.gmail.com>
Moritz,
thank you very much for the review.
On 10/06/2016 07:53 PM, Moritz Fischer wrote:
> Hi Joshua,
>
> On Thu, Oct 6, 2016 at 1:34 PM, Joshua Clayton <stillcompiling@gmail.com> wrote:
>> Describe a cyclonespi devicetree entry, required features
>>
>> Signed-off-by: Joshua Clayton <stillcompiling@gmail.com>
>> ---
>> .../bindings/fpga/cyclone-spi-fpga-mgr.txt | 23 ++++++++++++++++++++++
>> 1 file changed, 23 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/fpga/cyclone-spi-fpga-mgr.txt
>>
>> diff --git a/Documentation/devicetree/bindings/fpga/cyclone-spi-fpga-mgr.txt b/Documentation/devicetree/bindings/fpga/cyclone-spi-fpga-mgr.txt
>> new file mode 100644
>> index 0000000..8de34db
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/fpga/cyclone-spi-fpga-mgr.txt
>> @@ -0,0 +1,23 @@
>> +Altera SOCFPGA FPGA Manager
> Copy & Paste? :)
Oops :(
As you might image, documentation was the last item done with the least attention.
Will fix.
>
>> +Altera cyclone FPGAs support a method of loading the bitstream over what is
> cyclone->Cyclone
OK.
>> +referred to as "passive serial".
>> +The passive serial link is not technically spi, and might require extra
>> +circuits in order to play nicely with other spi slaves on the same bus.
>> +
>> +See https://www.altera.com/literature/hb/cyc/cyc_c51013.pdf
>> +
>> +Required properties:
>> +- compatible : should contain "altr,cyclonespi-fpga-mgr"
> Alan, do you guys have any input on the compat string?
I am open to change if it makes sense. I tried to keep the format similar.
> I think generally the bindings should go before the actual usage in
> your patch series. Meaning you wanna document the binding
> before you use it. I think this patch should be [1/3].
Ah, In my mind I had it backwards.
> Cheers,
>
> Moritz
I'll give Alan a chance to review and then spin a V2
Joshua Clayton
^ permalink raw reply
* [PATCH v13 15/15] vfio/type1: Return the MSI geometry through VFIO_IOMMU_GET_INFO capability chains
From: Alex Williamson @ 2016-10-07 20:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4adea280-4bdf-7d0e-be2f-88e7f6219b9c@redhat.com>
On Fri, 7 Oct 2016 19:10:27 +0200
Auger Eric <eric.auger@redhat.com> wrote:
> Hi Alex,
>
> On 06/10/2016 22:42, Alex Williamson wrote:
> > On Thu, 6 Oct 2016 14:20:40 -0600
> > Alex Williamson <alex.williamson@redhat.com> wrote:
> >
> >> On Thu, 6 Oct 2016 08:45:31 +0000
> >> Eric Auger <eric.auger@redhat.com> wrote:
> >>
> >>> This patch allows the user-space to retrieve the MSI geometry. The
> >>> implementation is based on capability chains, now also added to
> >>> VFIO_IOMMU_GET_INFO.
> >>>
> >>> The returned info comprise:
> >>> - whether the MSI IOVA are constrained to a reserved range (x86 case) and
> >>> in the positive, the start/end of the aperture,
> >>> - or whether the IOVA aperture need to be set by the userspace. In that
> >>> case, the size and alignment of the IOVA window to be provided are
> >>> returned.
> >>>
> >>> In case the userspace must provide the IOVA aperture, we currently report
> >>> a size/alignment based on all the doorbells registered by the host kernel.
> >>> This may exceed the actual needs.
> >>>
> >>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> >>>
> >>> ---
> >>> v11 -> v11:
> >>> - msi_doorbell_pages was renamed msi_doorbell_calc_pages
> >>>
> >>> v9 -> v10:
> >>> - move cap_offset after iova_pgsizes
> >>> - replace __u64 alignment by __u32 order
> >>> - introduce __u32 flags in vfio_iommu_type1_info_cap_msi_geometry and
> >>> fix alignment
> >>> - call msi-doorbell API to compute the size/alignment
> >>>
> >>> v8 -> v9:
> >>> - use iommu_msi_supported flag instead of programmable
> >>> - replace IOMMU_INFO_REQUIRE_MSI_MAP flag by a more sophisticated
> >>> capability chain, reporting the MSI geometry
> >>>
> >>> v7 -> v8:
> >>> - use iommu_domain_msi_geometry
> >>>
> >>> v6 -> v7:
> >>> - remove the computation of the number of IOVA pages to be provisionned.
> >>> This number depends on the domain/group/device topology which can
> >>> dynamically change. Let's rely instead rely on an arbitrary max depending
> >>> on the system
> >>>
> >>> v4 -> v5:
> >>> - move msi_info and ret declaration within the conditional code
> >>>
> >>> v3 -> v4:
> >>> - replace former vfio_domains_require_msi_mapping by
> >>> more complex computation of MSI mapping requirements, especially the
> >>> number of pages to be provided by the user-space.
> >>> - reword patch title
> >>>
> >>> RFC v1 -> v1:
> >>> - derived from
> >>> [RFC PATCH 3/6] vfio: Extend iommu-info to return MSIs automap state
> >>> - renamed allow_msi_reconfig into require_msi_mapping
> >>> - fixed VFIO_IOMMU_GET_INFO
> >>> ---
> >>> drivers/vfio/vfio_iommu_type1.c | 78 ++++++++++++++++++++++++++++++++++++++++-
> >>> include/uapi/linux/vfio.h | 32 ++++++++++++++++-
> >>> 2 files changed, 108 insertions(+), 2 deletions(-)
> >>>
> >>> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> >>> index dc3ee5d..ce5e7eb 100644
> >>> --- a/drivers/vfio/vfio_iommu_type1.c
> >>> +++ b/drivers/vfio/vfio_iommu_type1.c
> >>> @@ -38,6 +38,8 @@
> >>> #include <linux/workqueue.h>
> >>> #include <linux/dma-iommu.h>
> >>> #include <linux/msi-doorbell.h>
> >>> +#include <linux/irqdomain.h>
> >>> +#include <linux/msi.h>
> >>>
> >>> #define DRIVER_VERSION "0.2"
> >>> #define DRIVER_AUTHOR "Alex Williamson <alex.williamson@redhat.com>"
> >>> @@ -1101,6 +1103,55 @@ static int vfio_domains_have_iommu_cache(struct vfio_iommu *iommu)
> >>> return ret;
> >>> }
> >>>
> >>> +static int compute_msi_geometry_caps(struct vfio_iommu *iommu,
> >>> + struct vfio_info_cap *caps)
> >>> +{
> >>> + struct vfio_iommu_type1_info_cap_msi_geometry *vfio_msi_geometry;
> >>> + unsigned long order = __ffs(vfio_pgsize_bitmap(iommu));
> >>> + struct iommu_domain_msi_geometry msi_geometry;
> >>> + struct vfio_info_cap_header *header;
> >>> + struct vfio_domain *d;
> >>> + bool reserved;
> >>> + size_t size;
> >>> +
> >>> + mutex_lock(&iommu->lock);
> >>> + /* All domains have same require_msi_map property, pick first */
> >>> + d = list_first_entry(&iommu->domain_list, struct vfio_domain, next);
> >>> + iommu_domain_get_attr(d->domain, DOMAIN_ATTR_MSI_GEOMETRY,
> >>> + &msi_geometry);
> >>> + reserved = !msi_geometry.iommu_msi_supported;
> >>> +
> >>> + mutex_unlock(&iommu->lock);
> >>> +
> >>> + size = sizeof(*vfio_msi_geometry);
> >>> + header = vfio_info_cap_add(caps, size,
> >>> + VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY, 1);
> >>> +
> >>> + if (IS_ERR(header))
> >>> + return PTR_ERR(header);
> >>> +
> >>> + vfio_msi_geometry = container_of(header,
> >>> + struct vfio_iommu_type1_info_cap_msi_geometry,
> >>> + header);
> >>> +
> >>> + vfio_msi_geometry->flags = reserved;
> >>
> >> Use the bit flag VFIO_IOMMU_MSI_GEOMETRY_RESERVED
> >>
> >>> + if (reserved) {
> >>> + vfio_msi_geometry->aperture_start = msi_geometry.aperture_start;
> >>> + vfio_msi_geometry->aperture_end = msi_geometry.aperture_end;
> >>
> >> But maybe nobody has set these, did you intend to use
> >> iommu_domain_msi_aperture_valid(), which you defined early on but never
> >> used?
> >>
> >>> + return 0;
> >>> + }
> >>> +
> >>> + vfio_msi_geometry->order = order;
> >>
> >> I'm tempted to suggest that a user could do the same math on their own
> >> since we provide the supported bitmap already... could it ever not be
> >> the same?
> >>
> >>> + /*
> >>> + * we compute a system-wide requirement based on all the registered
> >>> + * doorbells
> >>> + */
> >>> + vfio_msi_geometry->size =
> >>> + msi_doorbell_calc_pages(order) * ((uint64_t) 1 << order);
> >>> +
> >>> + return 0;
> >>> +}
> >>> +
> >>> static long vfio_iommu_type1_ioctl(void *iommu_data,
> >>> unsigned int cmd, unsigned long arg)
> >>> {
> >>> @@ -1122,8 +1173,10 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
> >>> }
> >>> } else if (cmd == VFIO_IOMMU_GET_INFO) {
> >>> struct vfio_iommu_type1_info info;
> >>> + struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
> >>> + int ret;
> >>>
> >>> - minsz = offsetofend(struct vfio_iommu_type1_info, iova_pgsizes);
> >>> + minsz = offsetofend(struct vfio_iommu_type1_info, cap_offset);
> >>>
> >>> if (copy_from_user(&info, (void __user *)arg, minsz))
> >>> return -EFAULT;
> >>> @@ -1135,6 +1188,29 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
> >>>
> >>> info.iova_pgsizes = vfio_pgsize_bitmap(iommu);
> >>>
> >>> + ret = compute_msi_geometry_caps(iommu, &caps);
> >>> + if (ret)
> >>> + return ret;
> >>> +
> >>> + if (caps.size) {
> >>> + info.flags |= VFIO_IOMMU_INFO_CAPS;
> >>> + if (info.argsz < sizeof(info) + caps.size) {
> >>> + info.argsz = sizeof(info) + caps.size;
> >>> + info.cap_offset = 0;
> >>> + } else {
> >>> + vfio_info_cap_shift(&caps, sizeof(info));
> >>> + if (copy_to_user((void __user *)arg +
> >>> + sizeof(info), caps.buf,
> >>> + caps.size)) {
> >>> + kfree(caps.buf);
> >>> + return -EFAULT;
> >>> + }
> >>> + info.cap_offset = sizeof(info);
> >>> + }
> >>> +
> >>> + kfree(caps.buf);
> >>> + }
> >>> +
> >>> return copy_to_user((void __user *)arg, &info, minsz) ?
> >>> -EFAULT : 0;
> >>>
> >>> diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
> >>> index 4a9dbc2..8dae013 100644
> >>> --- a/include/uapi/linux/vfio.h
> >>> +++ b/include/uapi/linux/vfio.h
> >>> @@ -488,7 +488,35 @@ struct vfio_iommu_type1_info {
> >>> __u32 argsz;
> >>> __u32 flags;
> >>> #define VFIO_IOMMU_INFO_PGSIZES (1 << 0) /* supported page sizes info */
> >>> - __u64 iova_pgsizes; /* Bitmap of supported page sizes */
> >>> +#define VFIO_IOMMU_INFO_CAPS (1 << 1) /* Info supports caps */
> >>> + __u64 iova_pgsizes; /* Bitmap of supported page sizes */
> >>> + __u32 __resv;
> >>> + __u32 cap_offset; /* Offset within info struct of first cap */
> >>> +};
> >>
> >> I understand the padding, but not the ordering. Why not end with
> >> padding?
> >>
> >>> +
> >>> +#define VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY 1
> >>> +
> >>> +/*
> >>> + * The MSI geometry capability allows to report the MSI IOVA geometry:
> >>> + * - either the MSI IOVAs are constrained within a reserved IOVA aperture
> >>> + * whose boundaries are given by [@aperture_start, @aperture_end].
> >>> + * this is typically the case on x86 host. The userspace is not allowed
> >>> + * to map userspace memory at IOVAs intersecting this range using
> >>> + * VFIO_IOMMU_MAP_DMA.
> >>> + * - or the MSI IOVAs are not requested to belong to any reserved range;
> >>> + * in that case the userspace must provide an IOVA window characterized by
> >>> + * @size and @alignment using VFIO_IOMMU_MAP_DMA with RESERVED_MSI_IOVA flag.
> >>> + */
> >>> +struct vfio_iommu_type1_info_cap_msi_geometry {
> >>> + struct vfio_info_cap_header header;
> >>> + __u32 flags;
> >>> +#define VFIO_IOMMU_MSI_GEOMETRY_RESERVED (1 << 0) /* reserved geometry */
> >>> + /* not reserved */
> >>> + __u32 order; /* iommu page order used for aperture alignment*/
> >>> + __u64 size; /* IOVA aperture size (bytes) the userspace must provide */
> >>> + /* reserved */
> >>> + __u64 aperture_start;
> >>> + __u64 aperture_end;
> >>
> >> Should these be a union? We never set them both. Should the !reserved
> >> case have a flag as well, so the user can positively identify what's
> >> being provided?
> >
> > Actually, is there really any need to fit both of these within the same
> > structure? Part of the idea of the capability chains is we can create
> > a capability for each new thing we want to describe. So, we could
> > simply define a generic reserved IOVA range capability with a 'start'
> > and 'end' and then another capability to define MSI mapping
> > requirements. Thanks,
> Yes your suggested approach makes sense to me.
>
> One reason why I proceeded that way is we are mixing things at iommu.h
> level too. Personally I would have preferred to separate things:
> 1) add a new IOMMU_CAP_TRANSLATE_MSI capability in iommu_cap
> 2) rename iommu_msi_supported into "programmable" bool: reporting
> whether the aperture is reserved or programmable.
>
> In the early releases I think it was as above but slightly we moved to a
> mixed description.
>
> What do you think?
The API certainly doesn't seem like it has a cohesive feel to me. It's
not entirely clear to me how we know when we need to register a DMA MSI
cookie, or how we know that the MSI doorbell API is actually
initialized and in use by the MSI/IOMMU layer, or exactly what is the
MSI geometry telling me. Perhaps this is why the code doesn't seem to
have a good rejection mechanism for architectures that need it versus
those that don't, it's too hard to tell.
Maybe we can look at what we think the user API should be and work
backwards. For x86 we simply have a reserved range of IOVA. I'm not
entirely sure it adds to the user API to know that it's for MSI, it's
just a range of IOVAs that we cannot allocate for regular DMA. In
fact, we currently lack a mechanism for describing the IOVA space of
the IOMMU at all, so rather than focusing on a mechanism to describe a
hole in the IOVA space, we might simply want to focus on a mechanism to
describe the available IOVA space. Everybody needs that, not just
x86. That sort of sounds like a VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE
that perhaps looks like:
struct vfio_iommu_type1_info_cap_iova_range {
struct vfio_info_cap_header header;
u64 start;
u64 end;
};
Clearly we need to allow multiple of these in the capability chain
since the existing x86 MSI range bisects this address space.
To support this, we basically need the same information from the IOMMU
API. We already have DOMAIN_ATTR_GEOMETRY, which should give us the
base IOVA range, but we don't have anything describing the gaps. We
don't know how many sources of gaps we'll have in the future, but let's
keep it simple and assume we can look for MSI gaps and add other
possible sources of gaps in the future, it's an internal API after all.
So we can use DOMAIN_ATTR_MSI_GEOMETRY to tell us about the (we assume
one) MSI range of reserved IOVA within DOMAIN_ATTR_GEOMETRY. For x86
this is fixed, for SMMU this is a zero range until someone programs it.
Now, what does a user need to know to add a reserved MSI IOVA range?
They need to know a) that it needs to be done, and b) how big to make
it (and maybe alignment requirements). Really all we need to describe
then is b) since b) implies a). So maybe that gives us another
capability chain entry:
struct vfio_iommu_type1_info_cap_msi_resv {
struct vfio_info_cap_header header;
u64 size;
u64 alignment;
};
It doesn't seem like we need to waste a flag bit on
vfio_iommu_type1_info.flags for this since the existence of this
capability would imply that VFIO_IOMMU_MAP_DMA supports an MSI_RESV
flag.
So what do we need from the kernel infrastructure to make that happen?
Well, we need a) and b) above, and again b) can imply a), so if the
IOMMU API provided a DOMAIN_ATTR_MSI_RESV, providing the same
size/alignment, then we're nearly there. Then we just need a way to
set that range, which I'd probably try to plumb through the IOMMU API
rather than pulling in separate doorbell APIs and DMA cookie APIs. If
it's going to pull together all those different things, let's at least
only do that in one place so we can expose a consistent API through the
IOMMU API. Obviously once a range is set, DOMAIN_ATTR_MSI_RESV should
report that range, so if the user were to look at the type1 info
capability chain again, the available IOVA ranges would reflect the now
reserved range.
Maybe that's more than you're asking for, but that's the approach I
would take to solidify the API. Thanks,
Alex
^ permalink raw reply
* PROBLEM: DWC3 USB 3.0 not working on Odroid-XU4 with Exynos 5422
From: Michael Niewöhner @ 2016-10-07 20:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87y420wqoy.fsf@linux.intel.com>
Hi Felipe,
On Fr, 2016-10-07 at 10:42 +0300, Felipe Balbi wrote:
> Hi,
>
> Michael Niew?hner <linux@mniewoehner.de> writes:
> >
> > >
> > > The clocks are same across working/non-working.
> > > Is it possible to bisect the commit that's causing hang for 4.8x ?
> >
> >
> > [c499ff71ff2a281366c6ec7a904c547d806cbcd1] usb: dwc3: core: re-factor init and exit paths
> > This patch causes both the hang on reboot and the lsusb hang.
>
> How to reproduce? Why don't we see this on x86 and TI boards? I'm
> guessing this is failed bisection, as I can't see anything in that
> commit that would cause reboot hang. Also, that code path is *NOT*
> executed when you run lsusb.
>
I've tested this procedure multiple times to be sure:
- checkout?c499ff71, compile, boot the odroid
- run lsusb -v => lsusb hangs, can't terminate with ctrl-c
- hard reset, after boot run poweroff or reboot => board does not completely power off / reboot (see log below)
- revert c499ff71, mrproper, compile, boot the odroid
- run lsusb -v => shows full output, not hanging
- run reboot or poweroff => board powers off / reboots just fine
dmesg poweroff not working:
...
[??120.733519] systemd-journald[144]: systemd-journald stopped as pid 144???????
[??120.742663] systemd-shutdown[1]: Sending SIGKILL to remaining processes...???
[??120.769212] systemd-shutdown[1]: Unmounting file systems.????????????????????
[??120.773713] systemd-shutdown[1]: Unmounting /sys/kernel/debug.???????????????
[??120.827211] systemd-shutdown[1]: Unmounting /dev/mqueue.?????????????????????
[??121.081672] EXT4-fs (mmcblk1p2): re-mounted. Opts: (null)????????????????????
[??121.091687] EXT4-fs (mmcblk1p2): re-mounted. Opts: (null)????????????????????
[??121.095608] EXT4-fs (mmcblk1p2): re-mounted. Opts: (null)????????????????????
[??121.101014] systemd-shutdown[1]: All filesystems unmounted.??????????????????
[??121.106523] systemd-shutdown[1]: Deactivating swaps.?????????????????????????
[??121.111585] systemd-shutdown[1]: All swaps deactivated.??????????????????????
[??121.116661] systemd-shutdown[1]: Detaching loop devices.?????????????????????
[??121.126395] systemd-shutdown[1]: All loop devices detached.??????????????????
[??121.130525] systemd-shutdown[1]: Detaching DM devices.???????????????????????
[??121.135824] systemd-shutdown[1]: All DM devices detached.????????????????????
[??121.166327] systemd-shutdown[1]: /lib/systemd/system-shutdown succeeded.?????
[??121.171739] systemd-shutdown[1]: Powering off.
=> at this point removing the sd card would show a message?
"removed mmc0" (not sure what the real message was...) so the board is not completely off.
dmesg poweroff working:
...
[??120.733519] systemd-journald[144]: systemd-journald stopped as pid 144???????
[??120.742663] systemd-shutdown[1]: Sending SIGKILL to remaining processes...???
[??120.769212] systemd-shutdown[1]: Unmounting file systems.????????????????????
[??120.773713] systemd-shutdown[1]: Unmounting /sys/kernel/debug.???????????????
[??120.827211] systemd-shutdown[1]: Unmounting /dev/mqueue.?????????????????????
[??121.081672] EXT4-fs (mmcblk1p2): re-mounted. Opts: (null)????????????????????
[??121.091687] EXT4-fs (mmcblk1p2): re-mounted. Opts: (null)????????????????????
[??121.095608] EXT4-fs (mmcblk1p2): re-mounted. Opts: (null)????????????????????
[??121.101014] systemd-shutdown[1]: All filesystems unmounted.??????????????????
[??121.106523] systemd-shutdown[1]: Deactivating swaps.?????????????????????????
[??121.111585] systemd-shutdown[1]: All swaps deactivated.??????????????????????
[??121.116661] systemd-shutdown[1]: Detaching loop devices.?????????????????????
[??121.126395] systemd-shutdown[1]: All loop devices detached.??????????????????
[??121.130525] systemd-shutdown[1]: Detaching DM devices.???????????????????????
[??121.135824] systemd-shutdown[1]: All DM devices detached.????????????????????
[??121.166327] systemd-shutdown[1]: /lib/systemd/system-shutdown succeeded.?????
[??121.171739] systemd-shutdown[1]: Powering off.
[??121.182331] rebo?
Best regards
Michael
^ permalink raw reply
* [PATCH 1/5] PCI: aardvark: Name private struct pointer "advk" consistently
From: Thomas Petazzoni @ 2016-10-07 20:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161007162053.22668.91420.stgit@bhelgaas-glaptop2.roam.corp.google.com>
Hello,
On Fri, 07 Oct 2016 11:20:53 -0500, Bjorn Helgaas wrote:
> Use a device-specific name, "advk", for struct advk_pcie pointers to hint
> that this is device-specific information. No functional change intended.
>
> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
> ---
> drivers/pci/host/pci-aardvark.c | 370 +++++++++++++++++++--------------------
> 1 file changed, 183 insertions(+), 187 deletions(-)
For the entire series:
Reviewed-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Thanks for those cleanups/improvements!
Thomas
--
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH 1/3] fpga manager: Add cyclonespi driver for Altera fpgas
From: Moritz Fischer @ 2016-10-07 18:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.02.1610071248320.32627@linuxheads99>
Hi Alan,
On Fri, Oct 7, 2016 at 11:21 AM, atull <atull@opensource.altera.com> wrote:
> Moritz, Can you remind me what that issue was there (or point me to
> that email, I can't find it)? I don't think I had a problem with that
> in your case. In general I think if these drivers can take the
> bitstream that comes from the manufacturer's tools and stuff it into
> the FPGA, then we are accomplishing what we want. So I am OK with
> this here. The intent of the driver is to load a standard rbf, same
> as the other Altera FPGA drivers.
My first version of the zynq fpga manager had byte swapping in there
and detection of which format was used. Greg even (accidentially)
merged my initial code
which I then cleaned up in 4d10eaff5bfc69997a769f9c83b749f0a8c542fa
("fpga: zynq-fpga: Change fw format to handle bin instead of bit.") to
address the review
comments.
I do see your point about useability, and if this is something that
keeps coming up
we could pull that into the framework with a flag to SWAP or as part
of the image_information
struct.
Thoughts?
Cheers,
Moritz
[1] https://mail-archive.com/linux-kernel at vger.kernel.org/msg995245.html
^ permalink raw reply
* [PATCH 1/3] fpga manager: Add cyclonespi driver for Altera fpgas
From: atull @ 2016-10-07 18:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAAtXAHcWLpn3DFP6YLWqBxsMQ0O=HNNCmB+kHbHhyAHFHQUbwA@mail.gmail.com>
On Fri, 7 Oct 2016, Moritz Fischer wrote:
> > +static inline u32 revbit8x4(u32 n)
> > +{
> > + n = ((n & 0xF0F0F0F0UL) >> 4) | ((n & 0x0F0F0F0FUL) << 4);
> > + n = ((n & 0xCCCCCCCCUL) >> 2) | ((n & 0x33333333UL) << 2);
> > + n = ((n & 0xAAAAAAAAUL) >> 1) | ((n & 0x55555555UL) << 1);
> > + return n;
> > +}
>
> During the Zynq FPGA manager reviews we decided that manipulating the bitstream
> to be consumable by the driver is userland's job.
Moritz, Can you remind me what that issue was there (or point me to
that email, I can't find it)? I don't think I had a problem with that
in your case. In general I think if these drivers can take the
bitstream that comes from the manufacturer's tools and stuff it into
the FPGA, then we are accomplishing what we want. So I am OK with
this here. The intent of the driver is to load a standard rbf, same
as the other Altera FPGA drivers.
There is a problem here though it will be easy to fix. This call to
revbit8x4 should happen in cyclonespi_write(), not in
cyclonespi_write_init(). The reason for that is that write_init() may
just get the first chunk of the image (the header) and that write()
will be called multiple times for the remaining chunks. The current
FPGA manager API won't show this problem since you have to give
fpga_mgr_buf_load the whole image buffer at once. But it is easy to
imagine that some time in the future we may want to expand the FPGA
manager API to support streaming where we don't have the whole buffer.
Thanks for submitting, Joshua. Will be looking at this over the
next several days.
Alan
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox