diff options
| author | Prasad Sodagudi <psodagud@codeaurora.org> | 2017-01-31 13:56:40 -0800 |
|---|---|---|
| committer | Runmin Wang <runminw@codeaurora.org> | 2017-02-10 10:34:40 -0800 |
| commit | 0b8561aff0c4251d9fdd71381464bc3a1fa2e90c (patch) | |
| tree | 5c0e717261b4720b5ef4668170da3ecf3e24017f | |
| parent | d24550bbf50f61b07668a28a20878e1f91cf544c (diff) | |
arm64: raise exception to EL2 for sync aborts
Raise exception to EL2 for every EL1 sync data aborts,
so that EL2 handles the TLB conflicts.
Change-Id: Ib140599e23c399b23c12ddbeb59979d6caf5d38e
Signed-off-by: Prasad Sodagudi <psodagud@codeaurora.org>
Signed-off-by: Runmin Wang <runminw@codeaurora.org>
| -rw-r--r-- | arch/arm64/Kconfig | 5 | ||||
| -rw-r--r-- | arch/arm64/kernel/entry.S | 3 | ||||
| -rw-r--r-- | arch/arm64/mm/fault.c | 22 |
3 files changed, 19 insertions, 11 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 8ac5ba251136..f8d50d8c5379 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -620,6 +620,11 @@ config ARCH_NR_GPIO If unsure, leave the default value. +config QCOM_TLB_EL2_HANDLER + bool "Raise TLB conflict exception to EL2" + help + This option enables TLB conflict to be handled + by EL2. source kernel/Kconfig.preempt source kernel/Kconfig.hz diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index cab1821db191..d311c635a00e 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -347,6 +347,9 @@ ENDPROC(el1_error_invalid) */ .align 6 el1_sync: +#ifdef CONFIG_TLB_EL2_HANDLER + smc #0xffff +#endif kernel_entry 1 mrs x1, esr_el1 // read the syndrome register lsr x24, x1, #ESR_ELx_EC_SHIFT // exception class diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index eacaee18645b..a65dec4b001b 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -410,23 +410,19 @@ no_context: return 0; } +/* + * TLB conflict is already handled in EL2. This rourtine should return zero + * so that, do_mem_abort would not crash kernel thinking TLB conflict not + * handled. +*/ +#ifdef QCOM_TLB_EL2_HANDLER static int do_tlb_conf_fault(unsigned long addr, unsigned int esr, struct pt_regs *regs) { -#define SCM_TLB_CONFLICT_CMD 0x1B - struct scm_desc desc = { - .args[0] = addr, - .arginfo = SCM_ARGS(1), - }; - - if (scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_MP, SCM_TLB_CONFLICT_CMD), - &desc)) - return 1; - return 0; } - +#endif /* * First Level Translation Fault Handler * @@ -518,7 +514,11 @@ static struct fault_info { { do_bad, SIGBUS, 0, "unknown 45" }, { do_bad, SIGBUS, 0, "unknown 46" }, { do_bad, SIGBUS, 0, "unknown 47" }, +#ifdef QCOM_TLB_EL2_HANDLER { do_tlb_conf_fault, SIGBUS, 0, "TLB conflict abort" }, +#else + { do_bad, SIGBUS, 0, "TLB conflict abort" }, +#endif { do_bad, SIGBUS, 0, "unknown 49" }, { do_bad, SIGBUS, 0, "unknown 50" }, { do_bad, SIGBUS, 0, "unknown 51" }, |
