From e5f1d1e5aacf93880c1bf90af64f459dd3e4284f Mon Sep 17 00:00:00 2001
From: Jeffrey Lee <jlee@gitlab.riscosopen.org>
Date: Wed, 8 Jun 2011 23:09:41 +0000
Subject: [PATCH] Kernel fixes for ARMv6

Detail:
  hdr/ARMops - Amended ARMvF description to state that an ARMvF CPU can be ARMv6 or ARMv7
  s/ARMops - Move ARM11JZF_S CPUDesc to KnownCPUTable_Fancy, since it's ARMvF. Update ARM_Analyse_Fancy to detect whether ARMv6 or ARMv7 style cache control is in use, and react accordingly.
  s/HAL - Simplified system control register/MMUC initialisation. There are now just two types of setup - one for ARMv3-ARMv5 and one for ARMv6-ARMv7. Modified HAL_InvalidateCache_ARMvF to use the appropriate cache flush instructions depending on whether it's an ARMv6 or ARMv7 style cache.
Admin:
  S3C6410 and other ARMv6 machines should work now.
  Tested on BB-xM rev A2.


Version 5.35, 4.79.2.98.2.39. Tagged as 'Kernel-5_35-4_79_2_98_2_39'
---
 VersionASM | 10 ++++-----
 VersionNum | 14 ++++++-------
 hdr/ARMops |  2 +-
 s/ARMops   | 27 +++++++++++++++++++++---
 s/HAL      | 60 ++++++++++++++++++++++++++++++++++--------------------
 5 files changed, 75 insertions(+), 38 deletions(-)

diff --git a/VersionASM b/VersionASM
index 3249b42..019fd1e 100644
--- a/VersionASM
+++ b/VersionASM
@@ -13,11 +13,11 @@
                         GBLS    Module_ComponentPath
 Module_MajorVersion     SETS    "5.35"
 Module_Version          SETA    535
-Module_MinorVersion     SETS    "4.79.2.98.2.38"
-Module_Date             SETS    "04 Jun 2011"
-Module_ApplicationDate  SETS    "04-Jun-11"
+Module_MinorVersion     SETS    "4.79.2.98.2.39"
+Module_Date             SETS    "09 Jun 2011"
+Module_ApplicationDate  SETS    "09-Jun-11"
 Module_ComponentName    SETS    "Kernel"
 Module_ComponentPath    SETS    "castle/RiscOS/Sources/Kernel"
-Module_FullVersion      SETS    "5.35 (4.79.2.98.2.38)"
-Module_HelpVersion      SETS    "5.35 (04 Jun 2011) 4.79.2.98.2.38"
+Module_FullVersion      SETS    "5.35 (4.79.2.98.2.39)"
+Module_HelpVersion      SETS    "5.35 (09 Jun 2011) 4.79.2.98.2.39"
                         END
diff --git a/VersionNum b/VersionNum
index b4d2e26..8536505 100644
--- a/VersionNum
+++ b/VersionNum
@@ -5,19 +5,19 @@
  *
  */
 #define Module_MajorVersion_CMHG        5.35
-#define Module_MinorVersion_CMHG        4.79.2.98.2.38
-#define Module_Date_CMHG                04 Jun 2011
+#define Module_MinorVersion_CMHG        4.79.2.98.2.39
+#define Module_Date_CMHG                09 Jun 2011
 
 #define Module_MajorVersion             "5.35"
 #define Module_Version                  535
-#define Module_MinorVersion             "4.79.2.98.2.38"
-#define Module_Date                     "04 Jun 2011"
+#define Module_MinorVersion             "4.79.2.98.2.39"
+#define Module_Date                     "09 Jun 2011"
 
-#define Module_ApplicationDate          "04-Jun-11"
+#define Module_ApplicationDate          "09-Jun-11"
 
 #define Module_ComponentName            "Kernel"
 #define Module_ComponentPath            "castle/RiscOS/Sources/Kernel"
 
