Commit 6eee32dd authored by Jeffrey Lee's avatar Jeffrey Lee
Browse files

Improve safety of OS_Memory 0 "make temporarily uncacheable" and *Cache off

  s/MemInfo - Wrap OS_Memory 0 in some code which will temporarily claim the FIQ vector when making pages temporarily uncacheable, to avoid any issues caused by modern ARMs ignoring unexpected cache hits
  s/VMSAv6 - Claim FIQs when OS_MMUControl is asked to make a change to the SCTLR, to avoid similar issues on modern ARMs. Also make the stack temporarily uncacheable before disabling the cache, so that we don't run into any problems using the stack inbetween disabling the cache and completing the clean+invalidate.
  Tested on Pi 2B, 3B
  *Cache off now works reliably on Pi 2B, although there is sometimes a pause of a few seconds while things sort themselves out (USB?)
  *Cache off "works" on Pi 3B but everything will fall over soon afterwards due to the Cortex-A53 not supporting LDREX/STREX to non-cacheable pages (or when the page is effectively non-cacheable, i.e. cacheable page with cache disabled)

Version 5.35, Tagged as 'Kernel-5_35-4_79_2_311'
parent ff04e525
......@@ -13,11 +13,11 @@
GBLS Module_ComponentPath
Module_MajorVersion SETS "5.35"
Module_Version SETA 535
Module_MinorVersion SETS ""
Module_Date SETS "25 Mar 2016"
Module_ApplicationDate SETS "25-Mar-16"
Module_MinorVersion SETS ""
Module_Date SETS "27 Mar 2016"
Module_ApplicationDate SETS "27-Mar-16"
Module_ComponentName SETS "Kernel"
Module_ComponentPath SETS "castle/RiscOS/Sources/Kernel"
Module_FullVersion SETS "5.35 ("
Module_HelpVersion SETS "5.35 (25 Mar 2016)"
Module_FullVersion SETS "5.35 ("
Module_HelpVersion SETS "5.35 (27 Mar 2016)"
......@@ -5,19 +5,19 @@
#define Module_MajorVersion_CMHG 5.35
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 25 Mar 2016
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 27 Mar 2016
#define Module_MajorVersion "5.35"
#define Module_Version 535
#define Module_MinorVersion ""
#define Module_Date "25 Mar 2016"
#define Module_MinorVersion ""
#define Module_Date "27 Mar 2016"
#define Module_ApplicationDate "25-Mar-16"
#define Module_ApplicationDate "27-Mar-16"
#define Module_ComponentName "Kernel"
#define Module_ComponentPath "castle/RiscOS/Sources/Kernel"
#define Module_FullVersion "5.35 ("
#define Module_HelpVersion "5.35 (25 Mar 2016)"
#define Module_FullVersion "5.35 ("
#define Module_HelpVersion "5.35 (27 Mar 2016)"
#define Module_LibraryVersionInfo "5:35"
......@@ -2400,6 +2400,8 @@ DynArea_NaughtyRenum
DCB "illegal DA renumber",0
[ ShrinkableDAs
......@@ -50,7 +50,7 @@ MemReturn
B MemoryConvert ; 0
B MemoryConvertFIQCheck ; 0
B %BT20 ; Reason codes 1-5 are reserved.
B %BT20
B %BT20
......@@ -120,7 +120,26 @@ physical_bits * ((physical :SHL: 4) :OR: physical)
cacheable_bit * 1:SHL:15
alter_cacheable * 1:SHL:16
MemoryConvert ROUT
; Small wrapper to make sure FIQs are disabled if we're making pages uncacheable
; (Modern ARMs ignore unexpected cache hits, so big coherency issues if we make
; a page uncacheable which is being used by FIQ).
MemoryConvertFIQCheck ROUT
AND r11, r0, #3:SHL:14
TEQ r11, #2:SHL:14
BNE MemoryConvertNoFIQCheck
Entry "r0-r1"
MOV r1, #Service_ClaimFIQ
SWI XOS_ServiceCall
LDMIA sp, {r0-r1}
BL MemoryConvertNoFIQCheck
MOV r1, #Service_ReleaseFIQ
SWI XOS_ServiceCall
MSR CPSR_c, r11
MemoryConvertNoFIQCheck ROUT
Entry "r0-r11" ; Need lots of registers!!
; MRS lr, CPSR
......@@ -309,7 +328,7 @@ MemoryConvert ROUT
EOR r0, r0, #cacheable_bit ; If we made them uncacheable then make them cacheable again & v.v.
SUB r2, r3, r2
SUBS r2, r2, #1 ; Change back the entries we have changed up to (but excluding) the error entry.
BLNE MemoryConvert
BLNE MemoryConvertNoFIQCheck
ADRL r0, ErrorBlock_BadAddress
......@@ -412,14 +412,34 @@ MMUControl_Unknown
Pull "pc"
; Make current stack page(s) temporarily uncacheable to make cache disable operations safer
; In: R0 = OS_Memory 0 flags
Entry "r1-r2", 24 ; Make up to two pages uncacheable
ADD lr, sp, #24+12 ; Get original SP
STR lr, [sp, #4] ; Make current page uncacheable
ASSERT (SVCStackAddress :AND: ((1<<20)-1)) = 0 ; Assume MB aligned stack
TST lr, #(1<<20)-4096 ; Zero if this is the last stack page
SUBNE lr, lr, #4096
STRNE lr, [sp, #12+4] ; Make next page uncacheable
MOVNE r2, #2
MOV r1, sp
MOVEQ r2, #1
BL MemoryConvertNoFIQCheck ; Bypass FIQ disable logic within OS_Memory (we've already claimed the FIQ vector)
MMUControl_ModifyControl ROUT
Push "r0,r3,r4,r5"
CMP r1,#0
BEQ MMUC_modcon_readonly
MOV r3, r1
MOV r1, #Service_ClaimFIQ
SWI XOS_ServiceCall ; stop FIQs for safety
MOV r1, r3
LDR r3,=ZeroPage
PHPSEI r4 ; disable IRQs while we modify soft copy (and possibly switch caches off/on)
CPSID if ; disable IRQs while we modify soft copy (and possibly switch caches off/on)
; We're ARMv6+, just read the real control reg and ignore the soft copy
ARM_read_control lr
......@@ -457,6 +477,11 @@ MMUControl_ModifyControl ROUT
BIC lr, r1, r2 ; lr = bits going from 1->0
TST lr, #MMUC_C ; if cache turning off then clean data cache first
; When disabling the data cache we have the problem that modern ARMs generally ignore unexpected cache hits, so any stack usage between us disabling the cache and finishing the clean + invalidate is very unsafe
; Solve this problem by making the current pages of the SVC stack temporarily uncacheable for the duration of the dangerous bit
; (n.b. making the current stack page uncacheable has the same problems as turning off the cache globally, but OS_Memory 0 has its own workaround for that)
MOV r0, #(1<<9)+(2<<14)
BL ModifyStackCacheability
ARMop Cache_CleanAll,,,r3
ARM_write_control r2
......@@ -467,6 +492,11 @@ MMUControl_ModifyControl ROUT
LDR r3,=ZeroPage
ARMop Cache_InvalidateAll,,,r3
; Undo any stack uncaching we performed above
BIC lr, r1, r2
MOVNE r0, #(1<<9)+(3<<14)
BLNE ModifyStackCacheability
; If either I+D was disabled, and now both are turned on, turn on HAL
; L2 cache
......@@ -484,7 +514,12 @@ MMUControl_ModifyControl ROUT
LDR pc, [r0, #HALDevice_Activate]
Pull "r1-r3,r12"
PLP r4 ; restore IRQ state
MSR CPSR_c, r4 ; restore IRQ state
MOV r3, r1
MOV r1, #Service_ReleaseFIQ
SWI XOS_ServiceCall ; allow FIQs again
MOV r1, r3
Pull "r0,r3,r4,r5,pc"
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment