ARCv2: support manual regfile save on interrupts [Linux 5.0]

ARCv2: support manual regfile save on interrupts [Linux 5.0]

This Linux kernel change "ARCv2: support manual regfile save on interrupts" is included in the Linux 5.0 release. This change is authored by Vineet Gupta <vgupta [at] synopsys.com> on Wed Jun 6 10:20:37 2018 -0700. The commit for this change in Linux stable tree is e494239 (patch).

ARCv2: support manual regfile save on interrupts

There's a hardware bug which affects the HSDK platform, triggered by
micro-ops for auto-saving regfile on taken interrupt. The workaround is
to inhibit autosave.

Signed-off-by: Vineet Gupta <[email protected]>

There are 69 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 arch/arc/Kconfig                   |  8 ++++++
 arch/arc/include/asm/entry-arcv2.h | 54 ++++++++++++++++++++++++++++++++++++++
 arch/arc/kernel/entry-arcv2.S      |  4 ++-
 arch/arc/kernel/intc-arcv2.c       |  2 ++
 arch/arc/plat-hsdk/Kconfig         |  1 +
 5 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 376366a..7215f52 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -407,6 +407,14 @@ config ARC_HAS_ACCL_REGS
      (also referred to as r58:r59). These can also be used by gcc as GPR so
      kernel needs to save/restore per process

+config ARC_IRQ_NO_AUTOSAVE
+   bool "Disable hardware autosave regfile on interrupts"
+   default n
+   help
+     On HS cores, taken interrupt auto saves the regfile on stack.
+     This is programmable and can be optionally disabled in which case
+     software INTERRUPT_PROLOGUE/EPILGUE do the needed work
+
 endif  # ISA_ARCV2

 endmenu   # "ARC CPU Configuration"
diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h
index 309f4e6..225e7df 100644
--- a/arch/arc/include/asm/entry-arcv2.h
+++ b/arch/arc/include/asm/entry-arcv2.h
@@ -17,6 +17,33 @@
    ;
    ; Now manually save: r12, sp, fp, gp, r25

+#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
+.ifnc \called_from, exception
+   st.as   r9, [sp, -10]   ; save r9 in it's final stack slot
+   sub sp, sp, 12  ; skip JLI, LDI, EI
+
+   PUSH    lp_count
+   PUSHAX  lp_start
+   PUSHAX  lp_end
+   PUSH    blink
+
+   PUSH    r11
+   PUSH    r10
+
+   sub sp, sp, 4   ; skip r9
+
+   PUSH    r8
+   PUSH    r7
+   PUSH    r6
+   PUSH    r5
+   PUSH    r4
+   PUSH    r3
+   PUSH    r2
+   PUSH    r1
+   PUSH    r0
+.endif
+#endif
+
 #ifdef CONFIG_ARC_HAS_ACCL_REGS
    PUSH    r59
    PUSH    r58
@@ -86,6 +113,33 @@
    POP r59
 #endif

+#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
+.ifnc \called_from, exception
+   POP r0
+   POP r1
+   POP r2
+   POP r3
+   POP r4
+   POP r5
+   POP r6
+   POP r7
+   POP r8
+   POP r9
+   POP r10
+   POP r11
+
+   POP blink
+   POPAX   lp_end
+   POPAX   lp_start
+
+   POP r9
+   mov lp_count, r9
+
+   add sp, sp, 12  ; skip JLI, LDI, EI
+   ld.as   r9, [sp, -10]   ; reload r9 which got clobbered
+.endif
+#endif
+
 .endm

 /*------------------------------------------------------------------------*/
diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S
index cc558a2..562089d 100644
--- a/arch/arc/kernel/entry-arcv2.S
+++ b/arch/arc/kernel/entry-arcv2.S
@@ -209,7 +209,9 @@ restore_regs:
 ;####### Return from Intr #######

 debug_marker_l1:
-   bbit1.nt r0, STATUS_DE_BIT, .Lintr_ret_to_delay_slot
+   ; bbit1.nt r0, STATUS_DE_BIT, .Lintr_ret_to_delay_slot
+   btst    r0, STATUS_DE_BIT       ; Z flag set if bit clear
+   bnz .Lintr_ret_to_delay_slot    ; branch if STATUS_DE_BIT set

 .Lisr_ret_fast_path:
    ; Handle special case #1: (Entry via Exception, Return via IRQ)
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index 067ea36..cf18b3e 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -49,11 +49,13 @@ void arc_init_IRQ(void)

    *(unsigned int *)&ictrl = 0;

+#ifndef CONFIG_ARC_IRQ_NO_AUTOSAVE
    ictrl.save_nr_gpr_pairs = 6;    /* r0 to r11 (r12 saved manually) */
    ictrl.save_blink = 1;
    ictrl.save_lp_regs = 1;     /* LP_COUNT, LP_START, LP_END */
    ictrl.save_u_to_u = 0;      /* user ctxt saved on kernel stack */
    ictrl.save_idx_regs = 1;    /* JLI, LDI, EI */
+#endif

    WRITE_AUX(AUX_IRQ_CTRL, ictrl);

diff --git a/arch/arc/plat-hsdk/Kconfig b/arch/arc/plat-hsdk/Kconfig
index f25c085..23e0021 100644
--- a/arch/arc/plat-hsdk/Kconfig
+++ b/arch/arc/plat-hsdk/Kconfig
@@ -9,6 +9,7 @@ menuconfig ARC_SOC_HSDK
    bool "ARC HS Development Kit SOC"
    depends on ISA_ARCV2
    select ARC_HAS_ACCL_REGS
+   select ARC_IRQ_NO_AUTOSAVE
    select CLK_HSDK
    select RESET_HSDK
    select HAVE_PCI

Leave a Reply

Your email address will not be published. Required fields are marked *