ARM.Machine.Mod 104 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600
  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. (*
  15. Used for compatibility with WMPerfMon
  16. *)
  17. MMX* = 23; (** bits in features variable *)
  18. (* Lock levels *)
  19. TraceOutput* = 0;
  20. Memory* = 1;
  21. Heaps* = 2;
  22. Interrupts* = 3 ;
  23. Modules* = 4;
  24. Objects* = 5;
  25. Processors* = 6;
  26. KernelLog* = 7;
  27. MaxLock = 8;
  28. (* Unit prefixes *)
  29. k = 1024;
  30. M = k * k;
  31. G = M * k;
  32. LogM = 20; (* log2(M) *)
  33. (*LogK = 10; (* log2(K) *)*)
  34. (* CPU number *)
  35. MaxCPU* = 32(*BootConfig.CpuNb*);
  36. (* If TRUE, enables some assertions in the code *)
  37. StrongChecks = TRUE;
  38. (* Page size, in bytes *)
  39. PS = 4 * k;
  40. PSlog2 = 12; (* ASH(1, PSlog2) = PS *)
  41. PTSize = 400H; (* size of a coarse page table *)
  42. (*PTEntries = 100H; (* 32bit entries per page table *)*)
  43. (* Absolute maximal process stack numbers *)
  44. MaxStackNb = 1024;
  45. (* Hard limit on cache reference size *)
  46. MaxCacheRefSize = M;
  47. (* Interrupt Vector base. Valid only after MMU is enabled *)
  48. InterruptVector = 0FFFF0000H;
  49. (* Interrupts *)
  50. MinIRQ* = 0;
  51. MaxIRQ* = 255;
  52. IRQ0* = MinIRQ; (* Alias *)
  53. (** ID of the global timer IRQ *)
  54. TimerIRQ* = 27;
  55. PrivateTimerIRQ* = 29;
  56. MaxIRQHandlers = 16;
  57. (* Exceptions codes. DO NOT CHANGE: they represent interrupt vector offsets *)
  58. Reset * = 20H; (** Reset *)
  59. Undef * = 24H; (** Undefined Exception *)
  60. Swi * = 28H; (** Software Interrupt *)
  61. Prefetch * = 2CH; (** Prefetch Abort *)
  62. Data * = 30H; (** Data Abort *)
  63. Irq * = 38H; (** Interrupt Request *)
  64. Fiq * = 3CH; (** Fast Interrupt *)
  65. (* Initial Stack size for user stacks *)
  66. (*InitUserStackSize = PS;*)
  67. HeapMin = 50; (* "minimum" heap size as percentage of total memory size (used for heap expansion in scope of GC ) *)
  68. HeapMax = 95; (* "maximum" heap size as percentage of total memory size (used for heap expansion in scope of GC) *)
  69. ExpandRate = 1; (* always extend heap with at least this percentage of total memory size *)
  70. Threshold = 10; (* periodic GC initiated when this percentage of total memory size bytes has "passed through" NewBlock *)
  71. (* Stack parameters *)
  72. InitStackSize = PS;
  73. StackGuardSize = PS;
  74. (* access permissions *)
  75. SrwUrw = 3;
  76. FullAccess = (*SrwUrw*400H+SrwUrw*100H+SrwUrw*40H+*)SrwUrw*10H; (* for small pages only *)
  77. LastStackPage = SrwUrw*400H+SrwUrw*100H+SrwUrw*40H; (* for small pages only *)
  78. (* first level page table types *)
  79. flCoarse = 1;
  80. flSection = 2;
  81. (* Second Level *)
  82. slFault = 0;
  83. slSmall = 2;
  84. (* cachable/bufferable mapping options *)
  85. cb = 0;
  86. C = 8;
  87. B = 4;
  88. CB = C + B + 440H;
  89. (* Inner and Outer Cacheable, Write-Through, no Write Allocate *)
  90. Cacheable = 100CH; (* here inner cacheable, write-back, write-allocate *)
  91. (* Shareable *)
  92. Shareable = 10000H;
  93. (* NIL *)
  94. NilAdr* = -1;
  95. (* Control Register Flags *)
  96. DCache = 2;
  97. ICache = 12;
  98. Second* = 1000; (* frequency of ticks increments in Hz *)
  99. Preemption* = 31; (** flag for BreakAll() *)
  100. (* TEMP. Temporary implementation to get Objects to compile *)
  101. SSESupport* = FALSE;
  102. SSE2Support* = FALSE;
  103. KernelLevel * = 1;
  104. UserLevel* = 1;
  105. (*CS* = 1;*)
  106. VMBit* = 2;
  107. (** Period at which the CPU timer interrupts, in micro seconds *)
  108. TimerPeriod* = 1000;
  109. (** Last reboot info *)
  110. RebootPowerOn * = 0;
  111. RebootHardReset * = 1;
  112. RebootSoftReset * = 2;
  113. RebootSystemWatchdog * = 3;
  114. RebootWatchdogCPU0 * = 4;
  115. RebootWatchdogCPU1 * = 5;
  116. RebootDebug * = 6;
  117. (** Needed, but not used yet by Reals.Mod *)
  118. fcr * = {};
  119. IsCooperative * = FALSE;
  120. TYPE
  121. (** processor state *)
  122. State* = RECORD
  123. R*: ARRAY 12 OF ADDRESS; (** registers 0-11 *)
  124. BP*, SP*, LR*, PC*: ADDRESS; (** special registers *)
  125. PSR*: ADDRESS; (** processor state register *)
  126. INT*: ADDRESS; (** IRQ number *)
  127. END;
  128. (** NEON Coprocessor state *)
  129. NEONState* = RECORD
  130. D*: ARRAY 32 OF HUGEINT; (* 32 64-bits registers *)
  131. FPSCR*: ADDRESS;
  132. FPEXC*: ADDRESS;
  133. END;
  134. (** exception state *)
  135. ExceptionState* = RECORD
  136. halt*: LONGINT; (** halt code *)
  137. instn*: LONGINT; (** undefined instruction *)
  138. pf*: ADDRESS; (** page fault address *)
  139. status*: LONGINT; (** page fault status *)
  140. locks*: SET; (** active locks *)
  141. END;
  142. (** Interrupt Hanlder *)
  143. Handler* = PROCEDURE {DELEGATE} (VAR state: State);
  144. EventHandler = PROCEDURE (id: LONGINT; CONST state: State);
  145. (** Spinlock *)
  146. Lock = RECORD
  147. locked: BOOLEAN;
  148. (* Padding to the granularity of exclusive monitor: 8 words on Cortex-A9 *)
  149. pad: ARRAY 31 OF CHAR;
  150. END;
  151. (** Processor status *)
  152. Proc* = RECORD
  153. locksHeld*: SET;
  154. preemptCount*: LONGINT;
  155. (*nestCount-: LONGINT; (** total locks held by a processor *)*)
  156. intStatus*, mmu*: BOOLEAN; (* muu: if the MMU is enabled for this processor *)
  157. END;
  158. (** Virtual/physical address pair *)
  159. AddressTuple = RECORD virtual, physical: ADDRESS; END;
  160. (** Stack descriptor:
  161. low: lowest possible stack address
  162. adr: current lowest allocated address
  163. high: highest address
  164. *)
  165. Stack* = RECORD
  166. low: ADDRESS;
  167. adr*: ADDRESS;
  168. high*: ADDRESS;
  169. END;
  170. (** Heap memory block *)
  171. MemoryBlock* = POINTER TO MemoryBlockDesc;
  172. MemoryBlockDesc* = RECORD
  173. next- {UNTRACED}: MemoryBlock;
  174. startAdr-: ADDRESS; (* unused field for I386 *)
  175. size-: SIZE; (* unused field for I386 *)
  176. beginBlockAdr-, endBlockAdr-: ADDRESS
  177. END;
  178. Address32* = ADDRESS;
  179. Range* = RECORD
  180. adr*: ADDRESS; size*: SIZE;
  181. END;
  182. CacheRefs = POINTER {UNSAFE,UNTRACED} TO ARRAY MaxCacheRefSize OF SHORTINT;
  183. VAR
  184. version -: ARRAY 64 OF CHAR;
  185. features-: SET; (** processor features *)
  186. sp, fp: ADDRESS;
  187. (** Interrupt Mask *)
  188. IRQMask: SET;
  189. (** IRQ Handlers. IRQ can have multiple handlers. Dispatching to those is done in IRQGlue and IRQCaller. *)
  190. irqHandler: ARRAY MaxIRQ + 1, MaxIRQHandlers OF Handler;
  191. (* Exception handlers. Called by *Glue. *)
  192. undefHandler, swiHandler, prefetchHandler, dataHandler, fiqHandler: Handler;
  193. stateTag: LONGINT;
  194. dummyIRQHandler: ARRAY MaxIRQ+1 OF RECORD h: Handler; END;
  195. (** Low level locks *)
  196. lock: ARRAY MaxLock OF Lock;
  197. (** Processors status:
  198. - locksHeld: set of low-level locks held by the processor
  199. - preemptCount: preemption counter
  200. *)
  201. proc-: ARRAY MaxCPU OF Proc;
  202. (** IDs of all successfully started processors. *)
  203. allProcessors-: SET;
  204. heapHigh, heapLow, stackHigh, stackLow: AddressTuple;
  205. (* Memory *)
  206. pageTable: RECORD virtual, memory: ADDRESS END; (* contains the virtual & memory address of the first level page table *)
  207. memory: RECORD size, free: SIZE; END;
  208. stackPT: ADDRESS;
  209. (* Free stack bitmap: each set element is set to indicate free stack *)
  210. freeStack: ARRAY (MaxStackNb + 31) DIV 32 OF SET;
  211. freeStackIndex: SIZE;
  212. (* Address of the highest free page *)
  213. freePage: ADDRESS;
  214. (* Memory blocks -- For the heap *)
  215. memBlockHead-{UNTRACED}, memBlockTail-{UNTRACED}: MemoryBlock;
  216. initialMemBlock: MemoryBlockDesc;
  217. dCacheBase: ADDRESS;
  218. (** GC parameters *)
  219. expandMin, heapMinKB, heapMaxKB : SIZE;
  220. gcThreshold: SIZE;
  221. (** For preemptive scheduling. *)
  222. Timeslice*: Handler;
  223. timer: EventHandler;
  224. (** timer ticks. Written to by GetTicks. Read-only *)
  225. ticks*: LONGINT;
  226. eventCount, eventMax: LONGINT;
  227. event: Handler;
  228. (** Number of processor used. *)
  229. numProcessors*: LONGINT;
  230. numberOfProcessors: LONGINT;
  231. (** Scheduling start procedure for non-booting processors. *)
  232. start*: PROCEDURE;
  233. (** Upcall to get current stack -- used for stack extension *)
  234. getStack*: PROCEDURE (VAR stack: Stack);
  235. (* Memory Layout *)
  236. (* The system area contains:
  237. * - the interrupt vector, which will be mapped high
  238. * - interrupt stacks
  239. * - the page table
  240. * Except for the first 4kB page, it is mapped 1:1.
  241. *)
  242. memSysLowStart,
  243. memSysLowStop,
  244. (* The heap area contains:
  245. * - the static kernel image
  246. * - the heap
  247. * The heap is mapped 1:1 with 1MB pages.
  248. *)
  249. memHeapStart,
  250. memHeapStop,
  251. (* Process Stacks are allocated in this area.
  252. * Stacks are mapped with 4kB pages. They take at least 2 pages:
  253. * - 1 for the actual stack
  254. * - 1 kept unmapped as the stack guard.
  255. * Stacks are mapped 1:1.
  256. * The stack size can be tuned to allow the system to run more processes.
  257. *)
  258. memStackStart,
  259. memStackStop,
  260. (* Boot configuration is placed in memory. It takes 4 kB at most *)
  261. memConfigStart,
  262. memConfigStop,
  263. (* IO registers and peripheral control are located in this region. Mapped 1:1 with 1MB and 4kB
  264. * pages, as necessary. Mapped as Device memory. *)
  265. memIOStart,
  266. memIOStop,
  267. (* High system memory region. Within the last MB, contains: interrupt vector and reference counts
  268. * for caching. *)
  269. memSysHighStart,
  270. memSysHighStop,
  271. (* System Parameters *)
  272. (* Interrupt stacks. 8kB of virtual space (4kB for stack, 4kB for guard) and 4 stacks per processor. *)
  273. sysIntStackStart,
  274. sysIntStackStop,
  275. (* First Level Page Table: size of 16 * k to map 4GB with 1MB pages. *)
  276. sysFirstLvlPtStart,
  277. sysFirstLvlPtStop,
  278. (*
  279. * Second Level Page Table:
  280. * - 2 * 256 entries for the system area (first and last MB of VMem)
  281. * - 256 entries for each MB of virtual stack space
  282. * 256 entries take 1kB memory space.
  283. *)
  284. sysSecondLvlPtStart,
  285. sysSecondLvlPtStop,
  286. (*
  287. * Interrupt Vector. Located at 0FFFFFFF0H
  288. *)
  289. sysVectorStart,
  290. sysVectorStop,
  291. sysCacheRefStart,
  292. sysCacheRefStop,
  293. (*
  294. * Number of ref counters: 1 per 1st level heap page, 1 per 2nd level stack page.
  295. * This memory region is organized as follows: the first part [0 .. SysCacheStackOfs) is used for heap pages,
  296. * the second part, [SysCacheStackOfs .. SysCacheRefSize) is used for stack pages.
  297. *)
  298. sysCacheRefSize,
  299. (* Offset in the ref count table for stack pages. *)
  300. sysCacheStackOfs: ADDRESS;
  301. (* Process stack system *)
  302. maxUserStackSize: SIZE;
  303. maxUserStacks: LONGINT;
  304. (* TRUE iff caching should be globally enabled *)
  305. enableCaching: BOOLEAN;
  306. (* UART used for kernel output *)
  307. kernelOutputUart -: LONGINT;
  308. (** Interrupt tracing option *)
  309. traceInterrupts: BOOLEAN;
  310. (** Trace option for CPU state *)
  311. traceCpus: BOOLEAN;
  312. (** Use private watchdog to check scheduling timers? *)
  313. enableWatchdog: BOOLEAN;
  314. (** Array of reference counts for page caching *)
  315. cacheRefs -: CacheRefs;
  316. (** Reason for last reboot *)
  317. lastReboot -: LONGINT;
  318. (* ===== Processor Management ===== *)
  319. (* Current processor's ID, between 0 and MaxProc - 1 *)
  320. PROCEDURE - ID*(): LONGINT;
  321. CODE
  322. MRC p15, 0, R0, C0, C0, 5
  323. AND R0, R0, #3H; Get the last 2 bits of R0
  324. END ID;
  325. (** Enables current processor's L1 caches *)
  326. PROCEDURE EnableL1Cache;
  327. CODE
  328. ; Enable Cache and TLB maintenance broadcast
  329. mrc p15, 0, r0, c1, c0, 1
  330. orr r0, r0, #1H
  331. mcr p15, 0, r0, c1, c0, 1
  332. isb
  333. ; Enable Caching in SCTLR
  334. mrc p15, 0, r0, c1, c0, 0
  335. orr r0, r0, #4H
  336. mcr p15, 0, r0, c1, c0, 0
  337. isb
  338. END EnableL1Cache;
  339. (** Enable L2 cache, prefetching and other speculative execution support *)
  340. PROCEDURE EnableL2Cache;
  341. CODE
  342. ldr r0,[pc, #L2CCCrtl-$-8] ; Load L2CC base address base + control register
  343. mov r1, #0 ; force the disable bit
  344. str r1, [r0,#0] ; disable the L2 Caches
  345. ldr r0, [pc, #L2CCAuxCtrl-$-8] ; Load L2CC base address base + Aux control register
  346. ldr r1,[r0,#0] ; read the register
  347. ldr r2, [pc, #L2CCAuxControl-$-8] ; set the default bits
  348. orr r1,r1,r2
  349. str r1, [r0,#0] ; store the Aux Control Register
  350. ldr r0,[pc, #L2CCTAGLatReg-$-8] ; Load L2CC base address base + TAG Latency address
  351. ldr r1, [pc, #L2CCTAGLatency-$-8] ; set the latencies for the TAG
  352. str r1, [r0,#0] ; store the TAG Latency register Register
  353. ldr r0, [pc, #L2CCDataLatReg-$-8] ; Load L2CC base address base + Data Latency address
  354. ldr r1,[pc, #L2CCDataLatency-$-8] ; set the latencies for the Data
  355. str r1, [r0,#0] ; store the Data Latency register Register
  356. ldr r0,[pc, #L2CCWay-$-8] ; Load L2CC base address base + way register
  357. ldr r2, [pc, #H0xffff-$-8]
  358. str r2, [r0,#0] ; force invalidate
  359. ldr r0, [pc, #L2CCSync-$-8] ; need to poll 0x730, PSS_L2CC_CACHE_SYNC_OFFSET
  360. ; Load L2CC base address base + sync register
  361. ; poll for completion
  362. Sync:
  363. ldr r1, [r0,#0]
  364. cmp r1, #0
  365. bne Sync
  366. ldr r0,[pc, #L2CCIntRaw-$-8] ; clear pending interrupts
  367. ldr r1,[r0,#0]
  368. ldr r0,[pc, #L2CCIntClear-$-8]
  369. str r1,[r0,#0]
  370. ldr r0,[pc,#L2CCCrtl-$-8] ; Load L2CC base address base + control register
  371. ldr r1,[r0,#0] ; read the register
  372. mov r2, #1 ; set the enable bit
  373. orr r1,r1,r2
  374. str r1, [r0,#0] ; enable the L2 Caches
  375. mrc p15,0,r0,c1,c0,0 ; flow prediction enable
  376. orr r0, r0, #0x800 ; #0x800
  377. mcr p15,0,r0,c1,c0,0
  378. isb
  379. mrc p15,0,r0,c1,c0,1 ; read Auxiliary Control Register
  380. orr r0, r0, #4 ; enable Dside prefetch
  381. orr r0, r0, #2 ; enable L2 Prefetch hint
  382. mcr p15,0,r0,c1,c0,1 ; write Auxiliary Control Register
  383. isb
  384. b exit
  385. ; Data
  386. H0xffff: d32 0FFFFH
  387. L2CCWay: d32 0F8F02000H + 077CH
  388. L2CCSync: d32 0F8F02000H + 0730H
  389. L2CCCrtl: d32 0F8F02000H + 0100H
  390. L2CCAuxCtrl: d32 0F8F02000H + 0104H
  391. L2CCTAGLatReg: d32 0F8F02000H + 0108H
  392. L2CCDataLatReg: d32 0F8F02000H + 010CH
  393. L2CCIntClear: d32 0F8F02000H + 0220H
  394. L2CCIntRaw: d32 0F8F02000H + 021CH
  395. L2CCAuxControl: d32 72360000H
  396. L2CCTAGLatency: d32 0111H
  397. L2CCDataLatency: d32 0121H
  398. exit:
  399. END EnableL2Cache;
  400. (** Enables the Snoop Control Unit
  401. for L1 coherency and LDREX/STREX global monitor
  402. *)
  403. PROCEDURE EnableSCU;
  404. CODE
  405. ; set scu enable bit in scu
  406. ldr r7, [pc, #H0xf8f00000-$-8]
  407. ldr r0, [r7, #0]
  408. orr r0, r0, #1
  409. str r0, [r7,#0]
  410. ; invalidate scu
  411. ldr r7, [pc, #H0xf8f0000c-$-8]
  412. ldr r6, [pc, #H0xffff-$-8]
  413. str r6, [r7, #0]
  414. b exit
  415. ; Data
  416. H0xf8f00000: d32 0F8F00000H
  417. H0xf8f0000c: d32 0F8F0000CH
  418. H0xffff: d32 0FFFFH
  419. exit:
  420. END EnableSCU;
  421. (** Init NEON / VFP Engine *)
  422. PROCEDURE InitFPU;
  423. CODE
  424. MRC p15, 0, R0, C1, C0, 2;
  425. ORR R0, R0, #0x00f00000;
  426. MCR p15, 0, R0, C1, C0, 2;
  427. ISB
  428. MOV R0, #0x40000000;
  429. VMSR FPEXC, R0;
  430. VMRS R0, FPSCR
  431. BIC R0, R0, #0x0c00000 ; round to nearest as the default
  432. ; remark: if we put round to minus infinity as the default, we can spare quite some instructions in emission of ENTIER
  433. VMSR FPSCR, R0;
  434. END InitFPU;
  435. (** Activate the Symmetric Multiprocessing Mode for current CPU.
  436. This activates L1 cache coherency.
  437. *)
  438. PROCEDURE SetSmpMode;
  439. CODE
  440. (*
  441. mrc p15, 0, r0, c1, c0, 1 /* Read ACTLR*/
  442. orr r0, r0, #(0x01 << 6) /* set SMP bit */
  443. orr r0, r0, #(0x01 ) /* */
  444. mcr p15, 0, r0, c1, c0, 1 /* Write ACTLR*/
  445. *)
  446. MRC p15, 0, R0, C1, C0, 1
  447. ORR R0, R0, #047H
  448. MCR p15, 0, R0, C1, C0, 1
  449. ISB
  450. END SetSmpMode;
  451. (** Activate Assymmetric Multiprocessing Mode for current CPU.
  452. This desactivates L1 cache coherency
  453. *)
  454. PROCEDURE SetAmpMode;
  455. CODE
  456. MRC p15, 0, R0, C1, C0, 1
  457. MOV R1, #040H
  458. RSB R1, R1, #0
  459. ORR R0, R0, R1
  460. MCR p15, 0, R0, C1, C0, 1
  461. ISB
  462. END SetAmpMode;
  463. (** Enable coprocessors CP10 and CP11(= VFP and NEON engine) *)
  464. PROCEDURE EnableCoprocessors;
  465. CODE
  466. mov r0, r0
  467. mrc p15, 0, r1, c1, c0, 2 ; read cp access control register (CACR) into r1
  468. orr r1, r1, #0xf00000 ; enable full access for p10 & p11
  469. mcr p15, 0, r1, c1, c0, 2 ; write back into CACR
  470. isb
  471. END EnableCoprocessors;
  472. (* Initializes a processor. Has to be called once by each processor. *)
  473. PROCEDURE InitProcessor*;
  474. BEGIN
  475. timer := DummyEvent;
  476. Timeslice := DummyTimeslice;
  477. SetSmpMode;
  478. EnableSCU;
  479. EnableL1Cache;
  480. InvalidateTLB;
  481. InvalidateICache;
  482. Initializer.InvalidateDCache;
  483. (*InvalidateDCacheRange(0, SYSTEM.VAL(ADDRESS, LastAddress));*)
  484. (* SCU and L2 caches are enabled in the initialization sequence *)
  485. EnableL2Cache;
  486. EnableCoprocessors;
  487. InitFPU;
  488. allProcessors := {0}
  489. END InitProcessor;
  490. (** Shut system down. If reboot is TRUE, attempts to restart system. *)
  491. PROCEDURE Shutdown*(reboot: BOOLEAN);
  492. VAR i: LONGINT; procs: SET;
  493. BEGIN
  494. IF enableWatchdog THEN PrivateWatchdog.Stop END;
  495. StopTicks;
  496. Trace.String("Shutting down secondary CPUs... ");
  497. procs := allProcessors;
  498. FOR i := 0 TO numberOfProcessors - 1 DO
  499. IF (i # ID()) & (i IN allProcessors) THEN
  500. EXCL(allProcessors, i)
  501. END
  502. END;
  503. FOR i := 0 TO numberOfProcessors - 1 DO
  504. IF (i #ID()) & (i IN procs) THEN
  505. REPEAT UNTIL i IN allProcessors
  506. END
  507. END;
  508. Trace.StringLn("done");
  509. IF reboot THEN
  510. Platform.slcr.SLCR_UNLOCK := Platform.SlcrUnlockKey;
  511. Platform.slcr.PSS_RST_CTRL := 1
  512. ELSE
  513. EndInterrupts;
  514. LOOP
  515. CODE
  516. WFE
  517. END;
  518. END
  519. END;
  520. END Shutdown;
  521. (** Shut down secondary processors *)
  522. PROCEDURE ShutdownSecondary;
  523. BEGIN
  524. IF enableWatchdog THEN PrivateWatchdog.Stop END;
  525. INCL(allProcessors, ID());
  526. LOOP
  527. CODE
  528. WFE
  529. END
  530. END
  531. END ShutdownSecondary;
  532. (** Cleans the whole DCache. Taken from Minos *)
  533. PROCEDURE CleanDCache *;
  534. CONST
  535. L2CCBBase = 0F8F02000H;
  536. L2COfs = L2CCBBase + 7BCH;
  537. L2CSync = L2CCBBase + 730H;
  538. CODE
  539. ; Clean all sets of all ways of L1 cache
  540. MOV R0, #0
  541. WayLoop:
  542. CMP R0, #4
  543. BEQ EndWayLoop
  544. LSL R4, R0, #30
  545. MOV R1, #0
  546. SetLoop:
  547. CMP R1, #256
  548. BEQ EndSetLoop
  549. LSL R3, R1, #5
  550. ORR R3, R4, R3
  551. MCR P15, 0, R3, C7, C10, 2
  552. ADD R1, R1, #1
  553. B SetLoop
  554. EndSetLoop:
  555. ADD R0, R0, #1
  556. B WayLoop
  557. EndWayLoop:
  558. DSB
  559. ; Invalidate all L2 ways
  560. LDR R0, [PC, #L2COfsAdr - $ - 8] ; R0 := reg7_inv_way address
  561. MOV R1, #0FH ; R1 := 0FH => invalidate all ways
  562. STR R1, [R0, #0] ; reg7_inv_way <- R1
  563. Sync:
  564. DSB
  565. LDR R0, [PC, #L2CSyncAdr - $ - 8] ; R0 := L2 cache sync register address
  566. MOV R1, #1
  567. STR R1, [R0, #0] ; [R0] := 1
  568. SyncLoop: ; repeat
  569. LDR R1, [R0, #0] ; R1 := l2 cache syc state
  570. CMP R1, #0
  571. BEQ Exit ; until R1 = 0
  572. B SyncLoop
  573. L2COfsAdr: d32 L2COfs
  574. L2CSyncAdr: d32 L2CSync
  575. Exit:
  576. END CleanDCache;
  577. PROCEDURE FlushDCacheRange*(adr:ADDRESS; len: SIZE);
  578. CONST
  579. cacheline = 32;
  580. L2CCBBase = 0F8F02000H; (*XPS_L2CC_BASEADDR*)
  581. L2CCCacheSync = L2CCBBase + 00730H; (* Cache Sync *)(*XPS_L2CC_CACHE_SYNC_OFFSET *)
  582. L2CCCacheInvClnPAOfs= 007F0H; (* Cache Clean by PA *)(*XPS_L2CC_CACHE_INV_CLN_PA_OFFSET*)
  583. L2CCOffset = L2CCBBase + L2CCCacheInvClnPAOfs;
  584. BEGIN
  585. IF ~enableCaching OR (len = 0) THEN RETURN END;
  586. IF len MOD cacheline # 0 THEN INC(len, cacheline - len MOD cacheline) END;
  587. IF adr MOD cacheline # 0 THEN DEC(adr, len MOD cacheline) END;
  588. CODE
  589. LDR R0, [FP, #adr] ; R0 := adr
  590. LDR R1, [FP, #len] ; R1 := len
  591. LDR R2, [PC, #Cacheline - 8 - $] ; R2 := cacheline
  592. SUB R3, R2, #1 ; R3 := cacheline - 1
  593. AND R3, R0, R3 ; R3 := adr MOD cacheline
  594. ADD R1, R1, R0
  595. SUB R0, R0, R3 ; R0 := adr - adr MOD cacheline
  596. ;ADD R1, R1, R3 ; R1 := len + adr MOD cacheline
  597. MOV R3, #0
  598. MCR P15, 2, R3, C0, C0, 0 ; Select cache level 1
  599. LDR R4, [PC, #L2COfs - 8 - $] ; R4 := L2 cache flush address register address
  600. Loop:
  601. CMP R0, R1 ; while R0 < R1
  602. BEQ Sync
  603. BHI Sync
  604. MCR P15, 0, R0, C7, C14, 1 ; Clean Cache Level 1 By MVA (R0)
  605. STR R0, [R4, #0] ; Clean Cache Level 2 By PA (R0)
  606. DSB
  607. ADD R0, R0, R2 ; R0 := R0 + cacheline
  608. B Loop ; end
  609. Sync:
  610. DSB
  611. LDR R0, [PC, #L2CSync - 8 - $] ; R0 := L2 cache sync register address
  612. ;MOV R1, #1
  613. ;STR R1, [R0, #0] ; [R0] := 1
  614. SyncLoop: ; repeat
  615. LDR R1, [R0, #0] ; R1 := l2 cache syc state
  616. CMP R1, #0
  617. BEQ Exit ; until R1 = 0
  618. B SyncLoop
  619. Cacheline: d32 cacheline
  620. L2COfs: d32 L2CCOffset
  621. L2CSync: d32 L2CCCacheSync
  622. Exit:
  623. END;
  624. END FlushDCacheRange;
  625. PROCEDURE FlushDCachePhysRange * (adr: ADDRESS; len: LONGINT; CONST ranges: ARRAY OF Range; numRanges: LONGINT);
  626. CONST
  627. cacheline = 32;
  628. L2CCBBase = 0F8F02000H; (*XPS_L2CC_BASEADDR*)
  629. L2CCCacheSync = L2CCBBase + 00730H; (* Cache Sync *)(*XPS_L2CC_CACHE_SYNC_OFFSET *)
  630. L2CCCacheInvClnPAOfs= 007F0H; (* Cache Clean by PA *)(*XPS_L2CC_CACHE_INV_CLN_PA_OFFSET*)
  631. L2CCOffset = L2CCBBase + L2CCCacheInvClnPAOfs;
  632. VAR
  633. cur, end: ADDRESS;
  634. r: LONGINT;
  635. BEGIN
  636. IF ~enableCaching & (len # 0) THEN
  637. IF len MOD cacheline # 0 THEN INC(len, cacheline - len MOD cacheline) END;
  638. (* Select cache L0 Data cache in CSSR *)
  639. CODE
  640. mov r0, #0
  641. mcr p15, 2, r0, c0, c0, 0 (* mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);*)
  642. END;
  643. (* Flush all cache lines in the memory region *)
  644. FOR r := 0 TO numRanges - 1 DO
  645. cur := ranges[r].adr;
  646. end := cur + ranges[r].size;
  647. WHILE (cur < end) DO
  648. (* Flush L1 Data cache line with virtual address *)
  649. CODE
  650. ldr r3, [fp, #adr] (* load*)
  651. mcr p15, 0, r3, c7, c14, 1; MCR XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (adr));
  652. END;
  653. (* Flush L2 cache line with physical address *)
  654. SYSTEM.PUT(L2CCOffset, cur);
  655. cur := cur + cacheline;
  656. adr := adr + cacheline
  657. END
  658. END
  659. END;
  660. (* Wait for L1 and L2 flush to complete *)
  661. CODE
  662. DSB
  663. END;
  664. SYSTEM.PUT32(L2CCCacheSync, 1);
  665. REPEAT UNTIL SYSTEM.GET32(L2CCCacheSync) = 0;
  666. END FlushDCachePhysRange;
  667. PROCEDURE InvalidateDCacheRange*(adr: ADDRESS; len: SIZE);
  668. CONST
  669. cacheline = 32;
  670. L2CCBBase = 0F8F02000H; (*XPS_L2CC_BASEADDR*)
  671. L2CCCacheSync = L2CCBBase + 00730H; (* Cache Sync *)(*XPS_L2CC_CACHE_SYNC_OFFSET *)
  672. L2CCCacheInvPAOfs = 00770H; (* Cache Invalidate by PA *)(*XPS_L2CC_CACHE_INV_CLN_PA_OFFSET*)
  673. L2CCOffset = L2CCBBase + L2CCCacheInvPAOfs;
  674. BEGIN
  675. IF ~enableCaching OR (len = 0) THEN RETURN END;
  676. IF len MOD cacheline # 0 THEN INC(len, cacheline - len MOD cacheline) END;
  677. IF adr MOD cacheline # 0 THEN DEC(adr, len MOD cacheline) END;
  678. CODE
  679. LDR R0, [FP, #adr] ; R0 := adr
  680. LDR R1, [FP, #len] ; R1 := len
  681. LDR R2, [PC, #Cacheline - 8 - $] ; R2 := cacheline
  682. SUB R3, R2, #1 ; R3 := cacheline - 1
  683. AND R3, R0, R3 ; R3 := adr MOD cacheline
  684. SUB R0, R0, R3 ; R0 := adr - adr MOD cacheline
  685. ADD R1, R1, R3 ; R1 := len + adr MOD cacheline
  686. MOV R5, #0 ; R5 := 0 (counter value)
  687. MOV R3, #0
  688. MCR P15, 2, R3, C0, C0, 0 ; Select cache level 1
  689. LDR R4, [PC, #L2COfs - 8 - $] ; R4 := L2 cache invalidate address register address
  690. Loop:
  691. CMP R5, R1 ; while R5 < R1
  692. BEQ Sync
  693. BHI Sync
  694. STR R0, [R4, #0] ; Invalidate Cache Level 2 By PA (R0)
  695. DSB
  696. MCR P15, 0, R0, C7, C6, 1 ; Invalidate Cache Level 1 By MVA (R0)
  697. ADD R0, R0, R2 ; R0 := R0 + cacheline
  698. ADD R5, R5, R2
  699. B Loop ; end
  700. Sync:
  701. DSB
  702. LDR R0, [PC, #L2CSync - 8 - $] ; R0 := L2 cache sync register address
  703. MOV R1, #1
  704. STR R1, [R0, #0] ; [R0] := 1
  705. SyncLoop: ; repeat
  706. LDR R1, [R0, #0] ; R1 := l2 cache syc state
  707. CMP R1, #0
  708. BEQ Exit ; until R1 = 0
  709. B SyncLoop
  710. Cacheline: d32 cacheline
  711. L2COfs: d32 L2CCOffset
  712. L2CSync: d32 L2CCCacheSync
  713. Exit:
  714. END;
  715. END InvalidateDCacheRange;
  716. (**
  717. Disable data cache for the memory range [adr, adr + len). Repeated cache disabling is recorded. A maximum of 127 successive disabling is supported.
  718. Cache disabling is allowed for heap and stack memory ranges only.
  719. *)
  720. PROCEDURE DisableDCacheRange * (adr: ADDRESS; len: LONGINT);
  721. VAR
  722. range: ARRAY 1 OF Range;
  723. end: ADDRESS;
  724. ofs, entry: LONGINT;
  725. BEGIN
  726. (* Changing cache status allowed for heap and stack only. *)
  727. ASSERT(((memHeapStart <= adr) & (adr + len <= memHeapStop)) OR ((memStackStart <= adr) & (adr + len <= memStackStop)));
  728. end := adr + len;
  729. Acquire(Memory);
  730. WHILE adr < end DO
  731. entry := GetFirstLevelEntry(adr - adr MOD M);
  732. CASE entry MOD 4 OF
  733. 0:
  734. (* Page is not allocated: generate a data abort trap *)
  735. Release(Memory);
  736. ASSERT(entry MOD 4 # 0);
  737. |flSection:
  738. (* 1 MB heap page *)
  739. IF enableCaching THEN
  740. (* index in cache reference count array *)
  741. ofs := (adr - memHeapStart) DIV M;
  742. IF cacheRefs[ofs] = 0 THEN
  743. (* First disabling: disable cache *)
  744. range[0].adr := adr - adr MOD M;
  745. range[0].size := M;
  746. SetFirstLevelEntry(adr - adr MOD M, adr - adr MOD M(*SHRL(entry, 20)*), SrwUrw, Shareable + B, flSection);
  747. InvalidateTLBEntry(adr);
  748. FlushDCachePhysRange(adr - adr MOD M, M, range, 1);
  749. cacheRefs[ofs] := 1
  750. ELSE
  751. (* Increase reference count and avoid overflows. *)
  752. ASSERT(cacheRefs[ofs] < 127);
  753. INC(cacheRefs[ofs])
  754. END
  755. END;
  756. INC(adr, M);
  757. DEC(adr, adr MOD M);
  758. |flCoarse:
  759. (* Second level pt *)
  760. entry := GetSecondLevelEntry(adr - adr MOD PS);
  761. CASE entry MOD 4 OF
  762. 0:
  763. (* Page is not allocated: generate a data abort trap *)
  764. Release(Memory);
  765. ASSERT(entry MOD 4 # 0);
  766. |slSmall:
  767. (* 4 kB stack page *)
  768. IF enableCaching THEN
  769. (* Index in cache reference count array *)
  770. ofs := (adr - memStackStart) DIV PS + sysCacheStackOfs;
  771. IF cacheRefs[ofs] = 0 THEN
  772. (* First disabling: disable cache *)
  773. range[0].adr := adr - adr MOD PS;
  774. range[0].size := PS;
  775. SetSecondLevelEntry(adr - adr MOD PS, SHRL(entry, PSlog2), FullAccess + 400H + B);
  776. InvalidateTLBEntry(adr);
  777. FlushDCachePhysRange(adr - adr MOD PS, PS, range, 1);
  778. cacheRefs[ofs] := 1
  779. ELSE
  780. (* Increase reference count and avoid overflows *)
  781. ASSERT(cacheRefs[ofs] < 127);
  782. INC(cacheRefs[ofs])
  783. END
  784. END;
  785. INC(adr, PS);
  786. DEC(adr, adr MOD PS)
  787. END;
  788. END;
  789. END;
  790. Release(Memory)
  791. END DisableDCacheRange;
  792. (**
  793. Enable data cache for the memory range [adr, adr + len).
  794. The memory range must have been previously disabled.
  795. It is the responsibility of client software to re-enable cache for the regions that it disabled.
  796. *)
  797. PROCEDURE EnableDCacheRange * (adr: ADDRESS; len: LONGINT);
  798. VAR
  799. end: ADDRESS;
  800. ofs, entry: LONGINT;
  801. BEGIN
  802. (* Changing cache status allowed for heap and stack only. *)
  803. ASSERT(((memHeapStart <= adr) & (adr < memHeapStop)) OR ((memStackStart <= adr) & (adr < memStackStop)));
  804. (*InvalidateDCacheRange(adr - (adr MOD M), len + M - (adr + len) MOD M + adr MOD M);*)
  805. Acquire(Memory);
  806. end := adr + len;
  807. WHILE adr < end DO
  808. entry := GetFirstLevelEntry(SHRL(adr, LogM));
  809. CASE entry MOD 4 OF
  810. 0:
  811. (* page not mapped: generate trap *)
  812. Release(Memory);
  813. ASSERT(entry MOD 4 # 0);
  814. |flSection:
  815. (* 1 MB heap page *)
  816. IF enableCaching THEN
  817. ofs := (adr - memHeapStart) DIV M;
  818. ASSERT(cacheRefs[ofs] > 0);
  819. IF cacheRefs[ofs] = 1 THEN
  820. SetFirstLevelEntry(SHRL(adr, LogM), SHRL(entry, LogM), SrwUrw, Cacheable + Shareable, entry MOD 4);
  821. InvalidateTLBEntry(adr);
  822. cacheRefs[ofs] := 0
  823. ELSE
  824. DEC(cacheRefs[ofs])
  825. END
  826. END;
  827. INC(adr, M);
  828. DEC(adr, adr MOD M)
  829. |flCoarse:
  830. (* Second-level pt entry *)
  831. entry := GetSecondLevelEntry(SHRL(adr, PSlog2));
  832. CASE entry MOD 4 OF
  833. 0:
  834. (* Page not mapped: generate trap *)
  835. Release(Memory);
  836. ASSERT(entry MOD 4 # 0);
  837. |slSmall:
  838. (* 4 kB stack page *)
  839. IF enableCaching THEN
  840. ofs := (adr - memStackStart) DIV PS + sysCacheStackOfs;
  841. ASSERT(cacheRefs[ofs] > 0);
  842. IF cacheRefs[ofs] = 1 THEN
  843. SetSecondLevelEntry(SHRL(adr, PSlog2), SHRL(entry, PSlog2), FullAccess + CB);
  844. InvalidateTLBEntry(SHRL(adr, PSlog2));
  845. cacheRefs[ofs] := 0
  846. ELSE
  847. DEC(cacheRefs[ofs])
  848. END
  849. END;
  850. INC(adr, PS);
  851. DEC(adr, adr MOD PS)
  852. END;
  853. END;
  854. END;
  855. Release(Memory)
  856. END EnableDCacheRange;
  857. (* InvalidateICache - invalidates the ICache. Works only in a priviledged mode. *)
  858. PROCEDURE InvalidateICache*;
  859. CODE
  860. MCR p15, 0, R0, c7, c5, 0 ; invalidate ICache & BTB
  861. ISB
  862. ; cpwait
  863. MRC p15, 0, R0, c2, c0, 0
  864. MOV R0, R0
  865. SUB PC, PC, #4
  866. MOV R0, R0
  867. MOV R0, R0
  868. MOV R0, R0
  869. MOV R0, R0
  870. END InvalidateICache;
  871. (* InvalidateTLB: data and instruction TLBs - Works only in a priviledged mode *)
  872. PROCEDURE - InvalidateTLB *;
  873. CODE
  874. MCR p15, 0, R0, c8, c3, 0 ; invalidate I+D TLB
  875. ISB
  876. ; cpwait
  877. MRC p15, 0, R0, c2, c0, 0
  878. MOV R0, R0
  879. SUB PC, PC, #4
  880. MOV R0, R0
  881. MOV R0, R0
  882. MOV R0, R0
  883. MOV R0, R0
  884. DSB
  885. END InvalidateTLB;
  886. (* InvalidateTLBEntry - invalidates the TLB for a given virtual address. Works only in a priviledged mode *)
  887. PROCEDURE - InvalidateTLBEntry(address: LONGINT);
  888. CODE
  889. LDR R0, [SP, #address]
  890. ADD SP, SP, #4
  891. ;MCR p15, 0, R0, c8, c6, 1 ; invalidate address
  892. MCR p15, 0, R0, c8, c3, 1 ; invalidate address
  893. ISB
  894. ; cpwait
  895. MRC p15, 0, R0, c2, c0, 0
  896. MOV R0, R0
  897. SUB PC, PC, #4
  898. MOV R0, R0
  899. MOV R0, R0
  900. MOV R0, R0
  901. MOV R0, R0
  902. DSB
  903. END InvalidateTLBEntry;
  904. (* GetControlRegister - returns the control register of coprocessor 15 *)
  905. PROCEDURE -GetControlRegister(): SET;
  906. CODE
  907. MRC p15, 0, R0, c1, c0, 0
  908. END GetControlRegister;
  909. (* SetControlRegister - sets the control register of coprocessor 15. Works only in a priviledged mode *)
  910. PROCEDURE -SetControlRegister(cr: SET);
  911. CODE
  912. LDR R0, [SP, #cr]
  913. ADD SP, SP, #4 ; remove parameter
  914. MCR p15, 0, R0, c1, c0, 0
  915. ISB
  916. ; cpwait
  917. MRC p15, 0, R0, c2, c0, 0
  918. MOV R0, R0
  919. SUB PC, PC, #4
  920. MOV R0, R0
  921. MOV R0, R0
  922. MOV R0, R0
  923. MOV R0, R0
  924. END SetControlRegister;
  925. (* DrainWriteBuffer - drains the write buffer. Works only in a priviledged mode *)
  926. PROCEDURE DrainWriteBuffer*;
  927. CODE
  928. MCR p15, 0, R0, c7, c10, 4 ; drain WB
  929. ISB
  930. ; cpwait
  931. MRC p15, 0, R0, c2, c0, 0
  932. MOV R0, R0
  933. SUB PC, PC, #4
  934. MOV R0, R0
  935. MOV R0, R0
  936. MOV R0, R0
  937. MOV R0, R0
  938. END DrainWriteBuffer;
  939. PROCEDURE -CurrentPC*(): ADDRESS;
  940. CODE
  941. MOV R0, PC
  942. END CurrentPC;
  943. PROCEDURE GetTimer*(): HUGEINT;
  944. VAR t: ARRAY 2 OF LONGINT;
  945. BEGIN
  946. REPEAT
  947. t[1] := SYSTEM.GET32(Platform.GlobalTimerCounterRegister1);
  948. t[0] := SYSTEM.GET32(Platform.GlobalTimerCounterRegister0);
  949. UNTIL t[1] = SYSTEM.GET32(Platform.GlobalTimerCounterRegister1);
  950. RETURN SYSTEM.VAL(HUGEINT,t);
  951. END GetTimer;
  952. (* ===== Multiprocessor booting ===== *)
  953. (** Initializes non-booting processors *)
  954. PROCEDURE InitProcessors*;
  955. VAR
  956. i: LONGINT;
  957. val: ARRAY 8 OF CHAR;
  958. BEGIN
  959. GetConfig("TraceCpu", val);
  960. traceCpus := val = "1";
  961. InstallHandler(HandleUPTimer, PrivateTimerIRQ);
  962. InstallHandler(TimerInterruptHandler, PrivateTimerIRQ);
  963. InitTicks;
  964. InitWatchdog;
  965. CleanDCache;
  966. DrainWriteBuffer;
  967. FOR i := 1 TO numProcessors - 1 DO
  968. StartProcessor(i, BootMP);
  969. END;
  970. END InitProcessors;
  971. PROCEDURE StartAll*;
  972. BEGIN
  973. END StartAll;
  974. (** Start core id on procedure p. *)
  975. PROCEDURE StartProcessor(id: LONGINT; p: PROCEDURE);
  976. VAR
  977. time: LONGINT;
  978. started: BOOLEAN;
  979. BEGIN
  980. IF traceCpus THEN
  981. Acquire(TraceOutput);
  982. Trace.String("Starting CPU");
  983. Trace.Int(id, 0);
  984. Trace.String(" on address ");
  985. Trace.Address(SYSTEM.VAL(ADDRESS, p));
  986. Trace.Ln;
  987. Release(TraceOutput)
  988. END;
  989. time := ticks + 5000;
  990. Initializer.secondaryProcId := id;
  991. Initializer.secondaryBootProc := SYSTEM.VAL(ADDRESS, p);
  992. FlushDCacheRange(ADDRESSOF(Initializer.secondaryProcId), 4);
  993. FlushDCacheRange(ADDRESSOF(Initializer.secondaryBootProc), 4);
  994. CODE
  995. SEV
  996. END;
  997. REPEAT
  998. started := id IN allProcessors;
  999. UNTIL started OR (time <= ticks);
  1000. IF id IN allProcessors THEN
  1001. IF traceCpus THEN
  1002. Acquire(TraceOutput);
  1003. Trace.String("Confirm: CPU");
  1004. Trace.Int(id, 0);
  1005. Trace.StringLn(" started");
  1006. Release(TraceOutput)
  1007. END
  1008. ELSE
  1009. Acquire(TraceOutput);
  1010. Trace.String("WARNING: Could not start CPU");
  1011. Trace.Int(id, 0);
  1012. Trace.Ln;
  1013. Release(TraceOutput)
  1014. END
  1015. END StartProcessor;
  1016. (** Init Memory for non-booting processors.
  1017. This enables MMU and copies the mapping of CPU0
  1018. *)
  1019. PROCEDURE InitMPMemory;
  1020. VAR
  1021. tbFlags: LONGINT;
  1022. BEGIN
  1023. IF enableCaching THEN
  1024. tbFlags := 7BH
  1025. ELSE
  1026. tbFlags := 0
  1027. END;
  1028. EnableMM(sysFirstLvlPtStart, tbFlags, 2000H + 1007H);
  1029. END InitMPMemory;
  1030. (** Init code fo a non-booting processor. No local variable allowed. *)
  1031. PROCEDURE {NOPAF} BootMP;
  1032. BEGIN
  1033. (* Setup stack *)
  1034. SYSTEM.LDPSR( 0, Platform.IRQMode + Platform.FIQDisabled + Platform.IRQDisabled );
  1035. SYSTEM.SETSP(sysIntStackStart + 1000H * 5);
  1036. SYSTEM.LDPSR( 0, Platform.UndefMode + Platform.FIQDisabled + Platform.IRQDisabled );
  1037. SYSTEM.SETSP(sysIntStackStart + 1000H * 6);
  1038. SYSTEM.LDPSR( 0, Platform.AbortMode + Platform.FIQDisabled + Platform.IRQDisabled );
  1039. SYSTEM.SETSP(sysIntStackStart + 1000H * 7);
  1040. SYSTEM.LDPSR( 0, Platform.SVCMode + Platform.FIQDisabled + Platform.IRQDisabled ); (* Disable interrupts, init SP, FP *)
  1041. SYSTEM.SETSP(sysIntStackStart + 1000H * 8);
  1042. SYSTEM.LDPSR( 0, Platform.SystemMode + Platform.FIQDisabled + Platform.IRQDisabled ); (* Disable interrupts, init SP, FP *)
  1043. SYSTEM.SETSP(sysIntStackStart + 1000H * 8);
  1044. Initializer.InvalidateDCache;
  1045. SetSmpMode;
  1046. EnableL1Cache;
  1047. EnableCoprocessors;
  1048. InitFPU;
  1049. InvalidateICache;
  1050. Initializer.InvalidateDCache;
  1051. InitMPMemory;
  1052. (*InvalidateDCacheRange(4096, SYSTEM.VAL(ADDRESS, LastAddress));*)
  1053. (*InvalidateDCacheRange(memSysHighStart, memSysHighStop - memSysHighStart);*)
  1054. (*CODE
  1055. DSB
  1056. END;*)
  1057. InitInterrupts;
  1058. EnableIRQ(PrivateTimerIRQ);
  1059. EnableInterrupts;
  1060. IF traceCpus THEN
  1061. Acquire(TraceOutput);
  1062. Trace.String("CPU "); Trace.Int(ID(), 0); Trace.StringLn(" started.");
  1063. Release(TraceOutput)
  1064. END;
  1065. Acquire(Processors);
  1066. INCL(allProcessors, ID());
  1067. Release(Processors);
  1068. InitTicks;
  1069. InitWatchdog;
  1070. start;
  1071. HALT(400)
  1072. END BootMP;
  1073. PROCEDURE KernelCallHLT*;
  1074. BEGIN
  1075. END KernelCallHLT;
  1076. (* function returning the number of processors that are available to Aos *)
  1077. PROCEDURE NumberOfProcessors*( ): LONGINT;
  1078. BEGIN
  1079. RETURN numberOfProcessors
  1080. END NumberOfProcessors;
  1081. (*! non portable code, for native Aos only *)
  1082. PROCEDURE SetNumberOfProcessors*(num: LONGINT);
  1083. BEGIN
  1084. numberOfProcessors := num;
  1085. END SetNumberOfProcessors;
  1086. (* ===== Context Switching ===== *)
  1087. (** Pushes state of the processor on the stack. Used in task-switching.
  1088. Does not exactly represent the layout of State. Pushed data is always used by JumpState.
  1089. *)
  1090. PROCEDURE -PushState*(CONST state: State);
  1091. CODE
  1092. LDR R0, [SP, #0] ; R0 <- address of state
  1093. ADD SP, SP, #8
  1094. LDR R1, [R0, #60] ; push PC
  1095. STR R1, [SP, #-4]!
  1096. LDR R1, [R0, #56] ; push LR
  1097. STR R1, [SP, #-4]!
  1098. LDR R1, [R0, #48] ; push FP
  1099. STR R1, [SP, #-4]!
  1100. LDR R1, [R0, #44] ; push R11
  1101. STR R1, [SP, #-4]!
  1102. LDR R1, [R0, #40] ; push R10
  1103. STR R1, [SP, #-4]!
  1104. LDR R1, [R0, #36] ; push R9
  1105. STR R1, [SP, #-4]!
  1106. LDR R1, [R0, #32] ; push R8
  1107. STR R1, [SP, #-4]!
  1108. LDR R1, [R0, #28] ; push R7
  1109. STR R1, [SP, #-4]!
  1110. LDR R1, [R0, #24] ; push R6
  1111. STR R1, [SP, #-4]!
  1112. LDR R1, [R0, #20] ; push R5
  1113. STR R1, [SP, #-4]!
  1114. LDR R1, [R0, #16] ; push R4
  1115. STR R1, [SP, #-4]!
  1116. LDR R1, [R0, #12] ; push R3
  1117. STR R1, [SP, #-4]!
  1118. LDR R1, [R0, #8] ; push R2
  1119. STR R1, [SP, #-4]!
  1120. LDR R1, [R0, #4] ; push R1
  1121. STR R1, [SP, #-4]!
  1122. LDR R1, [R0, #0] ; push R0
  1123. STR R1, [SP, #-4]!
  1124. LDR R1, [R0, #64] ; push SPSR
  1125. STR R1, [SP, #-4]!
  1126. END PushState;
  1127. (** Pops a processor state from the stack and restore it. Including jumping to the PC. *)
  1128. PROCEDURE -JumpState*;
  1129. CODE
  1130. ; Load PSR
  1131. LDR R0, [SP], #4
  1132. MSR CPSR_cxsf, R0 ; set CPSR
  1133. ; Load registers, including branch
  1134. LDMIA SP!, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, LR}
  1135. LDR PC, [SP], #4
  1136. END JumpState;
  1137. PROCEDURE CopyState*(CONST from: State; VAR to: State);
  1138. BEGIN
  1139. to.R[0] := from.R[0];
  1140. to.R[1] := from.R[1];
  1141. to.R[2] := from.R[2];
  1142. to.R[3] := from.R[3];
  1143. to.R[4] := from.R[4];
  1144. to.R[5] := from.R[5];
  1145. to.R[6] := from.R[6];
  1146. to.R[7] := from.R[7];
  1147. to.R[8] := from.R[8];
  1148. to.R[9] := from.R[9];
  1149. to.R[10] := from.R[10];
  1150. to.R[11] := from.R[11];
  1151. to.BP := from.BP;
  1152. to.SP := from.SP;
  1153. to.LR := from.LR;
  1154. to.PC := from.PC;
  1155. to.PSR := from.PSR;
  1156. END CopyState;
  1157. PROCEDURE -JumpToUserLevel*(userFP: ADDRESS);
  1158. CODE
  1159. ; this is an inlined procedure, so the 'userFP' parameter lies on top of the stack
  1160. LDR FP, [SP, #userFP] ; pop FP (FP is not a banked register)
  1161. ADD SP, SP, #4
  1162. MRS R0, CPSR ; get current PSR
  1163. BIC R0, R0, #1FH ; clear bits 4:0
  1164. ORR R0, R0, #1FH ; CPU mode = System
  1165. MSR CPSR_c, R0 ; switch mode
  1166. MOV SP, FP
  1167. LDMIA SP! , {FP, LR}
  1168. BX LR
  1169. END JumpToUserLevel;
  1170. PROCEDURE UpdateState*;
  1171. BEGIN
  1172. END UpdateState;
  1173. (** Save complete VFP/NEON state *)
  1174. PROCEDURE -FPUSaveFull*(VAR state: NEONState);
  1175. CODE
  1176. LDR R0, [SP, #state]
  1177. ADD SP, SP, #8
  1178. VST1 D0, R0
  1179. ADD R0, R0, #8
  1180. VST1 D1, R0
  1181. ADD R0, R0, #8
  1182. VST1 D2, R0
  1183. ADD R0, R0, #8
  1184. VST1 D3, R0
  1185. ADD R0, R0, #8
  1186. VST1 D4, R0
  1187. ADD R0, R0, #8
  1188. VST1 D5, R0
  1189. ADD R0, R0, #8
  1190. VST1 D6, R0
  1191. ADD R0, R0, #8
  1192. VST1 D7, R0
  1193. ADD R0, R0, #8
  1194. VST1 D8, R0
  1195. ADD R0, R0, #8
  1196. VST1 D9, R0
  1197. ADD R0, R0, #8
  1198. VST1 D10, R0
  1199. ADD R0, R0, #8
  1200. VST1 D11, R0
  1201. ADD R0, R0, #8
  1202. VST1 D12, R0
  1203. ADD R0, R0, #8
  1204. VST1 D13, R0
  1205. ADD R0, R0, #8
  1206. VST1 D14, R0
  1207. ADD R0, R0, #8
  1208. VST1 D15, R0
  1209. ADD R0, R0, #8
  1210. VSTR D16, R0, #0
  1211. ADD R0, R0, #8
  1212. VSTR D17, R0, #0
  1213. ADD R0, R0, #8
  1214. VSTR D18, R0, #0
  1215. ADD R0, R0, #8
  1216. VSTR D19, R0, #0
  1217. ADD R0, R0, #8
  1218. VSTR D20, R0, #0
  1219. ADD R0, R0, #8
  1220. VSTR D21, R0, #0
  1221. ADD R0, R0, #8
  1222. VSTR D22, R0, #0
  1223. ADD R0, R0, #8
  1224. VSTR D23, R0, #0
  1225. ADD R0, R0, #8
  1226. VSTR D24, R0, #0
  1227. ADD R0, R0, #8
  1228. VSTR D25, R0, #0
  1229. ADD R0, R0, #8
  1230. VSTR D26, R0, #0
  1231. ADD R0, R0, #8
  1232. VSTR D27, R0, #0
  1233. ADD R0, R0, #8
  1234. VSTR D28, R0, #0
  1235. ADD R0, R0, #8
  1236. VSTR D29, R0, #0
  1237. ADD R0, R0, #8
  1238. VSTR D30, R0, #0
  1239. ADD R0, R0, #8
  1240. VSTR D31, R0, #0
  1241. ADD R0, R0, #8
  1242. VMRS R1, FPSCR
  1243. STR R1, [R0, #0]
  1244. ADD R0, R0, #4
  1245. VMRS R1, FPEXC
  1246. STR R1, [R0, #0]
  1247. END FPUSaveFull;
  1248. (** Save minimal VFP/NEON state *)
  1249. PROCEDURE -FPUSaveMin*(VAR state: NEONState);
  1250. CODE
  1251. ADD SP, SP, #4
  1252. END FPUSaveMin;
  1253. (** Restore full VFP/NEON state *)
  1254. PROCEDURE -FPURestoreFull*(VAR state: NEONState);
  1255. CODE
  1256. LDR R0, [SP, #state];
  1257. ADD SP, SP, #8
  1258. VLD1 D0, R0
  1259. ADD R0, R0, #8
  1260. VLD1 D1, R0
  1261. ADD R0, R0, #8
  1262. VLD1 D2, R0
  1263. ADD R0, R0, #8
  1264. VLD1 D3, R0
  1265. ADD R0, R0, #8
  1266. VLD1 D4, R0
  1267. ADD R0, R0, #8
  1268. VLD1 D5, R0
  1269. ADD R0, R0, #8
  1270. VLD1 D6, R0
  1271. ADD R0, R0, #8
  1272. VLD1 D7, R0
  1273. ADD R0, R0, #8
  1274. VLD1 D8, R0
  1275. ADD R0, R0, #8
  1276. VLD1 D9, R0
  1277. ADD R0, R0, #8
  1278. VLD1 D10, R0
  1279. ADD R0, R0, #8
  1280. VLD1 D11, R0
  1281. ADD R0, R0, #8
  1282. VLD1 D12, R0
  1283. ADD R0, R0, #8
  1284. VLD1 D13, R0
  1285. ADD R0, R0, #8
  1286. VLD1 D14, R0
  1287. ADD R0, R0, #8
  1288. VLD1 D15, R0
  1289. ADD R0, R0, #8
  1290. VLDR D16, R0, #0
  1291. ADD R0, R0, #8
  1292. VLDR D17, R0, #0
  1293. ADD R0, R0, #8
  1294. VLDR D18, R0, #0
  1295. ADD R0, R0, #8
  1296. VLDR D19, R0, #0
  1297. ADD R0, R0, #8
  1298. VLDR D20, R0, #0
  1299. ADD R0, R0, #8
  1300. VLDR D21, R0, #0
  1301. ADD R0, R0, #8
  1302. VLDR D22, R0, #0
  1303. ADD R0, R0, #8
  1304. VLDR D23, R0, #0
  1305. ADD R0, R0, #8
  1306. VLDR D24, R0, #0
  1307. ADD R0, R0, #8
  1308. VLDR D25, R0, #0
  1309. ADD R0, R0, #8
  1310. VLDR D26, R0, #0
  1311. ADD R0, R0, #8
  1312. VLDR D27, R0, #0
  1313. ADD R0, R0, #8
  1314. VLDR D28, R0, #0
  1315. ADD R0, R0, #8
  1316. VLDR D29, R0, #0
  1317. ADD R0, R0, #8
  1318. VLDR D30, R0, #0
  1319. ADD R0, R0, #8
  1320. VLDR D31, R0, #0
  1321. ADD R0, R0, #8
  1322. LDR R1, [R0, #0]
  1323. VMSR FPSCR, R1
  1324. ADD R0, R0, #4
  1325. LDR R1, [R0, #0]
  1326. VMSR FPEXC, R1
  1327. END FPURestoreFull;
  1328. (** Restore minimal VFP/NEON state *)
  1329. PROCEDURE -FPURestoreMin*(VAR state: NEONState);
  1330. CODE
  1331. ADD SP, SP, #4
  1332. END FPURestoreMin;
  1333. (* ===== Interrupts ===== *)
  1334. (* Taken from Minos/Kernel.Mos *)
  1335. PROCEDURE EnableInterrupts*;
  1336. VAR cpsr: LONGINT;
  1337. BEGIN
  1338. SYSTEM.STPSR(0, cpsr);
  1339. cpsr := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, cpsr) - {7(*, 8*)});
  1340. SYSTEM.LDPSR(0, cpsr);
  1341. (*SYSTEM.PUT32(Platform.ICDDCR, {EnableSecure, EnableNonSecure});*)
  1342. END EnableInterrupts;
  1343. (* Taken from Minos/Kernel.Mos *)
  1344. PROCEDURE DisableInterrupts*;
  1345. VAR cpsr: LONGINT;
  1346. BEGIN
  1347. SYSTEM.STPSR(0, cpsr);
  1348. cpsr := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, cpsr) + {7(*, 8*)});
  1349. SYSTEM.LDPSR( 0, cpsr);
  1350. (*SYSTEM.PUT32(Platform.ICDDCR, {});*)
  1351. END DisableInterrupts;
  1352. (** AreInterruptsEnabled - returns TRUE if interrupts are enabled at the current processor level, FALSE otherwise *)
  1353. PROCEDURE AreInterruptsEnabled*(): BOOLEAN;
  1354. CODE
  1355. MRS R0, CPSR ; move CPSR to R0
  1356. TST R0, #80H ; was IBit set ?
  1357. MOVEQ R0, #1 ; no, interrupts are enabled
  1358. MOVNE R0, #0 ; yep, interrupts are disabled
  1359. END AreInterruptsEnabled;
  1360. (* InstallDefaultInterrupts - installs default interrupt handlers *)
  1361. PROCEDURE InstallDefaultInterrupts;
  1362. VAR p: PROCEDURE; base: ADDRESS;
  1363. i, int: LONGINT;
  1364. BEGIN
  1365. base := 0;
  1366. (* Install all *Glue procedures. *)
  1367. p := undefGlue; SYSTEM.PUT32(base + Undef, SYSTEM.VAL(LONGINT, p));
  1368. p := SWIGlue; SYSTEM.PUT32(base + Swi, SYSTEM.VAL(LONGINT, p));
  1369. p := prefetchGlue; SYSTEM.PUT32(base + Prefetch, SYSTEM.VAL(LONGINT, p));
  1370. p := dataGlue; SYSTEM.PUT32(base + Data, SYSTEM.VAL(LONGINT, p));
  1371. p := DefaultIRQ; SYSTEM.PUT32(base + Irq, SYSTEM.VAL(LONGINT, p));
  1372. p := fiqGlue; SYSTEM.PUT32(base + Fiq, SYSTEM.VAL(LONGINT, p));
  1373. (* Install default exception handlers *)
  1374. InstallExceptionHandler(DefaultUndefined, Undef);
  1375. InstallExceptionHandler(DefaultSWI, Swi);
  1376. InstallExceptionHandler(DefaultPrefetchAbort, Prefetch);
  1377. InstallExceptionHandler(DefaultDataAbort, Data);
  1378. InstallExceptionHandler(DefaultFIQ, Fiq);
  1379. FOR int := 0 TO MaxIRQ DO
  1380. FOR i := 0 TO MaxIRQHandlers -1 DO
  1381. irqHandler[int, i] := NIL
  1382. END
  1383. END;
  1384. END InstallDefaultInterrupts;
  1385. (* DefaultUndef - default handler for undefined instruction exceptions *)
  1386. PROCEDURE DefaultUndefined (VAR state: State);
  1387. VAR
  1388. instn: LONGINT;
  1389. BEGIN
  1390. instn := SYSTEM.GET32(state.PC);
  1391. Acquire(TraceOutput);
  1392. Trace.Ln;
  1393. Trace.StringLn("Undefined Instruction Trap:");
  1394. Trace.String(" pc: "); Trace.Address(state.PC); Trace.Ln;
  1395. Trace.String(" instruction: "); Trace.Hex(instn, -8); Trace.Ln;
  1396. Trace.String(" CPU: "); Trace.Int(ID(), 0); Trace.Ln;
  1397. TraceState(state);
  1398. Trace.String("Kernel Halted");
  1399. Release(TraceOutput);
  1400. LOOP END
  1401. END DefaultUndefined;
  1402. (* DefaultSWI - default handler for software interrupts *)
  1403. PROCEDURE DefaultSWI (VAR state: State);
  1404. BEGIN
  1405. Acquire(TraceOutput);
  1406. Trace.Ln;
  1407. Trace.StringLn("Software Interrupt:");
  1408. Trace.String(" pc: "); Trace.Address(state.PC); Trace.Ln;
  1409. Trace.String(" number: "); Trace.Int(state.INT, -8); Trace.Ln;
  1410. Trace.String(" CPU: "); Trace.Int(ID(), 0); Trace.Ln;
  1411. TraceState(state);
  1412. Trace.Ln;
  1413. Trace.String("Kernel halted.");
  1414. Release(TraceOutput);
  1415. LOOP END
  1416. END DefaultSWI;
  1417. (* Instruction Prefetch abort *)
  1418. PROCEDURE DefaultPrefetchAbort (VAR state: State);
  1419. BEGIN
  1420. Acquire(TraceOutput);
  1421. Trace.String("Prefetch abort at location: "); Trace.Address(state.PC); Trace.Ln;
  1422. Trace.String(" CPU: "); Trace.Int(ID(), 0); Trace.Ln;
  1423. Trace.String(" FP: "); Trace.Address(state.BP); Trace.Ln;
  1424. Trace.String("SPSR: "); Trace.Hex(state.PSR, -8); Trace.Ln;
  1425. TraceState(state);
  1426. Trace.Ln;
  1427. Trace.StringLn("Kernel Halted");
  1428. Release(TraceOutput);
  1429. LOOP END;
  1430. END DefaultPrefetchAbort;
  1431. (* DefaultDataAbort - default handler for data abort exceptions *)
  1432. PROCEDURE DefaultDataAbort (VAR state: State);
  1433. VAR
  1434. faultAdr: ADDRESS;
  1435. faultStatus: LONGINT;
  1436. stack: Stack;
  1437. BEGIN
  1438. GetPageFault(faultAdr, faultStatus);
  1439. (*getStack(stack);
  1440. IF ~ExtendStack(stack, faultAdr) THEN*)
  1441. Acquire(TraceOutput);
  1442. IF faultAdr < 4 * k THEN
  1443. Trace.StringLn("NIL pointer exception");
  1444. Trace.String("pc: "); Trace.Address(state.PC); Trace.Ln
  1445. ELSE
  1446. Trace.StringLn("Data Abort Trap");
  1447. Trace.String("pc: "); Trace.Address(state.PC); Trace.Ln;
  1448. Trace.String("instn: "); Trace.Address(SYSTEM.GET32(state.PC)); Trace.Ln;
  1449. Trace.String("address: "); Trace.Address(faultAdr); Trace.Ln;
  1450. Trace.String("status: "); Trace.Address(faultStatus); Trace.Ln
  1451. END;
  1452. TraceState(state);
  1453. Trace.Ln; Trace.StringLn("Kernel Halted.");
  1454. Release(TraceOutput);
  1455. LOOP END
  1456. (*END*)
  1457. END DefaultDataAbort;
  1458. (* DefaultIRQ - default handler for IRQs *)
  1459. PROCEDURE DefaultIRQ;
  1460. BEGIN
  1461. Acquire(TraceOutput);
  1462. Trace.StringLn("(IRQ)");
  1463. Trace.String(" CPU: "); Trace.Address(ID()); Trace.Ln;
  1464. Trace.Ln; Trace.StringLn("Kernel Halted");
  1465. Release(TraceOutput);
  1466. LOOP END
  1467. END DefaultIRQ;
  1468. (* DefaultFIQ - default handler for fast interrupts *)
  1469. (*PROCEDURE DefaultFIQ;
  1470. BEGIN
  1471. Trace.StringLn("Fast IRQ Trap");
  1472. Trace.String(" CPU: "); Trace.Address(ID()); Trace.Ln;
  1473. Trace.String("Kernel halted.");
  1474. LOOP END
  1475. END DefaultFIQ;*)
  1476. PROCEDURE DefaultFIQ (VAR state: State);
  1477. BEGIN
  1478. Acquire(TraceOutput);
  1479. Trace.StringLn("Fast IRQ Trap");
  1480. Trace.String(" CPU: "); Trace.Address(ID()); Trace.Ln;
  1481. Trace.String("Kernel halted.");
  1482. Release(TraceOutput);
  1483. LOOP END
  1484. END DefaultFIQ;
  1485. PROCEDURE DummyISR(VAR state: State);
  1486. VAR i: LONGINT; icip : SET;
  1487. BEGIN
  1488. icip := SYSTEM.VAL(SET, SYSTEM.GET32((*IC +*) Platform.ICIP));
  1489. FOR i:=MinIRQ TO MaxIRQ DO
  1490. IF i IN icip THEN
  1491. state.INT := i;
  1492. dummyIRQHandler[state.INT].h(state);
  1493. END;
  1494. END;
  1495. END DummyISR;
  1496. (** EnableIRQ - enables a hardware interrupt (also done automatically by InstallHandler) *)
  1497. PROCEDURE InEnableIRQ(num: LONGINT);
  1498. BEGIN
  1499. ASSERT((MinIRQ <= num) & (num<= MaxIRQ));
  1500. (*IF TRUE OR (num = 53) THEN Trace.StringLn("Enable USB IRQ") END;*)
  1501. SYSTEM.PUT32(Platform.ICDISER + 4 * (num DIV 32) , {num MOD 32});
  1502. END InEnableIRQ;
  1503. PROCEDURE EnableIRQ*(int: LONGINT);
  1504. BEGIN
  1505. Acquire(Interrupts);
  1506. InEnableIRQ(int);
  1507. Release(Interrupts)
  1508. END EnableIRQ;
  1509. (** DisableIRQ - disables a hardware interrupt (also done automatically by RemoveHandler) *)
  1510. PROCEDURE InDisableIRQ(num: LONGINT);
  1511. BEGIN
  1512. ASSERT((MinIRQ <= num) & (num <= MaxIRQ));
  1513. (*IF TRUE OR (num = 53) THEN Trace.StringLn("Disable USB IRQ") END;*)
  1514. SYSTEM.PUT32(Platform.ICDICER + 4 * (num DIV 32) , {num MOD 32});
  1515. END InDisableIRQ;
  1516. PROCEDURE DisableIRQ*(int: LONGINT);
  1517. BEGIN
  1518. Acquire(Interrupts);
  1519. InDisableIRQ(int);
  1520. Release(Interrupts)
  1521. END DisableIRQ;
  1522. PROCEDURE IsIRQEnabled(int: LONGINT): BOOLEAN;
  1523. VAR
  1524. enabled: BOOLEAN;
  1525. reg: SET;
  1526. BEGIN
  1527. Acquire(Interrupts);
  1528. SYSTEM.GET(Platform.ICDISER + 4 * (int DIV 32) , reg);
  1529. enabled := (int MOD 32) IN reg;
  1530. Release(Interrupts);
  1531. RETURN enabled
  1532. END IsIRQEnabled;
  1533. (** InstallHandler - installs a interrupt handler & enable IRQ if necessary.
  1534. On entry to h interrupts are disabled and may be enabled with XXXXX. After handling the interrupt
  1535. the state of interrupts are restored. The acknowledgement of a hardware interrupt is done automatically.
  1536. IRQs are mapped from MinIRQ to MaxIRQ. *)
  1537. PROCEDURE InstallHandler*(h: Handler; int: LONGINT);
  1538. VAR
  1539. i: LONGINT;
  1540. BEGIN
  1541. (*NEW(n);*) (* outside locked region, to allow gc *)
  1542. i := 0;
  1543. WHILE irqHandler[int, i] # NIL DO
  1544. INC(i)
  1545. END;
  1546. Acquire(Interrupts);
  1547. (* IRQGlue may traverse list while it is being modified. *)
  1548. irqHandler[int, i] := h;
  1549. IF DummyTest THEN
  1550. irqHandler[int, i] := DummyISR;
  1551. dummyIRQHandler[int].h := h;
  1552. END;
  1553. IF (int >= MinIRQ) & (int <= MaxIRQ) THEN InEnableIRQ(int) END;
  1554. Release(Interrupts);
  1555. IF traceInterrupts THEN
  1556. Acquire(TraceOutput);
  1557. Trace.String("[Machine]InstallHandler: h = 0x"); Trace.Address(SYSTEM.VAL(LONGINT, h));
  1558. Trace.String("; int = "); Trace.Address(int);
  1559. Trace.String("; IRQMask = 0x"); Trace.Address(SYSTEM.VAL(LONGINT, IRQMask));
  1560. Trace.Ln;
  1561. Release(TraceOutput)
  1562. END
  1563. END InstallHandler;
  1564. PROCEDURE RemoveHandler * (h: Handler; int: LONGINT);
  1565. END RemoveHandler;
  1566. PROCEDURE InstallExceptionHandler * (h: Handler; e: LONGINT);
  1567. BEGIN
  1568. CASE e OF
  1569. Undef: undefHandler := h
  1570. |Swi: swiHandler := h
  1571. |Prefetch: prefetchHandler := h
  1572. |Data: dataHandler := h
  1573. |Fiq: fiqHandler := h
  1574. ELSE
  1575. Trace.String("Unknown exception offset: ");
  1576. Trace.Int(e, 0);
  1577. Trace.Ln;
  1578. HALT(99)
  1579. END
  1580. END InstallExceptionHandler;
  1581. (*
  1582. IRQGlue - every IRQ enters through this handler. It reads the IRR (Interrupt Request Register) of the PIC and calls the
  1583. appropriate handlers for each pending IRQ. A problem (which caused a nice debugging session of ~1 day...) is this
  1584. 'VAR state: State' parameter. Theoretically, a interrupt handler can change the values of this field to continue execution in
  1585. a different process, e.g. the scheduler works that way. This means that we can't call the handlers of every pending IRQ in
  1586. one loop - we must exit this procedure after each handled IRQ.
  1587. - routine has been changed so that all handlers of pending interrupts will be called
  1588. - using ICIP (interrupt Pending Register) instead of IRR (Interrupt Request Register)
  1589. - after handler call we don't turn interrupts off explicitly
  1590. *)
  1591. PROCEDURE {NOPAF} IRQGlue;
  1592. CODE
  1593. CLREX
  1594. SUB SP, SP, #72 ; Room for the State record
  1595. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1596. MOV R0, R0
  1597. ADD SP, SP, #60
  1598. SUB R0, LR, #4 ; return address = LR-4
  1599. STR R0, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1600. MRS R0, SPSR ; get saved PSR
  1601. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1602. SUB SP, SP, #68
  1603. MOV R11, SP
  1604. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1605. STR R5, [SP, #-4]! ; push value (type tag)
  1606. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1607. BL IRQCaller
  1608. LDR R11, [SP], #4
  1609. ADD SP, SP, #4
  1610. ADD SP, SP, #72 ; adjust SP & remove PAF
  1611. LDR R0, [R11, #64] ; load 'State.PSR'
  1612. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1613. LDR R0, [R11, #60] ; load 'State.PC'...
  1614. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1615. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1616. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1617. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1618. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1619. LDR R11, [R11, #44]
  1620. MOVS PC, LR ; SPSR -> CPSR & return
  1621. ; Data section
  1622. state: d32 stateTag ; address of stateTag
  1623. END IRQGlue;
  1624. (** Calls all handlers for all pending IRQs.
  1625. Is called by IRQGlue.
  1626. *)
  1627. PROCEDURE IRQCaller(VAR state: State);
  1628. VAR i, reg, irq, ack, count: LONGINT; handler: Handler; icip: SET;
  1629. BEGIN
  1630. ack := SYSTEM.GET32(Platform.ICCIAR);
  1631. (* service this irq *)
  1632. irq := ack MOD 1024;
  1633. IF irq # 1023 THEN (* not a spurious IRQ *)
  1634. state.INT := irq;
  1635. IF (MinIRQ <= irq) & (irq<= MaxIRQ) THEN
  1636. count := 0;
  1637. handler := irqHandler[irq, count];
  1638. WHILE (handler # NIL) & (count < MaxIRQHandlers - 1) DO
  1639. handler(state);
  1640. DisableInterrupts; (* handler may have reactivated interrupts *)
  1641. INC(count);
  1642. handler := irqHandler[irq, count];
  1643. END;
  1644. SYSTEM.PUT32(Platform.ICCEOIR, ack);
  1645. END;
  1646. END;
  1647. (* service pending IRQs *)
  1648. FOR reg := 0 TO 2 DO
  1649. SYSTEM.GET( Platform.ICDISPR+reg*4, icip );
  1650. i := 0;
  1651. WHILE (i <= 31) & (icip # {}) DO
  1652. IF (i IN icip) THEN
  1653. icip := icip - {i};
  1654. irq := i+reg*32;
  1655. (* Do not service pending interrupts that are disabled: this allows state triggered interrupts to be
  1656. * handled by software in an interrupt process. *)
  1657. IF IsIRQEnabled(irq) & (irq # PrivateTimerIRQ) THEN
  1658. (*Trace.String("Pending IRQ "); Trace.Int(irq, 0); Trace.Ln;*)
  1659. count := 0;
  1660. state.INT := irq;
  1661. handler := irqHandler[irq, count];
  1662. WHILE (handler # NIL) & (count < MaxIRQHandlers - 1) DO
  1663. handler(state);
  1664. DisableInterrupts; (* handler may have reactivated interrupts *)
  1665. INC(count);
  1666. handler := irqHandler[irq, count]
  1667. END;
  1668. SYSTEM.PUT32(Platform.ICCEOIR, irq); (* end of interrupt *)
  1669. SYSTEM.PUT32(Platform.ICDICPR+reg*4, {i}); (* clear pending bit *)
  1670. END
  1671. END;
  1672. INC( i )
  1673. END
  1674. END;
  1675. END IRQCaller;
  1676. (** Undefined Exception Handler. Saves the processor state and calls the registered handler. *)
  1677. PROCEDURE {NOPAF} undefGlue;
  1678. CODE
  1679. CLREX
  1680. SUB SP, SP, #72 ; Room for the State record
  1681. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1682. MOV R0, R0
  1683. ADD SP, SP, #60
  1684. SUB R0, LR, #4 ; return address = LR-4
  1685. STR R0, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1686. MRS R0, SPSR ; get saved PSR
  1687. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1688. LDR R0, [PC, #undefined-8-$] ; save -Undef in the INT field
  1689. STR R0, [SP], #4
  1690. SUB SP, SP, #72
  1691. MOV R11, SP
  1692. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1693. STR R5, [SP, #-4]! ; push value (type tag)
  1694. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1695. LDR R0, [PC,#handler-8-$]
  1696. LDR R0, [R0, #0]
  1697. BLX R0
  1698. LDR R11, [SP], #4
  1699. ADD SP, SP, #4
  1700. ADD SP, SP, #72 ; adjust SP & remove PAF
  1701. LDR R0, [R11, #64] ; load 'State.PSR'
  1702. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1703. LDR R0, [R11, #60] ; load 'State.PC'...
  1704. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1705. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1706. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1707. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1708. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1709. LDR R11, [R11, #44]
  1710. MOVS PC, LR ; SPSR -> CPSR & return
  1711. ; Data section
  1712. state: d32 stateTag ; address of stateTag
  1713. handler: d32 undefHandler ; handler
  1714. undefined: d32 -Undef ; INT number for undefined instructions
  1715. END undefGlue;
  1716. (**
  1717. * Software Interrupt Handler. Saves the processor state and calls the registered handler.
  1718. * The SWI number is stored into the INT field of the state record.
  1719. *)
  1720. PROCEDURE {NOPAF} SWIGlue;
  1721. CODE
  1722. SUB SP, SP, #72 ; Room for the State record
  1723. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1724. MOV R0, R0
  1725. ADD SP, SP, #60
  1726. SUB R1, LR, #4 ; return address = LR-4
  1727. STR R1, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1728. MRS R0, SPSR ; get saved PSR
  1729. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1730. LDR R0, [R1, #0] ; Load SWI instruction
  1731. LDR R2, [PC, #HFFFFFF-8-$]
  1732. AND R0, R0, R2 ; R0 MOD 1000000 = SWI number
  1733. STR R0, [SP], #4 ; push SWI number as INT. SP points to offset 72
  1734. SUB SP, SP, #72 ; Update SP to correct location
  1735. MOV R11, SP
  1736. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1737. STR R5, [SP, #-4]! ; push value (type tag)
  1738. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1739. LDR R0, [PC,#handler-8-$]
  1740. LDR R0, [R0, #0]
  1741. BLX R0
  1742. LDR R11, [SP], #4
  1743. ADD SP, SP, #4
  1744. ADD SP, SP, #72 ; adjust SP & remove PAF
  1745. LDR R0, [R11, #64] ; load 'State.PSR'
  1746. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1747. LDR R0, [R11, #60] ; load 'State.PC'...
  1748. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1749. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1750. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1751. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1752. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1753. LDR R11, [R11, #44]
  1754. MOVS PC, LR ; SPSR -> CPSR & return
  1755. ; Data section
  1756. state: d32 stateTag ; address of stateTag
  1757. HFFFFFF: d32 0FFFFFFH ; SWI number mask
  1758. handler: d32 swiHandler ; swiHandler
  1759. END SWIGlue;
  1760. (**
  1761. * Prefetch Abort Handler. Saves the processor state and calls the registered handler.
  1762. * The PC field of the state record holds the address at which the prefetch fault occurred.
  1763. *)
  1764. PROCEDURE {NOPAF} prefetchGlue;
  1765. CODE
  1766. CLREX
  1767. SUB SP, SP, #72 ; Room for the State record
  1768. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1769. MOV R0, R0
  1770. ADD SP, SP, #60
  1771. SUB R0, LR, #4 ; return address = LR-4
  1772. STR R0, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1773. MRS R0, SPSR ; get saved PSR
  1774. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1775. LDR R0, [PC, #prefetchAbort-8-$] ; save -Data in the INT field
  1776. STR R0, [SP], #4
  1777. SUB SP, SP, #72
  1778. MOV R11, SP
  1779. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1780. STR R5, [SP, #-4]! ; push value (type tag)
  1781. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1782. LDR R0, [PC,#handler-8-$]
  1783. LDR R0, [R0, #0]
  1784. BLX R0
  1785. LDR R11, [SP], #4
  1786. ADD SP, SP, #4
  1787. ADD SP, SP, #72 ; adjust SP & remove PAF
  1788. LDR R0, [R11, #64] ; load 'State.PSR'
  1789. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1790. LDR R0, [R11, #60] ; load 'State.PC'...
  1791. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1792. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1793. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1794. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1795. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1796. LDR R11, [R11, #44]
  1797. MOVS PC, LR ; SPSR -> CPSR & return
  1798. ; Data section
  1799. state: d32 stateTag ; address of stateTag
  1800. handler: d32 prefetchHandler ; handler
  1801. prefetchAbort: d32 -Prefetch ; prefetch INT number
  1802. END prefetchGlue;
  1803. (**
  1804. * Data Abort Handler. Saves the processor state and calls the registered handler.
  1805. * Use procedure GetPageFault to get abort status and address.
  1806. *)
  1807. PROCEDURE {NOPAF} dataGlue;
  1808. CODE
  1809. CLREX
  1810. SUB SP, SP, #72 ; Room for the State record
  1811. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1812. MOV R0, R0
  1813. ADD SP, SP, #60
  1814. SUB R0, LR, #8 ; return address = LR-8
  1815. STR R0, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1816. MRS R0, SPSR ; get saved PSR
  1817. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1818. LDR R0, [PC, #dataAbort-8-$] ; save -Data in the INT field
  1819. STR R0, [SP], #4
  1820. SUB SP, SP, #72
  1821. MOV R11, SP
  1822. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1823. STR R5, [SP, #-4]! ; push value (type tag)
  1824. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1825. LDR R0, [PC,#handler-8-$]
  1826. LDR R0, [R0, #0]
  1827. BLX R0
  1828. LDR R11, [SP], #4
  1829. ADD SP, SP, #4
  1830. ADD SP, SP, #72 ; adjust SP & remove PAF
  1831. LDR R0, [R11, #64] ; load 'State.PSR'
  1832. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1833. LDR R0, [R11, #60] ; load 'State.PC'...
  1834. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1835. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1836. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1837. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1838. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1839. LDR R11, [R11, #44]
  1840. MOVS PC, LR ; SPSR -> CPSR & return
  1841. ; Data section
  1842. state: d32 stateTag ; address of stateTag
  1843. handler: d32 dataHandler ; address of the handler variable
  1844. dataAbort: d32 -Data
  1845. END dataGlue;
  1846. (** Fast Interrupt Handler. Saves the processor state and calls the registered handler *)
  1847. PROCEDURE {NOPAF} fiqGlue;
  1848. CODE
  1849. CLREX
  1850. SUB SP, SP, #72 ; Room for the State record
  1851. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1852. MOV R0, R0
  1853. ADD SP, SP, #60
  1854. SUB R0, LR, #4 ; return address = LR-4
  1855. STR R0, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1856. MRS R0, SPSR ; get saved PSR
  1857. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1858. SUB SP, SP, #68
  1859. MOV R11, SP
  1860. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1861. STR R5, [SP, #-4]! ; push value (type tag)
  1862. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1863. BL fiqHandler
  1864. LDR R11, [SP], #4
  1865. ADD SP, SP, #4
  1866. ADD SP, SP, #72 ; adjust SP & remove PAF
  1867. LDR R0, [R11, #64] ; load 'State.PSR'
  1868. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1869. LDR R0, [R11, #60] ; load 'State.PC'...
  1870. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1871. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1872. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1873. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1874. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1875. LDR R11, [R11, #44]
  1876. MOVS PC, LR ; SPSR -> CPSR & return
  1877. ; Data section
  1878. state: d32 stateTag ; address of stateTag
  1879. END fiqGlue;
  1880. (** Initializes IRQ handling. *)
  1881. PROCEDURE InitInterrupts*;
  1882. CONST
  1883. EnableSecure=0;
  1884. EnableNonSecure=1;
  1885. NumberIRQs = 96;
  1886. VAR p: PROCEDURE; i: LONGINT;
  1887. BEGIN
  1888. Acquire(Interrupts);
  1889. IRQMask := {};
  1890. p := IRQGlue;
  1891. SYSTEM.PUT32(InterruptVector + Irq, SYSTEM.VAL(LONGINT, p)); (* install new IRQ handler *)
  1892. SYSTEM.PUT32(Platform.ICDDCR, 0);
  1893. FOR i := 32 DIV 16 TO (NumberIRQs-1) DIV 16 (* 2 bits per IRQ *) DO
  1894. SYSTEM.PUT32(Platform.ICDICFR+i*4, 0);
  1895. END;
  1896. FOR i := 0 TO (NumberIRQs-1) DIV 4 (* 8 bits per IRQ *) DO
  1897. SYSTEM.PUT32(Platform.ICDIPR+i*4, LONGINT(0A0A0A0A0H)); (* set priority of each interrupt to 160 *)
  1898. END;
  1899. FOR i := (32 DIV 4) TO (NumberIRQs-1) DIV 4 (* 8 bits per IRQ *) DO
  1900. SYSTEM.PUT32(Platform.ICDIPTR+i*4, 1010101H); (* reset interrupt targets to processor 0 *)
  1901. END;
  1902. (* disable all interrupt forwardings *)
  1903. FOR i := 0 TO (NumberIRQs-1) DIV 32 (* 1 bit per IRQ *) DO
  1904. SYSTEM.PUT32(Platform.ICDICER+i*4, LONGINT(0FFFFFFFFH));
  1905. END;
  1906. SYSTEM.PUT32(Platform.ICCPMR, 0F0H);
  1907. SYSTEM.PUT32(Platform.ICCICR, {0,1,2});
  1908. SYSTEM.PUT32(Platform.ICCBPR, 0);
  1909. SYSTEM.PUT32(Platform.ICDDCR, {EnableSecure, EnableNonSecure});
  1910. Release(Interrupts);
  1911. (*InvalidateDCache(dCacheBase);*)
  1912. (*EnableIRQ(PrivateTimerIRQ);*)
  1913. END InitInterrupts;
  1914. (** Restore silent, infinitly-looping exception handlers *)
  1915. PROCEDURE EndInterrupts;
  1916. BEGIN
  1917. SYSTEM.PUT32(InterruptVector + Undef, InterruptVector + Undef);
  1918. SYSTEM.PUT32(InterruptVector + Swi, InterruptVector + Swi);
  1919. SYSTEM.PUT32(InterruptVector + Prefetch, InterruptVector + Prefetch);
  1920. SYSTEM.PUT32(InterruptVector + Data, InterruptVector + Data);
  1921. SYSTEM.PUT32(InterruptVector + Irq, InterruptVector + Irq);
  1922. SYSTEM.PUT32(InterruptVector + Fiq, InterruptVector + Fiq);
  1923. END EndInterrupts;
  1924. (* GetExceptionState *)
  1925. PROCEDURE GetExceptionState*(VAR int: State; VAR exc: ExceptionState);
  1926. BEGIN
  1927. (* save all state information while interrupts are still disabled *)
  1928. exc.locks := BreakAll();
  1929. IF int.INT = -Undef THEN
  1930. exc.halt := 17;
  1931. exc.instn := SYSTEM.GET32(int.PC)
  1932. ELSIF int.INT = -Prefetch THEN
  1933. exc.pf := int.PC;
  1934. exc.status := -1;
  1935. exc.halt := 19
  1936. ELSIF int.INT = -Data THEN
  1937. GetPageFault(exc.pf, exc.status);
  1938. IF exc.pf < 4 * k THEN
  1939. (* NIL pointer *)
  1940. exc.halt := 18
  1941. ELSE
  1942. exc.halt := 19
  1943. END
  1944. ELSE
  1945. (* SWI *)
  1946. exc.halt := int.INT
  1947. END
  1948. END GetExceptionState;
  1949. PROCEDURE GetPageFault * (VAR adr: ADDRESS; VAR status: LONGINT);
  1950. CODE
  1951. MRC p15, 0, R0, C5, C0 ; load fault status register (FSR)
  1952. AND R0, R0, #0FFH ; only bits 7:0 are valid
  1953. LDR R1, [FP, #status]
  1954. STR R0, [R1, #0]
  1955. MRC p15, 0, R0, C6, C0 ; load fault address (FAR)
  1956. LDR R1, [FP, #adr]
  1957. STR R0, [R1, #0]
  1958. END GetPageFault;
  1959. (* FAR - returns the Fault Address Register. *)
  1960. PROCEDURE -FAR*(): LONGINT;
  1961. CODE
  1962. MRC p15, 0, R0, C6, C0 ; FAR is co-processor 15 register 6
  1963. END FAR;
  1964. (** Init global timer *)
  1965. PROCEDURE InitGlobalTimer;
  1966. CONST
  1967. TimerEnable=0;
  1968. BEGIN
  1969. (* disable first *)
  1970. SYSTEM.PUT32(Platform.GlobalTimerControlRegister, {});
  1971. (* reset global counter *)
  1972. SYSTEM.PUT32(Platform.GlobalTimerCounterRegister0, 0);
  1973. SYSTEM.PUT32(Platform.GlobalTimerCounterRegister1, 0);
  1974. SYSTEM.PUT32(Platform.GlobalTimerControlRegister, {TimerEnable});
  1975. END InitGlobalTimer;
  1976. (** Init private timer *)
  1977. PROCEDURE InitTicks;
  1978. CONST
  1979. TimerEnable=0;
  1980. AutoReload=1;
  1981. IRQEnable=2;
  1982. VAR
  1983. (* time slot in private timer counts; take into account that private timer clock frequency is equal to half of the CPU clock frequency *)
  1984. delay: LONGINT;
  1985. BEGIN
  1986. delay := ENTIER( ( LONGREAL(TimerPeriod) * 0.5D0 * LONGREAL(BootConfig.GetIntValue("CpuClockHz")) ) / 1.0D6 + 0.5D0 );
  1987. (* disable first *)
  1988. SYSTEM.PUT32(Platform.PrivateTimerControlRegister, {});
  1989. (*SYSTEM.PUT32(Platform.PrivateTimerCounterRegister, Delay);*)
  1990. SYSTEM.PUT32(Platform.PrivateLoadValueRegister, delay);
  1991. SYSTEM.PUT32(Platform.PrivateTimerControlRegister, {TimerEnable, AutoReload, IRQEnable});
  1992. END InitTicks;
  1993. PROCEDURE StopTicks;
  1994. BEGIN
  1995. SYSTEM.PUT32(Platform.PrivateTimerControlRegister, {});
  1996. END StopTicks;
  1997. (** Handle multiprocessor timer interrupt. *)
  1998. PROCEDURE HandleMPTimer*(VAR state: State);
  1999. BEGIN (* {interrupts off} *)
  2000. timer(ID(), state); (* rarely used *)
  2001. (* Clear timer interrupt *)
  2002. SYSTEM.PUT32(Platform.GlobalTimerInterruptStatusRegister, 1);
  2003. EnableInterrupts; (* enable interrupts before acquiring locks below - to avoid deadlock with StopAll. *)
  2004. Timeslice(state); (* fixme: check recursive interrupt *)
  2005. END HandleMPTimer;
  2006. (** Handle uniprocessor timer interrupt. *)
  2007. PROCEDURE HandleUPTimer(VAR state: State);
  2008. BEGIN (* {interrupts off} *)
  2009. timer(ID(), state);
  2010. SYSTEM.PUT32(Platform.PrivateTimerInterruptStatusRegister, 1);
  2011. (* Shutdown if requested *)
  2012. IF ~(ID() IN allProcessors) THEN ShutdownSecondary END;
  2013. IF enableWatchdog THEN PrivateWatchdog.Feed(Second) END;
  2014. Timeslice(state)
  2015. END HandleUPTimer;
  2016. (** Install a processor timer event handler. *)
  2017. PROCEDURE InstallEventHandler* (h: EventHandler);
  2018. BEGIN
  2019. IF h # NIL THEN timer := h ELSE timer := DummyEvent END
  2020. END InstallEventHandler;
  2021. PROCEDURE DummyEvent*(id: LONGINT; CONST state: State);
  2022. BEGIN
  2023. END DummyEvent;
  2024. PROCEDURE DummyTimeslice*(VAR state: State);
  2025. BEGIN
  2026. END DummyTimeslice;
  2027. PROCEDURE DummyIRQ*;
  2028. BEGIN
  2029. END DummyIRQ;
  2030. PROCEDURE IRQBeginPrinter;
  2031. BEGIN
  2032. Trace.StringLn("IRQ BEGIN");
  2033. END IRQBeginPrinter;
  2034. PROCEDURE IRQEndPrinter;
  2035. BEGIN
  2036. Trace.StringLn("IRQ END");
  2037. END IRQEndPrinter;
  2038. (* Timer interrupt handler. *)
  2039. PROCEDURE TimerInterruptHandler(VAR state: State);
  2040. BEGIN
  2041. IF ID() = 0 THEN
  2042. INC(ticks);
  2043. DEC(eventCount);
  2044. IF eventCount = 0 THEN
  2045. eventCount := eventMax; event(state)
  2046. END;
  2047. END
  2048. END TimerInterruptHandler;
  2049. (* Set timer upcall. The handler procedure will be called at a rate of Second/divisor Hz. *)
  2050. PROCEDURE InstallTickHandler(handler: Handler; divisor: LONGINT);
  2051. BEGIN
  2052. eventMax := divisor; event := handler;
  2053. eventCount := eventMax
  2054. END InstallTickHandler;
  2055. (* ===== Low-Level Locks ===== *)
  2056. (* Initializes spinlocks. This is not exported in Intel version. *)
  2057. PROCEDURE InitLocks;
  2058. VAR
  2059. i: LONGINT;
  2060. BEGIN
  2061. FOR i := 0 TO MaxLock - 1 DO
  2062. lock[i].locked := FALSE
  2063. END;
  2064. END InitLocks;
  2065. PROCEDURE AcquirePreemption*(): LONGINT;
  2066. VAR
  2067. id: LONGINT;
  2068. BEGIN
  2069. id := ID();
  2070. INC(proc[id].preemptCount);
  2071. RETURN id
  2072. END AcquirePreemption;
  2073. PROCEDURE ReleasePreemption*;
  2074. VAR
  2075. id: LONGINT;
  2076. BEGIN
  2077. id := ID();
  2078. IF StrongChecks THEN
  2079. ASSERT(proc[id].preemptCount > 0);
  2080. END;
  2081. DEC(proc[id].preemptCount);
  2082. END ReleasePreemption;
  2083. PROCEDURE PreemptCount*(id: LONGINT): LONGINT;
  2084. BEGIN
  2085. IF StrongChecks THEN
  2086. ASSERT(id = ID());
  2087. END;
  2088. RETURN proc[id].preemptCount;
  2089. END PreemptCount;
  2090. (* Acquire spinlock 'lock'. Does not time out *)
  2091. PROCEDURE AcquireSpin(VAR lock: BOOLEAN); (* DEBUG: temporarily exported *)
  2092. CODE
  2093. CLREX
  2094. DMB
  2095. LDR R0, [FP, #lock]
  2096. MOV R1, #1
  2097. loop:
  2098. LDREXB R2, R0 ; R2 := lock
  2099. CMP R2, #0 ; if R2 != 0 => lock held, try again
  2100. BNE loop
  2101. STREXB R2, R1, R0 ; lock := R1
  2102. CMP R2, #0 ; if R2 # 0 exclusive write failed: try whole process again.
  2103. BNE loop
  2104. ;DSB ; Data Memory Barrier
  2105. END AcquireSpin;
  2106. (* Releases spinlock 'lock'. *)
  2107. PROCEDURE ReleaseSpin(VAR lock: BOOLEAN); (* DEBUG: temporarily exported *)
  2108. BEGIN
  2109. CODE
  2110. CLREX
  2111. DMB
  2112. END;
  2113. lock := FALSE;
  2114. (*CODE
  2115. loop:
  2116. LDR R0, [FP, #lock]
  2117. LDREX R1, R0
  2118. MOV R1, #0
  2119. STREX R2, R1, R0
  2120. CMP R2, #0
  2121. BNE loop
  2122. END;*)
  2123. (*CODE
  2124. DMB
  2125. DSB
  2126. LDR R0, [FP, #lock]
  2127. MCR P15, 0, R0, C7, C10, 4
  2128. END;*)
  2129. END ReleaseSpin;
  2130. (* Acquire lock. Disables interrupts. *)
  2131. PROCEDURE Acquire*(level: LONGINT);
  2132. VAR
  2133. id: LONGINT;
  2134. enabled: BOOLEAN;
  2135. BEGIN
  2136. enabled := AreInterruptsEnabled();
  2137. DisableInterrupts();
  2138. id := AcquirePreemption();
  2139. IF proc[id].locksHeld = {} THEN
  2140. proc[id].intStatus := enabled
  2141. END;
  2142. IF StrongChecks THEN
  2143. ASSERT(~AreInterruptsEnabled());
  2144. ASSERT((~enabled) OR (proc[id].locksHeld = {})); (* interrupts enabled => no locks held *)
  2145. ASSERT(~(level IN proc[id].locksHeld)) (* recursive locks not allowed *)
  2146. END;
  2147. AcquireSpin(lock[level].locked);
  2148. (* Now, we hold the lock *)
  2149. INCL(proc[id].locksHeld, level);
  2150. IF StrongChecks THEN (* no lower-level locks currently held by this processor *)
  2151. ASSERT((level = 0) OR (proc[id].locksHeld * {0..level-1} = {}));
  2152. END;
  2153. END Acquire;
  2154. (* Release lock. Enables interrupts if last lock held. *)
  2155. PROCEDURE Release*(level: LONGINT);
  2156. VAR
  2157. id: LONGINT;
  2158. BEGIN
  2159. id := ID();
  2160. IF StrongChecks THEN
  2161. ASSERT(~AreInterruptsEnabled());
  2162. ASSERT(level IN proc[id].locksHeld);
  2163. ASSERT(lock[level].locked # FALSE)
  2164. END;
  2165. EXCL(proc[id].locksHeld, level);
  2166. ReleaseSpin(lock[level].locked);
  2167. ReleasePreemption;
  2168. IF (proc[id].locksHeld = {}) & proc[id].intStatus THEN
  2169. EnableInterrupts
  2170. END;
  2171. END Release;
  2172. PROCEDURE AcquireAll*;
  2173. VAR
  2174. i: LONGINT;
  2175. BEGIN
  2176. FOR i := MaxLock - 1 TO 0 BY -1 DO
  2177. Acquire(i)
  2178. END
  2179. END AcquireAll;
  2180. PROCEDURE ReleaseAll*;
  2181. VAR
  2182. i: LONGINT;
  2183. BEGIN
  2184. FOR i := 0 TO MaxLock - 1 DO
  2185. Release(i)
  2186. END
  2187. END ReleaseAll;
  2188. (** Acquire a fine-grained lock on an active object. *)
  2189. PROCEDURE AcquireObject*(VAR locked: BOOLEAN);
  2190. BEGIN
  2191. AcquireSpin(locked)
  2192. END AcquireObject;
  2193. (** Release an active object lock. *)
  2194. PROCEDURE ReleaseObject*(VAR locked: BOOLEAN);
  2195. BEGIN
  2196. ReleaseSpin(locked)
  2197. END ReleaseObject;
  2198. (** Break all locks held by current processor (for exception handling). Returns levels released. *)
  2199. PROCEDURE BreakAll*(): SET;
  2200. VAR id, level: LONGINT; released: SET;
  2201. BEGIN
  2202. id := AcquirePreemption();
  2203. released := {};
  2204. FOR level := 0 TO MaxLock-1 DO
  2205. IF level IN proc[id].locksHeld THEN
  2206. lock[level].locked := FALSE; (* break the lock *)
  2207. EXCL(proc[id].locksHeld, level);
  2208. INCL(released, level)
  2209. END
  2210. END;
  2211. (*IF released = {} THEN
  2212. ASSERT(proc[id].nestCount = 0) (* no locks held *)
  2213. ELSE
  2214. ASSERT(proc[id].nestCount > 0); (* some locks held *)
  2215. proc[id].nestCount := 0 (* interrupt state will be restored later *)
  2216. END;*)
  2217. IF proc[id].preemptCount > 1 THEN INCL(released, Preemption) END;
  2218. proc[id].preemptCount := 0; (* clear preemption flag *)
  2219. RETURN released
  2220. END BreakAll; (* !!! interrupts are still off !!! *)
  2221. (* ===== Atomic Operations ===== *)
  2222. (* Atomic INC(x) *)
  2223. PROCEDURE -AtomicInc*(VAR x: LONGINT);
  2224. CODE
  2225. ;loop:
  2226. ; ADD R0, SP, #x ; R0 := ADR(x)
  2227. ; LDREX R1, R0 ; R1 := x
  2228. ; ADD R1, R1, #1 ; increment x
  2229. ; STREX R2, R1, R0
  2230. ; CMP R2, #0
  2231. ; BEQ loop ; if store failed, try again, else exit
  2232. ; ADD SP, SP, #4
  2233. LDR R0, [SP], #4
  2234. loop:
  2235. LDREX R1, R0
  2236. ADD R1, R1, #1
  2237. STREX R2, R1, R0
  2238. CMP R2, #0
  2239. BNE loop
  2240. END AtomicInc;
  2241. (* Atomic INC(x) *)
  2242. PROCEDURE -AtomicDec*(VAR x: LONGINT);
  2243. CODE
  2244. LDR R0, [SP], #4
  2245. loop:
  2246. LDREX R1, R0
  2247. SUB R1, R1, #1
  2248. STREX R2, R1, R0
  2249. CMP R2, #0
  2250. BNE loop
  2251. END AtomicDec;
  2252. PROCEDURE -AtomicAdd * (VAR x: LONGINT; y: LONGINT);
  2253. CODE
  2254. LDR R3, [SP, #y] ; R3 := y
  2255. LDR R0, [SP, #x] ; R0 := ADR(x)
  2256. loop:
  2257. LDREX R1, R0 ; R1 := x
  2258. ADD R1, R1, R3 ; increment x
  2259. STREX R2, R1, R0
  2260. CMP R2, #0
  2261. BNE loop ; if store failed, try again, else exit
  2262. ADD SP, SP, #8
  2263. END AtomicAdd;
  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] ; R0 := 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.