-#define Module_FullVersion              "5.35 (4.79.2.98.2.38)"
-#define Module_HelpVersion              "5.35 (04 Jun 2011) 4.79.2.98.2.38"
+#define Module_FullVersion              "5.35 (4.79.2.98.2.39)"
+#define Module_HelpVersion              "5.35 (09 Jun 2011) 4.79.2.98.2.39"
 #define Module_LibraryVersionInfo       "5:35"
diff --git a/hdr/ARMops b/hdr/ARMops
index 214e5dd..3ea8e16 100644
--- a/hdr/ARMops
+++ b/hdr/ARMops
@@ -21,7 +21,7 @@ ARMv5T   *       4
 ARMv5TE  *       5
 ARMv5TEJ *       6
 ARMv6    *       7
-ARMvF    *       &F ; 'Fancy' ARM that describes its features in the feature registers (Cortex/ARMv7 and above?)
+ARMvF    *       &F ; 'Fancy' ARM that describes its features in the feature registers. Generally this implies ARMv7+, but there are also a few ARMv6 CPUs with this value (e.g. ARM1176JZF-S)
 
                 ^       0
 ARM600          #       1
diff --git a/s/ARMops b/s/ARMops
index 8a8a723..47fa353 100644
--- a/s/ARMops
+++ b/s/ARMops
@@ -718,13 +718,13 @@ KnownCPUTable
         CPUDesc ARM922T,       &029220, &0FFFF0, ARMv4T,  WB_CR7_LDa, 1,  8K, 64, 8,  8K, 64, 8
         CPUDesc X80200,        &052000, &0FFFF0, ARMv5TE, WB_Cal_LD,  1, 32K, 32, 8, 32K, 32, 8
         CPUDesc X80321,    &69052400, &FFFFF700, ARMv5TE, WB_Cal_LD,  1, 32K, 32, 8, 32K, 32, 8
-        CPUDesc ARM1176JZF_S,  &00B760, &00FFF0, ARMv6,   WB_CR7_LDa, 1, 16K, 32, 16,16K, 32, 16
         DCD     -1
 
-; Simplified CPUDesc table for ARMv7 only
-; The cache size data is ignored
+; Simplified CPUDesc table for ARMvF
+; The cache size data is ignored for ARMv7.
 KnownCPUTable_Fancy
         CPUDesc Cortex_A8,     &00C080, &00FFF0, ARMvF, WB_CR7_Lx, 1, 16K, 32, 16, 16K, 32, 16
+        CPUDesc ARM1176JZF_S,  &00B760, &00FFF0, ARMv6, WB_CR7_LDa, 1, 16K, 32, 16,16K, 32, 16
         DCD     -1
 
 ; Peculiar characteristics of individual ARMs not deducable otherwise. First field is
@@ -792,12 +792,33 @@ ARM_Analyse_Fancy
 
         MOV     v5, #CPUFlag_32bitOS+CPUFlag_No26bitMode ; 26bit has been obsolete for a long time
 
+        ; Work out whether the cache info is in ARMv6 or ARMv7 style
+        MRC     p15, 0, a1, c0, c0, 1
+        TST     a1, #&80000000
+        BNE     %FT25
+
+        ; ARMv6 format cache type register.
+        ; TODO - Use the cache type register to deduce the cache info.
+        ; For now, just fall back on the values in the CPU table.
+        ASSERT  CT_Isize_pos = 0
+        MOV     a1, v2
+        ADD     a2, v6, #ICache_Info
+        BL      EvaluateCache
+        MOV     a1, v2, LSR #CT_Dsize_pos
+        ADD     a2, v6, #DCache_Info
+        BL      EvaluateCache
+        B       %FT27
+
+25
+        ; ARMv7 format cache type register. This should(!) mean that we have the cache level ID register, and all the other ARMv7 cache registers.
+
         ; Do we have a split cache?
         MRC     p15, 1, a1, c0, c0, 1
         AND     a2, a1, #7
         TEQ     a2, #3
         ORREQ   v5, v5, #CPUFlag_SynchroniseCodeAreas+CPUFlag_SplitCache
 
+27
         [ CacheOff
         ORR     v5, v5, #CPUFlag_SynchroniseCodeAreas
         |
diff --git a/s/HAL b/s/HAL
index 0e766b5..3143e3f 100644
--- a/s/HAL
+++ b/s/HAL
@@ -27,20 +27,32 @@ DRAMOffset_LastFixed    #       0
 ;        IMPORT  Init_ARMarch
 ;        IMPORT  ARM_Analyse
 
-
  [ MEMM_Type = "VMSAv6"
-mmuc_table ; Table of MMUC init values. First word is value to ORR, second is value to BIC
- DCD MMUC_F+MMUC_L+MMUC_D+MMUC_P, MMUC_B+MMUC_W+MMUC_C+MMUC_A+MMUC_M+MMUC_RR+MMUC_V+MMUC_I+MMUC_Z+MMUC_R+MMUC_S ; ARMv3
- DCD MMUC_F+MMUC_L+MMUC_D+MMUC_P, MMUC_B+MMUC_W+MMUC_C+MMUC_A+MMUC_M+MMUC_RR+MMUC_V+MMUC_I+MMUC_Z+MMUC_R+MMUC_S ; ARMv4
- DCD MMUC_F+MMUC_L+MMUC_D+MMUC_P, MMUC_B+MMUC_W+MMUC_C+MMUC_A+MMUC_M+MMUC_RR+MMUC_V+MMUC_I+MMUC_Z+MMUC_R+MMUC_S ; ARMv4T
- DCD MMUC_F+MMUC_L+MMUC_D+MMUC_P, MMUC_B+MMUC_W+MMUC_C+MMUC_A+MMUC_M+MMUC_RR+MMUC_V+MMUC_I+MMUC_Z+MMUC_R+MMUC_S ; ARMv5
- DCD MMUC_F+MMUC_L+MMUC_D+MMUC_P, MMUC_B+MMUC_W+MMUC_C+MMUC_A+MMUC_M+MMUC_RR+MMUC_V+MMUC_I+MMUC_Z+MMUC_R+MMUC_S ; ARMv5T
- DCD MMUC_F+MMUC_L+MMUC_D+MMUC_P, MMUC_B+MMUC_W+MMUC_C+MMUC_A+MMUC_M+MMUC_RR+MMUC_V+MMUC_I+MMUC_Z+MMUC_R+MMUC_S ; ARMv5TE
- DCD MMUC_F+MMUC_L+MMUC_D+MMUC_P, MMUC_B+MMUC_W+MMUC_C+MMUC_A+MMUC_M+MMUC_RR+MMUC_V+MMUC_I+MMUC_Z+MMUC_R+MMUC_S ; ARMv5TEJ
- DCD MMUC_F+MMUC_L+MMUC_D+MMUC_P+MMUC_U, MMUC_B+MMUC_W+MMUC_C+MMUC_A+MMUC_M+MMUC_RR+MMUC_V+MMUC_I+MMUC_Z+MMUC_R+MMUC_S+MMUC_VE+MMUC_EE+MMUC_L2 ; ARMv6
- ; Skip undefined architecture numbers
-mmuc_table_armvf
- DCD 0, MMUC_C+MMUC_A+MMUC_M+MMUC_V+MMUC_I+MMUC_Z+MMUC_RR+MMUC_TRE+MMUC_AFE+MMUC_TE ; ARMvF (Cortex)
+mmuc_init_new
+        ; MMUC initialisation flags for ARMv6/ARMv7
+        ; This tries to leave the reserved/unpredictable bits untouched, while initialising everything else to what we want
+                ; ARMv7MP (probably) wants SW. ARMv6 wants U+XP (which should both be fixed at 1 on ARMv7)
+        DCD     MMUC_SW+MMUC_U+MMUC_XP
+                ; M+C+W+Z+I+L2 clear to keep MMU/caches off.
+                ; A to keep alignment exceptions off (for now at least)
+                ; B+EE clear for little-endian
+                ; S+R+RR clear to match mmuc_init_old
+                ; V+VE clear to keep processor vectors at &0
+                ; FI clear to disable fast FIQs (interruptible LDM/STM)
+                ; TRE+AFE clear for our VMSAv6 implementation
+                ; TE clear for processor vectors to run in ARM mode
+        DCD     MMUC_M+MMUC_A+MMUC_C+MMUC_W+MMUC_B+MMUC_S+MMUC_R+MMUC_Z+MMUC_I+MMUC_V+MMUC_RR+MMUC_FI+MMUC_VE+MMUC_EE+MMUC_L2+MMUC_TRE+MMUC_AFE+MMUC_TE
+mmuc_init_old
+        ; MMUC initialisation flags for ARMv5 and below, as per ARM600 MMU code
+                ; Late abort (ARM6 only), 32-bit Data and Program space. No Write buffer (ARM920T
+                ; spec says W bit should be set, but I reckon they're bluffing).
+                ;
+                ; The F bit's tricky. (1 => CPCLK=FCLK, 0=>CPCLK=FCLK/2). The only chip using it was the
+                ; ARM700, it never really reached the customer, and it's always been programmed with
+                ; CPCLK=FCLK. Therefore we'll keep it that way, and ignore the layering violation.
+        DCD     MMUC_F+MMUC_L+MMUC_D+MMUC_P
+                ; All of these bits should be off already, but just in case...
+        DCD     MMUC_B+MMUC_W+MMUC_C+MMUC_A+MMUC_M+MMUC_RR+MMUC_V+MMUC_I+MMUC_Z+MMUC_R+MMUC_S
  ]
 
 ; void RISCOS_InitARM(unsigned int flags)
@@ -52,15 +64,13 @@ RISCOS_InitARM
         MOVEQ   a3, #0
         ARM_read_control a3, NE
  [ MEMM_Type = "VMSAv6"
-        ; Use a lookup table to get the correct control register set/clear mask
-        CMP     a1, #ARMvF
-        ADREQ   a2, mmuc_table_armvf
-        ADRLT   a2, mmuc_table
-        ADDLT   a2, a2, a1, LSL #3
-        LDMIA   a2, {a2, a4}
+        CMP     a1, #ARMv6
+        CMPNE   a1, #ARMvF
+        ADREQ   a2, mmuc_init_new
+        ADRNE   a2, mmuc_init_old
+        LDMIA   a2, {a2, lr}
         ORR     a3, a3, a2
-        BIC     a3, a3, a4
-        CMP     a1,#0
+        BIC     a3, a3, lr
  |
         ; Late abort (ARM6 only), 32-bit Data and Program space. No Write buffer (ARM920T
         ; spec says W bit should be set, but I reckon they're bluffing).
@@ -693,7 +703,7 @@ MMU_activation_zone
         MCRGT   p15, 0, lr, c12, c0, 0          ; Ensure exception vector base is 0 (Cortex)
         myISB   ,lr,,y
         ORRGE   v5, v5, #MMUC_XP ; Extended pages enabled (v6)
-        BICGT   v5, v5, #MMUC_TRE+MMUC_AFE ; TEX remap, Access Flag disabled (Cortex)
+        BICGE   v5, v5, #MMUC_TRE+MMUC_AFE ; TEX remap, Access Flag disabled
         BICGE   v5, v5, #MMUC_EE+MMUC_TE+MMUC_VE ; Exceptions = nonvectored LE ARM
         CMP     ip, #0
   ]
@@ -1059,6 +1069,12 @@ HAL_InvalidateCache_ARMvF
         MCR     p15, 0, r8, c7, c5, 6           ; invalidate branch target predictor
         myDSB   ,r8,,y                          ; Wait for completion
         myISB   ,r8,,y
+        ; Check whether we're ARMv7 (and thus multi-level cache) or ARMv6 (and thus single-level cache)
+        MRC     p15, 0, r9, c0, c0, 1
+        TST     r9, #&80000000 ; EQ=ARMv6, NE=ARMv7
+        MCREQ   ARM_config_cp,0,r8,ARMv4_cache_reg,C7 ; ARMv3-ARMv6 I+D cache flush
+        BEQ     %FT10 ; Skip to the end
+
         MRC     p15, 1, r8, c0, c0, 1 ; Cache level ID register
         BIC     r8, r8, #&FF000000 ; Discard unification/coherency bits
         MOV     r9, #0 ; Current cache level
-- 
GitLab