ARM.Machine.Mod 105 KB

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