summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPrasad Sodagudi <psodagud@codeaurora.org>2017-01-31 13:56:40 -0800
committerRunmin Wang <runminw@codeaurora.org>2017-02-10 10:34:40 -0800
commit0b8561aff0c4251d9fdd71381464bc3a1fa2e90c (patch)
tree5c0e717261b4720b5ef4668170da3ecf3e24017f
parentd24550bbf50f61b07668a28a20878e1f91cf544c (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/Kconfig5
-rw-r--r--arch/arm64/kernel/entry.S3
-rw-r--r--arch/arm64/mm/fault.c22
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" },