OSDN Git Service

arm64: raise exception to EL2 for sync aborts
authorPrasad Sodagudi <psodagud@codeaurora.org>
Tue, 31 Jan 2017 21:56:40 +0000 (13:56 -0800)
committerRunmin Wang <runminw@codeaurora.org>
Fri, 10 Feb 2017 18:34:40 +0000 (10:34 -0800)
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>
arch/arm64/Kconfig
arch/arm64/kernel/entry.S
arch/arm64/mm/fault.c

index 8ac5ba2..f8d50d8 100644 (file)
@@ -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
index cab1821..d311c63 100644 (file)
@@ -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
index eacaee1..a65dec4 100644 (file)
@@ -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"                    },