ARM.Machine.Mod 105 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604
  1. MODULE Machine; (** AUTHOR "Timothée Martiel"; PURPOSE "Machine abstraction module for ARM"; *)
  2. (**
  3. * Machine abstraction:
  4. * - processor management: caches, FPU
  5. * - interrupts and exceptions
  6. * - virtual memory management
  7. *)
  8. IMPORT SYSTEM, Initializer, Trace, Platform, TraceDevice, BootConfig, PrivateWatchdog;
  9. CONST
  10. Version = "A2 on ARM, revision 4677 (15.10.2017)";
  11. DefaultObjectFileExtension* = ".Gof";
  12. (* Interrupts Dummy Test *)
  13. DummyTest = FALSE;
  14. (* Lock levels *)
  15. TraceOutput* = 0;
  16. Memory* = 1;
  17. Heaps* = 2;
  18. Interrupts* = 3 ;
  19. Modules* = 4;
  20. Objects* = 5;
  21. Processors* = 6;
  22. KernelLog* = 7;
  23. MaxLock = 8;
  24. (* Unit prefixes *)
  25. k = 1024;
  26. M = k * k;
  27. G = M * k;
  28. LogM = 20; (* log2(M) *)
  29. (*LogK = 10; (* log2(K) *)*)
  30. (* CPU number *)
  31. MaxCPU* = 32(*BootConfig.CpuNb*);
  32. (* If TRUE, enables some assertions in the code *)
  33. StrongChecks = TRUE;
  34. (* Page size, in bytes *)
  35. PS = 4 * k;
  36. PSlog2 = 12; (* ASH(1, PSlog2) = PS *)
  37. PTSize = 400H; (* size of a coarse page table *)
  38. (*PTEntries = 100H; (* 32bit entries per page table *)*)
  39. (* Absolute maximal process stack numbers *)
  40. MaxStackNb = 1024;
  41. (* Hard limit on cache reference size *)
  42. MaxCacheRefSize = M;
  43. (* Interrupt Vector base. Valid only after MMU is enabled *)
  44. InterruptVector = 0FFFF0000H;
  45. (* Interrupts *)
  46. MinIRQ* = 0;
  47. MaxIRQ* = 255;
  48. IRQ0* = MinIRQ; (* Alias *)
  49. (** ID of the global timer IRQ *)
  50. TimerIRQ* = 27;
  51. PrivateTimerIRQ* = 29;
  52. MaxIRQHandlers = 16;
  53. (* Exceptions codes. DO NOT CHANGE: they represent interrupt vector offsets *)
  54. Reset * = 20H; (** Reset *)
  55. Undef * = 24H; (** Undefined Exception *)
  56. Swi * = 28H; (** Software Interrupt *)
  57. Prefetch * = 2CH; (** Prefetch Abort *)
  58. Data * = 30H; (** Data Abort *)
  59. Irq * = 38H; (** Interrupt Request *)
  60. Fiq * = 3CH; (** Fast Interrupt *)
  61. (* Initial Stack size for user stacks *)
  62. (*InitUserStackSize = PS;*)
  63. HeapMin = 50; (* "minimum" heap size as percentage of total memory size (used for heap expansion in scope of GC ) *)
  64. HeapMax = 95; (* "maximum" heap size as percentage of total memory size (used for heap expansion in scope of GC) *)
  65. ExpandRate = 1; (* always extend heap with at least this percentage of total memory size *)
  66. Threshold = 10; (* periodic GC initiated when this percentage of total memory size bytes has "passed through" NewBlock *)
  67. (* Stack parameters *)
  68. InitStackSize = PS;
  69. StackGuardSize = PS;
  70. (* access permissions *)
  71. SrwUrw = 3;
  72. FullAccess = (*SrwUrw*400H+SrwUrw*100H+SrwUrw*40H+*)SrwUrw*10H; (* for small pages only *)
  73. LastStackPage = SrwUrw*400H+SrwUrw*100H+SrwUrw*40H; (* for small pages only *)
  74. (* first level page table types *)
  75. flCoarse = 1;
  76. flSection = 2;
  77. (* Second Level *)
  78. slFault = 0;
  79. slSmall = 2;
  80. (* cachable/bufferable mapping options *)
  81. cb = 0;
  82. C = 8;
  83. B = 4;
  84. CB = C + B + 440H;
  85. (* Inner and Outer Cacheable, Write-Through, no Write Allocate *)
  86. Cacheable = 100CH; (* here inner cacheable, write-back, write-allocate *)
  87. (* Shareable *)
  88. Shareable = 10000H;
  89. (* NIL *)
  90. NilAdr* = -1;
  91. (* Control Register Flags *)
  92. DCache = 2;
  93. ICache = 12;
  94. Second* = 1000; (* frequency of ticks increments in Hz *)
  95. Preemption* = 31; (** flag for BreakAll() *)
  96. (** Period at which the CPU timer interrupts, in micro seconds *)
  97. TimerPeriod* = 1000;
  98. (** Last reboot info *)
  99. RebootPowerOn * = 0;
  100. RebootHardReset * = 1;
  101. RebootSoftReset * = 2;
  102. RebootSystemWatchdog * = 3;
  103. RebootWatchdogCPU0 * = 4;
  104. RebootWatchdogCPU1 * = 5;
  105. RebootDebug * = 6;
  106. (** Needed, but not used yet by Reals.Mod *)
  107. fcr * = {};
  108. TYPE
  109. (** processor state *)
  110. State* = RECORD
  111. R*: ARRAY 12 OF ADDRESS; (** registers 0-11 *)
  112. BP*, SP*, LR*, PC*: ADDRESS; (** special registers *)
  113. PSR*: ADDRESS; (** processor state register *)
  114. INT*: ADDRESS; (** IRQ number *)
  115. END;
  116. (** NEON Coprocessor state *)
  117. NEONState* = RECORD
  118. D*: ARRAY 32 OF HUGEINT; (* 32 64-bits registers *)
  119. FPSCR*: ADDRESS;
  120. FPEXC*: ADDRESS;
  121. END;
  122. (** exception state *)
  123. ExceptionState* = RECORD
  124. halt*: LONGINT; (** halt code *)
  125. instn*: LONGINT; (** undefined instruction *)
  126. pf*: ADDRESS; (** page fault address *)
  127. status*: LONGINT; (** page fault status *)
  128. locks*: SET; (** active locks *)
  129. END;
  130. (** Interrupt Hanlder *)
  131. Handler* = PROCEDURE {DELEGATE} (VAR state: State);
  132. EventHandler = PROCEDURE (id: LONGINT; CONST state: State);
  133. (** Spinlock *)
  134. Lock = RECORD
  135. locked: BOOLEAN;
  136. (* Padding to the granularity of exclusive monitor: 8 words on Cortex-A9 *)
  137. pad: ARRAY 31 OF CHAR;
  138. END;
  139. (** Processor status *)
  140. Proc* = RECORD
  141. locksHeld*: SET;
  142. preemptCount*: LONGINT;
  143. (*nestCount-: LONGINT; (** total locks held by a processor *)*)
  144. intStatus*, mmu*: BOOLEAN; (* muu: if the MMU is enabled for this processor *)
  145. END;
  146. (** Virtual/physical address pair *)
  147. AddressTuple = RECORD virtual, physical: ADDRESS; END;
  148. (** Stack descriptor:
  149. low: lowest possible stack address
  150. adr: current lowest allocated address
  151. high: highest address
  152. *)
  153. Stack* = RECORD
  154. low: ADDRESS;
  155. adr*: ADDRESS;
  156. high*: ADDRESS;
  157. END;
  158. (** Heap memory block *)
  159. MemoryBlock* = POINTER TO MemoryBlockDesc;
  160. MemoryBlockDesc* = RECORD
  161. next- {UNTRACED}: MemoryBlock;
  162. startAdr-: ADDRESS; (* unused field for I386 *)
  163. size-: SIZE; (* unused field for I386 *)
  164. beginBlockAdr-, endBlockAdr-: ADDRESS
  165. END;
  166. Address32* = ADDRESS;
  167. Range* = RECORD
  168. adr*: ADDRESS; size*: SIZE;
  169. END;
  170. CacheRefs = POINTER {UNSAFE,UNTRACED} TO ARRAY MaxCacheRefSize OF SHORTINT;
  171. VAR
  172. version -: ARRAY 64 OF CHAR;
  173. sp, fp: ADDRESS;
  174. (** Interrupt Mask *)
  175. IRQMask: SET;
  176. (** IRQ Handlers. IRQ can have multiple handlers. Dispatching to those is done in IRQGlue and IRQCaller. *)
  177. irqHandler: ARRAY MaxIRQ + 1, MaxIRQHandlers OF Handler;
  178. (* Exception handlers. Called by *Glue. *)
  179. undefHandler, swiHandler, prefetchHandler, dataHandler, fiqHandler: Handler;
  180. stateTag: LONGINT;
  181. dummyIRQHandler: ARRAY MaxIRQ+1 OF RECORD h: Handler; END;
  182. (** Low level locks *)
  183. lock: ARRAY MaxLock OF Lock;
  184. (** Processors status:
  185. - locksHeld: set of low-level locks held by the processor
  186. - preemptCount: preemption counter
  187. *)
  188. proc-: ARRAY MaxCPU OF Proc;
  189. (** IDs of all successfully started processors. *)
  190. allProcessors-: SET;
  191. heapHigh, heapLow, stackHigh, stackLow: AddressTuple;
  192. (* Memory *)
  193. pageTable: RECORD virtual, memory: ADDRESS END; (* contains the virtual & memory address of the first level page table *)
  194. memory: RECORD size, free: SIZE; END;
  195. stackPT: ADDRESS;
  196. (* Free stack bitmap: each set element is set to indicate free stack *)
  197. freeStack: ARRAY (MaxStackNb + 31) DIV 32 OF SET;
  198. freeStackIndex: SIZE;
  199. (* Address of the highest free page *)
  200. freePage: ADDRESS;
  201. (* Memory blocks -- For the heap *)
  202. memBlockHead-{UNTRACED}, memBlockTail-{UNTRACED}: MemoryBlock;
  203. initialMemBlock: MemoryBlockDesc;
  204. dCacheBase: ADDRESS;
  205. (** GC parameters *)
  206. expandMin, heapMinKB, heapMaxKB : SIZE;
  207. gcThreshold: SIZE;
  208. (** For preemptive scheduling. *)
  209. Timeslice*: Handler;
  210. timer: EventHandler;
  211. (** timer ticks. Written to by GetTicks. Read-only *)
  212. ticks*: LONGINT;
  213. eventCount, eventMax: LONGINT;
  214. event: Handler;
  215. (** Number of processor used. *)
  216. numProcessors*: LONGINT;
  217. numberOfProcessors: LONGINT;
  218. (** Scheduling start procedure for non-booting processors. *)
  219. start*: PROCEDURE;
  220. (** Upcall to get current stack -- used for stack extension *)
  221. getStack*: PROCEDURE (VAR stack: Stack);
  222. (* Memory Layout *)
  223. (* The system area contains:
  224. * - the interrupt vector, which will be mapped high
  225. * - interrupt stacks
  226. * - the page table
  227. * Except for the first 4kB page, it is mapped 1:1.
  228. *)
  229. memSysLowStart,
  230. memSysLowStop,
  231. (* The heap area contains:
  232. * - the static kernel image
  233. * - the heap
  234. * The heap is mapped 1:1 with 1MB pages.
  235. *)
  236. memHeapStart,
  237. memHeapStop,
  238. (* Process Stacks are allocated in this area.
  239. * Stacks are mapped with 4kB pages. They take at least 2 pages:
  240. * - 1 for the actual stack
  241. * - 1 kept unmapped as the stack guard.
  242. * Stacks are mapped 1:1.
  243. * The stack size can be tuned to allow the system to run more processes.
  244. *)
  245. memStackStart,
  246. memStackStop,
  247. (* Boot configuration is placed in memory. It takes 4 kB at most *)
  248. memConfigStart,
  249. memConfigStop,
  250. (* IO registers and peripheral control are located in this region. Mapped 1:1 with 1MB and 4kB
  251. * pages, as necessary. Mapped as Device memory. *)
  252. memIOStart,
  253. memIOStop,
  254. (* High system memory region. Within the last MB, contains: interrupt vector and reference counts
  255. * for caching. *)
  256. memSysHighStart,
  257. memSysHighStop,
  258. (* System Parameters *)
  259. (* Interrupt stacks. 8kB of virtual space (4kB for stack, 4kB for guard) and 4 stacks per processor. *)
  260. sysIntStackStart,
  261. sysIntStackStop,
  262. (* First Level Page Table: size of 16 * k to map 4GB with 1MB pages. *)
  263. sysFirstLvlPtStart,
  264. sysFirstLvlPtStop,
  265. (*
  266. * Second Level Page Table:
  267. * - 2 * 256 entries for the system area (first and last MB of VMem)
  268. * - 256 entries for each MB of virtual stack space
  269. * 256 entries take 1kB memory space.
  270. *)
  271. sysSecondLvlPtStart,
  272. sysSecondLvlPtStop,
  273. (*
  274. * Interrupt Vector. Located at 0FFFFFFF0H
  275. *)
  276. sysVectorStart,
  277. sysVectorStop,
  278. sysCacheRefStart,
  279. sysCacheRefStop,
  280. (*
  281. * Number of ref counters: 1 per 1st level heap page, 1 per 2nd level stack page.
  282. * This memory region is organized as follows: the first part [0 .. SysCacheStackOfs) is used for heap pages,
  283. * the second part, [SysCacheStackOfs .. SysCacheRefSize) is used for stack pages.
  284. *)
  285. sysCacheRefSize,
  286. (* Offset in the ref count table for stack pages. *)
  287. sysCacheStackOfs: ADDRESS;
  288. (* Process stack system *)
  289. maxUserStackSize: SIZE;
  290. maxUserStacks: LONGINT;
  291. (* TRUE iff caching should be globally enabled *)
  292. enableCaching: BOOLEAN;
  293. (* UART used for kernel output *)
  294. kernelOutputUart -: LONGINT;
  295. (** Interrupt tracing option *)
  296. traceInterrupts: BOOLEAN;
  297. (** Trace option for CPU state *)
  298. traceCpus: BOOLEAN;
  299. (** Use private watchdog to check scheduling timers? *)
  300. enableWatchdog: BOOLEAN;
  301. (** Array of reference counts for page caching *)
  302. cacheRefs -: CacheRefs;
  303. (** Reason for last reboot *)
  304. lastReboot -: LONGINT;
  305. (* ===== Processor Management ===== *)
  306. (* Current processor's ID, between 0 and MaxProc - 1 *)
  307. PROCEDURE - ID*(): LONGINT;
  308. CODE
  309. MRC p15, 0, R0, C0, C0, 5
  310. AND R0, R0, #3H; Get the last 2 bits of R0
  311. END ID;
  312. (** Enables current processor's L1 caches *)
  313. PROCEDURE EnableL1Cache;
  314. CODE
  315. ; Enable Cache and TLB maintenance broadcast
  316. mrc p15, 0, r0, c1, c0, 1
  317. orr r0, r0, #1H
  318. mcr p15, 0, r0, c1, c0, 1
  319. isb
  320. ; Enable Caching in SCTLR
  321. mrc p15, 0, r0, c1, c0, 0
  322. orr r0, r0, #4H
  323. mcr p15, 0, r0, c1, c0, 0
  324. isb
  325. END EnableL1Cache;
  326. (** Enable L2 cache, prefetching and other speculative execution support *)
  327. PROCEDURE EnableL2Cache;
  328. CODE
  329. ldr r0,[pc, #L2CCCrtl-$-8] ; Load L2CC base address base + control register
  330. mov r1, #0 ; force the disable bit
  331. str r1, [r0,#0] ; disable the L2 Caches
  332. ldr r0, [pc, #L2CCAuxCtrl-$-8] ; Load L2CC base address base + Aux control register
  333. ldr r1,[r0,#0] ; read the register
  334. ldr r2, [pc, #L2CCAuxControl-$-8] ; set the default bits
  335. orr r1,r1,r2
  336. str r1, [r0,#0] ; store the Aux Control Register
  337. ldr r0,[pc, #L2CCTAGLatReg-$-8] ; Load L2CC base address base + TAG Latency address
  338. ldr r1, [pc, #L2CCTAGLatency-$-8] ; set the latencies for the TAG
  339. str r1, [r0,#0] ; store the TAG Latency register Register
  340. ldr r0, [pc, #L2CCDataLatReg-$-8] ; Load L2CC base address base + Data Latency address
  341. ldr r1,[pc, #L2CCDataLatency-$-8] ; set the latencies for the Data
  342. str r1, [r0,#0] ; store the Data Latency register Register
  343. ldr r0,[pc, #L2CCWay-$-8] ; Load L2CC base address base + way register
  344. ldr r2, [pc, #H0xffff-$-8]
  345. str r2, [r0,#0] ; force invalidate
  346. ldr r0, [pc, #L2CCSync-$-8] ; need to poll 0x730, PSS_L2CC_CACHE_SYNC_OFFSET
  347. ; Load L2CC base address base + sync register
  348. ; poll for completion
  349. Sync:
  350. ldr r1, [r0,#0]
  351. cmp r1, #0
  352. bne Sync
  353. ldr r0,[pc, #L2CCIntRaw-$-8] ; clear pending interrupts
  354. ldr r1,[r0,#0]
  355. ldr r0,[pc, #L2CCIntClear-$-8]
  356. str r1,[r0,#0]
  357. ldr r0,[pc,#L2CCCrtl-$-8] ; Load L2CC base address base + control register
  358. ldr r1,[r0,#0] ; read the register
  359. mov r2, #1 ; set the enable bit
  360. orr r1,r1,r2
  361. str r1, [r0,#0] ; enable the L2 Caches
  362. mrc p15,0,r0,c1,c0,0 ; flow prediction enable
  363. orr r0, r0, #0x800 ; #0x800
  364. mcr p15,0,r0,c1,c0,0
  365. isb
  366. mrc p15,0,r0,c1,c0,1 ; read Auxiliary Control Register
  367. orr r0, r0, #4 ; enable Dside prefetch
  368. orr r0, r0, #2 ; enable L2 Prefetch hint
  369. mcr p15,0,r0,c1,c0,1 ; write Auxiliary Control Register
  370. isb
  371. b exit
  372. ; Data
  373. H0xffff: d32 0FFFFH
  374. L2CCWay: d32 0F8F02000H + 077CH
  375. L2CCSync: d32 0F8F02000H + 0730H
  376. L2CCCrtl: d32 0F8F02000H + 0100H
  377. L2CCAuxCtrl: d32 0F8F02000H + 0104H
  378. L2CCTAGLatReg: d32 0F8F02000H + 0108H
  379. L2CCDataLatReg: d32 0F8F02000H + 010CH
  380. L2CCIntClear: d32 0F8F02000H + 0220H
  381. L2CCIntRaw: d32 0F8F02000H + 021CH
  382. L2CCAuxControl: d32 72360000H
  383. L2CCTAGLatency: d32 0111H
  384. L2CCDataLatency: d32 0121H
  385. exit:
  386. END EnableL2Cache;
  387. (** Enables the Snoop Control Unit
  388. for L1 coherency and LDREX/STREX global monitor
  389. *)
  390. PROCEDURE EnableSCU;
  391. CODE
  392. ; set scu enable bit in scu
  393. ldr r7, [pc, #H0xf8f00000-$-8]
  394. ldr r0, [r7, #0]
  395. orr r0, r0, #1
  396. str r0, [r7,#0]
  397. ; invalidate scu
  398. ldr r7, [pc, #H0xf8f0000c-$-8]
  399. ldr r6, [pc, #H0xffff-$-8]
  400. str r6, [r7, #0]
  401. b exit
  402. ; Data
  403. H0xf8f00000: d32 0F8F00000H
  404. H0xf8f0000c: d32 0F8F0000CH
  405. H0xffff: d32 0FFFFH
  406. exit:
  407. END EnableSCU;
  408. (** Init NEON / VFP Engine *)
  409. PROCEDURE InitFPU;
  410. CODE
  411. MRC p15, 0, R0, C1, C0, 2;
  412. ORR R0, R0, #0x00f00000;
  413. MCR p15, 0, R0, C1, C0, 2;
  414. ISB
  415. MOV R0, #0x40000000;
  416. VMSR FPEXC, R0;
  417. VMRS R0, FPSCR
  418. BIC R0, R0, #0x0c00000 ; round to nearest as the default
  419. ; remark: if we put round to minus infinity as the default, we can spare quite some instructions in emission of ENTIER
  420. VMSR FPSCR, R0;
  421. END InitFPU;
  422. (** Activate the Symmetric Multiprocessing Mode for current CPU.
  423. This activates L1 cache coherency.
  424. *)
  425. PROCEDURE SetSmpMode;
  426. CODE
  427. (*
  428. mrc p15, 0, r0, c1, c0, 1 /* Read ACTLR*/
  429. orr r0, r0, #(0x01 << 6) /* set SMP bit */
  430. orr r0, r0, #(0x01 ) /* */
  431. mcr p15, 0, r0, c1, c0, 1 /* Write ACTLR*/
  432. *)
  433. MRC p15, 0, R0, C1, C0, 1
  434. ORR R0, R0, #047H
  435. MCR p15, 0, R0, C1, C0, 1
  436. ISB
  437. END SetSmpMode;
  438. (** Activate Assymmetric Multiprocessing Mode for current CPU.
  439. This desactivates L1 cache coherency
  440. *)
  441. PROCEDURE SetAmpMode;
  442. CODE
  443. MRC p15, 0, R0, C1, C0, 1
  444. MOV R1, #040H
  445. RSB R1, R1, #0
  446. ORR R0, R0, R1
  447. MCR p15, 0, R0, C1, C0, 1
  448. ISB
  449. END SetAmpMode;
  450. (** Enable coprocessors CP10 and CP11(= VFP and NEON engine) *)
  451. PROCEDURE EnableCoprocessors;
  452. CODE
  453. mov r0, r0
  454. mrc p15, 0, r1, c1, c0, 2 ; read cp access control register (CACR) into r1
  455. orr r1, r1, #0xf00000 ; enable full access for p10 & p11
  456. mcr p15, 0, r1, c1, c0, 2 ; write back into CACR
  457. isb
  458. END EnableCoprocessors;
  459. (* Initializes a processor. Has to be called once by each processor. *)
  460. PROCEDURE InitProcessor*;
  461. BEGIN
  462. timer := DummyEvent;
  463. Timeslice := DummyTimeslice;
  464. SetSmpMode;
  465. EnableSCU;
  466. EnableL1Cache;
  467. InvalidateTLB;
  468. InvalidateICache;
  469. Initializer.InvalidateDCache;
  470. (*InvalidateDCacheRange(0, SYSTEM.VAL(ADDRESS, LastAddress));*)
  471. (* SCU and L2 caches are enabled in the initialization sequence *)
  472. EnableL2Cache;
  473. EnableCoprocessors;
  474. InitFPU;
  475. allProcessors := {0}
  476. END InitProcessor;
  477. (** Shut system down. If reboot is TRUE, attempts to restart system. *)
  478. PROCEDURE Shutdown*(reboot: BOOLEAN);
  479. VAR i: LONGINT; procs: SET;
  480. BEGIN
  481. IF enableWatchdog THEN PrivateWatchdog.Stop END;
  482. StopTicks;
  483. Trace.String("Shutting down secondary CPUs... ");
  484. procs := allProcessors;
  485. FOR i := 0 TO numberOfProcessors - 1 DO
  486. IF (i # ID()) & (i IN allProcessors) THEN
  487. EXCL(allProcessors, i)
  488. END
  489. END;
  490. FOR i := 0 TO numberOfProcessors - 1 DO
  491. IF (i #ID()) & (i IN procs) THEN
  492. REPEAT UNTIL i IN allProcessors
  493. END
  494. END;
  495. Trace.StringLn("done");
  496. IF reboot THEN
  497. Platform.slcr.SLCR_UNLOCK := Platform.SlcrUnlockKey;
  498. Platform.slcr.PSS_RST_CTRL := 1
  499. ELSE
  500. EndInterrupts;
  501. LOOP
  502. CODE
  503. WFE
  504. END;
  505. END
  506. END;
  507. END Shutdown;
  508. (** Shut down secondary processors *)
  509. PROCEDURE ShutdownSecondary;
  510. BEGIN
  511. IF enableWatchdog THEN PrivateWatchdog.Stop END;
  512. INCL(allProcessors, ID());
  513. LOOP
  514. CODE
  515. WFE
  516. END
  517. END
  518. END ShutdownSecondary;
  519. (** Cleans the whole DCache. Taken from Minos *)
  520. PROCEDURE CleanDCache *;
  521. CONST
  522. L2CCBBase = 0F8F02000H;
  523. L2COfs = L2CCBBase + 7BCH;
  524. L2CSync = L2CCBBase + 730H;
  525. CODE
  526. ; Clean all sets of all ways of L1 cache
  527. MOV R0, #0
  528. WayLoop:
  529. CMP R0, #4
  530. BEQ EndWayLoop
  531. LSL R4, R0, #30
  532. MOV R1, #0
  533. SetLoop:
  534. CMP R1, #256
  535. BEQ EndSetLoop
  536. LSL R3, R1, #5
  537. ORR R3, R4, R3
  538. MCR P15, 0, R3, C7, C10, 2
  539. ADD R1, R1, #1
  540. B SetLoop
  541. EndSetLoop:
  542. ADD R0, R0, #1
  543. B WayLoop
  544. EndWayLoop:
  545. DSB
  546. ; Invalidate all L2 ways
  547. LDR R0, [PC, #L2COfsAdr - $ - 8] ; R0 := reg7_inv_way address
  548. MOV R1, #0FH ; R1 := 0FH => invalidate all ways
  549. STR R1, [R0, #0] ; reg7_inv_way <- R1
  550. Sync:
  551. DSB
  552. LDR R0, [PC, #L2CSyncAdr - $ - 8] ; R0 := L2 cache sync register address
  553. MOV R1, #1
  554. STR R1, [R0, #0] ; [R0] := 1
  555. SyncLoop: ; repeat
  556. LDR R1, [R0, #0] ; R1 := l2 cache syc state
  557. CMP R1, #0
  558. BEQ Exit ; until R1 = 0
  559. B SyncLoop
  560. L2COfsAdr: d32 L2COfs
  561. L2CSyncAdr: d32 L2CSync
  562. Exit:
  563. END CleanDCache;
  564. PROCEDURE FlushDCacheRange*(adr:ADDRESS; len: SIZE);
  565. CONST
  566. cacheline = 32;
  567. L2CCBBase = 0F8F02000H; (*XPS_L2CC_BASEADDR*)
  568. L2CCCacheSync = L2CCBBase + 00730H; (* Cache Sync *)(*XPS_L2CC_CACHE_SYNC_OFFSET *)
  569. L2CCCacheInvClnPAOfs= 007F0H; (* Cache Clean by PA *)(*XPS_L2CC_CACHE_INV_CLN_PA_OFFSET*)
  570. L2CCOffset = L2CCBBase + L2CCCacheInvClnPAOfs;
  571. BEGIN
  572. IF ~enableCaching OR (len = 0) THEN RETURN END;
  573. IF len MOD cacheline # 0 THEN INC(len, cacheline - len MOD cacheline) END;
  574. IF adr MOD cacheline # 0 THEN DEC(adr, len MOD cacheline) END;
  575. CODE
  576. LDR R0, [FP, #adr] ; R0 := adr
  577. LDR R1, [FP, #len] ; R1 := len
  578. LDR R2, [PC, #Cacheline - 8 - $] ; R2 := cacheline
  579. SUB R3, R2, #1 ; R3 := cacheline - 1
  580. AND R3, R0, R3 ; R3 := adr MOD cacheline
  581. ADD R1, R1, R0
  582. SUB R0, R0, R3 ; R0 := adr - adr MOD cacheline
  583. ;ADD R1, R1, R3 ; R1 := len + adr MOD cacheline
  584. MOV R3, #0
  585. MCR P15, 2, R3, C0, C0, 0 ; Select cache level 1
  586. LDR R4, [PC, #L2COfs - 8 - $] ; R4 := L2 cache flush address register address
  587. Loop:
  588. CMP R0, R1 ; while R0 < R1
  589. BEQ Sync
  590. BHI Sync
  591. MCR P15, 0, R0, C7, C14, 1 ; Clean Cache Level 1 By MVA (R0)
  592. STR R0, [R4, #0] ; Clean Cache Level 2 By PA (R0)
  593. DSB
  594. ADD R0, R0, R2 ; R0 := R0 + cacheline
  595. B Loop ; end
  596. Sync:
  597. DSB
  598. LDR R0, [PC, #L2CSync - 8 - $] ; R0 := L2 cache sync register address
  599. ;MOV R1, #1
  600. ;STR R1, [R0, #0] ; [R0] := 1
  601. SyncLoop: ; repeat
  602. LDR R1, [R0, #0] ; R1 := l2 cache syc state
  603. CMP R1, #0
  604. BEQ Exit ; until R1 = 0
  605. B SyncLoop
  606. Cacheline: d32 cacheline
  607. L2COfs: d32 L2CCOffset
  608. L2CSync: d32 L2CCCacheSync
  609. Exit:
  610. END;
  611. END FlushDCacheRange;
  612. PROCEDURE FlushDCachePhysRange * (adr: ADDRESS; len: LONGINT; CONST ranges: ARRAY OF Range; numRanges: LONGINT);
  613. CONST
  614. cacheline = 32;
  615. L2CCBBase = 0F8F02000H; (*XPS_L2CC_BASEADDR*)
  616. L2CCCacheSync = L2CCBBase + 00730H; (* Cache Sync *)(*XPS_L2CC_CACHE_SYNC_OFFSET *)
  617. L2CCCacheInvClnPAOfs= 007F0H; (* Cache Clean by PA *)(*XPS_L2CC_CACHE_INV_CLN_PA_OFFSET*)
  618. L2CCOffset = L2CCBBase + L2CCCacheInvClnPAOfs;
  619. VAR
  620. cur, end: ADDRESS;
  621. r: LONGINT;
  622. BEGIN
  623. IF ~enableCaching & (len # 0) THEN
  624. IF len MOD cacheline # 0 THEN INC(len, cacheline - len MOD cacheline) END;
  625. (* Select cache L0 Data cache in CSSR *)
  626. CODE
  627. mov r0, #0
  628. mcr p15, 2, r0, c0, c0, 0 (* mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);*)
  629. END;
  630. (* Flush all cache lines in the memory region *)
  631. FOR r := 0 TO numRanges - 1 DO
  632. cur := ranges[r].adr;
  633. end := cur + ranges[r].size;
  634. WHILE (cur < end) DO
  635. (* Flush L1 Data cache line with virtual address *)
  636. CODE
  637. ldr r3, [fp, #adr] (* load*)
  638. mcr p15, 0, r3, c7, c14, 1; MCR XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (adr));
  639. END;
  640. (* Flush L2 cache line with physical address *)
  641. SYSTEM.PUT(L2CCOffset, cur);
  642. cur := cur + cacheline;
  643. adr := adr + cacheline
  644. END
  645. END
  646. END;
  647. (* Wait for L1 and L2 flush to complete *)
  648. CODE
  649. DSB
  650. END;
  651. SYSTEM.PUT32(L2CCCacheSync, 1);
  652. REPEAT UNTIL SYSTEM.GET32(L2CCCacheSync) = 0;
  653. END FlushDCachePhysRange;
  654. PROCEDURE InvalidateDCacheRange*(adr: ADDRESS; len: SIZE);
  655. CONST
  656. cacheline = 32;
  657. L2CCBBase = 0F8F02000H; (*XPS_L2CC_BASEADDR*)
  658. L2CCCacheSync = L2CCBBase + 00730H; (* Cache Sync *)(*XPS_L2CC_CACHE_SYNC_OFFSET *)
  659. L2CCCacheInvPAOfs = 00770H; (* Cache Invalidate by PA *)(*XPS_L2CC_CACHE_INV_CLN_PA_OFFSET*)
  660. L2CCOffset = L2CCBBase + L2CCCacheInvPAOfs;
  661. BEGIN
  662. IF ~enableCaching OR (len = 0) THEN RETURN END;
  663. IF len MOD cacheline # 0 THEN INC(len, cacheline - len MOD cacheline) END;
  664. IF adr MOD cacheline # 0 THEN DEC(adr, len MOD cacheline) END;
  665. CODE
  666. LDR R0, [FP, #adr] ; R0 := adr
  667. LDR R1, [FP, #len] ; R1 := len
  668. LDR R2, [PC, #Cacheline - 8 - $] ; R2 := cacheline
  669. SUB R3, R2, #1 ; R3 := cacheline - 1
  670. AND R3, R0, R3 ; R3 := adr MOD cacheline
  671. SUB R0, R0, R3 ; R0 := adr - adr MOD cacheline
  672. ADD R1, R1, R3 ; R1 := len + adr MOD cacheline
  673. MOV R5, #0 ; R5 := 0 (counter value)
  674. MOV R3, #0
  675. MCR P15, 2, R3, C0, C0, 0 ; Select cache level 1
  676. LDR R4, [PC, #L2COfs - 8 - $] ; R4 := L2 cache invalidate address register address
  677. Loop:
  678. CMP R5, R1 ; while R5 < R1
  679. BEQ Sync
  680. BHI Sync
  681. STR R0, [R4, #0] ; Invalidate Cache Level 2 By PA (R0)
  682. DSB
  683. MCR P15, 0, R0, C7, C6, 1 ; Invalidate Cache Level 1 By MVA (R0)
  684. ADD R0, R0, R2 ; R0 := R0 + cacheline
  685. ADD R5, R5, R2
  686. B Loop ; end
  687. Sync:
  688. DSB
  689. LDR R0, [PC, #L2CSync - 8 - $] ; R0 := L2 cache sync register address
  690. MOV R1, #1
  691. STR R1, [R0, #0] ; [R0] := 1
  692. SyncLoop: ; repeat
  693. LDR R1, [R0, #0] ; R1 := l2 cache syc state
  694. CMP R1, #0
  695. BEQ Exit ; until R1 = 0
  696. B SyncLoop
  697. Cacheline: d32 cacheline
  698. L2COfs: d32 L2CCOffset
  699. L2CSync: d32 L2CCCacheSync
  700. Exit:
  701. END;
  702. END InvalidateDCacheRange;
  703. (**
  704. Disable data cache for the memory range [adr, adr + len). Repeated cache disabling is recorded. A maximum of 127 successive disabling is supported.
  705. Cache disabling is allowed for heap and stack memory ranges only.
  706. *)
  707. PROCEDURE DisableDCacheRange * (adr: ADDRESS; len: LONGINT);
  708. VAR
  709. range: ARRAY 1 OF Range;
  710. end: ADDRESS;
  711. ofs, entry: LONGINT;
  712. BEGIN
  713. (* Changing cache status allowed for heap and stack only. *)
  714. ASSERT(((memHeapStart <= adr) & (adr + len <= memHeapStop)) OR ((memStackStart <= adr) & (adr + len <= memStackStop)));
  715. end := adr + len;
  716. Acquire(Memory);
  717. WHILE adr < end DO
  718. entry := GetFirstLevelEntry(adr - adr MOD M);
  719. CASE entry MOD 4 OF
  720. 0:
  721. (* Page is not allocated: generate a data abort trap *)
  722. Release(Memory);
  723. ASSERT(entry MOD 4 # 0);
  724. |flSection:
  725. (* 1 MB heap page *)
  726. IF enableCaching THEN
  727. (* index in cache reference count array *)
  728. ofs := (adr - memHeapStart) DIV M;
  729. IF cacheRefs[ofs] = 0 THEN
  730. (* First disabling: disable cache *)
  731. range[0].adr := adr - adr MOD M;
  732. range[0].size := M;
  733. SetFirstLevelEntry(adr - adr MOD M, adr - adr MOD M(*SHRL(entry, 20)*), SrwUrw, Shareable + B, flSection);
  734. InvalidateTLBEntry(adr);
  735. FlushDCachePhysRange(adr - adr MOD M, M, range, 1);
  736. cacheRefs[ofs] := 1
  737. ELSE
  738. (* Increase reference count and avoid overflows. *)
  739. ASSERT(cacheRefs[ofs] < 127);
  740. INC(cacheRefs[ofs])
  741. END
  742. END;
  743. INC(adr, M);
  744. DEC(adr, adr MOD M);
  745. |flCoarse:
  746. (* Second level pt *)
  747. entry := GetSecondLevelEntry(adr - adr MOD PS);
  748. CASE entry MOD 4 OF
  749. 0:
  750. (* Page is not allocated: generate a data abort trap *)
  751. Release(Memory);
  752. ASSERT(entry MOD 4 # 0);
  753. |slSmall:
  754. (* 4 kB stack page *)
  755. IF enableCaching THEN
  756. (* Index in cache reference count array *)
  757. ofs := (adr - memStackStart) DIV PS + sysCacheStackOfs;
  758. IF cacheRefs[ofs] = 0 THEN
  759. (* First disabling: disable cache *)
  760. range[0].adr := adr - adr MOD PS;
  761. range[0].size := PS;
  762. SetSecondLevelEntry(adr - adr MOD PS, SHRL(entry, PSlog2), FullAccess + 400H + B);
  763. InvalidateTLBEntry(adr);
  764. FlushDCachePhysRange(adr - adr MOD PS, PS, range, 1);
  765. cacheRefs[ofs] := 1
  766. ELSE
  767. (* Increase reference count and avoid overflows *)
  768. ASSERT(cacheRefs[ofs] < 127);
  769. INC(cacheRefs[ofs])
  770. END
  771. END;
  772. INC(adr, PS);
  773. DEC(adr, adr MOD PS)
  774. END;
  775. END;
  776. END;
  777. Release(Memory)
  778. END DisableDCacheRange;
  779. (**
  780. Enable data cache for the memory range [adr, adr + len).
  781. The memory range must have been previously disabled.
  782. It is the responsibility of client software to re-enable cache for the regions that it disabled.
  783. *)
  784. PROCEDURE EnableDCacheRange * (adr: ADDRESS; len: LONGINT);
  785. VAR
  786. end: ADDRESS;
  787. ofs, entry: LONGINT;
  788. BEGIN
  789. (* Changing cache status allowed for heap and stack only. *)
  790. ASSERT(((memHeapStart <= adr) & (adr < memHeapStop)) OR ((memStackStart <= adr) & (adr < memStackStop)));
  791. (*InvalidateDCacheRange(adr - (adr MOD M), len + M - (adr + len) MOD M + adr MOD M);*)
  792. Acquire(Memory);
  793. end := adr + len;
  794. WHILE adr < end DO
  795. entry := GetFirstLevelEntry(SHRL(adr, LogM));
  796. CASE entry MOD 4 OF
  797. 0:
  798. (* page not mapped: generate trap *)
  799. Release(Memory);
  800. ASSERT(entry MOD 4 # 0);
  801. |flSection:
  802. (* 1 MB heap page *)
  803. IF enableCaching THEN
  804. ofs := (adr - memHeapStart) DIV M;
  805. ASSERT(cacheRefs[ofs] > 0);
  806. IF cacheRefs[ofs] = 1 THEN
  807. SetFirstLevelEntry(SHRL(adr, LogM), SHRL(entry, LogM), SrwUrw, Cacheable + Shareable, entry MOD 4);
  808. InvalidateTLBEntry(adr);
  809. cacheRefs[ofs] := 0
  810. ELSE
  811. DEC(cacheRefs[ofs])
  812. END
  813. END;
  814. INC(adr, M);
  815. DEC(adr, adr MOD M)
  816. |flCoarse:
  817. (* Second-level pt entry *)
  818. entry := GetSecondLevelEntry(SHRL(adr, PSlog2));
  819. CASE entry MOD 4 OF
  820. 0:
  821. (* Page not mapped: generate trap *)
  822. Release(Memory);
  823. ASSERT(entry MOD 4 # 0);
  824. |slSmall:
  825. (* 4 kB stack page *)
  826. IF enableCaching THEN
  827. ofs := (adr - memStackStart) DIV PS + sysCacheStackOfs;
  828. ASSERT(cacheRefs[ofs] > 0);
  829. IF cacheRefs[ofs] = 1 THEN
  830. SetSecondLevelEntry(SHRL(adr, PSlog2), SHRL(entry, PSlog2), FullAccess + CB);
  831. InvalidateTLBEntry(SHRL(adr, PSlog2));
  832. cacheRefs[ofs] := 0
  833. ELSE
  834. DEC(cacheRefs[ofs])
  835. END
  836. END;
  837. INC(adr, PS);
  838. DEC(adr, adr MOD PS)
  839. END;
  840. END;
  841. END;
  842. Release(Memory)
  843. END EnableDCacheRange;
  844. (* InvalidateICache - invalidates the ICache. Works only in a priviledged mode. *)
  845. PROCEDURE InvalidateICache*;
  846. CODE
  847. MCR p15, 0, R0, c7, c5, 0 ; invalidate ICache & BTB
  848. ISB
  849. ; cpwait
  850. MRC p15, 0, R0, c2, c0, 0
  851. MOV R0, R0
  852. SUB PC, PC, #4
  853. MOV R0, R0
  854. MOV R0, R0
  855. MOV R0, R0
  856. MOV R0, R0
  857. END InvalidateICache;
  858. (* InvalidateTLB: data and instruction TLBs - Works only in a priviledged mode *)
  859. PROCEDURE - InvalidateTLB *;
  860. CODE
  861. MCR p15, 0, R0, c8, c3, 0 ; invalidate I+D TLB
  862. ISB
  863. ; cpwait
  864. MRC p15, 0, R0, c2, c0, 0
  865. MOV R0, R0
  866. SUB PC, PC, #4
  867. MOV R0, R0
  868. MOV R0, R0
  869. MOV R0, R0
  870. MOV R0, R0
  871. DSB
  872. END InvalidateTLB;
  873. (* InvalidateTLBEntry - invalidates the TLB for a given virtual address. Works only in a priviledged mode *)
  874. PROCEDURE - InvalidateTLBEntry(address: LONGINT);
  875. CODE
  876. LDR R0, [SP, #address]
  877. ADD SP, SP, #4
  878. ;MCR p15, 0, R0, c8, c6, 1 ; invalidate address
  879. MCR p15, 0, R0, c8, c3, 1 ; invalidate address
  880. ISB
  881. ; cpwait
  882. MRC p15, 0, R0, c2, c0, 0
  883. MOV R0, R0
  884. SUB PC, PC, #4
  885. MOV R0, R0
  886. MOV R0, R0
  887. MOV R0, R0
  888. MOV R0, R0
  889. DSB
  890. END InvalidateTLBEntry;
  891. (* GetControlRegister - returns the control register of coprocessor 15 *)
  892. PROCEDURE -GetControlRegister(): SET;
  893. CODE
  894. MRC p15, 0, R0, c1, c0, 0
  895. END GetControlRegister;
  896. (* SetControlRegister - sets the control register of coprocessor 15. Works only in a priviledged mode *)
  897. PROCEDURE -SetControlRegister(cr: SET);
  898. CODE
  899. LDR R0, [SP, #cr]
  900. ADD SP, SP, #4 ; remove parameter
  901. MCR p15, 0, R0, c1, c0, 0
  902. ISB
  903. ; cpwait
  904. MRC p15, 0, R0, c2, c0, 0
  905. MOV R0, R0
  906. SUB PC, PC, #4
  907. MOV R0, R0
  908. MOV R0, R0
  909. MOV R0, R0
  910. MOV R0, R0
  911. END SetControlRegister;
  912. (* DrainWriteBuffer - drains the write buffer. Works only in a priviledged mode *)
  913. PROCEDURE DrainWriteBuffer*;
  914. CODE
  915. MCR p15, 0, R0, c7, c10, 4 ; drain WB
  916. ISB
  917. ; cpwait
  918. MRC p15, 0, R0, c2, c0, 0
  919. MOV R0, R0
  920. SUB PC, PC, #4
  921. MOV R0, R0
  922. MOV R0, R0
  923. MOV R0, R0
  924. MOV R0, R0
  925. END DrainWriteBuffer;
  926. PROCEDURE -CurrentPC*(): ADDRESS;
  927. CODE
  928. MOV R0, PC
  929. END CurrentPC;
  930. PROCEDURE GetTimer*(): HUGEINT;
  931. VAR t: ARRAY 2 OF LONGINT;
  932. BEGIN
  933. REPEAT
  934. t[1] := SYSTEM.GET32(Platform.GlobalTimerCounterRegister1);
  935. t[0] := SYSTEM.GET32(Platform.GlobalTimerCounterRegister0);
  936. UNTIL t[1] = SYSTEM.GET32(Platform.GlobalTimerCounterRegister1);
  937. RETURN SYSTEM.VAL(HUGEINT,t);
  938. END GetTimer;
  939. (* ===== Multiprocessor booting ===== *)
  940. (** Initializes non-booting processors *)
  941. PROCEDURE InitProcessors*;
  942. VAR
  943. i: LONGINT;
  944. val: ARRAY 8 OF CHAR;
  945. BEGIN
  946. GetConfig("TraceCpu", val);
  947. traceCpus := val = "1";
  948. InstallHandler(HandleUPTimer, PrivateTimerIRQ);
  949. InstallHandler(TimerInterruptHandler, PrivateTimerIRQ);
  950. InitTicks;
  951. InitWatchdog;
  952. CleanDCache;
  953. DrainWriteBuffer;
  954. FOR i := 1 TO numProcessors - 1 DO
  955. StartProcessor(i, BootMP);
  956. END;
  957. END InitProcessors;
  958. PROCEDURE StartAll*;
  959. BEGIN
  960. END StartAll;
  961. (* Send event instruction *)
  962. PROCEDURE -Sev;
  963. CODE
  964. SEV
  965. END Sev;
  966. (** Start core id on procedure p. *)
  967. PROCEDURE StartProcessor(id: LONGINT; p: PROCEDURE);
  968. VAR
  969. time, ticks0: LONGINT;
  970. started: BOOLEAN;
  971. sevCount: SIZE;
  972. BEGIN
  973. IF traceCpus THEN
  974. Acquire(TraceOutput);
  975. Trace.String("Starting CPU");
  976. Trace.Int(id, 0);
  977. Trace.String(" on address ");
  978. Trace.Address(SYSTEM.VAL(ADDRESS, p));
  979. Trace.Ln;
  980. Release(TraceOutput)
  981. END;
  982. Initializer.secondaryProcId := id;
  983. Initializer.secondaryBootProc := SYSTEM.VAL(ADDRESS, p);
  984. FlushDCacheRange(ADDRESSOF(Initializer.secondaryProcId), 4);
  985. FlushDCacheRange(ADDRESSOF(Initializer.secondaryBootProc), 4);
  986. (* wake up the other cores *)
  987. Sev;
  988. time := ticks + 1000;
  989. sevCount := 0;
  990. ticks0 := ticks;
  991. REPEAT
  992. started := id IN allProcessors;
  993. (*! a workaround for rare but nevertheless occurring case when the other CPU does not wake up *)
  994. IF ~started & (ticks - ticks0 > 1) THEN
  995. Sev;
  996. ticks0 := ticks;
  997. INC(sevCount);
  998. END;
  999. UNTIL started OR (time <= ticks);
  1000. IF traceCpus THEN
  1001. Acquire(TraceOutput);
  1002. Trace.String("SEV call count="); Trace.Int(sevCount,0); Trace.Ln;
  1003. Release(TraceOutput);
  1004. END;
  1005. IF id IN allProcessors THEN
  1006. IF traceCpus THEN
  1007. Acquire(TraceOutput);
  1008. Trace.String("Confirm: CPU");
  1009. Trace.Int(id, 0);
  1010. Trace.StringLn(" started");
  1011. Release(TraceOutput)
  1012. END
  1013. ELSE
  1014. Acquire(TraceOutput);
  1015. Trace.String("WARNING: Could not start CPU");
  1016. Trace.Int(id, 0);
  1017. Trace.Ln;
  1018. Release(TraceOutput)
  1019. END
  1020. END StartProcessor;
  1021. (** Init Memory for non-booting processors.
  1022. This enables MMU and copies the mapping of CPU0
  1023. *)
  1024. PROCEDURE InitMPMemory;
  1025. VAR
  1026. tbFlags: LONGINT;
  1027. BEGIN
  1028. IF enableCaching THEN
  1029. tbFlags := 7BH
  1030. ELSE
  1031. tbFlags := 0
  1032. END;
  1033. EnableMM(sysFirstLvlPtStart, tbFlags, 2000H + 1007H);
  1034. END InitMPMemory;
  1035. (** Init code fo a non-booting processor. No local variable allowed. *)
  1036. PROCEDURE {NOPAF} BootMP;
  1037. BEGIN
  1038. (* Setup stack *)
  1039. SYSTEM.LDPSR( 0, Platform.IRQMode + Platform.FIQDisabled + Platform.IRQDisabled );
  1040. SYSTEM.SETSP(sysIntStackStart + 1000H * 5);
  1041. SYSTEM.LDPSR( 0, Platform.UndefMode + Platform.FIQDisabled + Platform.IRQDisabled );
  1042. SYSTEM.SETSP(sysIntStackStart + 1000H * 6);
  1043. SYSTEM.LDPSR( 0, Platform.AbortMode + Platform.FIQDisabled + Platform.IRQDisabled );
  1044. SYSTEM.SETSP(sysIntStackStart + 1000H * 7);
  1045. SYSTEM.LDPSR( 0, Platform.SVCMode + Platform.FIQDisabled + Platform.IRQDisabled ); (* Disable interrupts, init SP, FP *)
  1046. SYSTEM.SETSP(sysIntStackStart + 1000H * 8);
  1047. SYSTEM.LDPSR( 0, Platform.SystemMode + Platform.FIQDisabled + Platform.IRQDisabled ); (* Disable interrupts, init SP, FP *)
  1048. SYSTEM.SETSP(sysIntStackStart + 1000H * 8);
  1049. Initializer.InvalidateDCache;
  1050. SetSmpMode;
  1051. EnableL1Cache;
  1052. EnableCoprocessors;
  1053. InitFPU;
  1054. InvalidateICache;
  1055. Initializer.InvalidateDCache;
  1056. InitMPMemory;
  1057. (*InvalidateDCacheRange(4096, SYSTEM.VAL(ADDRESS, LastAddress));*)
  1058. (*InvalidateDCacheRange(memSysHighStart, memSysHighStop - memSysHighStart);*)
  1059. (*CODE
  1060. DSB
  1061. END;*)
  1062. InitInterrupts;
  1063. EnableIRQ(PrivateTimerIRQ);
  1064. EnableInterrupts;
  1065. IF traceCpus THEN
  1066. Acquire(TraceOutput);
  1067. Trace.String("CPU "); Trace.Int(ID(), 0); Trace.StringLn(" started.");
  1068. Release(TraceOutput)
  1069. END;
  1070. Acquire(Processors);
  1071. INCL(allProcessors, ID());
  1072. Release(Processors);
  1073. InitTicks;
  1074. InitWatchdog;
  1075. start;
  1076. HALT(400)
  1077. END BootMP;
  1078. PROCEDURE KernelCallHLT*;
  1079. BEGIN
  1080. END KernelCallHLT;
  1081. (* function returning the number of processors that are available to Aos *)
  1082. PROCEDURE NumberOfProcessors*( ): LONGINT;
  1083. BEGIN
  1084. RETURN numberOfProcessors
  1085. END NumberOfProcessors;
  1086. (*! non portable code, for native Aos only *)
  1087. PROCEDURE SetNumberOfProcessors*(num: LONGINT);
  1088. BEGIN
  1089. numberOfProcessors := num;
  1090. END SetNumberOfProcessors;
  1091. (* ===== Context Switching ===== *)
  1092. (** Pushes state of the processor on the stack. Used in task-switching.
  1093. Does not exactly represent the layout of State. Pushed data is always used by JumpState.
  1094. *)
  1095. PROCEDURE -PushState*(CONST state: State);
  1096. CODE
  1097. LDR R0, [SP, #0] ; R0 <- address of state
  1098. ADD SP, SP, #8
  1099. LDR R1, [R0, #60] ; push PC
  1100. STR R1, [SP, #-4]!
  1101. LDR R1, [R0, #56] ; push LR
  1102. STR R1, [SP, #-4]!
  1103. LDR R1, [R0, #48] ; push FP
  1104. STR R1, [SP, #-4]!
  1105. LDR R1, [R0, #44] ; push R11
  1106. STR R1, [SP, #-4]!
  1107. LDR R1, [R0, #40] ; push R10
  1108. STR R1, [SP, #-4]!
  1109. LDR R1, [R0, #36] ; push R9
  1110. STR R1, [SP, #-4]!
  1111. LDR R1, [R0, #32] ; push R8
  1112. STR R1, [SP, #-4]!
  1113. LDR R1, [R0, #28] ; push R7
  1114. STR R1, [SP, #-4]!
  1115. LDR R1, [R0, #24] ; push R6
  1116. STR R1, [SP, #-4]!
  1117. LDR R1, [R0, #20] ; push R5
  1118. STR R1, [SP, #-4]!
  1119. LDR R1, [R0, #16] ; push R4
  1120. STR R1, [SP, #-4]!
  1121. LDR R1, [R0, #12] ; push R3
  1122. STR R1, [SP, #-4]!
  1123. LDR R1, [R0, #8] ; push R2
  1124. STR R1, [SP, #-4]!
  1125. LDR R1, [R0, #4] ; push R1
  1126. STR R1, [SP, #-4]!
  1127. LDR R1, [R0, #0] ; push R0
  1128. STR R1, [SP, #-4]!
  1129. LDR R1, [R0, #64] ; push SPSR
  1130. STR R1, [SP, #-4]!
  1131. END PushState;
  1132. (** Pops a processor state from the stack and restore it. Including jumping to the PC. *)
  1133. PROCEDURE -JumpState*;
  1134. CODE
  1135. ; Load PSR
  1136. LDR R0, [SP], #4
  1137. MSR CPSR_cxsf, R0 ; set CPSR
  1138. ; Load registers, including branch
  1139. LDMIA SP!, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, LR}
  1140. LDR PC, [SP], #4
  1141. END JumpState;
  1142. PROCEDURE CopyState*(CONST from: State; VAR to: State);
  1143. BEGIN
  1144. to.R[0] := from.R[0];
  1145. to.R[1] := from.R[1];
  1146. to.R[2] := from.R[2];
  1147. to.R[3] := from.R[3];
  1148. to.R[4] := from.R[4];
  1149. to.R[5] := from.R[5];
  1150. to.R[6] := from.R[6];
  1151. to.R[7] := from.R[7];
  1152. to.R[8] := from.R[8];
  1153. to.R[9] := from.R[9];
  1154. to.R[10] := from.R[10];
  1155. to.R[11] := from.R[11];
  1156. to.BP := from.BP;
  1157. to.SP := from.SP;
  1158. to.LR := from.LR;
  1159. to.PC := from.PC;
  1160. to.PSR := from.PSR;
  1161. END CopyState;
  1162. PROCEDURE -JumpToUserLevel*(userFP: ADDRESS);
  1163. CODE
  1164. ; this is an inlined procedure, so the 'userFP' parameter lies on top of the stack
  1165. LDR FP, [SP, #userFP] ; pop FP (FP is not a banked register)
  1166. ADD SP, SP, #4
  1167. MRS R0, CPSR ; get current PSR
  1168. BIC R0, R0, #1FH ; clear bits 4:0
  1169. ORR R0, R0, #1FH ; CPU mode = System
  1170. MSR CPSR_c, R0 ; switch mode
  1171. MOV SP, FP
  1172. LDMIA SP! , {FP, LR}
  1173. BX LR
  1174. END JumpToUserLevel;
  1175. PROCEDURE UpdateState*;
  1176. BEGIN
  1177. END UpdateState;
  1178. (** Save complete VFP/NEON state *)
  1179. PROCEDURE -FPUSaveFull*(VAR state: NEONState);
  1180. CODE
  1181. LDR R0, [SP, #state]
  1182. ADD SP, SP, #8
  1183. VST1 D0, R0
  1184. ADD R0, R0, #8
  1185. VST1 D1, R0
  1186. ADD R0, R0, #8
  1187. VST1 D2, R0
  1188. ADD R0, R0, #8
  1189. VST1 D3, R0
  1190. ADD R0, R0, #8
  1191. VST1 D4, R0
  1192. ADD R0, R0, #8
  1193. VST1 D5, R0
  1194. ADD R0, R0, #8
  1195. VST1 D6, R0
  1196. ADD R0, R0, #8
  1197. VST1 D7, R0
  1198. ADD R0, R0, #8
  1199. VST1 D8, R0
  1200. ADD R0, R0, #8
  1201. VST1 D9, R0
  1202. ADD R0, R0, #8
  1203. VST1 D10, R0
  1204. ADD R0, R0, #8
  1205. VST1 D11, R0
  1206. ADD R0, R0, #8
  1207. VST1 D12, R0
  1208. ADD R0, R0, #8
  1209. VST1 D13, R0
  1210. ADD R0, R0, #8
  1211. VST1 D14, R0
  1212. ADD R0, R0, #8
  1213. VST1 D15, R0
  1214. ADD R0, R0, #8
  1215. VSTR D16, R0, #0
  1216. ADD R0, R0, #8
  1217. VSTR D17, R0, #0
  1218. ADD R0, R0, #8
  1219. VSTR D18, R0, #0
  1220. ADD R0, R0, #8
  1221. VSTR D19, R0, #0
  1222. ADD R0, R0, #8
  1223. VSTR D20, R0, #0
  1224. ADD R0, R0, #8
  1225. VSTR D21, R0, #0
  1226. ADD R0, R0, #8
  1227. VSTR D22, R0, #0
  1228. ADD R0, R0, #8
  1229. VSTR D23, R0, #0
  1230. ADD R0, R0, #8
  1231. VSTR D24, R0, #0
  1232. ADD R0, R0, #8
  1233. VSTR D25, R0, #0
  1234. ADD R0, R0, #8
  1235. VSTR D26, R0, #0
  1236. ADD R0, R0, #8
  1237. VSTR D27, R0, #0
  1238. ADD R0, R0, #8
  1239. VSTR D28, R0, #0
  1240. ADD R0, R0, #8
  1241. VSTR D29, R0, #0
  1242. ADD R0, R0, #8
  1243. VSTR D30, R0, #0
  1244. ADD R0, R0, #8
  1245. VSTR D31, R0, #0
  1246. ADD R0, R0, #8
  1247. VMRS R1, FPSCR
  1248. STR R1, [R0, #0]
  1249. ADD R0, R0, #4
  1250. VMRS R1, FPEXC
  1251. STR R1, [R0, #0]
  1252. END FPUSaveFull;
  1253. (** Save minimal VFP/NEON state *)
  1254. PROCEDURE -FPUSaveMin*(VAR state: NEONState);
  1255. CODE
  1256. ADD SP, SP, #4
  1257. END FPUSaveMin;
  1258. (** Restore full VFP/NEON state *)
  1259. PROCEDURE -FPURestoreFull*(VAR state: NEONState);
  1260. CODE
  1261. LDR R0, [SP, #state];
  1262. ADD SP, SP, #8
  1263. VLD1 D0, R0
  1264. ADD R0, R0, #8
  1265. VLD1 D1, R0
  1266. ADD R0, R0, #8
  1267. VLD1 D2, R0
  1268. ADD R0, R0, #8
  1269. VLD1 D3, R0
  1270. ADD R0, R0, #8
  1271. VLD1 D4, R0
  1272. ADD R0, R0, #8
  1273. VLD1 D5, R0
  1274. ADD R0, R0, #8
  1275. VLD1 D6, R0
  1276. ADD R0, R0, #8
  1277. VLD1 D7, R0
  1278. ADD R0, R0, #8
  1279. VLD1 D8, R0
  1280. ADD R0, R0, #8
  1281. VLD1 D9, R0
  1282. ADD R0, R0, #8
  1283. VLD1 D10, R0
  1284. ADD R0, R0, #8
  1285. VLD1 D11, R0
  1286. ADD R0, R0, #8
  1287. VLD1 D12, R0
  1288. ADD R0, R0, #8
  1289. VLD1 D13, R0
  1290. ADD R0, R0, #8
  1291. VLD1 D14, R0
  1292. ADD R0, R0, #8
  1293. VLD1 D15, R0
  1294. ADD R0, R0, #8
  1295. VLDR D16, R0, #0
  1296. ADD R0, R0, #8
  1297. VLDR D17, R0, #0
  1298. ADD R0, R0, #8
  1299. VLDR D18, R0, #0
  1300. ADD R0, R0, #8
  1301. VLDR D19, R0, #0
  1302. ADD R0, R0, #8
  1303. VLDR D20, R0, #0
  1304. ADD R0, R0, #8
  1305. VLDR D21, R0, #0
  1306. ADD R0, R0, #8
  1307. VLDR D22, R0, #0
  1308. ADD R0, R0, #8
  1309. VLDR D23, R0, #0
  1310. ADD R0, R0, #8
  1311. VLDR D24, R0, #0
  1312. ADD R0, R0, #8
  1313. VLDR D25, R0, #0
  1314. ADD R0, R0, #8
  1315. VLDR D26, R0, #0
  1316. ADD R0, R0, #8
  1317. VLDR D27, R0, #0
  1318. ADD R0, R0, #8
  1319. VLDR D28, R0, #0
  1320. ADD R0, R0, #8
  1321. VLDR D29, R0, #0
  1322. ADD R0, R0, #8
  1323. VLDR D30, R0, #0
  1324. ADD R0, R0, #8
  1325. VLDR D31, R0, #0
  1326. ADD R0, R0, #8
  1327. LDR R1, [R0, #0]
  1328. VMSR FPSCR, R1
  1329. ADD R0, R0, #4
  1330. LDR R1, [R0, #0]
  1331. VMSR FPEXC, R1
  1332. END FPURestoreFull;
  1333. (** Restore minimal VFP/NEON state *)
  1334. PROCEDURE -FPURestoreMin*(VAR state: NEONState);
  1335. CODE
  1336. ADD SP, SP, #4
  1337. END FPURestoreMin;
  1338. (* ===== Interrupts ===== *)
  1339. (* Taken from Minos/Kernel.Mos *)
  1340. PROCEDURE EnableInterrupts*;
  1341. VAR cpsr: LONGINT;
  1342. BEGIN
  1343. SYSTEM.STPSR(0, cpsr);
  1344. cpsr := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, cpsr) - {7(*, 8*)});
  1345. SYSTEM.LDPSR(0, cpsr);
  1346. (*SYSTEM.PUT32(Platform.ICDDCR, {EnableSecure, EnableNonSecure});*)
  1347. END EnableInterrupts;
  1348. (* Taken from Minos/Kernel.Mos *)
  1349. PROCEDURE DisableInterrupts*;
  1350. VAR cpsr: LONGINT;
  1351. BEGIN
  1352. SYSTEM.STPSR(0, cpsr);
  1353. cpsr := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, cpsr) + {7(*, 8*)});
  1354. SYSTEM.LDPSR( 0, cpsr);
  1355. (*SYSTEM.PUT32(Platform.ICDDCR, {});*)
  1356. END DisableInterrupts;
  1357. (** AreInterruptsEnabled - returns TRUE if interrupts are enabled at the current processor level, FALSE otherwise *)
  1358. PROCEDURE AreInterruptsEnabled*(): BOOLEAN;
  1359. CODE
  1360. MRS R0, CPSR ; move CPSR to R0
  1361. TST R0, #80H ; was IBit set ?
  1362. MOVEQ R0, #1 ; no, interrupts are enabled
  1363. MOVNE R0, #0 ; yep, interrupts are disabled
  1364. END AreInterruptsEnabled;
  1365. (* InstallDefaultInterrupts - installs default interrupt handlers *)
  1366. PROCEDURE InstallDefaultInterrupts;
  1367. VAR p: PROCEDURE; base: ADDRESS;
  1368. i, int: LONGINT;
  1369. BEGIN
  1370. base := 0;
  1371. (* Install all *Glue procedures. *)
  1372. p := undefGlue; SYSTEM.PUT32(base + Undef, SYSTEM.VAL(LONGINT, p));
  1373. p := SWIGlue; SYSTEM.PUT32(base + Swi, SYSTEM.VAL(LONGINT, p));
  1374. p := prefetchGlue; SYSTEM.PUT32(base + Prefetch, SYSTEM.VAL(LONGINT, p));
  1375. p := dataGlue; SYSTEM.PUT32(base + Data, SYSTEM.VAL(LONGINT, p));
  1376. p := DefaultIRQ; SYSTEM.PUT32(base + Irq, SYSTEM.VAL(LONGINT, p));
  1377. p := fiqGlue; SYSTEM.PUT32(base + Fiq, SYSTEM.VAL(LONGINT, p));
  1378. (* Install default exception handlers *)
  1379. InstallExceptionHandler(DefaultUndefined, Undef);
  1380. InstallExceptionHandler(DefaultSWI, Swi);
  1381. InstallExceptionHandler(DefaultPrefetchAbort, Prefetch);
  1382. InstallExceptionHandler(DefaultDataAbort, Data);
  1383. InstallExceptionHandler(DefaultFIQ, Fiq);
  1384. FOR int := 0 TO MaxIRQ DO
  1385. FOR i := 0 TO MaxIRQHandlers -1 DO
  1386. irqHandler[int, i] := NIL
  1387. END
  1388. END;
  1389. END InstallDefaultInterrupts;
  1390. (* DefaultUndef - default handler for undefined instruction exceptions *)
  1391. PROCEDURE DefaultUndefined (VAR state: State);
  1392. VAR
  1393. instn: LONGINT;
  1394. BEGIN
  1395. instn := SYSTEM.GET32(state.PC);
  1396. Acquire(TraceOutput);
  1397. Trace.Ln;
  1398. Trace.StringLn("Undefined Instruction Trap:");
  1399. Trace.String(" pc: "); Trace.Address(state.PC); Trace.Ln;
  1400. Trace.String(" instruction: "); Trace.Hex(instn, -8); Trace.Ln;
  1401. Trace.String(" CPU: "); Trace.Int(ID(), 0); Trace.Ln;
  1402. TraceState(state);
  1403. Trace.String("Kernel Halted");
  1404. Release(TraceOutput);
  1405. LOOP END
  1406. END DefaultUndefined;
  1407. (* DefaultSWI - default handler for software interrupts *)
  1408. PROCEDURE DefaultSWI (VAR state: State);
  1409. BEGIN
  1410. Acquire(TraceOutput);
  1411. Trace.Ln;
  1412. Trace.StringLn("Software Interrupt:");
  1413. Trace.String(" pc: "); Trace.Address(state.PC); Trace.Ln;
  1414. Trace.String(" number: "); Trace.Int(state.INT, -8); Trace.Ln;
  1415. Trace.String(" CPU: "); Trace.Int(ID(), 0); Trace.Ln;
  1416. TraceState(state);
  1417. Trace.Ln;
  1418. Trace.String("Kernel halted.");
  1419. Release(TraceOutput);
  1420. LOOP END
  1421. END DefaultSWI;
  1422. (* Instruction Prefetch abort *)
  1423. PROCEDURE DefaultPrefetchAbort (VAR state: State);
  1424. BEGIN
  1425. Acquire(TraceOutput);
  1426. Trace.String("Prefetch abort at location: "); Trace.Address(state.PC); Trace.Ln;
  1427. Trace.String(" CPU: "); Trace.Int(ID(), 0); Trace.Ln;
  1428. Trace.String(" FP: "); Trace.Address(state.BP); Trace.Ln;
  1429. Trace.String("SPSR: "); Trace.Hex(state.PSR, -8); Trace.Ln;
  1430. TraceState(state);
  1431. Trace.Ln;
  1432. Trace.StringLn("Kernel Halted");
  1433. Release(TraceOutput);
  1434. LOOP END;
  1435. END DefaultPrefetchAbort;
  1436. (* DefaultDataAbort - default handler for data abort exceptions *)
  1437. PROCEDURE DefaultDataAbort (VAR state: State);
  1438. VAR
  1439. faultAdr: ADDRESS;
  1440. faultStatus: LONGINT;
  1441. stack: Stack;
  1442. BEGIN
  1443. GetPageFault(faultAdr, faultStatus);
  1444. (*getStack(stack);
  1445. IF ~ExtendStack(stack, faultAdr) THEN*)
  1446. Acquire(TraceOutput);
  1447. IF faultAdr < 4 * k THEN
  1448. Trace.StringLn("NIL pointer exception");
  1449. Trace.String("pc: "); Trace.Address(state.PC); Trace.Ln
  1450. ELSE
  1451. Trace.StringLn("Data Abort Trap");
  1452. Trace.String("pc: "); Trace.Address(state.PC); Trace.Ln;
  1453. Trace.String("instn: "); Trace.Address(SYSTEM.GET32(state.PC)); Trace.Ln;
  1454. Trace.String("address: "); Trace.Address(faultAdr); Trace.Ln;
  1455. Trace.String("status: "); Trace.Address(faultStatus); Trace.Ln
  1456. END;
  1457. TraceState(state);
  1458. Trace.Ln; Trace.StringLn("Kernel Halted.");
  1459. Release(TraceOutput);
  1460. LOOP END
  1461. (*END*)
  1462. END DefaultDataAbort;
  1463. (* DefaultIRQ - default handler for IRQs *)
  1464. PROCEDURE DefaultIRQ;
  1465. BEGIN
  1466. Acquire(TraceOutput);
  1467. Trace.StringLn("(IRQ)");
  1468. Trace.String(" CPU: "); Trace.Address(ID()); Trace.Ln;
  1469. Trace.Ln; Trace.StringLn("Kernel Halted");
  1470. Release(TraceOutput);
  1471. LOOP END
  1472. END DefaultIRQ;
  1473. (* DefaultFIQ - default handler for fast interrupts *)
  1474. (*PROCEDURE DefaultFIQ;
  1475. BEGIN
  1476. Trace.StringLn("Fast IRQ Trap");
  1477. Trace.String(" CPU: "); Trace.Address(ID()); Trace.Ln;
  1478. Trace.String("Kernel halted.");
  1479. LOOP END
  1480. END DefaultFIQ;*)
  1481. PROCEDURE DefaultFIQ (VAR state: State);
  1482. BEGIN
  1483. Acquire(TraceOutput);
  1484. Trace.StringLn("Fast IRQ Trap");
  1485. Trace.String(" CPU: "); Trace.Address(ID()); Trace.Ln;
  1486. Trace.String("Kernel halted.");
  1487. Release(TraceOutput);
  1488. LOOP END
  1489. END DefaultFIQ;
  1490. PROCEDURE DummyISR(VAR state: State);
  1491. VAR i: LONGINT; icip : SET;
  1492. BEGIN
  1493. icip := SYSTEM.VAL(SET, SYSTEM.GET32((*IC +*) Platform.ICIP));
  1494. FOR i:=MinIRQ TO MaxIRQ DO
  1495. IF i IN icip THEN
  1496. state.INT := i;
  1497. dummyIRQHandler[state.INT].h(state);
  1498. END;
  1499. END;
  1500. END DummyISR;
  1501. (** EnableIRQ - enables a hardware interrupt (also done automatically by InstallHandler) *)
  1502. PROCEDURE InEnableIRQ(num: LONGINT);
  1503. BEGIN
  1504. ASSERT((MinIRQ <= num) & (num<= MaxIRQ));
  1505. (*IF TRUE OR (num = 53) THEN Trace.StringLn("Enable USB IRQ") END;*)
  1506. SYSTEM.PUT32(Platform.ICDISER + 4 * (num DIV 32) , {num MOD 32});
  1507. END InEnableIRQ;
  1508. PROCEDURE EnableIRQ*(int: LONGINT);
  1509. BEGIN
  1510. Acquire(Interrupts);
  1511. InEnableIRQ(int);
  1512. Release(Interrupts)
  1513. END EnableIRQ;
  1514. (** DisableIRQ - disables a hardware interrupt (also done automatically by RemoveHandler) *)
  1515. PROCEDURE InDisableIRQ(num: LONGINT);
  1516. BEGIN
  1517. ASSERT((MinIRQ <= num) & (num <= MaxIRQ));
  1518. (*IF TRUE OR (num = 53) THEN Trace.StringLn("Disable USB IRQ") END;*)
  1519. SYSTEM.PUT32(Platform.ICDICER + 4 * (num DIV 32) , {num MOD 32});
  1520. END InDisableIRQ;
  1521. PROCEDURE DisableIRQ*(int: LONGINT);
  1522. BEGIN
  1523. Acquire(Interrupts);
  1524. InDisableIRQ(int);
  1525. Release(Interrupts)
  1526. END DisableIRQ;
  1527. PROCEDURE IsIRQEnabled(int: LONGINT): BOOLEAN;
  1528. VAR
  1529. enabled: BOOLEAN;
  1530. reg: SET;
  1531. BEGIN
  1532. Acquire(Interrupts);
  1533. SYSTEM.GET(Platform.ICDISER + 4 * (int DIV 32) , reg);
  1534. enabled := (int MOD 32) IN reg;
  1535. Release(Interrupts);
  1536. RETURN enabled
  1537. END IsIRQEnabled;
  1538. (** InstallHandler - installs a interrupt handler & enable IRQ if necessary.
  1539. On entry to h interrupts are disabled and may be enabled with XXXXX. After handling the interrupt
  1540. the state of interrupts are restored. The acknowledgement of a hardware interrupt is done automatically.
  1541. IRQs are mapped from MinIRQ to MaxIRQ. *)
  1542. PROCEDURE InstallHandler*(h: Handler; int: LONGINT);
  1543. VAR
  1544. i: LONGINT;
  1545. BEGIN
  1546. (*NEW(n);*) (* outside locked region, to allow gc *)
  1547. i := 0;
  1548. WHILE irqHandler[int, i] # NIL DO
  1549. INC(i)
  1550. END;
  1551. Acquire(Interrupts);
  1552. (* IRQGlue may traverse list while it is being modified. *)
  1553. irqHandler[int, i] := h;
  1554. IF DummyTest THEN
  1555. irqHandler[int, i] := DummyISR;
  1556. dummyIRQHandler[int].h := h;
  1557. END;
  1558. IF (int >= MinIRQ) & (int <= MaxIRQ) THEN InEnableIRQ(int) END;
  1559. Release(Interrupts);
  1560. IF traceInterrupts THEN
  1561. Acquire(TraceOutput);
  1562. Trace.String("[Machine]InstallHandler: h = 0x"); Trace.Address(SYSTEM.VAL(LONGINT, h));
  1563. Trace.String("; int = "); Trace.Address(int);
  1564. Trace.String("; IRQMask = 0x"); Trace.Address(SYSTEM.VAL(LONGINT, IRQMask));
  1565. Trace.Ln;
  1566. Release(TraceOutput)
  1567. END
  1568. END InstallHandler;
  1569. PROCEDURE RemoveHandler * (h: Handler; int: LONGINT);
  1570. END RemoveHandler;
  1571. PROCEDURE InstallExceptionHandler * (h: Handler; e: LONGINT);
  1572. BEGIN
  1573. CASE e OF
  1574. Undef: undefHandler := h
  1575. |Swi: swiHandler := h
  1576. |Prefetch: prefetchHandler := h
  1577. |Data: dataHandler := h
  1578. |Fiq: fiqHandler := h
  1579. ELSE
  1580. Trace.String("Unknown exception offset: ");
  1581. Trace.Int(e, 0);
  1582. Trace.Ln;
  1583. HALT(99)
  1584. END
  1585. END InstallExceptionHandler;
  1586. (*
  1587. IRQGlue - every IRQ enters through this handler. It reads the IRR (Interrupt Request Register) of the PIC and calls the
  1588. appropriate handlers for each pending IRQ. A problem (which caused a nice debugging session of ~1 day...) is this
  1589. 'VAR state: State' parameter. Theoretically, a interrupt handler can change the values of this field to continue execution in
  1590. a different process, e.g. the scheduler works that way. This means that we can't call the handlers of every pending IRQ in
  1591. one loop - we must exit this procedure after each handled IRQ.
  1592. - routine has been changed so that all handlers of pending interrupts will be called
  1593. - using ICIP (interrupt Pending Register) instead of IRR (Interrupt Request Register)
  1594. - after handler call we don't turn interrupts off explicitly
  1595. *)
  1596. PROCEDURE {NOPAF} IRQGlue;
  1597. CODE
  1598. CLREX
  1599. SUB SP, SP, #72 ; Room for the State record
  1600. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1601. MOV R0, R0
  1602. ADD SP, SP, #60
  1603. SUB R0, LR, #4 ; return address = LR-4
  1604. STR R0, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1605. MRS R0, SPSR ; get saved PSR
  1606. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1607. SUB SP, SP, #68
  1608. MOV R11, SP
  1609. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1610. STR R5, [SP, #-4]! ; push value (type tag)
  1611. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1612. BL IRQCaller
  1613. LDR R11, [SP], #4
  1614. ADD SP, SP, #4
  1615. ADD SP, SP, #72 ; adjust SP & remove PAF
  1616. LDR R0, [R11, #64] ; load 'State.PSR'
  1617. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1618. LDR R0, [R11, #60] ; load 'State.PC'...
  1619. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1620. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1621. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1622. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1623. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1624. LDR R11, [R11, #44]
  1625. MOVS PC, LR ; SPSR -> CPSR & return
  1626. ; Data section
  1627. state: d32 stateTag ; address of stateTag
  1628. END IRQGlue;
  1629. (** Calls all handlers for all pending IRQs.
  1630. Is called by IRQGlue.
  1631. *)
  1632. PROCEDURE IRQCaller(VAR state: State);
  1633. VAR i, reg, irq, ack, count: LONGINT; handler: Handler; icip: SET;
  1634. BEGIN
  1635. ack := SYSTEM.GET32(Platform.ICCIAR);
  1636. (* service this irq *)
  1637. irq := ack MOD 1024;
  1638. IF irq # 1023 THEN (* not a spurious IRQ *)
  1639. state.INT := irq;
  1640. IF (MinIRQ <= irq) & (irq<= MaxIRQ) THEN
  1641. count := 0;
  1642. handler := irqHandler[irq, count];
  1643. WHILE (handler # NIL) & (count < MaxIRQHandlers - 1) DO
  1644. handler(state);
  1645. DisableInterrupts; (* handler may have reactivated interrupts *)
  1646. INC(count);
  1647. handler := irqHandler[irq, count];
  1648. END;
  1649. SYSTEM.PUT32(Platform.ICCEOIR, ack);
  1650. END;
  1651. END;
  1652. (* service pending IRQs *)
  1653. FOR reg := 0 TO 2 DO
  1654. SYSTEM.GET( Platform.ICDISPR+reg*4, icip );
  1655. i := 0;
  1656. WHILE (i <= 31) & (icip # {}) DO
  1657. IF (i IN icip) THEN
  1658. icip := icip - {i};
  1659. irq := i+reg*32;
  1660. (* Do not service pending interrupts that are disabled: this allows state triggered interrupts to be
  1661. * handled by software in an interrupt process. *)
  1662. IF IsIRQEnabled(irq) & (irq # PrivateTimerIRQ) THEN
  1663. (*Trace.String("Pending IRQ "); Trace.Int(irq, 0); Trace.Ln;*)
  1664. count := 0;
  1665. state.INT := irq;
  1666. handler := irqHandler[irq, count];
  1667. WHILE (handler # NIL) & (count < MaxIRQHandlers - 1) DO
  1668. handler(state);
  1669. DisableInterrupts; (* handler may have reactivated interrupts *)
  1670. INC(count);
  1671. handler := irqHandler[irq, count]
  1672. END;
  1673. SYSTEM.PUT32(Platform.ICCEOIR, irq); (* end of interrupt *)
  1674. SYSTEM.PUT32(Platform.ICDICPR+reg*4, {i}); (* clear pending bit *)
  1675. END
  1676. END;
  1677. INC( i )
  1678. END
  1679. END;
  1680. END IRQCaller;
  1681. (** Undefined Exception Handler. Saves the processor state and calls the registered handler. *)
  1682. PROCEDURE {NOPAF} undefGlue;
  1683. CODE
  1684. CLREX
  1685. SUB SP, SP, #72 ; Room for the State record
  1686. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1687. MOV R0, R0
  1688. ADD SP, SP, #60
  1689. SUB R0, LR, #4 ; return address = LR-4
  1690. STR R0, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1691. MRS R0, SPSR ; get saved PSR
  1692. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1693. LDR R0, [PC, #undefined-8-$] ; save -Undef in the INT field
  1694. STR R0, [SP], #4
  1695. SUB SP, SP, #72
  1696. MOV R11, SP
  1697. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1698. STR R5, [SP, #-4]! ; push value (type tag)
  1699. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1700. LDR R0, [PC,#handler-8-$]
  1701. LDR R0, [R0, #0]
  1702. BLX R0
  1703. LDR R11, [SP], #4
  1704. ADD SP, SP, #4
  1705. ADD SP, SP, #72 ; adjust SP & remove PAF
  1706. LDR R0, [R11, #64] ; load 'State.PSR'
  1707. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1708. LDR R0, [R11, #60] ; load 'State.PC'...
  1709. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1710. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1711. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1712. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1713. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1714. LDR R11, [R11, #44]
  1715. MOVS PC, LR ; SPSR -> CPSR & return
  1716. ; Data section
  1717. state: d32 stateTag ; address of stateTag
  1718. handler: d32 undefHandler ; handler
  1719. undefined: d32 -Undef ; INT number for undefined instructions
  1720. END undefGlue;
  1721. (**
  1722. * Software Interrupt Handler. Saves the processor state and calls the registered handler.
  1723. * The SWI number is stored into the INT field of the state record.
  1724. *)
  1725. PROCEDURE {NOPAF} SWIGlue;
  1726. CODE
  1727. SUB SP, SP, #72 ; Room for the State record
  1728. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1729. MOV R0, R0
  1730. ADD SP, SP, #60
  1731. SUB R1, LR, #4 ; return address = LR-4
  1732. STR R1, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1733. MRS R0, SPSR ; get saved PSR
  1734. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1735. LDR R0, [R1, #0] ; Load SWI instruction
  1736. LDR R2, [PC, #HFFFFFF-8-$]
  1737. AND R0, R0, R2 ; R0 MOD 1000000 = SWI number
  1738. STR R0, [SP], #4 ; push SWI number as INT. SP points to offset 72
  1739. SUB SP, SP, #72 ; Update SP to correct location
  1740. MOV R11, SP
  1741. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1742. STR R5, [SP, #-4]! ; push value (type tag)
  1743. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1744. LDR R0, [PC,#handler-8-$]
  1745. LDR R0, [R0, #0]
  1746. BLX R0
  1747. LDR R11, [SP], #4
  1748. ADD SP, SP, #4
  1749. ADD SP, SP, #72 ; adjust SP & remove PAF
  1750. LDR R0, [R11, #64] ; load 'State.PSR'
  1751. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1752. LDR R0, [R11, #60] ; load 'State.PC'...
  1753. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1754. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1755. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1756. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1757. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1758. LDR R11, [R11, #44]
  1759. MOVS PC, LR ; SPSR -> CPSR & return
  1760. ; Data section
  1761. state: d32 stateTag ; address of stateTag
  1762. HFFFFFF: d32 0FFFFFFH ; SWI number mask
  1763. handler: d32 swiHandler ; swiHandler
  1764. END SWIGlue;
  1765. (**
  1766. * Prefetch Abort Handler. Saves the processor state and calls the registered handler.
  1767. * The PC field of the state record holds the address at which the prefetch fault occurred.
  1768. *)
  1769. PROCEDURE {NOPAF} prefetchGlue;
  1770. CODE
  1771. CLREX
  1772. SUB SP, SP, #72 ; Room for the State record
  1773. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1774. MOV R0, R0
  1775. ADD SP, SP, #60
  1776. SUB R0, LR, #4 ; return address = LR-4
  1777. STR R0, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1778. MRS R0, SPSR ; get saved PSR
  1779. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1780. LDR R0, [PC, #prefetchAbort-8-$] ; save -Data in the INT field
  1781. STR R0, [SP], #4
  1782. SUB SP, SP, #72
  1783. MOV R11, SP
  1784. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1785. STR R5, [SP, #-4]! ; push value (type tag)
  1786. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1787. LDR R0, [PC,#handler-8-$]
  1788. LDR R0, [R0, #0]
  1789. BLX R0
  1790. LDR R11, [SP], #4
  1791. ADD SP, SP, #4
  1792. ADD SP, SP, #72 ; adjust SP & remove PAF
  1793. LDR R0, [R11, #64] ; load 'State.PSR'
  1794. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1795. LDR R0, [R11, #60] ; load 'State.PC'...
  1796. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1797. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1798. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1799. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1800. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1801. LDR R11, [R11, #44]
  1802. MOVS PC, LR ; SPSR -> CPSR & return
  1803. ; Data section
  1804. state: d32 stateTag ; address of stateTag
  1805. handler: d32 prefetchHandler ; handler
  1806. prefetchAbort: d32 -Prefetch ; prefetch INT number
  1807. END prefetchGlue;
  1808. (**
  1809. * Data Abort Handler. Saves the processor state and calls the registered handler.
  1810. * Use procedure GetPageFault to get abort status and address.
  1811. *)
  1812. PROCEDURE {NOPAF} dataGlue;
  1813. CODE
  1814. CLREX
  1815. SUB SP, SP, #72 ; Room for the State record
  1816. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1817. MOV R0, R0
  1818. ADD SP, SP, #60
  1819. SUB R0, LR, #8 ; return address = LR-8
  1820. STR R0, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1821. MRS R0, SPSR ; get saved PSR
  1822. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1823. LDR R0, [PC, #dataAbort-8-$] ; save -Data in the INT field
  1824. STR R0, [SP], #4
  1825. SUB SP, SP, #72
  1826. MOV R11, SP
  1827. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1828. STR R5, [SP, #-4]! ; push value (type tag)
  1829. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1830. LDR R0, [PC,#handler-8-$]
  1831. LDR R0, [R0, #0]
  1832. BLX R0
  1833. LDR R11, [SP], #4
  1834. ADD SP, SP, #4
  1835. ADD SP, SP, #72 ; adjust SP & remove PAF
  1836. LDR R0, [R11, #64] ; load 'State.PSR'
  1837. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1838. LDR R0, [R11, #60] ; load 'State.PC'...
  1839. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1840. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1841. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1842. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1843. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1844. LDR R11, [R11, #44]
  1845. MOVS PC, LR ; SPSR -> CPSR & return
  1846. ; Data section
  1847. state: d32 stateTag ; address of stateTag
  1848. handler: d32 dataHandler ; address of the handler variable
  1849. dataAbort: d32 -Data
  1850. END dataGlue;
  1851. (** Fast Interrupt Handler. Saves the processor state and calls the registered handler *)
  1852. PROCEDURE {NOPAF} fiqGlue;
  1853. CODE
  1854. CLREX
  1855. SUB SP, SP, #72 ; Room for the State record
  1856. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1857. MOV R0, R0
  1858. ADD SP, SP, #60
  1859. SUB R0, LR, #4 ; return address = LR-4
  1860. STR R0, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1861. MRS R0, SPSR ; get saved PSR
  1862. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1863. SUB SP, SP, #68
  1864. MOV R11, SP
  1865. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1866. STR R5, [SP, #-4]! ; push value (type tag)
  1867. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1868. BL fiqHandler
  1869. LDR R11, [SP], #4
  1870. ADD SP, SP, #4
  1871. ADD SP, SP, #72 ; adjust SP & remove PAF
  1872. LDR R0, [R11, #64] ; load 'State.PSR'
  1873. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1874. LDR R0, [R11, #60] ; load 'State.PC'...
  1875. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1876. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1877. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1878. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1879. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1880. LDR R11, [R11, #44]
  1881. MOVS PC, LR ; SPSR -> CPSR & return
  1882. ; Data section
  1883. state: d32 stateTag ; address of stateTag
  1884. END fiqGlue;
  1885. (** Initializes IRQ handling. *)
  1886. PROCEDURE InitInterrupts*;
  1887. CONST
  1888. EnableSecure=0;
  1889. EnableNonSecure=1;
  1890. NumberIRQs = 96;
  1891. VAR p: PROCEDURE; i: LONGINT;
  1892. BEGIN
  1893. Acquire(Interrupts);
  1894. IRQMask := {};
  1895. p := IRQGlue;
  1896. SYSTEM.PUT32(InterruptVector + Irq, SYSTEM.VAL(LONGINT, p)); (* install new IRQ handler *)
  1897. SYSTEM.PUT32(Platform.ICDDCR, 0);
  1898. FOR i := 32 DIV 16 TO (NumberIRQs-1) DIV 16 (* 2 bits per IRQ *) DO
  1899. SYSTEM.PUT32(Platform.ICDICFR+i*4, 0);
  1900. END;
  1901. FOR i := 0 TO (NumberIRQs-1) DIV 4 (* 8 bits per IRQ *) DO
  1902. SYSTEM.PUT32(Platform.ICDIPR+i*4, LONGINT(0A0A0A0A0H)); (* set priority of each interrupt to 160 *)
  1903. END;
  1904. FOR i := (32 DIV 4) TO (NumberIRQs-1) DIV 4 (* 8 bits per IRQ *) DO
  1905. SYSTEM.PUT32(Platform.ICDIPTR+i*4, 1010101H); (* reset interrupt targets to processor 0 *)
  1906. END;
  1907. (* disable all interrupt forwardings *)
  1908. FOR i := 0 TO (NumberIRQs-1) DIV 32 (* 1 bit per IRQ *) DO
  1909. SYSTEM.PUT32(Platform.ICDICER+i*4, LONGINT(0FFFFFFFFH));
  1910. END;
  1911. SYSTEM.PUT32(Platform.ICCPMR, 0F0H);
  1912. SYSTEM.PUT32(Platform.ICCICR, {0,1,2});
  1913. SYSTEM.PUT32(Platform.ICCBPR, 0);
  1914. SYSTEM.PUT32(Platform.ICDDCR, {EnableSecure, EnableNonSecure});
  1915. Release(Interrupts);
  1916. (*InvalidateDCache(dCacheBase);*)
  1917. (*EnableIRQ(PrivateTimerIRQ);*)
  1918. END InitInterrupts;
  1919. (** Restore silent, infinitly-looping exception handlers *)
  1920. PROCEDURE EndInterrupts;
  1921. BEGIN
  1922. SYSTEM.PUT32(InterruptVector + Undef, InterruptVector + Undef);
  1923. SYSTEM.PUT32(InterruptVector + Swi, InterruptVector + Swi);
  1924. SYSTEM.PUT32(InterruptVector + Prefetch, InterruptVector + Prefetch);
  1925. SYSTEM.PUT32(InterruptVector + Data, InterruptVector + Data);
  1926. SYSTEM.PUT32(InterruptVector + Irq, InterruptVector + Irq);
  1927. SYSTEM.PUT32(InterruptVector + Fiq, InterruptVector + Fiq);
  1928. END EndInterrupts;
  1929. (* GetExceptionState *)
  1930. PROCEDURE GetExceptionState*(VAR int: State; VAR exc: ExceptionState);
  1931. BEGIN
  1932. (* save all state information while interrupts are still disabled *)
  1933. exc.locks := BreakAll();
  1934. IF int.INT = -Undef THEN
  1935. exc.halt := 17;
  1936. exc.instn := SYSTEM.GET32(int.PC)
  1937. ELSIF int.INT = -Prefetch THEN
  1938. exc.pf := int.PC;
  1939. exc.status := -1;
  1940. exc.halt := 19
  1941. ELSIF int.INT = -Data THEN
  1942. GetPageFault(exc.pf, exc.status);
  1943. IF exc.pf < 4 * k THEN
  1944. (* NIL pointer *)
  1945. exc.halt := 18
  1946. ELSE
  1947. exc.halt := 19
  1948. END
  1949. ELSE
  1950. (* SWI *)
  1951. exc.halt := int.INT
  1952. END
  1953. END GetExceptionState;
  1954. PROCEDURE GetPageFault * (VAR adr: ADDRESS; VAR status: LONGINT);
  1955. CODE
  1956. MRC p15, 0, R0, C5, C0 ; load fault status register (FSR)
  1957. AND R0, R0, #0FFH ; only bits 7:0 are valid
  1958. LDR R1, [FP, #status]
  1959. STR R0, [R1, #0]
  1960. MRC p15, 0, R0, C6, C0 ; load fault address (FAR)
  1961. LDR R1, [FP, #adr]
  1962. STR R0, [R1, #0]
  1963. END GetPageFault;
  1964. (* FAR - returns the Fault Address Register. *)
  1965. PROCEDURE -FAR*(): LONGINT;
  1966. CODE
  1967. MRC p15, 0, R0, C6, C0 ; FAR is co-processor 15 register 6
  1968. END FAR;
  1969. (** Init global timer *)
  1970. PROCEDURE InitGlobalTimer;
  1971. CONST
  1972. TimerEnable=0;
  1973. BEGIN
  1974. (* disable first *)
  1975. SYSTEM.PUT32(Platform.GlobalTimerControlRegister, {});
  1976. (* reset global counter *)
  1977. SYSTEM.PUT32(Platform.GlobalTimerCounterRegister0, 0);
  1978. SYSTEM.PUT32(Platform.GlobalTimerCounterRegister1, 0);
  1979. SYSTEM.PUT32(Platform.GlobalTimerControlRegister, {TimerEnable});
  1980. END InitGlobalTimer;
  1981. (** Init private timer *)
  1982. PROCEDURE InitTicks;
  1983. CONST
  1984. TimerEnable=0;
  1985. AutoReload=1;
  1986. IRQEnable=2;
  1987. VAR
  1988. (* time slot in private timer counts; take into account that private timer clock frequency is equal to half of the CPU clock frequency *)
  1989. delay: LONGINT;
  1990. BEGIN
  1991. delay := ENTIER( ( LONGREAL(TimerPeriod) * 0.5D0 * LONGREAL(BootConfig.GetIntValue("CpuClockHz")) ) / 1.0D6 + 0.5D0 );
  1992. (* disable first *)
  1993. SYSTEM.PUT32(Platform.PrivateTimerControlRegister, {});
  1994. (*SYSTEM.PUT32(Platform.PrivateTimerCounterRegister, Delay);*)
  1995. SYSTEM.PUT32(Platform.PrivateLoadValueRegister, delay);
  1996. SYSTEM.PUT32(Platform.PrivateTimerControlRegister, {TimerEnable, AutoReload, IRQEnable});
  1997. END InitTicks;
  1998. PROCEDURE StopTicks;
  1999. BEGIN
  2000. SYSTEM.PUT32(Platform.PrivateTimerControlRegister, {});
  2001. END StopTicks;
  2002. (** Handle multiprocessor timer interrupt. *)
  2003. PROCEDURE HandleMPTimer*(VAR state: State);
  2004. BEGIN (* {interrupts off} *)
  2005. timer(ID(), state); (* rarely used *)
  2006. (* Clear timer interrupt *)
  2007. SYSTEM.PUT32(Platform.GlobalTimerInterruptStatusRegister, 1);
  2008. EnableInterrupts; (* enable interrupts before acquiring locks below - to avoid deadlock with StopAll. *)
  2009. Timeslice(state); (* fixme: check recursive interrupt *)
  2010. END HandleMPTimer;
  2011. (** Handle uniprocessor timer interrupt. *)
  2012. PROCEDURE HandleUPTimer(VAR state: State);
  2013. BEGIN (* {interrupts off} *)
  2014. timer(ID(), state);
  2015. SYSTEM.PUT32(Platform.PrivateTimerInterruptStatusRegister, 1);
  2016. (* Shutdown if requested *)
  2017. IF ~(ID() IN allProcessors) THEN ShutdownSecondary END;
  2018. IF enableWatchdog THEN PrivateWatchdog.Feed(Second) END;
  2019. Timeslice(state)
  2020. END HandleUPTimer;
  2021. (** Install a processor timer event handler. *)
  2022. PROCEDURE InstallEventHandler* (h: EventHandler);
  2023. BEGIN
  2024. IF h # NIL THEN timer := h ELSE timer := DummyEvent END
  2025. END InstallEventHandler;
  2026. PROCEDURE DummyEvent*(id: LONGINT; CONST state: State);
  2027. BEGIN
  2028. END DummyEvent;
  2029. PROCEDURE DummyTimeslice*(VAR state: State);
  2030. BEGIN
  2031. END DummyTimeslice;
  2032. PROCEDURE DummyIRQ*;
  2033. BEGIN
  2034. END DummyIRQ;
  2035. PROCEDURE IRQBeginPrinter;
  2036. BEGIN
  2037. Trace.StringLn("IRQ BEGIN");
  2038. END IRQBeginPrinter;
  2039. PROCEDURE IRQEndPrinter;
  2040. BEGIN
  2041. Trace.StringLn("IRQ END");
  2042. END IRQEndPrinter;
  2043. (* Timer interrupt handler. *)
  2044. PROCEDURE TimerInterruptHandler(VAR state: State);
  2045. BEGIN
  2046. IF ID() = 0 THEN
  2047. INC(ticks);
  2048. DEC(eventCount);
  2049. IF eventCount = 0 THEN
  2050. eventCount := eventMax; event(state)
  2051. END;
  2052. END
  2053. END TimerInterruptHandler;
  2054. (* Set timer upcall. The handler procedure will be called at a rate of Second/divisor Hz. *)
  2055. PROCEDURE InstallTickHandler(handler: Handler; divisor: LONGINT);
  2056. BEGIN
  2057. eventMax := divisor; event := handler;
  2058. eventCount := eventMax
  2059. END InstallTickHandler;
  2060. (* ===== Low-Level Locks ===== *)
  2061. (* Initializes spinlocks. This is not exported in Intel version. *)
  2062. PROCEDURE InitLocks;
  2063. VAR
  2064. i: LONGINT;
  2065. BEGIN
  2066. FOR i := 0 TO MaxLock - 1 DO
  2067. lock[i].locked := FALSE
  2068. END;
  2069. END InitLocks;
  2070. PROCEDURE AcquirePreemption*(): LONGINT;
  2071. VAR
  2072. id: LONGINT;
  2073. BEGIN
  2074. id := ID();
  2075. INC(proc[id].preemptCount);
  2076. RETURN id
  2077. END AcquirePreemption;
  2078. PROCEDURE ReleasePreemption*;
  2079. VAR
  2080. id: LONGINT;
  2081. BEGIN
  2082. id := ID();
  2083. IF StrongChecks THEN
  2084. ASSERT(proc[id].preemptCount > 0);
  2085. END;
  2086. DEC(proc[id].preemptCount);
  2087. END ReleasePreemption;
  2088. PROCEDURE PreemptCount*(id: LONGINT): LONGINT;
  2089. BEGIN
  2090. IF StrongChecks THEN
  2091. ASSERT(id = ID());
  2092. END;
  2093. RETURN proc[id].preemptCount;
  2094. END PreemptCount;
  2095. (* Acquire lock. Disables interrupts. *)
  2096. PROCEDURE Acquire*(level: LONGINT);
  2097. VAR
  2098. id: LONGINT;
  2099. enabled: BOOLEAN;
  2100. BEGIN
  2101. enabled := AreInterruptsEnabled();
  2102. DisableInterrupts();
  2103. id := AcquirePreemption();
  2104. IF proc[id].locksHeld = {} THEN
  2105. proc[id].intStatus := enabled
  2106. END;
  2107. IF StrongChecks THEN
  2108. ASSERT(~AreInterruptsEnabled());
  2109. ASSERT((~enabled) OR (proc[id].locksHeld = {})); (* interrupts enabled => no locks held *)
  2110. ASSERT(~(level IN proc[id].locksHeld)) (* recursive locks not allowed *)
  2111. END;
  2112. AcquireObject(lock[level].locked);
  2113. (* Now, we hold the lock *)
  2114. INCL(proc[id].locksHeld, level);
  2115. IF StrongChecks THEN (* no lower-level locks currently held by this processor *)
  2116. ASSERT((level = 0) OR (proc[id].locksHeld * {0..level-1} = {}));
  2117. END;
  2118. END Acquire;
  2119. (* Release lock. Enables interrupts if last lock held. *)
  2120. PROCEDURE Release*(level: LONGINT);
  2121. VAR
  2122. id: LONGINT;
  2123. BEGIN
  2124. id := ID();
  2125. IF StrongChecks THEN
  2126. ASSERT(~AreInterruptsEnabled());
  2127. ASSERT(level IN proc[id].locksHeld);
  2128. ASSERT(lock[level].locked # FALSE)
  2129. END;
  2130. EXCL(proc[id].locksHeld, level);
  2131. ReleaseObject(lock[level].locked);
  2132. ReleasePreemption;
  2133. IF (proc[id].locksHeld = {}) & proc[id].intStatus THEN
  2134. EnableInterrupts
  2135. END;
  2136. END Release;
  2137. PROCEDURE AcquireAll*;
  2138. VAR
  2139. i: LONGINT;
  2140. BEGIN
  2141. FOR i := MaxLock - 1 TO 0 BY -1 DO
  2142. Acquire(i)
  2143. END
  2144. END AcquireAll;
  2145. PROCEDURE ReleaseAll*;
  2146. VAR
  2147. i: LONGINT;
  2148. BEGIN
  2149. FOR i := 0 TO MaxLock - 1 DO
  2150. Release(i)
  2151. END
  2152. END ReleaseAll;
  2153. (** Acquire a fine-grained lock on an active object. *)
  2154. (* Based on the code from "Barrier Litmus Tests and Cookbook" by Richard Grisenthwaite, ARM, 26.11.2009 *)
  2155. PROCEDURE AcquireObject*(VAR locked: BOOLEAN);
  2156. CODE
  2157. CLREX ; ensure that the local monitor is in the Open Access state after a context switch
  2158. LDR R1, [FP, #locked]
  2159. MOV R0, #1
  2160. Loop:
  2161. LDREXB R5, R1 ; read lock
  2162. CMP R5, #0 ; check if 0
  2163. WFENE ; sleep if the lock is held
  2164. STREXBEQ R5, R0, R1 ; attempt to store new value
  2165. CMPEQ R5, #0 ; test if store suceeded
  2166. BNE Loop ; retry if not
  2167. DMB ; ensures that all subsequent accesses are observed after the gaining of the lock is observed
  2168. ; loads and stores in the critical region can now be performed
  2169. END AcquireObject;
  2170. (** Release an active object lock. *)
  2171. (* Based on the code from "Barrier Litmus Tests and Cookbook" by Richard Grisenthwaite, ARM, 26.11.2009 *)
  2172. PROCEDURE ReleaseObject*(VAR locked: BOOLEAN);
  2173. CODE
  2174. LDR R1, [FP, #locked]
  2175. MOV R0, #0
  2176. DMB ; ensure all previous accesses are observed before the lock is cleared
  2177. STRB R0, [R1, #0] ; clear the lock.
  2178. DSB ; ensure completion of the store that cleared the lock before sending the event
  2179. SEV
  2180. END ReleaseObject;
  2181. (** Break all locks held by current processor (for exception handling). Returns levels released. *)
  2182. PROCEDURE BreakAll*(): SET;
  2183. VAR id, level: LONGINT; released: SET;
  2184. BEGIN
  2185. id := AcquirePreemption();
  2186. released := {};
  2187. FOR level := 0 TO MaxLock-1 DO
  2188. IF level IN proc[id].locksHeld THEN
  2189. lock[level].locked := FALSE; (* break the lock *)
  2190. EXCL(proc[id].locksHeld, level);
  2191. INCL(released, level)
  2192. END
  2193. END;
  2194. (*IF released = {} THEN
  2195. ASSERT(proc[id].nestCount = 0) (* no locks held *)
  2196. ELSE
  2197. ASSERT(proc[id].nestCount > 0); (* some locks held *)
  2198. proc[id].nestCount := 0 (* interrupt state will be restored later *)
  2199. END;*)
  2200. IF proc[id].preemptCount > 1 THEN INCL(released, Preemption) END;
  2201. proc[id].preemptCount := 0; (* clear preemption flag *)
  2202. RETURN released
  2203. END BreakAll; (* !!! interrupts are still off !!! *)
  2204. (* ===== Atomic Operations ===== *)
  2205. (* Atomic INC(x) *)
  2206. PROCEDURE -AtomicInc*(VAR x: LONGINT);
  2207. CODE
  2208. ;loop:
  2209. ; ADD R0, SP, #x ; R0 := ADR(x)
  2210. ; LDREX R1, R0 ; R1 := x
  2211. ; ADD R1, R1, #1 ; increment x
  2212. ; STREX R2, R1, R0
  2213. ; CMP R2, #0
  2214. ; BEQ loop ; if store failed, try again, else exit
  2215. ; ADD SP, SP, #4
  2216. LDR R0, [SP], #4
  2217. loop:
  2218. LDREX R1, R0
  2219. ADD R1, R1, #1
  2220. STREX R2, R1, R0
  2221. CMP R2, #0
  2222. BNE loop
  2223. END AtomicInc;
  2224. (* Atomic INC(x) *)
  2225. PROCEDURE -AtomicDec*(VAR x: LONGINT);
  2226. CODE
  2227. LDR R0, [SP], #4
  2228. loop:
  2229. LDREX R1, R0
  2230. SUB R1, R1, #1
  2231. STREX R2, R1, R0
  2232. CMP R2, #0
  2233. BNE loop
  2234. END AtomicDec;
  2235. PROCEDURE -AtomicAdd * (VAR x: LONGINT; y: LONGINT);
  2236. CODE
  2237. LDR R3, [SP, #y] ; R3 := y
  2238. LDR R0, [SP, #x] ; R0 := ADR(x)
  2239. loop:
  2240. LDREX R1, R0 ; R1 := x
  2241. ADD R1, R1, R3 ; increment x
  2242. STREX R2, R1, R0
  2243. CMP R2, #0
  2244. BNE loop ; if store failed, try again, else exit
  2245. ADD SP, SP, #8
  2246. END AtomicAdd;
  2247. (* Atomic test-and-set. Set x = TRUE and return old value of x. *)
  2248. PROCEDURE -AtomicTestSet * (VAR x: BOOLEAN): BOOLEAN;
  2249. CODE
  2250. LDR R3, [SP, #x] ; R3 := ADDRESSOF(x)
  2251. MOV R1, #0 ; R1 := FALSE
  2252. MOV R2, #1 ; R2 := TRUE
  2253. ADD SP, SP, #4 ; pop variable from stack
  2254. loop:
  2255. LDREXB R0, R3 ; load excl x
  2256. CMP R0, R1
  2257. BNE exit ; x # old -> exit
  2258. STREXB R4, R2, R3 ; x = old -> store excl new -> x
  2259. CMP R4, #0
  2260. BNE loop ; store exclusive failed: retry
  2261. exit:
  2262. END AtomicTestSet;
  2263. (* Atomic compare-and-swap. Set x = new if x = old and return old value of x *)
  2264. PROCEDURE -AtomicCAS * (VAR x: LONGINT; old, new: LONGINT): LONGINT;
  2265. CODE
  2266. LDR R3, [SP, #x] ; R3 := ADDRESSOF(x)
  2267. LDR R1, [SP, #old] ; R1 := old
  2268. LDR R2, [SP, #new] ; R2 := new
  2269. ADD SP, SP, #12 ; pop variable from stack
  2270. loop:
  2271. LDREX R0, R3 ; load excl x
  2272. CMP R0, R1
  2273. BNE exit ; x # old -> exit
  2274. STREX R4, R2, R3 ; x = old -> store excl new -> x
  2275. CMP R4, #0
  2276. BNE loop ; store exclusive failed: retry
  2277. exit:
  2278. END AtomicCAS;
  2279. (* ===== Virtual Memory Management ===== *)
  2280. PROCEDURE Ensure32BitAddress*(adr: ADDRESS): LONGINT;
  2281. BEGIN
  2282. RETURN adr
  2283. END Ensure32BitAddress;
  2284. PROCEDURE GetSecondLevelEntry(virtualAddress: ADDRESS): ADDRESS;
  2285. VAR
  2286. ptIdx, basePT, entry: ADDRESS;
  2287. BEGIN
  2288. IF (PS <= virtualAddress) & (virtualAddress < M) THEN
  2289. (* First 256 entries *)
  2290. basePT := sysSecondLvlPtStart
  2291. ELSIF (4 * G - M <= virtualAddress) THEN
  2292. (* Entries 256 to 511 *)
  2293. basePT := sysSecondLvlPtStart + 400H
  2294. ELSIF (memStackStart <= virtualAddress) & (virtualAddress < memStackStop) THEN
  2295. basePT := sysSecondLvlPtStart + 800H + virtualAddress DIV M * k - memStackStart DIV k
  2296. ELSIF (memConfigStart <= virtualAddress) & (virtualAddress < memConfigStop) THEN
  2297. basePT := sysSecondLvlPtStop - (memConfigStop DIV k - virtualAddress DIV M * k)
  2298. END;
  2299. ptIdx := SHR(virtualAddress MOD M, PSlog2);
  2300. ASSERT(basePT + 4 * ptIdx >= sysSecondLvlPtStart);
  2301. ASSERT(basePT + 4 * ptIdx < sysSecondLvlPtStop);
  2302. entry := SYSTEM.GET32(basePT + 4 * ptIdx);
  2303. RETURN entry
  2304. END GetSecondLevelEntry;
  2305. PROCEDURE SetSecondLevelEntry(virtualAddress, physicalAddress, flags: ADDRESS);
  2306. VAR ptIdx, basePT, entry: ADDRESS;
  2307. firstLvlEntry: ADDRESS;
  2308. BEGIN
  2309. IF (PS <= virtualAddress) & (virtualAddress < M) THEN
  2310. (* First 256 entries *)
  2311. basePT := sysSecondLvlPtStart
  2312. ELSIF (4 * G - M <= virtualAddress) THEN
  2313. (* Entries 256 to 511 *)
  2314. basePT := sysSecondLvlPtStart + 400H
  2315. ELSIF (memStackStart <= virtualAddress) & (virtualAddress < memStackStop) THEN
  2316. basePT := sysSecondLvlPtStart + 800H + virtualAddress DIV M * k - memStackStart DIV k
  2317. ELSIF (memConfigStart <= virtualAddress) & (virtualAddress < memConfigStop) THEN
  2318. basePT := sysSecondLvlPtStop - (memConfigStop DIV k - virtualAddress DIV M * k)
  2319. END;
  2320. ptIdx := SHR(virtualAddress MOD M, PSlog2);
  2321. IF physicalAddress = NilAdr THEN
  2322. entry := slFault
  2323. ELSE
  2324. ASSERT(physicalAddress MOD PS = 0);
  2325. ASSERT((flags DIV PS = 0) & (flags MOD 4 = 0));
  2326. entry := physicalAddress + flags + slSmall
  2327. END;
  2328. ASSERT(basePT + 4 * ptIdx >= sysSecondLvlPtStart);
  2329. ASSERT(basePT + 4 * ptIdx < sysSecondLvlPtStop);
  2330. SYSTEM.PUT32(basePT + 4 * ptIdx, entry);
  2331. END SetSecondLevelEntry;
  2332. PROCEDURE UnmapPhysical*(viartAdr: ADDRESS; size: SIZE);
  2333. BEGIN
  2334. END UnmapPhysical;
  2335. (* Unmap a virtual page and deallocate the corresponding physical page *)
  2336. PROCEDURE DeallocatePage(virtualAdr: ADDRESS);
  2337. VAR memoryAdr: LONGINT;
  2338. BEGIN
  2339. (* unmap the page *)
  2340. memoryAdr := GetSecondLevelEntry(virtualAdr);
  2341. ASSERT(memoryAdr MOD 4 = slSmall); (* page must be mapped *)
  2342. SYSTEM.PUT32(virtualAdr, freePage); (* link freePage list (must be done as long as the page is still mapped !) *)
  2343. SetSecondLevelEntry(virtualAdr, NilAdr, 0);
  2344. InvalidateTLBEntry(SHRL(virtualAdr, PSlog2));
  2345. (* free the page *)
  2346. memoryAdr := SHRL(memoryAdr, 12);
  2347. freePage := memoryAdr;
  2348. INC(memory.free, PS)
  2349. END DeallocatePage;
  2350. (* AllocatePage - allocates and maps one memory page to [virtualAdr...virtualAdr+PageSize]. Returns TRUE iff successful *)
  2351. PROCEDURE AllocatePage(virtualAdr, accessPermissions, flags: ADDRESS): BOOLEAN;
  2352. VAR memoryAdr, entry: ADDRESS;
  2353. BEGIN
  2354. (* Use 1:1 Mapping for stack *)
  2355. (* map the page *)
  2356. entry := GetSecondLevelEntry(virtualAdr);
  2357. IF entry MOD 4 # slFault THEN
  2358. Acquire(TraceOutput);
  2359. Trace.String("Allocate Page: entry = ");
  2360. Trace.Address(entry);
  2361. Trace.String("; vadr = ");
  2362. Trace.Address(virtualAdr);
  2363. Trace.String("; CPU = ");
  2364. Trace.Int(ID(), 0);
  2365. Trace.Ln;
  2366. Release(TraceOutput)
  2367. END;
  2368. ASSERT(entry MOD 4 = slFault); (* page must not be mapped *)
  2369. SetSecondLevelEntry(virtualAdr, (*memoryAdr*) virtualAdr, accessPermissions + flags);
  2370. InvalidateTLBEntry(SHRL(virtualAdr, PSlog2));
  2371. RETURN TRUE
  2372. END AllocatePage;
  2373. (** PhysicalAdr - returns the (real) physical address of the specified range of memory, or NilAdr if the range is not contiguous.
  2374. It is the caller's responsiblilty to assure the range remains allocated during the time it is in use.
  2375. *)
  2376. PROCEDURE PhysicalAdr*(adr, size: LONGINT): LONGINT;
  2377. VAR physAdr: ARRAY 400H OF Range; num, i, end: LONGINT;
  2378. BEGIN
  2379. TranslateVirtual(adr, size, num, physAdr);
  2380. IF (num > 0) THEN
  2381. FOR i := 1 TO num-1 DO
  2382. IF (physAdr[i].adr # (physAdr[i-1].adr + physAdr[i-1].size)) THEN
  2383. RETURN NilAdr
  2384. END
  2385. END;
  2386. RETURN physAdr[0].adr
  2387. ELSE
  2388. RETURN NilAdr
  2389. END
  2390. END PhysicalAdr;
  2391. (** TranslateVirtual - translates a virtual address range to num ranges of (real) physical addresses. num returns 0 on error.*)
  2392. PROCEDURE TranslateVirtual*(virtAdr: ADDRESS; size: LONGINT; VAR num: LONGINT; VAR physAdr: ARRAY OF Range);
  2393. VAR entry, base, ofs, len: LONGINT; endAdr: ADDRESS; abort: BOOLEAN;
  2394. BEGIN
  2395. Acquire(Memory);
  2396. endAdr := virtAdr + size;
  2397. IF ((memHeapStart <= virtAdr) & (endAdr <= memHeapStop)) OR ((memStackStart <= virtAdr) & (endAdr <= memStackStop)) OR ((memIOStart <= virtAdr) & (endAdr <= memIOStop)) THEN
  2398. (* Optimizations: we know that heap, stacks and I/O regions are mapped 1:1. *)
  2399. (*! This code is very aggressive: it returns only 1 range, and not 1 range per physical page. It assumes that all stack pages of the specified region are mapped *)
  2400. num := 1;
  2401. physAdr[0].adr := virtAdr;
  2402. physAdr[0].size := size;
  2403. ELSE
  2404. abort := FALSE;
  2405. num := 0;
  2406. WHILE (size > 0) & (num < LEN(physAdr)) & ~abort DO
  2407. entry := (*SYSTEM.GET32(pageTable.virtual + 4*SHR(virtAdr, LogM));*)GetFirstLevelEntry(virtAdr - virtAdr MOD M);
  2408. IF (entry MOD 4 = flSection) THEN
  2409. ofs := virtAdr MOD M;
  2410. len := MIN(size, M - ofs);
  2411. physAdr[num].adr := SHRL(entry, LogM) + ofs;
  2412. physAdr[num].size := len;
  2413. INC(num);
  2414. INC(virtAdr, len); DEC(size, len)
  2415. ELSIF (entry MOD 4 = flCoarse) THEN
  2416. base := SHRL(entry, 10);
  2417. WHILE (size > 0) & (num < LEN(physAdr)) & ~abort DO
  2418. entry := GetSecondLevelEntry(virtAdr);
  2419. IF (entry MOD 4 = slSmall) THEN
  2420. ofs := virtAdr MOD PS;
  2421. len := MIN(size, PS - ofs);
  2422. physAdr[num].adr := SHRL(entry, 12) + ofs;
  2423. physAdr[num].size := len;
  2424. INC(num);
  2425. INC(virtAdr, len); DEC(size, len)
  2426. ELSE
  2427. num := 0;
  2428. abort := TRUE
  2429. END
  2430. END
  2431. ELSE
  2432. num := 0; abort := TRUE
  2433. END;
  2434. END;
  2435. IF (size > 0) & (num = LEN(physAdr)) THEN num := 0 END; (* array 'physAdr' was too small *)
  2436. END;
  2437. Release(Memory)
  2438. END TranslateVirtual;
  2439. PROCEDURE SetFirstLevelEntry (virtual, physical: ADDRESS; permissions, flags, type: LONGINT);
  2440. VAR
  2441. index, entry: LONGINT;
  2442. BEGIN
  2443. index := SHR(virtual, LogM) * 4;
  2444. ASSERT(index >= 0);
  2445. ASSERT(sysFirstLvlPtStart + index < sysFirstLvlPtStop);
  2446. entry := physical + permissions * 400H + flags + type;
  2447. (*Trace.Address(virtual); Trace.String(" "); Trace.Address(physical); Trace.String(" "); Trace.Address(SysFirstLvlPtStart(*pageTable.virtual*) + index); Trace.String(" "); Trace.Address(entry); Trace.Ln;*)
  2448. SYSTEM.PUT32(sysFirstLvlPtStart + index, entry)
  2449. END SetFirstLevelEntry;
  2450. PROCEDURE GetFirstLevelEntry (virtual: ADDRESS): LONGINT;
  2451. VAR
  2452. index: LONGINT;
  2453. BEGIN
  2454. index := LSH(virtual, -(LogM)) * 4;
  2455. ASSERT(index >= 0);
  2456. ASSERT(sysFirstLvlPtStart + index < sysFirstLvlPtStop);
  2457. RETURN SYSTEM.GET32(sysFirstLvlPtStart + index)
  2458. END GetFirstLevelEntry;
  2459. (* AllocateHeap - allocates and maps [physicalAddress...physicalAddress+size] to [virtualAddress...virtualAddress+size] *)
  2460. PROCEDURE AllocateHeap(virtualAddress, physicalAddress, size: ADDRESS; accessPermissions, flags: LONGINT);
  2461. VAR i, entry: LONGINT;
  2462. BEGIN
  2463. ASSERT(size MOD M = 0);
  2464. FOR i := 0 TO (size DIV M) - 1 DO
  2465. entry := GetFirstLevelEntry(virtualAddress + i * M);
  2466. ASSERT(entry = 0);
  2467. SetFirstLevelEntry(virtualAddress + i * M, physicalAddress + i * M, accessPermissions, flags, flSection)
  2468. END
  2469. END AllocateHeap;
  2470. (** Enable Memory Management and virtual memory. *)
  2471. PROCEDURE EnableMM(translationBase, tbFlags, mmuFlags: ADDRESS);
  2472. BEGIN
  2473. InvalidateTLB;
  2474. CODE
  2475. ; Disable AFE (special permission mode) and TRE (special memory mode)
  2476. ldr r0, [pc, #pattern-$-8]
  2477. mrc p15, 0, r1, c1, c0, 0
  2478. and r1, r0, r1
  2479. mcr p15, 0, r1, c1, c0, 0
  2480. isb
  2481. ;mrc p15, 0, r0, c2, c0, 2
  2482. ;ldr r1, [pc, #TLBCRPattern-$-8]
  2483. ;and r0, r0, r1
  2484. ;mcr p15, 0, r0, c2, c0, 2
  2485. ldr r0, [FP, #translationBase]
  2486. ldr r1, [fp, #tbFlags]
  2487. orr r0, r0, r1
  2488. mcr p15, 0, r0, c2, c0, 0
  2489. isb
  2490. ;mvn r0, #0 ; mmu domains: 16 x 11 = manager on all domains
  2491. ldr r0, [pc, #domains-$-8]
  2492. mcr p15, 0, r0, c3, c0, 0
  2493. isb
  2494. ldr r0, [FP, #mmuFlags]
  2495. ldr r1, [FP, #sctlr-$-8]
  2496. orr r0, r0, r1 ; 1 bits in SCTLR
  2497. mcr p15, 0, r0, c1, c0, 0
  2498. isb
  2499. ;dsb
  2500. ;isb
  2501. b exit
  2502. domains: d32 55555555H ; Client on each domain
  2503. pattern: d32 0CFFFFFFFH ; NOT(AFE+TRE)
  2504. sctlr: d32 0C50078H
  2505. TLBCRPattern: d32 0FFFFFFF8H
  2506. exit:
  2507. END;
  2508. proc[ID()].mmu := TRUE
  2509. END EnableMM;
  2510. PROCEDURE InitMemory;
  2511. VAR
  2512. cr1: SET;
  2513. i: LONGINT;
  2514. base: ADDRESS;
  2515. coarseFlags, fineFlags, tbFlags: LONGINT;
  2516. trace: BOOLEAN;
  2517. val: ARRAY 8 OF CHAR;
  2518. BEGIN
  2519. BootConfig.GetValue("TraceMemory", val);
  2520. trace := val = '1';
  2521. IF trace THEN
  2522. (* Debug Tracing *)
  2523. Trace.String("Memory Layout");
  2524. IF ~enableCaching THEN Trace.String(" - WARNING: Caching Disabled") END;
  2525. Trace.Ln;
  2526. Trace.String("System Start: "); Trace.Address(memSysLowStart); Trace.Ln;
  2527. Trace.String("System Stop: "); Trace.Address(memSysLowStop); Trace.Ln;
  2528. Trace.String("System Size: "); Trace.Address(memSysLowStop - memSysLowStart); Trace.Ln;
  2529. Trace.String(" Interrupt Stack Start: "); Trace.Address(sysIntStackStart); Trace.Ln;
  2530. Trace.String(" Interrupt Stack Stop: "); Trace.Address(sysIntStackStop); Trace.Ln;
  2531. Trace.String(" Interrupt Stack Size: "); Trace.Address(sysIntStackStop - sysIntStackStart); Trace.Ln;
  2532. Trace.String(" First Page Table Start: "); Trace.Address(sysFirstLvlPtStart); Trace.Ln;
  2533. Trace.String(" First Page Table Stop: "); Trace.Address(sysFirstLvlPtStop); Trace.Ln;
  2534. Trace.String(" First Page Table Size: "); Trace.Address(sysFirstLvlPtStop - sysFirstLvlPtStart); Trace.Ln;
  2535. Trace.String(" Second Page Table Start: "); Trace.Address(sysSecondLvlPtStart); Trace.Ln;
  2536. Trace.String(" Second Page Table Stop: "); Trace.Address(sysSecondLvlPtStop); Trace.Ln;
  2537. Trace.String(" Second Page Table Size: "); Trace.Address(sysSecondLvlPtStop - sysSecondLvlPtStart); Trace.Ln;
  2538. Trace.String("Heap Start: "); Trace.Address(memHeapStart); Trace.Ln;
  2539. Trace.String("Heap Stop: "); Trace.Address(memHeapStop); Trace.Ln;
  2540. Trace.String("Heap Size: "); Trace.Address(memHeapStop - memHeapStart); Trace.Ln;
  2541. Trace.String("Stack Start: "); Trace.Address(memStackStart); Trace.Ln;
  2542. Trace.String("Stack Stop: "); Trace.Address(memStackStop); Trace.Ln;
  2543. Trace.String("Stack Size: "); Trace.Address(memStackStop - memStackStart); Trace.Ln;
  2544. Trace.String("Config Start: "); Trace.Address(memConfigStart); Trace.Ln;
  2545. Trace.String("Config Stop: "); Trace.Address(memConfigStop); Trace.Ln;
  2546. Trace.String("Config Size: "); Trace.Address(memConfigStop - memConfigStart); Trace.Ln;
  2547. Trace.String("I/O Start: "); Trace.Address(memIOStart); Trace.Ln;
  2548. Trace.String("I/O Stop: "); Trace.Address(memIOStop); Trace.Ln;
  2549. Trace.String("I/O Size: "); Trace.Address(memIOStop - memIOStart); Trace.Ln;
  2550. Trace.String("SysHigh Start: "); Trace.Address(memSysHighStart); Trace.Ln;
  2551. Trace.String("SysHigh Stop: "); Trace.Hex(memSysHighStop - 1, -8); Trace.Ln;
  2552. Trace.String(" Interrupt Vector Start: "); Trace.Address(sysVectorStart); Trace.Ln;
  2553. Trace.String(" Interrupt Vector Stop: "); Trace.Address(sysVectorStop); Trace.Ln;
  2554. Trace.String(" Interrupt Vector Size: "); Trace.Address(sysVectorStop - sysVectorStart); Trace.Ln;
  2555. Trace.String(" Cache References Start: "); Trace.Address(sysCacheRefStart); Trace.Ln;
  2556. Trace.String(" Cache References Stop: "); Trace.Address(sysCacheRefStop); Trace.Ln;
  2557. Trace.String(" Cache References Size: "); Trace.Address(sysCacheRefSize); Trace.Ln;
  2558. Trace.String(" Cache References Stack Offset: "); Trace.Address(sysCacheStackOfs); Trace.Ln;
  2559. END;
  2560. (* disable caching & buffering globally *)
  2561. cr1 := GetControlRegister();
  2562. SetControlRegister(cr1 - {DCache, ICache});
  2563. (*InvalidateDCache(dCacheBase);*)
  2564. (*InvalidateDCacheRange(0, MemStackStop);*)
  2565. InvalidateICache;
  2566. DrainWriteBuffer;
  2567. (* initialize memory ranges *)
  2568. heapLow.physical := memHeapStart;
  2569. heapLow.virtual := memHeapStart;
  2570. heapHigh.physical := memHeapStop;
  2571. heapHigh.virtual := memHeapStart;
  2572. stackHigh.physical := memStackStop;
  2573. stackHigh.virtual := memStackStop;
  2574. stackLow.physical := memStackStop;
  2575. stackLow.virtual := memStackStart;
  2576. (* initialize global variables *)
  2577. pageTable.virtual := sysFirstLvlPtStart;
  2578. pageTable.memory := sysFirstLvlPtStart;
  2579. stackPT := sysSecondLvlPtStart + 2 * k;
  2580. freePage := NilAdr;
  2581. (* Determine global caching parameter *)
  2582. IF enableCaching THEN
  2583. coarseFlags := Cacheable + Shareable;
  2584. fineFlags := CB
  2585. ELSE
  2586. coarseFlags:= Shareable;
  2587. fineFlags := 0;
  2588. END;
  2589. (* Clear first level page table *)
  2590. Fill32(sysFirstLvlPtStart, sysFirstLvlPtStop - sysFirstLvlPtStart, 0);
  2591. (* Clear second level page table *)
  2592. Fill32(sysSecondLvlPtStart, sysSecondLvlPtStop - sysSecondLvlPtStart, 0);
  2593. (* Map system area *)
  2594. SetFirstLevelEntry(0, sysSecondLvlPtStart, 0, 0, flCoarse);
  2595. FOR i := 1 TO 0FFH DO
  2596. SetSecondLevelEntry(PS * i, PS * i, FullAccess + fineFlags);
  2597. END;
  2598. (* Map page for high part of OCM *)
  2599. AllocateHeap(memSysHighStart, memSysHighStart, MAX(M, LONGINT(memSysHighStop - memSysHighStart)), SrwUrw, coarseFlags);
  2600. (* Map heap area *)
  2601. AllocateHeap(memHeapStart, memHeapStart, memHeapStop - memHeapStart, SrwUrw, coarseFlags);
  2602. (* Map I/O area, device-type, shared memory *)
  2603. AllocateHeap(memIOStart, memIOStart, memIOStop - memIOStart, SrwUrw, Shareable + B);
  2604. (* initialize stack & config page tables (excluding the last MB that is already initalized) *)
  2605. base := SHR(memStackStart, LogM);
  2606. FOR i := memStackStart TO memConfigStop - 1 BY M DO
  2607. SetFirstLevelEntry(i, sysSecondLvlPtStart + 2 * k + PTSize * (SHR(i, LogM) - base), 0, 0, flCoarse)
  2608. END;
  2609. (* Map config region directly *)
  2610. FOR i := 0 TO SHR(memConfigStop - memConfigStart, PSlog2) - 1 DO
  2611. SetSecondLevelEntry(memConfigStart + PS * i, memConfigStart + PS * i, FullAccess + fineFlags)
  2612. END;
  2613. (* flush all caches & the write buffer and invalidate both TLBs *)
  2614. FlushDCacheRange(0, SYSTEM.VAL(ADDRESS, LastAddress));
  2615. InvalidateICache;
  2616. DrainWriteBuffer;
  2617. InvalidateTLB;
  2618. (* get memory size *)
  2619. memory.size := memHeapStop - memHeapStart;
  2620. memory.free := memory.size;
  2621. (* get heap size (check how many MBs are allocated) *)
  2622. heapLow.physical := 1*M; heapLow.virtual := memHeapStart;
  2623. heapHigh.physical := 1*M;
  2624. i := SHR(memHeapStart, LogM);
  2625. WHILE (SYSTEM.GET32(pageTable.virtual + i*4) MOD 4 = flSection) DO
  2626. INC(heapHigh.physical, M);
  2627. DEC(memory.free, M);
  2628. INC(i)
  2629. END;
  2630. heapHigh.virtual := heapLow.virtual + heapHigh.physical - heapLow.physical;
  2631. (* allocate empty memory block with enough space for at least one free block *)
  2632. memBlockHead := SYSTEM.VAL (MemoryBlock, ADDRESSOF (initialMemBlock));
  2633. memBlockTail := memBlockHead;
  2634. initialMemBlock.beginBlockAdr := SYSTEM.VAL (ADDRESS, LastAddress);
  2635. initialMemBlock.endBlockAdr := heapHigh.virtual;
  2636. initialMemBlock.size := initialMemBlock.endBlockAdr - initialMemBlock.beginBlockAdr;
  2637. initialMemBlock.next := NIL;
  2638. freeStackIndex := 0;
  2639. (* init stack bitmap *)
  2640. FOR i := 0 TO (maxUserStacks) DIV 32 - 1 DO
  2641. freeStack[i] := {0..31};
  2642. END;
  2643. freeStack[(maxUserStacks) DIV 32] := {0 .. (LONGINT(maxUserStacks) MOD 32) - 1};
  2644. freeStackIndex := 0;
  2645. (* Init cache ref counts *)
  2646. cacheRefs := sysCacheRefStart;
  2647. Fill32(sysCacheRefStart, sysCacheRefSize, 0);
  2648. IF enableCaching THEN
  2649. tbFlags := 7BH
  2650. ELSE
  2651. tbFlags := 0
  2652. END;
  2653. (* Copy interrupt vector *)
  2654. SYSTEM.MOVE(0, 0FFFF0000H, 4096);
  2655. EnableMM(sysFirstLvlPtStart, tbFlags, 2000H + 1007H);
  2656. END InitMemory;
  2657. (** GetFreeK - returns information on free memory in Kbytes.*)
  2658. PROCEDURE GetFreeK*(VAR total, lowFree, highFree: SIZE);
  2659. BEGIN
  2660. Acquire(Memory);
  2661. total := SHR(memory.size, 10);
  2662. lowFree := 0;
  2663. highFree := SHR(memory.free, 10);
  2664. Release(Memory)
  2665. END GetFreeK;
  2666. (* ===== Stack Management ===== *)
  2667. (** Extend stack to address. Returns TRUE iff done.
  2668. * If a procedure that holds Memory needs triggers a stack extension, this procedure is called by the interrupt handler:
  2669. * we get a trap because Acquire is not reentrant. To solve this, we do not acquire memory iff:
  2670. * - we are in interrupt mode
  2671. * - the current processor holds Memory already
  2672. *)
  2673. PROCEDURE ExtendStack*(VAR s: Stack; virtAdr: ADDRESS): BOOLEAN;
  2674. VAR
  2675. ok, doLock: BOOLEAN;
  2676. access, psr, flags: LONGINT;
  2677. BEGIN
  2678. IF enableCaching THEN
  2679. flags := CB
  2680. ELSE
  2681. flags := 0
  2682. END;
  2683. SYSTEM.STPSR(0, psr);
  2684. (* Need to acquire Memory: if we are not in interrupt mode or if we do not hold this lock yet. *)
  2685. doLock := ~(Memory IN proc[ID()].locksHeld);
  2686. IF doLock THEN Acquire(Memory) END;
  2687. ok := FALSE;
  2688. IF (virtAdr < s.high) & (virtAdr >= s.low) THEN
  2689. (* Get page boundary *)
  2690. DEC(virtAdr, virtAdr MOD PS);
  2691. (* Check if page is mapped *)
  2692. (*InvalidateDCacheRange(memSysLowStart, memSysLowStop - memSysLowStart);*)
  2693. Initializer.InvalidateDCache;
  2694. IF (GetSecondLevelEntry(virtAdr) MOD 4 = slSmall) THEN
  2695. InvalidateTLBEntry(virtAdr);
  2696. Acquire(TraceOutput);
  2697. Trace.String("Stack address already mapped: ");
  2698. Trace.Address(virtAdr); Trace.Ln;
  2699. Release(TraceOutput)
  2700. ELSE
  2701. (* Allocate page: set different permissions for last stack page. *)
  2702. (*IF (virtAdr <= s.low) THEN HALT(100) ELSE access := FullAccess END;*)
  2703. access := FullAccess;
  2704. ok := AllocatePage(virtAdr, access, flags);
  2705. IF virtAdr < s.adr THEN
  2706. s.adr := virtAdr
  2707. END
  2708. END
  2709. ELSE
  2710. Acquire(TraceOutput);
  2711. Trace.StringLn("Address not in stack");Trace.Address(virtAdr);
  2712. Release(TraceOutput);
  2713. ok := FALSE
  2714. END;
  2715. IF doLock THEN Release(Memory) END;
  2716. RETURN ok
  2717. END ExtendStack;
  2718. (** Create a new stack s, for process with the initial stack pointer initSP. *)
  2719. PROCEDURE NewStack*(VAR s: Stack; process: ANY; VAR initSP: ADDRESS);
  2720. VAR
  2721. old, flags: LONGINT;
  2722. adr: ADDRESS;
  2723. free: SET;
  2724. b: BOOLEAN;
  2725. BEGIN
  2726. Acquire(Memory);
  2727. old := freeStackIndex;
  2728. IF enableCaching THEN
  2729. flags := CB
  2730. ELSE
  2731. flags := 0
  2732. END;
  2733. LOOP
  2734. free := freeStack[freeStackIndex];
  2735. IF free # {} THEN
  2736. (* Find the free stack space in that region and mark it as allocated *)
  2737. adr := 0;
  2738. WHILE ~(adr IN free) DO INC(adr) END;
  2739. EXCL(freeStack[freeStackIndex], SIZE(adr));
  2740. adr := memStackStart + (freeStackIndex * 32 + adr) * maxUserStackSize;
  2741. EXIT
  2742. END;
  2743. INC(freeStackIndex);
  2744. IF freeStackIndex = LEN(freeStack) THEN freeStackIndex := 0 END;
  2745. IF freeStackIndex = old THEN HALT(1503) END
  2746. END;
  2747. s.high := adr + maxUserStackSize; s.low := adr + StackGuardSize;
  2748. s.adr := s.high - InitStackSize; (* at the top of the virtual area *)
  2749. initSP := s.high;
  2750. b := AllocatePage(s.adr, FullAccess, flags); (* allocate one physical page first *)
  2751. ASSERT(b);
  2752. FlushDCacheRange(sysSecondLvlPtStart, sysSecondLvlPtStop - sysSecondLvlPtStart);
  2753. Release(Memory)
  2754. END NewStack;
  2755. PROCEDURE DisposeStack*(s: Stack);
  2756. VAR
  2757. adr: ADDRESS;
  2758. BEGIN
  2759. Acquire(Memory);
  2760. adr := s.adr;
  2761. WHILE adr # s.high DO
  2762. DeallocatePage(adr);
  2763. INC(adr, PS)
  2764. END;
  2765. adr := (adr - maxUserStacks - memStackStart) DIV maxUserStackSize;
  2766. INCL(freeStack[adr DIV 32], SIZE(adr MOD 32));
  2767. Release(Memory)
  2768. END DisposeStack;
  2769. (** Check if the specified stack is valid. *)
  2770. PROCEDURE ValidStack*(CONST s: Stack; sp: ADDRESS): BOOLEAN;
  2771. VAR valid: BOOLEAN;
  2772. BEGIN
  2773. Acquire(Memory);
  2774. valid := (sp MOD 4 = 0) & (sp >= s.adr) & (sp <= s.high);
  2775. WHILE valid & (sp < s.high) DO
  2776. valid := GetSecondLevelEntry(sp) MOD 4 = slSmall;
  2777. INC(sp, PS)
  2778. END;
  2779. Release(Memory);
  2780. RETURN valid
  2781. END ValidStack;
  2782. PROCEDURE GetStack(adr: ADDRESS; VAR s: Stack): BOOLEAN;
  2783. BEGIN
  2784. IF (adr < memStackStart) OR (adr > memStackStop) THEN
  2785. RETURN FALSE
  2786. END;
  2787. s.high := adr - PS;
  2788. s.low := adr - 4;
  2789. s.adr := adr;
  2790. RETURN TRUE
  2791. END GetStack;
  2792. (* ===== Heap ===== *)
  2793. PROCEDURE ValidHeapAddress*(p: ADDRESS): BOOLEAN;
  2794. BEGIN
  2795. RETURN (memHeapStart <= p) & (p < memHeapStop) & (p MOD 4 = 0)
  2796. END ValidHeapAddress;
  2797. (* Free unused memory block *)
  2798. PROCEDURE FreeMemBlock*(memBlock: MemoryBlock);
  2799. BEGIN
  2800. HALT(515) (* impossible to free heap *)
  2801. END FreeMemBlock;
  2802. (** Set memory block end address *)
  2803. PROCEDURE SetMemoryBlockEndAddress*(memBlock: MemoryBlock; endBlockAdr: ADDRESS);
  2804. BEGIN
  2805. ASSERT(endBlockAdr >= memBlock.beginBlockAdr);
  2806. memBlock.endBlockAdr := endBlockAdr
  2807. END SetMemoryBlockEndAddress;
  2808. (* Policy decision for heap expansion. NewBlock for the same block has failed try times. *)
  2809. (*PROCEDURE ExpandNow(try: LONGINT): BOOLEAN;
  2810. VAR size: SIZE;
  2811. BEGIN
  2812. size := LSH(memBlockTail.endBlockAdr - memBlockHead.beginBlockAdr, -10); (* heap size in KB *)
  2813. RETURN (~ODD(try) OR (size < heapMinKB)) & (size < heapMaxKB)
  2814. END ExpandNow;*)
  2815. (** Attempt to set the heap end address to the specified address. The returned value is the actual new end address (never smaller than previous value). *)
  2816. (*PROCEDURE SetHeapEndAdr(VAR endAdr: ADDRESS);
  2817. VAR n, m: SIZE;
  2818. BEGIN
  2819. HALT(100);
  2820. Acquire(Memory);
  2821. (*
  2822. n := LSH(endAdr+(PS-1), -PSlog2) - LSH(heapEndAdr, -PSlog2); (* pages requested *)
  2823. m := LSH(pageHeapAdr, -PSlog2) - LSH(heapEndAdr, -PSlog2) - ReservedPages; (* max pages *)
  2824. IF n > m THEN n := m END;
  2825. IF n > 0 THEN INC(heapEndAdr, n*PS); DEC(freeHighPages, n) END;
  2826. endAdr := heapEndAdr;
  2827. *)
  2828. Release(Memory)
  2829. END SetHeapEndAdr;*)
  2830. (* Try to expand the heap by at least "size" bytes *)
  2831. PROCEDURE ExpandHeap*(try: LONGINT; size: SIZE; VAR memBlock: MemoryBlock; VAR beginBlockAdr, endBlockAdr: ADDRESS);
  2832. BEGIN
  2833. (*IF ExpandNow(try) THEN
  2834. IF size < expandMin THEN size := expandMin END;
  2835. beginBlockAdr := memBlockHead.endBlockAdr;
  2836. endBlockAdr := beginBlockAdr;
  2837. INC(endBlockAdr, size);
  2838. SetHeapEndAdr(endBlockAdr); (* in/out parameter *)
  2839. memBlock := memBlockHead;
  2840. (* endBlockAdr of memory block is set by caller after free block has been set in memory block - this process is part of lock-free heap expansion *)
  2841. ELSE*)
  2842. beginBlockAdr := memBlockHead.endBlockAdr;
  2843. endBlockAdr := memBlockHead.endBlockAdr;
  2844. memBlock := NIL
  2845. (*END*)
  2846. END ExpandHeap;
  2847. (** GetStaticHeap - get page range (beginAdr..endAdr-1) and first and last block of static heap.*)
  2848. PROCEDURE GetStaticHeap*(VAR beginBlockAdr, endBlockAdr, freeBlockAdr: ADDRESS);
  2849. BEGIN
  2850. beginBlockAdr := initialMemBlock.beginBlockAdr;
  2851. endBlockAdr := initialMemBlock.endBlockAdr;
  2852. freeBlockAdr := beginBlockAdr;
  2853. END GetStaticHeap;
  2854. (* ===== Caches, TLB & other ===== *)
  2855. (** SHR - logical shift right *)
  2856. PROCEDURE SHR(value, shift: ADDRESS): LONGINT;
  2857. CODE
  2858. LDR R0, [FP, #value]
  2859. LDR R1, [FP, #shift]
  2860. MOV R0, R0, LSR R1
  2861. END SHR;
  2862. (** SHRL - shift right and left. Mask out 'shift' lowest bits *)
  2863. PROCEDURE SHRL(value, shift: LONGINT): LONGINT;
  2864. (*CODE
  2865. LDR R0, [FP, #value]
  2866. LDR R1, [FP, #shift]
  2867. MOV R0, R0, LSR R1
  2868. MOV R0, R0, LSL R1*)
  2869. BEGIN
  2870. value := LSH(value, -shift);
  2871. value := LSH(value, shift);
  2872. RETURN value
  2873. END SHRL;
  2874. (** Fills 'size' bytes with 'filler', from 'destAdr' on. size must be multiple of 4 *)
  2875. PROCEDURE Fill32*(destAdr: ADDRESS; size: SIZE; filler: LONGINT);
  2876. CODE
  2877. LDR R0, [FP, #filler]
  2878. LDR R1, [FP, #size]
  2879. LDR R3, [FP, #destAdr]
  2880. ADD R4, R1, R3 ; R4 = size + destAdr
  2881. AND R5, R3, #3 ; R5 := R3 MOD 4
  2882. CMP R5, #0 ; ASSERT(R5 = 0)
  2883. BEQ CheckSize
  2884. SWI #8
  2885. CheckSize:
  2886. AND R5, R1, #3 ; R5 := R1 MOD 4
  2887. CMP R5, #0 ; ASSERT(R5 = 0)
  2888. BEQ Loop
  2889. SWI #8
  2890. Loop:
  2891. CMP R4, R3
  2892. BLS Exit
  2893. STR R0, [R3, #0] ; put(destAdr + counter, filler)
  2894. ADD R3, R3, #4 ; R3 := R3 + 4
  2895. B Loop
  2896. Exit:
  2897. END Fill32;
  2898. (* GetPageTableBase - returns the memory address of the first level page table *)
  2899. PROCEDURE -GetPageTableBase(): LONGINT;
  2900. CODE
  2901. MRC p15, 0, R0, c2, c0, 0
  2902. MOV R0, R0, LSR #14 ; clear bits 13..0
  2903. MOV R0, R0, LSL #14
  2904. END GetPageTableBase;
  2905. (** GC Initialization -- Set machine-dependent parameters gcThreshold, expandMin, heapMinKB and heapMaxKB *)
  2906. PROCEDURE SetGCParams*;
  2907. VAR size, t: SIZE;
  2908. BEGIN
  2909. GetFreeK(size, t, t); (* size is total memory size in KB *)
  2910. heapMinKB := size * HeapMin DIV 100;
  2911. heapMaxKB := size * HeapMax DIV 100;
  2912. expandMin := size * ExpandRate DIV 100 * 1024;
  2913. IF expandMin < 0 THEN expandMin := MAX(LONGINT) END;
  2914. gcThreshold := size * Threshold DIV 100 * 1024;
  2915. IF gcThreshold < 0 THEN gcThreshold := MAX(LONGINT) END
  2916. END SetGCParams;
  2917. (** Called when spinning, just does a NOP *)
  2918. PROCEDURE -SpinHint*;
  2919. CODE
  2920. MOV R0, R0
  2921. END SpinHint;
  2922. (** Convert a string to an integer. Parameter i specifies where in the string scanning should begin (usually 0 in the first call). Scanning stops at the first non-valid character, and i returns the updated position. Parameter s is the string to be scanned. The value is returned as result, or 0 if not valid. Syntax: number = ["-"] digit {digit} ["H" | "h"] . digit = "0" | ... "9" | "A" .. "F" | "a" .. "f" . If the number contains any hexdecimal letter, or if it ends in "H" or "h", it is interpreted as hexadecimal. *)
  2923. PROCEDURE StrToInt* (VAR i: LONGINT; CONST s: ARRAY OF CHAR): LONGINT;
  2924. VAR vd, vh, sgn, d: LONGINT; hex: BOOLEAN;
  2925. BEGIN
  2926. vd := 0; vh := 0; hex := FALSE;
  2927. IF s[i] = "-" THEN sgn := -1; INC (i) ELSE sgn := 1 END;
  2928. LOOP
  2929. IF (s[i] >= "0") & (s[i] <= "9") THEN d := ORD (s[i])-ORD ("0")
  2930. ELSIF (CAP (s[i]) >= "A") & (CAP (s[i]) <= "F") THEN d := ORD (CAP (s[i]))-ORD ("A") + 10; hex := TRUE
  2931. ELSE EXIT
  2932. END;
  2933. vd := 10*vd + d; vh := 16*vh + d;
  2934. INC (i)
  2935. END;
  2936. IF CAP (s[i]) = "H" THEN hex := TRUE; INC (i) END; (* optional H *)
  2937. IF hex THEN vd := vh END;
  2938. RETURN sgn * vd
  2939. END StrToInt;
  2940. (** Read Non Volatile memory. Not implemented. Required by clock. *)
  2941. PROCEDURE GetNVByte* (ofs: LONGINT): CHAR;
  2942. BEGIN
  2943. RETURN 10X
  2944. END GetNVByte;
  2945. (** Write Non Volatile memory. Not implemented. Required by clock. *)
  2946. PROCEDURE PutNVByte* (ofs: LONGINT; val: CHAR);
  2947. END PutNVByte;
  2948. (* empty section allocated at end of bootfile *)
  2949. PROCEDURE {NOPAF, ALIGNED(32)} LastAddress;
  2950. CODE
  2951. END LastAddress;
  2952. PROCEDURE GetConfig*(CONST name: ARRAY OF CHAR; VAR res: ARRAY OF CHAR);
  2953. BEGIN
  2954. BootConfig.GetValue(name, res)
  2955. END GetConfig;
  2956. PROCEDURE MulH * (x, y: HUGEINT): HUGEINT;
  2957. BEGIN
  2958. RETURN LONGINT(x) * LONGINT(y)
  2959. END MulH;
  2960. PROCEDURE DivH * (x, y: HUGEINT): HUGEINT;
  2961. BEGIN
  2962. RETURN x DIV y
  2963. END DivH;
  2964. (** Not implemented yet *)
  2965. PROCEDURE Portin8*(port: LONGINT; VAR val: CHAR);
  2966. END Portin8;
  2967. PROCEDURE Portout8*(port: LONGINT; val: CHAR);
  2968. END Portout8;
  2969. PROCEDURE TraceState * (CONST state: State);
  2970. BEGIN
  2971. Trace.StringLn("General Purpose Registers");
  2972. Trace.String("R0 "); Trace.Address(state.R[0]); Trace.Ln;
  2973. Trace.String("R1 "); Trace.Address(state.R[1]); Trace.Ln;
  2974. Trace.String("R2 "); Trace.Address(state.R[2]); Trace.Ln;
  2975. Trace.String("R3 "); Trace.Address(state.R[3]); Trace.Ln;
  2976. Trace.String("R4 "); Trace.Address(state.R[4]); Trace.Ln;
  2977. Trace.String("R5 "); Trace.Address(state.R[5]); Trace.Ln;
  2978. Trace.String("R6 "); Trace.Address(state.R[6]); Trace.Ln;
  2979. Trace.String("R7 "); Trace.Address(state.R[7]); Trace.Ln;
  2980. Trace.String("R8 "); Trace.Address(state.R[8]); Trace.Ln;
  2981. Trace.String("R9 "); Trace.Address(state.R[9]); Trace.Ln;
  2982. Trace.String("R10 "); Trace.Address(state.R[10]); Trace.Ln;
  2983. Trace.String("R11 "); Trace.Address(state.R[11]); Trace.Ln;
  2984. Trace.StringLn("Stack");
  2985. Trace.String("SP "); Trace.Address(state.SP); Trace.Ln;
  2986. Trace.String("FP "); Trace.Address(state.BP); Trace.Ln;
  2987. Trace.StringLn("Code");
  2988. Trace.String("LR "); Trace.Address(state.LR); Trace.Ln;
  2989. Trace.String("PC "); Trace.Address(state.PC); Trace.Ln;
  2990. Trace.Ln;
  2991. Trace.String("PSR "); Trace.Address(state.PSR); Trace.Ln;
  2992. Trace.Ln;
  2993. Trace.String("int "); Trace.Address(state.INT); Trace.Ln;
  2994. END TraceState;
  2995. PROCEDURE ReadMemLayout;
  2996. VAR
  2997. value: ARRAY 64 OF CHAR;
  2998. i: LONGINT;
  2999. BEGIN
  3000. memSysLowStart := Platform.OCMStart;
  3001. memSysLowStop := memSysLowStart + Platform.OCMSize;
  3002. GetConfig("KernelLoadAdr", value);
  3003. i := 0;
  3004. memHeapStart := StrToInt(i, value);
  3005. GetConfig("HeapSize", value);
  3006. i := 0;
  3007. memHeapStop := memHeapStart + StrToInt(i, value);
  3008. GetConfig("DDRSize", value);
  3009. i := 0;
  3010. memConfigStop := Platform.DDRStart + StrToInt(i, value);
  3011. GetConfig("ConfigSize", value);
  3012. i := 0;
  3013. memConfigStart := memConfigStop - StrToInt(i, value);
  3014. memStackStart := memHeapStop;
  3015. memStackStop := memConfigStart;
  3016. memIOStart := Platform.IOStart;
  3017. memIOStop := memIOStart + Platform.IOSize;
  3018. memSysHighStart := ADDRESS(4 * G - M);
  3019. memSysHighStop := 4 * G - 1;
  3020. (* System Parameters *)
  3021. sysIntStackStart := memSysLowStart + 1000H;
  3022. sysIntStackStop := memSysLowStart + Platform.MaxCpuNb * 4 * 4 * k;
  3023. (* The first level page table is always 16 k large, to map all 4 G of virtual memory space *)
  3024. sysFirstLvlPtStop := memSysLowStop;
  3025. sysFirstLvlPtStart := sysFirstLvlPtStop - 16 * k;
  3026. (*
  3027. * Second Level Page Table:
  3028. * - 2 * 256 entries for the system area (first and last MB of VMem)
  3029. * - 256 entries for each MB of virtual stack space
  3030. * 256 entries take 1kB memory space.
  3031. *)
  3032. sysSecondLvlPtStop := sysFirstLvlPtStart;
  3033. sysSecondLvlPtStart := sysSecondLvlPtStop - (2 + (memStackStop - memStackStart + memConfigStop - memConfigStart) DIV M) * k;
  3034. (*
  3035. * Interrupt Vector. Located at 0FFFFFFF0H
  3036. *)
  3037. sysVectorStart := 0FFFF0000H;
  3038. sysVectorStop := sysVectorStart + PS;
  3039. sysCacheRefStart := 0FFFF1000H;
  3040. (*
  3041. * Number of ref counters: 1 per 1st level heap page, 1 per 2nd level stack page.
  3042. * This memory region is organized as follows: the first part [0 .. SysCacheStackOfs) is used for heap pages,
  3043. * the second part, [SysCacheStackOfs .. SysCacheRefSize) is used for stack pages.
  3044. *)
  3045. sysCacheRefSize := (memHeapStop - memHeapStart) DIV M + (memStackStop - memStackStart) DIV PS;
  3046. INC(sysCacheRefSize, 4 - sysCacheRefSize MOD 4);
  3047. (* Offset in the ref count table for stack pages. *)
  3048. sysCacheStackOfs := (memHeapStop - memHeapStart) DIV M;
  3049. sysCacheRefStop := sysCacheRefStart + sysCacheRefSize;
  3050. (* Process stack system *)
  3051. GetConfig("StackSize", value);
  3052. i := 0;
  3053. maxUserStackSize := StrToInt(i, value);
  3054. maxUserStacks := (memStackStop - memStackStart) DIV maxUserStackSize;
  3055. GetConfig("EnableCaching", value);
  3056. enableCaching := value[0] # '0';
  3057. traceInterrupts := BootConfig.GetBoolValue("TraceInterrupts")
  3058. END ReadMemLayout;
  3059. PROCEDURE GetProcessorNumber;
  3060. VAR
  3061. value: ARRAY 64 OF CHAR;
  3062. i: LONGINT;
  3063. BEGIN
  3064. FOR i := 0 TO 63 DO value[i] := 0X END;
  3065. GetConfig("CpuNb", value);
  3066. i := 0;
  3067. numProcessors := StrToInt(i, value)
  3068. END GetProcessorNumber;
  3069. (** Analyse reasons for reset, print and record them. *)
  3070. PROCEDURE ResetAnalysis;
  3071. CONST
  3072. (* We need these constants as Platform.slcr is not initialized yet *)
  3073. SLCR_REBOOT_STATUS = ADDRESS(0F8000258H);
  3074. SLCR_LOCK = ADDRESS(0F8000004H);
  3075. SLCR_UNLOCK = ADDRESS(0F8000008H);
  3076. Lock = LONGINT(767BH);
  3077. Unlock = LONGINT(0DF0DH);
  3078. VAR
  3079. val: SET;
  3080. error: LONGINT;
  3081. BEGIN
  3082. SYSTEM.GET(SLCR_REBOOT_STATUS, val);
  3083. IF 16 IN val THEN
  3084. lastReboot := RebootSystemWatchdog;
  3085. Trace.StringLn("Starting after system watchdog reset")
  3086. END;
  3087. IF 17 IN val THEN
  3088. lastReboot := RebootWatchdogCPU0;
  3089. Trace.StringLn("Starting after private watchdog reset on CPU0")
  3090. END;
  3091. IF 18 IN val THEN
  3092. lastReboot := RebootWatchdogCPU1;
  3093. Trace.StringLn("Starting after private watchdog reset on CPU1")
  3094. END;
  3095. IF 19 IN val THEN
  3096. lastReboot := RebootSoftReset;
  3097. Trace.StringLn("Starting after software reboot")
  3098. END;
  3099. IF 20 IN val THEN
  3100. lastReboot := RebootDebug;
  3101. Trace.StringLn("Starting after debug reset")
  3102. END;
  3103. IF 21 IN val THEN
  3104. lastReboot := RebootHardReset;
  3105. Trace.StringLn("Starting after hard reset")
  3106. END;
  3107. IF 22 IN val THEN
  3108. lastReboot := RebootPowerOn;
  3109. Trace.StringLn("Starting after power on")
  3110. END;
  3111. error := SYSTEM.VAL(INTEGER, val);
  3112. IF error # 0 THEN
  3113. Trace.String("BootROM error code: "); Trace.Int(error, 0); Trace.Ln
  3114. END;
  3115. SYSTEM.PUT(SLCR_UNLOCK, Unlock);
  3116. SYSTEM.PUT(SLCR_REBOOT_STATUS, LONGINT(0));
  3117. SYSTEM.PUT(SLCR_LOCK, Lock)
  3118. END ResetAnalysis;
  3119. PROCEDURE InitWatchdog;
  3120. VAR val: ARRAY 32 OF CHAR;
  3121. BEGIN
  3122. GetConfig("EnableKernelWatchdog", val);
  3123. enableWatchdog := val = '1';
  3124. IF enableWatchdog THEN
  3125. PrivateWatchdog.Init(BootConfig.GetIntValue("CpuClockHz") DIV 2);
  3126. PrivateWatchdog.Start(PrivateWatchdog.Reset, Second)
  3127. END
  3128. END InitWatchdog;
  3129. PROCEDURE Init;
  3130. BEGIN
  3131. BootConfig.Init;
  3132. ReadMemLayout;
  3133. sp := SYSTEM.GetStackPointer();
  3134. fp := SYSTEM.GetFramePointer();
  3135. SYSTEM.LDPSR( 0, Platform.IRQMode + Platform.FIQDisabled + Platform.IRQDisabled );
  3136. SYSTEM.SETSP(sysIntStackStart + 1000H);
  3137. SYSTEM.LDPSR( 0, Platform.UndefMode + Platform.FIQDisabled + Platform.IRQDisabled );
  3138. SYSTEM.SETSP(sysIntStackStart + 1000H * 2);
  3139. SYSTEM.LDPSR( 0, Platform.AbortMode + Platform.FIQDisabled + Platform.IRQDisabled );
  3140. SYSTEM.SETSP(sysIntStackStart + 1000H * 3);
  3141. SYSTEM.LDPSR( 0, Platform.SVCMode + Platform.FIQDisabled + Platform.IRQDisabled );
  3142. SYSTEM.SETSP(sysIntStackStart + 1000H * 4);
  3143. SYSTEM.LDPSR( 0, Platform.SystemMode + Platform.FIQDisabled + Platform.IRQDisabled ); (* Disable interrupts, init SP, FP *)
  3144. SYSTEM.SETSP(sp);
  3145. SYSTEM.SETFP(fp);
  3146. TraceDevice.Install;
  3147. Trace.String("Machine: "); Trace.StringLn (Version);
  3148. version := Version;
  3149. InitProcessor;
  3150. InstallDefaultInterrupts;
  3151. DisableInterrupts;
  3152. ResetAnalysis;
  3153. (* Ensure memory layout consistency *)
  3154. ASSERT(sysIntStackStart >= 4 * k);
  3155. ASSERT(sysIntStackStop <= sysSecondLvlPtStart);
  3156. ASSERT(sysFirstLvlPtStart MOD (16 * k) = 0);
  3157. ASSERT(memStackStop <= memIOStart);
  3158. ASSERT(memIOStop <= memSysHighStart);
  3159. ASSERT(sysVectorStop <= sysCacheRefStart);
  3160. ASSERT(sysCacheRefStop <= memSysHighStop);
  3161. InitMemory;
  3162. GetProcessorNumber;
  3163. InitLocks;
  3164. InitGlobalTimer
  3165. END Init;
  3166. PROCEDURE {INITIAL} Initial;
  3167. BEGIN
  3168. Init;
  3169. END Initial;
  3170. END Machine.