ARMv8: declaring sysreg functions as inline assembly
authorReto Achermann <reto.achermann@inf.ethz.ch>
Mon, 6 Mar 2017 16:58:01 +0000 (17:58 +0100)
committerReto Achermann <reto.achermann@inf.ethz.ch>
Mon, 6 Mar 2017 16:58:01 +0000 (17:58 +0100)
Signed-off-by: Reto Achermann <reto.achermann@inf.ethz.ch>

kernel/arch/armv8/sysreg.S
kernel/include/arch/armv8/sysreg.h

index fda8292..1f37fd5 100644 (file)
         .globl sysreg_invalidate_d_cache,\
                sysreg_invalidate_i_and_d_caches,\
                sysreg_invalidate_i_and_d_caches_fast, \
-                  sysreg_invalidate_tlb_fn, \
-                  sysreg_enable_mmu
+                  sysreg_invalidate_tlb_fn, \
+                  sysreg_enable_mmu
 
 /* Based on algorithm from ARM Architecture Reference Manual */
 sysreg_invalidate_d_cache:
 
-       sub     sp, sp, #96
+    sub     sp, sp, #96
 
     stp     x0, x1, [sp, #16 * 0]
     stp     x2, x3, [sp, #16 * 1]
@@ -35,66 +35,66 @@ sysreg_invalidate_d_cache:
     stp     x8, x9, [sp, #16 * 4]
     stp     x10, x11, [sp, #16 * 5]
 
-       dmb     sy                              // ensure ordering with previous memory accesses
+    dmb    sy                // ensure ordering with previous memory accesses
 
-       mrs x0, clidr_el1
-       and w3, w0, #0x07000000         // get 2 x level of coherency
-       lsr w3, w3, #23
-       cbz w3, finished
-       mov w10, #0                             // w10 = 2 x cache level
-       mov w8, #1                                      // w8 = constant 0b1
+    mrs x0, clidr_el1
+    and w3, w0, #0x07000000     // get 2 x level of coherency
+    lsr w3, w3, #23
+    cbz w3, finished
+    mov w10, #0                 // w10 = 2 x cache level
+    mov w8, #1                     // w8 = constant 0b1
 
 loop1: 
-       add w2, w10, w10, lsr #1        // calculate 3 x cache level
-       lsr w1, w0, w2                          // extract 3-bit cache type for this level
-       and w1, w1, #0x7
-       cmp w1, #2
-       b.lt skip                                       // no data or unified cache at this level
-       msr csselr_el1, x10             // select this cache level
-       isb                                             // sync change of csselr
-       mrs x1, ccsidr_el1                      // read ccsidr
-       and w2, w1, #7                          // w2 = log2(linelen)-4
-       add w2, w2, #4                          // w2 = log2(linelen)
-       ubfx w4, w1, #3, #10            // w4 = max way number, right aligned
-       clz w5, w4                                      // w5 = 32-log2(ways), bit position of way in dc operand
-       lsl w9, w4, w5                          // w9 = max way number, aligned to position in dc operand
-       lsl w16, w8, w5                         // w16 = amount to decrement way number per iteration
+    add w2, w10, w10, lsr #1     // calculate 3 x cache level
+    lsr w1, w0, w2                 // extract 3-bit cache type for this level
+    and w1, w1, #0x7
+    cmp w1, #2
+    b.lt skip                     // no data or unified cache at this level
+    msr csselr_el1, x10         // select this cache level
+    isb                         // sync change of csselr
+    mrs x1, ccsidr_el1             // read ccsidr
+    and w2, w1, #7                 // w2 = log2(linelen)-4
+    add w2, w2, #4                 // w2 = log2(linelen)
+    ubfx w4, w1, #3, #10         // w4 = max way number, right aligned
+    clz w5, w4                     // w5 = 32-log2(ways), bit position of way in dc operand
+    lsl w9, w4, w5                 // w9 = max way number, aligned to position in dc operand
+    lsl w16, w8, w5             // w16 = amount to decrement way number per iteration
 loop2: 
-       ubfx w7, w1, #13, #15           // w7 = max set number, right aligned
-       lsl w7, w7, w2                          // w7 = max set number, aligned to position in dc operand
-       lsl w17, w8, w2                         // w17 = amount to decrement set number per iteration
+    ubfx w7, w1, #13, #15         // w7 = max set number, right aligned
+    lsl w7, w7, w2                 // w7 = max set number, aligned to position in dc operand
+    lsl w17, w8, w2             // w17 = amount to decrement set number per iteration
 loop3: 
-       orr w11, w10, w9                        // w11 = combine way number and cache number ...
-       orr w11, w11, w7                        // ... and set number for dc operand
-       dc csw, x11                             // do data cache clean by set and way
-       subs w7, w7, w17                        // decrement set number
-       b.ge loop3
-       subs x9, x9, x16                        // decrement way number
-       b.ge loop2
+    orr w11, w10, w9             // w11 = combine way number and cache number ...
+    orr w11, w11, w7             // ... and set number for dc operand
+    dc csw, x11                 // do data cache clean by set and way
+    subs w7, w7, w17             // decrement set number
+    b.ge loop3
+    subs x9, x9, x16             // decrement way number
+    b.ge loop2
 skip: 
-       add w10, w10, #2                // increment 2 x cache level
-       cmp w3, w10
-       b.gt loop1
+    add w10, w10, #2         // increment 2 x cache level
+    cmp w3, w10
+    b.gt loop1
 finished:
-       mov     x10, #0
-       msr     csselr_el1, x10
-       dsb     sy
-       isb
+    mov    x10, #0
+    msr    csselr_el1, x10
+    dsb    sy
+    isb
 
     ldp x0, x1,  [sp], #16
     ldp x2, x3,  [sp], #16
     ldp x4, x5,  [sp], #16
-       ldp x6, x7,  [sp], #16
-       ldp x8, x9,  [sp], #16
-       ldp x10, x11,  [sp], #16
+    ldp x6, x7,  [sp], #16
+    ldp x8, x9,  [sp], #16
+    ldp x10, x11,  [sp], #16
     ret
 
 sysreg_invalidate_i_and_d_caches:
-       mov     x12, x30 //lr
-       bl      sysreg_invalidate_d_cache
-       mov     x0, #0
-       ic      ialluis                         // I+BTB cache invalidate
-       ret     x12     
+    mov    x12, x30 //lr
+    bl    sysreg_invalidate_d_cache
+    mov    x0, #0
+    ic    ialluis                // I+BTB cache invalidate
+    ret    x12
 
 sysreg_invalidate_d_cache_fast:
     mov x12, x30 //lr
@@ -119,8 +119,8 @@ sysreg_invalidate_tlb:
     stp     x8, x9, [sp, #16 * 4]
     stp     x10, x11, [sp, #16 * 5]
 
-    tlbi       vmalle1
-    dsb        sy
+    tlbi    vmalle1
+    dsb    sy
     isb
 
     ldp x0, x1,  [sp], #16
@@ -137,95 +137,30 @@ sysreg_invalidate_tlb_fn:
     ret x12
 
 sysreg_enable_mmu:
-       mov x12, x30 //lr
+    mov x12, x30 //lr
 
-       ic      iallu                           // I+BTB cache invalidate
-       tlbi    vmalle1                         // invalidate I + D TLBs
-       dsb     sy
+    ic      iallu                           // I+BTB cache invalidate
+    tlbi    vmalle1                         // invalidate I + D TLBs
+    dsb     sy
 
     ldr     x0, =0xff440c0400
-    msr            mair_el1, x0
+    msr        mair_el1, x0
     isb
 
-       /*  TCR - Translation Control Register
-        *      4K granularity, 32-bit addresses, two subranges:
-        *
-        * TTBR1_EL1 -> 0xffff_ffff_8000_0000 to 0xffff_ffff_ffff_ffff
-        * TTBR0_EL1 -> 0x0000_0000_0000_0000 to 0x0000_0000_7fff_ffff
-        */
-
-       ldr     x0, =0x10b5203520
-       msr     tcr_el1, x0
-       isb
-
-       ldr     x0, =0x30d0199d
-       msr     sctlr_el1, x0
-       isb
-       
-       ret x12
-
-.macro sysreg_read sz name reg
-.globl armv8_sysreg_read\()_\sz\()_\name
-armv8_sysreg_read\()_\sz\()_\name :
-    mov x12, x30
-    mrs x0, \reg
+    /*  TCR - Translation Control Register
+     *    4K granularity, 32-bit addresses, two subranges:
+     *
+     * TTBR1_EL1 -> 0xffff_ffff_8000_0000 to 0xffff_ffff_ffff_ffff
+     * TTBR0_EL1 -> 0x0000_0000_0000_0000 to 0x0000_0000_7fff_ffff
+     */
+
+    ldr     x0, =0x10b5203520
+    msr     tcr_el1, x0
     isb
-    ret x12
-    nop
-.endm
-
-.macro sysreg_write sz name reg
-.globl armv8_sysreg_write\()_\sz\()_\name
-armv8_sysreg_write\()_\sz\()_\name :
-    mov x12, x30
-    msr \reg , x0
+
+    ldr     x0, =0x30d0199d
+    msr     sctlr_el1, x0
     isb
+
     ret x12
-    nop
-.endm
-
-.macro sysreg_rw sz name reg
-sysreg_read \sz \name \reg
-sysreg_write \sz \name \reg
-.endm
-
-.macro sysreg_ro sz name reg
-sysreg_read \sz \name \reg
-.endm
-
-.macro sysreg_wo sz name reg
-sysreg_write \sz \name \reg
-.endm
-
-sysreg_rw 64 TCR_EL1            TCR_EL1
-sysreg_rw 32 TCR_EL2            TCR_EL2
-sysreg_rw 32 SCTLR_EL1          SCTLR_EL1
-sysreg_rw 32 SCTLR_EL2          SCTLR_EL2
-sysreg_rw 32 SCTLR_EL3          SCTLR_EL3
-sysreg_rw 32 CPACR_EL1          CPACR_EL1
-sysreg_rw 32 ICC_PMR_EL1        S3_0_C4_C6_0
-sysreg_ro 32 ICC_IAR0_EL1       S3_0_C12_C8_0
-sysreg_wo 32 ICC_EOIR0_EL1      S3_0_C12_C8_1
-sysreg_ro 32 ICC_HPPIR0_EL1     S3_0_C12_C8_2
-sysreg_rw 32 ICC_BPR0_EL1       S3_0_C12_C8_3
-sysreg_rw 32 ICC_AP0R0_EL1      S3_0_C12_C8_4
-sysreg_rw 32 ICC_AP0R1_EL1      S3_0_C12_C8_5
-sysreg_rw 32 ICC_AP0R2_EL1      S3_0_C12_C8_6
-sysreg_rw 32 ICC_AP0R3_EL1      S3_0_C12_C8_7
-sysreg_rw 32 ICC_AP1R0_EL1      S3_0_C12_C9_0
-sysreg_rw 32 ICC_AP1R1_EL1      S3_0_C12_C9_1
-sysreg_rw 32 ICC_AP1R2_EL1      S3_0_C12_C9_2
-sysreg_rw 32 ICC_AP1R3_EL1      S3_0_C12_C9_3
-sysreg_wo 32 ICC_DIR_EL1        S3_0_C12_C11_1
-sysreg_ro 32 ICC_RPR_El1        S3_0_C12_C11_3
-sysreg_wo 64 ICC_SGI1R_EL1      S3_0_C12_C11_5
-sysreg_wo 64 ICC_ASGI1R_EL1     S3_0_C12_C11_6
-sysreg_wo 64 ICC_SGI0R_EL1      S3_0_C12_C11_7
-sysreg_ro 32 ICC_IAR1_EL1       S3_0_C12_C12_0
-sysreg_wo 32 ICC_EOIR1_EL1      S3_0_C12_C12_1
-sysreg_ro 32 ICC_HPPIR1_EL1     S3_0_C12_C12_2
-sysreg_rw 32 ICC_BPR1_EL1       S3_0_C12_C12_3
-sysreg_rw 32 ICC_CTLR_EL1       S3_0_C12_C12_4
-sysreg_rw 32 ICC_SRE_EL1        S3_0_C12_C12_5
-sysreg_rw 32 ICC_IGRPEN0_EL1    S3_0_C12_C12_6
-sysreg_rw 32 ICC_IGRPEN1_EL1    S3_0_C12_C12_7
+
index 2e98c93..3eedf40 100644 (file)
@@ -18,6 +18,87 @@ void sysreg_invalidate_i_and_d_caches(void);
 void sysreg_invalidate_tlb_fn(void);
 void sysreg_enable_mmu(void);
 
+
+#define ARMV8_SYSREG_WRITE_FN(_bits, _name, _reg) \
+        static inline void \
+        armv8_sysreg_write_## _bits ## _ ## _name(uint## _bits ## _t val) { \
+            __asm volatile ("msr "#_reg ", %[val]\n" \
+                            "isb \n" : : [val] "r" (val)); \
+        }
+
+#define ARMV8_SYSREG_READ_FN(_bits, _name, _reg) \
+        static inline uint## _bits ## _t \
+        armv8_sysreg_read_## _bits ## _ ## _name(void) { \
+            uint## _bits ## _t val; \
+            __asm volatile("mrs %[val], "#_reg "\n" \
+                           "isb \n" : [val] "=r" (val)); \
+            return val; \
+        }
+
+#define ARMV8_SYSREG_WO(_bits, _name, _reg) \
+    ARMV8_SYSREG_WRITE_FN(_bits, _name, _reg)
+
+#define ARMV8_SYSREG_RO(_bits, _name, _reg) \
+    ARMV8_SYSREG_READ_FN(_bits, _name, _reg)
+
+#define ARMV8_SYSREG_RW(_bits, _name, _reg) \
+    ARMV8_SYSREG_READ_FN(_bits, _name, _reg) \
+    ARMV8_SYSREG_WRITE_FN(_bits, _name, _reg)
+
+ARMV8_SYSREG_RO(32, CurrentEL, CurrentEL)
+
+ARMV8_SYSREG_RW(64, esr_el1, esr_el1)
+ARMV8_SYSREG_RW(64, TCR_EL1, TCR_EL1)
+ARMV8_SYSREG_RW(32, FCPR, FCPR)
+ARMV8_SYSREG_RW(32, DAIFSet,    DAIFSet)
+ARMV8_SYSREG_RW(32, DAIFClr,   DAIFClr)
+ARMV8_SYSREG_RW(32, TCR_EL2, TCR_EL2)
+ARMV8_SYSREG_RW(32, SCTLR_EL1, SCTLR_EL1)
+ARMV8_SYSREG_RW(32, SCTLR_EL2, SCTLR_EL2)
+ARMV8_SYSREG_RW(32, SCTLR_EL3, SCTLR_EL3)
+ARMV8_SYSREG_RW(32, CPACR_EL1, CPACR_EL1)
+ARMV8_SYSREG_RW(64, ELR_EL1, ELR_EL1)
+ARMV8_SYSREG_RW(64, ELR_EL2, ELR_EL2)
+ARMV8_SYSREG_RW(64, ELR_EL3, ELR_EL3)
+ARMV8_SYSREG_RW(64, DLR_EL0, DLR_EL0)
+ARMV8_SYSREG_RW(32, FPSR, FPSR)
+ARMV8_SYSREG_RW(32, NZCV, NZCV)
+ARMV8_SYSREG_RW(32, SPSel, SPSel)
+ARMV8_SYSREG_RW(32, TTBCR, TTBCR)
+ARMV8_SYSREG_RW(64, SP_EL0, SP_EL0)
+ARMV8_SYSREG_RW(64, SP_EL1, SP_EL1)
+ARMV8_SYSREG_RW(64, SP_EL2, SP_EL2)
+ARMV8_SYSREG_RW(64, SP_EL3, SP_EL3)
+ARMV8_SYSREG_RW(32, DSPSR_EL0, DSPSR_EL0)
+ARMV8_SYSREG_RW(32, ICC_PMR_EL1, S3_0_C4_C6_0)
+ARMV8_SYSREG_RW(32, ICC_IAR0_EL1, S3_0_C12_C8_0)
+ARMV8_SYSREG_RW(32, ICC_EOIR0_EL1, S3_0_C12_C8_1)
+ARMV8_SYSREG_RW(32, ICC_HPPIR0_EL1, S3_0_C12_C8_2)
+ARMV8_SYSREG_RW(32, ICC_BPR0_EL1, S3_0_C12_C8_3)
+ARMV8_SYSREG_RW(32, ICC_AP0R0_EL1, S3_0_C12_C8_4)
+ARMV8_SYSREG_RW(32, ICC_AP0R1_EL1, S3_0_C12_C8_5)
+ARMV8_SYSREG_RW(32, ICC_AP0R2_EL1, S3_0_C12_C8_6)
+ARMV8_SYSREG_RW(32, ICC_AP0R3_EL1, S3_0_C12_C8_7)
+ARMV8_SYSREG_RW(32, ICC_AP1R0_EL1, S3_0_C12_C9_0)
+ARMV8_SYSREG_RW(32, ICC_AP1R1_EL1, S3_0_C12_C9_1)
+ARMV8_SYSREG_RW(32, ICC_AP1R2_EL1, S3_0_C12_C9_2)
+ARMV8_SYSREG_RW(32, ICC_AP1R3_EL1, S3_0_C12_C9_3)
+ARMV8_SYSREG_RW(32, ICC_DIR_EL1, S3_0_C12_C11_1)
+ARMV8_SYSREG_RW(32, ICC_RPR_EL1,    S3_0_C12_C11_3)
+ARMV8_SYSREG_RW(64, ICC_SGI1R_EL1, S3_0_C12_C11_5)
+ARMV8_SYSREG_RW(64, ICC_ASGI1R_EL1, S3_0_C12_C11_6)
+ARMV8_SYSREG_RW(64, ICC_SGI0R_EL1, S3_0_C12_C11_7)
+ARMV8_SYSREG_RW(32, ICC_IAR1_EL1, S3_0_C12_C12_0)
+ARMV8_SYSREG_RW(32, ICC_EOIR1_EL1, S3_0_C12_C12_1)
+ARMV8_SYSREG_RW(32, ICC_HPPIR1_EL1, S3_0_C12_C12_2)
+ARMV8_SYSREG_RW(32, ICC_BPR1_EL1, S3_0_C12_C12_3)
+ARMV8_SYSREG_RW(32, ICC_CTLR_EL1, S3_0_C12_C12_4)
+ARMV8_SYSREG_RW(32, ICC_SRE_EL1, S3_0_C12_C12_5)
+ARMV8_SYSREG_RW(32, ICC_IGRPEN0_EL1, S3_0_C12_C12_6)
+ARMV8_SYSREG_RW(32, ICC_IGRPEN1_EL1, S3_0_C12_C12_7)
+ARMV8_SYSREG_RW(32, ICC_EOI1_EL1, ICC_EOI1_EL1)
+
+
 /**
  * \brief Read instruction fault status register.
  */