2
0

ARM.Machine.Mod 105 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602
  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. (* Send event instruction *)
  975. PROCEDURE -Sev;
  976. CODE
  977. SEV
  978. END Sev;
  979. (** Start core id on procedure p. *)
  980. PROCEDURE StartProcessor(id: LONGINT; p: PROCEDURE);
  981. VAR
  982. time, ticks0: LONGINT;
  983. started: BOOLEAN;
  984. sevCount: SIZE;
  985. BEGIN
  986. IF traceCpus THEN
  987. Acquire(TraceOutput);
  988. Trace.String("Starting CPU");
  989. Trace.Int(id, 0);
  990. Trace.String(" on address ");
  991. Trace.Address(SYSTEM.VAL(ADDRESS, p));
  992. Trace.Ln;
  993. Release(TraceOutput)
  994. END;
  995. Initializer.secondaryProcId := id;
  996. Initializer.secondaryBootProc := SYSTEM.VAL(ADDRESS, p);
  997. FlushDCacheRange(ADDRESSOF(Initializer.secondaryProcId), 4);
  998. FlushDCacheRange(ADDRESSOF(Initializer.secondaryBootProc), 4);
  999. (* wake up the other cores *)
  1000. Sev;
  1001. time := ticks + 1000;
  1002. sevCount := 0;
  1003. ticks0 := ticks;
  1004. REPEAT
  1005. started := id IN allProcessors;
  1006. (*! a workaround for rare but nevertheless occurring case when the other CPU does not wake up *)
  1007. IF ~started & (ticks - ticks0 > 1) THEN
  1008. Sev;
  1009. ticks0 := ticks;
  1010. INC(sevCount);
  1011. END;
  1012. UNTIL started OR (time <= ticks);
  1013. IF traceCpus THEN
  1014. Acquire(TraceOutput);
  1015. Trace.String("SEV call count="); Trace.Int(sevCount,0); Trace.Ln;
  1016. Release(TraceOutput);
  1017. END;
  1018. IF id IN allProcessors THEN
  1019. IF traceCpus THEN
  1020. Acquire(TraceOutput);
  1021. Trace.String("Confirm: CPU");
  1022. Trace.Int(id, 0);
  1023. Trace.StringLn(" started");
  1024. Release(TraceOutput)
  1025. END
  1026. ELSE
  1027. Acquire(TraceOutput);
  1028. Trace.String("WARNING: Could not start CPU");
  1029. Trace.Int(id, 0);
  1030. Trace.Ln;
  1031. Release(TraceOutput)
  1032. END
  1033. END StartProcessor;
  1034. (** Init Memory for non-booting processors.
  1035. This enables MMU and copies the mapping of CPU0
  1036. *)
  1037. PROCEDURE InitMPMemory;
  1038. VAR
  1039. tbFlags: LONGINT;
  1040. BEGIN
  1041. IF enableCaching THEN
  1042. tbFlags := 7BH
  1043. ELSE
  1044. tbFlags := 0
  1045. END;
  1046. EnableMM(sysFirstLvlPtStart, tbFlags, 2000H + 1007H);
  1047. END InitMPMemory;
  1048. (** Init code fo a non-booting processor. No local variable allowed. *)
  1049. PROCEDURE {NOPAF} BootMP;
  1050. BEGIN
  1051. (* Setup stack *)
  1052. SYSTEM.LDPSR( 0, Platform.IRQMode + Platform.FIQDisabled + Platform.IRQDisabled );
  1053. SYSTEM.SETSP(sysIntStackStart + 1000H * 5);
  1054. SYSTEM.LDPSR( 0, Platform.UndefMode + Platform.FIQDisabled + Platform.IRQDisabled );
  1055. SYSTEM.SETSP(sysIntStackStart + 1000H * 6);
  1056. SYSTEM.LDPSR( 0, Platform.AbortMode + Platform.FIQDisabled + Platform.IRQDisabled );
  1057. SYSTEM.SETSP(sysIntStackStart + 1000H * 7);
  1058. SYSTEM.LDPSR( 0, Platform.SVCMode + Platform.FIQDisabled + Platform.IRQDisabled ); (* Disable interrupts, init SP, FP *)
  1059. SYSTEM.SETSP(sysIntStackStart + 1000H * 8);
  1060. SYSTEM.LDPSR( 0, Platform.SystemMode + Platform.FIQDisabled + Platform.IRQDisabled ); (* Disable interrupts, init SP, FP *)
  1061. SYSTEM.SETSP(sysIntStackStart + 1000H * 8);
  1062. Initializer.InvalidateDCache;
  1063. SetSmpMode;
  1064. EnableL1Cache;
  1065. EnableCoprocessors;
  1066. InitFPU;
  1067. InvalidateICache;
  1068. Initializer.InvalidateDCache;
  1069. InitMPMemory;
  1070. (*InvalidateDCacheRange(4096, SYSTEM.VAL(ADDRESS, LastAddress));*)
  1071. (*InvalidateDCacheRange(memSysHighStart, memSysHighStop - memSysHighStart);*)
  1072. (*CODE
  1073. DSB
  1074. END;*)
  1075. InitInterrupts;
  1076. EnableIRQ(PrivateTimerIRQ);
  1077. EnableInterrupts;
  1078. IF traceCpus THEN
  1079. Acquire(TraceOutput);
  1080. Trace.String("CPU "); Trace.Int(ID(), 0); Trace.StringLn(" started.");
  1081. Release(TraceOutput)
  1082. END;
  1083. Acquire(Processors);
  1084. INCL(allProcessors, ID());
  1085. Release(Processors);
  1086. InitTicks;
  1087. InitWatchdog;
  1088. start;
  1089. HALT(400)
  1090. END BootMP;
  1091. PROCEDURE KernelCallHLT*;
  1092. BEGIN
  1093. END KernelCallHLT;
  1094. (* function returning the number of processors that are available to Aos *)
  1095. PROCEDURE NumberOfProcessors*( ): LONGINT;
  1096. BEGIN
  1097. RETURN numberOfProcessors
  1098. END NumberOfProcessors;
  1099. (*! non portable code, for native Aos only *)
  1100. PROCEDURE SetNumberOfProcessors*(num: LONGINT);
  1101. BEGIN
  1102. numberOfProcessors := num;
  1103. END SetNumberOfProcessors;
  1104. (* ===== Context Switching ===== *)
  1105. (** Pushes state of the processor on the stack. Used in task-switching.
  1106. Does not exactly represent the layout of State. Pushed data is always used by JumpState.
  1107. *)
  1108. PROCEDURE -PushState*(CONST state: State);
  1109. CODE
  1110. LDR R0, [SP, #0] ; R0 <- address of state
  1111. ADD SP, SP, #8
  1112. LDR R1, [R0, #60] ; push PC
  1113. STR R1, [SP, #-4]!
  1114. LDR R1, [R0, #56] ; push LR
  1115. STR R1, [SP, #-4]!
  1116. LDR R1, [R0, #48] ; push FP
  1117. STR R1, [SP, #-4]!
  1118. LDR R1, [R0, #44] ; push R11
  1119. STR R1, [SP, #-4]!
  1120. LDR R1, [R0, #40] ; push R10
  1121. STR R1, [SP, #-4]!
  1122. LDR R1, [R0, #36] ; push R9
  1123. STR R1, [SP, #-4]!
  1124. LDR R1, [R0, #32] ; push R8
  1125. STR R1, [SP, #-4]!
  1126. LDR R1, [R0, #28] ; push R7
  1127. STR R1, [SP, #-4]!
  1128. LDR R1, [R0, #24] ; push R6
  1129. STR R1, [SP, #-4]!
  1130. LDR R1, [R0, #20] ; push R5
  1131. STR R1, [SP, #-4]!
  1132. LDR R1, [R0, #16] ; push R4
  1133. STR R1, [SP, #-4]!
  1134. LDR R1, [R0, #12] ; push R3
  1135. STR R1, [SP, #-4]!
  1136. LDR R1, [R0, #8] ; push R2
  1137. STR R1, [SP, #-4]!
  1138. LDR R1, [R0, #4] ; push R1
  1139. STR R1, [SP, #-4]!
  1140. LDR R1, [R0, #0] ; push R0
  1141. STR R1, [SP, #-4]!
  1142. LDR R1, [R0, #64] ; push SPSR
  1143. STR R1, [SP, #-4]!
  1144. END PushState;
  1145. (** Pops a processor state from the stack and restore it. Including jumping to the PC. *)
  1146. PROCEDURE -JumpState*;
  1147. CODE
  1148. ; Load PSR
  1149. LDR R0, [SP], #4
  1150. MSR CPSR_cxsf, R0 ; set CPSR
  1151. ; Load registers, including branch
  1152. LDMIA SP!, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, LR}
  1153. LDR PC, [SP], #4
  1154. END JumpState;
  1155. PROCEDURE CopyState*(CONST from: State; VAR to: State);
  1156. BEGIN
  1157. to.R[0] := from.R[0];
  1158. to.R[1] := from.R[1];
  1159. to.R[2] := from.R[2];
  1160. to.R[3] := from.R[3];
  1161. to.R[4] := from.R[4];
  1162. to.R[5] := from.R[5];
  1163. to.R[6] := from.R[6];
  1164. to.R[7] := from.R[7];
  1165. to.R[8] := from.R[8];
  1166. to.R[9] := from.R[9];
  1167. to.R[10] := from.R[10];
  1168. to.R[11] := from.R[11];
  1169. to.BP := from.BP;
  1170. to.SP := from.SP;
  1171. to.LR := from.LR;
  1172. to.PC := from.PC;
  1173. to.PSR := from.PSR;
  1174. END CopyState;
  1175. PROCEDURE -JumpToUserLevel*(userFP: ADDRESS);
  1176. CODE
  1177. ; this is an inlined procedure, so the 'userFP' parameter lies on top of the stack
  1178. LDR FP, [SP, #userFP] ; pop FP (FP is not a banked register)
  1179. ADD SP, SP, #4
  1180. MRS R0, CPSR ; get current PSR
  1181. BIC R0, R0, #1FH ; clear bits 4:0
  1182. ORR R0, R0, #1FH ; CPU mode = System
  1183. MSR CPSR_c, R0 ; switch mode
  1184. MOV SP, FP
  1185. LDMIA SP! , {FP, LR}
  1186. BX LR
  1187. END JumpToUserLevel;
  1188. PROCEDURE UpdateState*;
  1189. BEGIN
  1190. END UpdateState;
  1191. (** Save complete VFP/NEON state *)
  1192. PROCEDURE -FPUSaveFull*(VAR state: NEONState);
  1193. CODE
  1194. LDR R0, [SP, #state]
  1195. ADD SP, SP, #8
  1196. VST1 D0, R0
  1197. ADD R0, R0, #8
  1198. VST1 D1, R0
  1199. ADD R0, R0, #8
  1200. VST1 D2, R0
  1201. ADD R0, R0, #8
  1202. VST1 D3, R0
  1203. ADD R0, R0, #8
  1204. VST1 D4, R0
  1205. ADD R0, R0, #8
  1206. VST1 D5, R0
  1207. ADD R0, R0, #8
  1208. VST1 D6, R0
  1209. ADD R0, R0, #8
  1210. VST1 D7, R0
  1211. ADD R0, R0, #8
  1212. VST1 D8, R0
  1213. ADD R0, R0, #8
  1214. VST1 D9, R0
  1215. ADD R0, R0, #8
  1216. VST1 D10, R0
  1217. ADD R0, R0, #8
  1218. VST1 D11, R0
  1219. ADD R0, R0, #8
  1220. VST1 D12, R0
  1221. ADD R0, R0, #8
  1222. VST1 D13, R0
  1223. ADD R0, R0, #8
  1224. VST1 D14, R0
  1225. ADD R0, R0, #8
  1226. VST1 D15, R0
  1227. ADD R0, R0, #8
  1228. VSTR D16, R0, #0
  1229. ADD R0, R0, #8
  1230. VSTR D17, R0, #0
  1231. ADD R0, R0, #8
  1232. VSTR D18, R0, #0
  1233. ADD R0, R0, #8
  1234. VSTR D19, R0, #0
  1235. ADD R0, R0, #8
  1236. VSTR D20, R0, #0
  1237. ADD R0, R0, #8
  1238. VSTR D21, R0, #0
  1239. ADD R0, R0, #8
  1240. VSTR D22, R0, #0
  1241. ADD R0, R0, #8
  1242. VSTR D23, R0, #0
  1243. ADD R0, R0, #8
  1244. VSTR D24, R0, #0
  1245. ADD R0, R0, #8
  1246. VSTR D25, R0, #0
  1247. ADD R0, R0, #8
  1248. VSTR D26, R0, #0
  1249. ADD R0, R0, #8
  1250. VSTR D27, R0, #0
  1251. ADD R0, R0, #8
  1252. VSTR D28, R0, #0
  1253. ADD R0, R0, #8
  1254. VSTR D29, R0, #0
  1255. ADD R0, R0, #8
  1256. VSTR D30, R0, #0
  1257. ADD R0, R0, #8
  1258. VSTR D31, R0, #0
  1259. ADD R0, R0, #8
  1260. VMRS R1, FPSCR
  1261. STR R1, [R0, #0]
  1262. ADD R0, R0, #4
  1263. VMRS R1, FPEXC
  1264. STR R1, [R0, #0]
  1265. END FPUSaveFull;
  1266. (** Save minimal VFP/NEON state *)
  1267. PROCEDURE -FPUSaveMin*(VAR state: NEONState);
  1268. CODE
  1269. ADD SP, SP, #4
  1270. END FPUSaveMin;
  1271. (** Restore full VFP/NEON state *)
  1272. PROCEDURE -FPURestoreFull*(VAR state: NEONState);
  1273. CODE
  1274. LDR R0, [SP, #state];
  1275. ADD SP, SP, #8
  1276. VLD1 D0, R0
  1277. ADD R0, R0, #8
  1278. VLD1 D1, R0
  1279. ADD R0, R0, #8
  1280. VLD1 D2, R0
  1281. ADD R0, R0, #8
  1282. VLD1 D3, R0
  1283. ADD R0, R0, #8
  1284. VLD1 D4, R0
  1285. ADD R0, R0, #8
  1286. VLD1 D5, R0
  1287. ADD R0, R0, #8
  1288. VLD1 D6, R0
  1289. ADD R0, R0, #8
  1290. VLD1 D7, R0
  1291. ADD R0, R0, #8
  1292. VLD1 D8, R0
  1293. ADD R0, R0, #8
  1294. VLD1 D9, R0
  1295. ADD R0, R0, #8
  1296. VLD1 D10, R0
  1297. ADD R0, R0, #8
  1298. VLD1 D11, R0
  1299. ADD R0, R0, #8
  1300. VLD1 D12, R0
  1301. ADD R0, R0, #8
  1302. VLD1 D13, R0
  1303. ADD R0, R0, #8
  1304. VLD1 D14, R0
  1305. ADD R0, R0, #8
  1306. VLD1 D15, R0
  1307. ADD R0, R0, #8
  1308. VLDR D16, R0, #0
  1309. ADD R0, R0, #8
  1310. VLDR D17, R0, #0
  1311. ADD R0, R0, #8
  1312. VLDR D18, R0, #0
  1313. ADD R0, R0, #8
  1314. VLDR D19, R0, #0
  1315. ADD R0, R0, #8
  1316. VLDR D20, R0, #0
  1317. ADD R0, R0, #8
  1318. VLDR D21, R0, #0
  1319. ADD R0, R0, #8
  1320. VLDR D22, R0, #0
  1321. ADD R0, R0, #8
  1322. VLDR D23, R0, #0
  1323. ADD R0, R0, #8
  1324. VLDR D24, R0, #0
  1325. ADD R0, R0, #8
  1326. VLDR D25, R0, #0
  1327. ADD R0, R0, #8
  1328. VLDR D26, R0, #0
  1329. ADD R0, R0, #8
  1330. VLDR D27, R0, #0
  1331. ADD R0, R0, #8
  1332. VLDR D28, R0, #0
  1333. ADD R0, R0, #8
  1334. VLDR D29, R0, #0
  1335. ADD R0, R0, #8
  1336. VLDR D30, R0, #0
  1337. ADD R0, R0, #8
  1338. VLDR D31, R0, #0
  1339. ADD R0, R0, #8
  1340. LDR R1, [R0, #0]
  1341. VMSR FPSCR, R1
  1342. ADD R0, R0, #4
  1343. LDR R1, [R0, #0]
  1344. VMSR FPEXC, R1
  1345. END FPURestoreFull;
  1346. (** Restore minimal VFP/NEON state *)
  1347. PROCEDURE -FPURestoreMin*(VAR state: NEONState);
  1348. CODE
  1349. ADD SP, SP, #4
  1350. END FPURestoreMin;
  1351. (* ===== Interrupts ===== *)
  1352. (* Taken from Minos/Kernel.Mos *)
  1353. PROCEDURE EnableInterrupts*;
  1354. VAR cpsr: LONGINT;
  1355. BEGIN
  1356. SYSTEM.STPSR(0, cpsr);
  1357. cpsr := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, cpsr) - {7(*, 8*)});
  1358. SYSTEM.LDPSR(0, cpsr);
  1359. (*SYSTEM.PUT32(Platform.ICDDCR, {EnableSecure, EnableNonSecure});*)
  1360. END EnableInterrupts;
  1361. (* Taken from Minos/Kernel.Mos *)
  1362. PROCEDURE DisableInterrupts*;
  1363. VAR cpsr: LONGINT;
  1364. BEGIN
  1365. SYSTEM.STPSR(0, cpsr);
  1366. cpsr := SYSTEM.VAL(LONGINT, SYSTEM.VAL(SET, cpsr) + {7(*, 8*)});
  1367. SYSTEM.LDPSR( 0, cpsr);
  1368. (*SYSTEM.PUT32(Platform.ICDDCR, {});*)
  1369. END DisableInterrupts;
  1370. (** AreInterruptsEnabled - returns TRUE if interrupts are enabled at the current processor level, FALSE otherwise *)
  1371. PROCEDURE AreInterruptsEnabled*(): BOOLEAN;
  1372. CODE
  1373. MRS R0, CPSR ; move CPSR to R0
  1374. TST R0, #80H ; was IBit set ?
  1375. MOVEQ R0, #1 ; no, interrupts are enabled
  1376. MOVNE R0, #0 ; yep, interrupts are disabled
  1377. END AreInterruptsEnabled;
  1378. (* InstallDefaultInterrupts - installs default interrupt handlers *)
  1379. PROCEDURE InstallDefaultInterrupts;
  1380. VAR p: PROCEDURE; base: ADDRESS;
  1381. i, int: LONGINT;
  1382. BEGIN
  1383. base := 0;
  1384. (* Install all *Glue procedures. *)
  1385. p := undefGlue; SYSTEM.PUT32(base + Undef, SYSTEM.VAL(LONGINT, p));
  1386. p := SWIGlue; SYSTEM.PUT32(base + Swi, SYSTEM.VAL(LONGINT, p));
  1387. p := prefetchGlue; SYSTEM.PUT32(base + Prefetch, SYSTEM.VAL(LONGINT, p));
  1388. p := dataGlue; SYSTEM.PUT32(base + Data, SYSTEM.VAL(LONGINT, p));
  1389. p := DefaultIRQ; SYSTEM.PUT32(base + Irq, SYSTEM.VAL(LONGINT, p));
  1390. p := fiqGlue; SYSTEM.PUT32(base + Fiq, SYSTEM.VAL(LONGINT, p));
  1391. (* Install default exception handlers *)
  1392. InstallExceptionHandler(DefaultUndefined, Undef);
  1393. InstallExceptionHandler(DefaultSWI, Swi);
  1394. InstallExceptionHandler(DefaultPrefetchAbort, Prefetch);
  1395. InstallExceptionHandler(DefaultDataAbort, Data);
  1396. InstallExceptionHandler(DefaultFIQ, Fiq);
  1397. FOR int := 0 TO MaxIRQ DO
  1398. FOR i := 0 TO MaxIRQHandlers -1 DO
  1399. irqHandler[int, i] := NIL
  1400. END
  1401. END;
  1402. END InstallDefaultInterrupts;
  1403. (* DefaultUndef - default handler for undefined instruction exceptions *)
  1404. PROCEDURE DefaultUndefined (VAR state: State);
  1405. VAR
  1406. instn: LONGINT;
  1407. BEGIN
  1408. instn := SYSTEM.GET32(state.PC);
  1409. Acquire(TraceOutput);
  1410. Trace.Ln;
  1411. Trace.StringLn("Undefined Instruction Trap:");
  1412. Trace.String(" pc: "); Trace.Address(state.PC); Trace.Ln;
  1413. Trace.String(" instruction: "); Trace.Hex(instn, -8); Trace.Ln;
  1414. Trace.String(" CPU: "); Trace.Int(ID(), 0); Trace.Ln;
  1415. TraceState(state);
  1416. Trace.String("Kernel Halted");
  1417. Release(TraceOutput);
  1418. LOOP END
  1419. END DefaultUndefined;
  1420. (* DefaultSWI - default handler for software interrupts *)
  1421. PROCEDURE DefaultSWI (VAR state: State);
  1422. BEGIN
  1423. Acquire(TraceOutput);
  1424. Trace.Ln;
  1425. Trace.StringLn("Software Interrupt:");
  1426. Trace.String(" pc: "); Trace.Address(state.PC); Trace.Ln;
  1427. Trace.String(" number: "); Trace.Int(state.INT, -8); Trace.Ln;
  1428. Trace.String(" CPU: "); Trace.Int(ID(), 0); Trace.Ln;
  1429. TraceState(state);
  1430. Trace.Ln;
  1431. Trace.String("Kernel halted.");
  1432. Release(TraceOutput);
  1433. LOOP END
  1434. END DefaultSWI;
  1435. (* Instruction Prefetch abort *)
  1436. PROCEDURE DefaultPrefetchAbort (VAR state: State);
  1437. BEGIN
  1438. Acquire(TraceOutput);
  1439. Trace.String("Prefetch abort at location: "); Trace.Address(state.PC); Trace.Ln;
  1440. Trace.String(" CPU: "); Trace.Int(ID(), 0); Trace.Ln;
  1441. Trace.String(" FP: "); Trace.Address(state.BP); Trace.Ln;
  1442. Trace.String("SPSR: "); Trace.Hex(state.PSR, -8); Trace.Ln;
  1443. TraceState(state);
  1444. Trace.Ln;
  1445. Trace.StringLn("Kernel Halted");
  1446. Release(TraceOutput);
  1447. LOOP END;
  1448. END DefaultPrefetchAbort;
  1449. (* DefaultDataAbort - default handler for data abort exceptions *)
  1450. PROCEDURE DefaultDataAbort (VAR state: State);
  1451. VAR
  1452. faultAdr: ADDRESS;
  1453. faultStatus: LONGINT;
  1454. stack: Stack;
  1455. BEGIN
  1456. GetPageFault(faultAdr, faultStatus);
  1457. (*getStack(stack);
  1458. IF ~ExtendStack(stack, faultAdr) THEN*)
  1459. Acquire(TraceOutput);
  1460. IF faultAdr < 4 * k THEN
  1461. Trace.StringLn("NIL pointer exception");
  1462. Trace.String("pc: "); Trace.Address(state.PC); Trace.Ln
  1463. ELSE
  1464. Trace.StringLn("Data Abort Trap");
  1465. Trace.String("pc: "); Trace.Address(state.PC); Trace.Ln;
  1466. Trace.String("instn: "); Trace.Address(SYSTEM.GET32(state.PC)); Trace.Ln;
  1467. Trace.String("address: "); Trace.Address(faultAdr); Trace.Ln;
  1468. Trace.String("status: "); Trace.Address(faultStatus); Trace.Ln
  1469. END;
  1470. TraceState(state);
  1471. Trace.Ln; Trace.StringLn("Kernel Halted.");
  1472. Release(TraceOutput);
  1473. LOOP END
  1474. (*END*)
  1475. END DefaultDataAbort;
  1476. (* DefaultIRQ - default handler for IRQs *)
  1477. PROCEDURE DefaultIRQ;
  1478. BEGIN
  1479. Acquire(TraceOutput);
  1480. Trace.StringLn("(IRQ)");
  1481. Trace.String(" CPU: "); Trace.Address(ID()); Trace.Ln;
  1482. Trace.Ln; Trace.StringLn("Kernel Halted");
  1483. Release(TraceOutput);
  1484. LOOP END
  1485. END DefaultIRQ;
  1486. (* DefaultFIQ - default handler for fast interrupts *)
  1487. (*PROCEDURE DefaultFIQ;
  1488. BEGIN
  1489. Trace.StringLn("Fast IRQ Trap");
  1490. Trace.String(" CPU: "); Trace.Address(ID()); Trace.Ln;
  1491. Trace.String("Kernel halted.");
  1492. LOOP END
  1493. END DefaultFIQ;*)
  1494. PROCEDURE DefaultFIQ (VAR state: State);
  1495. BEGIN
  1496. Acquire(TraceOutput);
  1497. Trace.StringLn("Fast IRQ Trap");
  1498. Trace.String(" CPU: "); Trace.Address(ID()); Trace.Ln;
  1499. Trace.String("Kernel halted.");
  1500. Release(TraceOutput);
  1501. LOOP END
  1502. END DefaultFIQ;
  1503. PROCEDURE DummyISR(VAR state: State);
  1504. VAR i: LONGINT; icip : SET;
  1505. BEGIN
  1506. icip := SYSTEM.VAL(SET, SYSTEM.GET32((*IC +*) Platform.ICIP));
  1507. FOR i:=MinIRQ TO MaxIRQ DO
  1508. IF i IN icip THEN
  1509. state.INT := i;
  1510. dummyIRQHandler[state.INT].h(state);
  1511. END;
  1512. END;
  1513. END DummyISR;
  1514. (** EnableIRQ - enables a hardware interrupt (also done automatically by InstallHandler) *)
  1515. PROCEDURE InEnableIRQ(num: LONGINT);
  1516. BEGIN
  1517. ASSERT((MinIRQ <= num) & (num<= MaxIRQ));
  1518. (*IF TRUE OR (num = 53) THEN Trace.StringLn("Enable USB IRQ") END;*)
  1519. SYSTEM.PUT32(Platform.ICDISER + 4 * (num DIV 32) , {num MOD 32});
  1520. END InEnableIRQ;
  1521. PROCEDURE EnableIRQ*(int: LONGINT);
  1522. BEGIN
  1523. Acquire(Interrupts);
  1524. InEnableIRQ(int);
  1525. Release(Interrupts)
  1526. END EnableIRQ;
  1527. (** DisableIRQ - disables a hardware interrupt (also done automatically by RemoveHandler) *)
  1528. PROCEDURE InDisableIRQ(num: LONGINT);
  1529. BEGIN
  1530. ASSERT((MinIRQ <= num) & (num <= MaxIRQ));
  1531. (*IF TRUE OR (num = 53) THEN Trace.StringLn("Disable USB IRQ") END;*)
  1532. SYSTEM.PUT32(Platform.ICDICER + 4 * (num DIV 32) , {num MOD 32});
  1533. END InDisableIRQ;
  1534. PROCEDURE DisableIRQ*(int: LONGINT);
  1535. BEGIN
  1536. Acquire(Interrupts);
  1537. InDisableIRQ(int);
  1538. Release(Interrupts)
  1539. END DisableIRQ;
  1540. PROCEDURE IsIRQEnabled(int: LONGINT): BOOLEAN;
  1541. VAR
  1542. enabled: BOOLEAN;
  1543. reg: SET;
  1544. BEGIN
  1545. Acquire(Interrupts);
  1546. SYSTEM.GET(Platform.ICDISER + 4 * (int DIV 32) , reg);
  1547. enabled := (int MOD 32) IN reg;
  1548. Release(Interrupts);
  1549. RETURN enabled
  1550. END IsIRQEnabled;
  1551. (** InstallHandler - installs a interrupt handler & enable IRQ if necessary.
  1552. On entry to h interrupts are disabled and may be enabled with XXXXX. After handling the interrupt
  1553. the state of interrupts are restored. The acknowledgement of a hardware interrupt is done automatically.
  1554. IRQs are mapped from MinIRQ to MaxIRQ. *)
  1555. PROCEDURE InstallHandler*(h: Handler; int: LONGINT);
  1556. VAR
  1557. i: LONGINT;
  1558. BEGIN
  1559. (*NEW(n);*) (* outside locked region, to allow gc *)
  1560. i := 0;
  1561. WHILE irqHandler[int, i] # NIL DO
  1562. INC(i)
  1563. END;
  1564. Acquire(Interrupts);
  1565. (* IRQGlue may traverse list while it is being modified. *)
  1566. irqHandler[int, i] := h;
  1567. IF DummyTest THEN
  1568. irqHandler[int, i] := DummyISR;
  1569. dummyIRQHandler[int].h := h;
  1570. END;
  1571. IF (int >= MinIRQ) & (int <= MaxIRQ) THEN InEnableIRQ(int) END;
  1572. Release(Interrupts);
  1573. IF traceInterrupts THEN
  1574. Acquire(TraceOutput);
  1575. Trace.String("[Machine]InstallHandler: h = 0x"); Trace.Address(SYSTEM.VAL(LONGINT, h));
  1576. Trace.String("; int = "); Trace.Address(int);
  1577. Trace.String("; IRQMask = 0x"); Trace.Address(SYSTEM.VAL(LONGINT, IRQMask));
  1578. Trace.Ln;
  1579. Release(TraceOutput)
  1580. END
  1581. END InstallHandler;
  1582. PROCEDURE RemoveHandler * (h: Handler; int: LONGINT);
  1583. END RemoveHandler;
  1584. PROCEDURE InstallExceptionHandler * (h: Handler; e: LONGINT);
  1585. BEGIN
  1586. CASE e OF
  1587. Undef: undefHandler := h
  1588. |Swi: swiHandler := h
  1589. |Prefetch: prefetchHandler := h
  1590. |Data: dataHandler := h
  1591. |Fiq: fiqHandler := h
  1592. ELSE
  1593. Trace.String("Unknown exception offset: ");
  1594. Trace.Int(e, 0);
  1595. Trace.Ln;
  1596. HALT(99)
  1597. END
  1598. END InstallExceptionHandler;
  1599. (*
  1600. IRQGlue - every IRQ enters through this handler. It reads the IRR (Interrupt Request Register) of the PIC and calls the
  1601. appropriate handlers for each pending IRQ. A problem (which caused a nice debugging session of ~1 day...) is this
  1602. 'VAR state: State' parameter. Theoretically, a interrupt handler can change the values of this field to continue execution in
  1603. a different process, e.g. the scheduler works that way. This means that we can't call the handlers of every pending IRQ in
  1604. one loop - we must exit this procedure after each handled IRQ.
  1605. - routine has been changed so that all handlers of pending interrupts will be called
  1606. - using ICIP (interrupt Pending Register) instead of IRR (Interrupt Request Register)
  1607. - after handler call we don't turn interrupts off explicitly
  1608. *)
  1609. PROCEDURE {NOPAF} IRQGlue;
  1610. CODE
  1611. CLREX
  1612. SUB SP, SP, #72 ; Room for the State record
  1613. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1614. MOV R0, R0
  1615. ADD SP, SP, #60
  1616. SUB R0, LR, #4 ; return address = LR-4
  1617. STR R0, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1618. MRS R0, SPSR ; get saved PSR
  1619. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1620. SUB SP, SP, #68
  1621. MOV R11, SP
  1622. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1623. STR R5, [SP, #-4]! ; push value (type tag)
  1624. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1625. BL IRQCaller
  1626. LDR R11, [SP], #4
  1627. ADD SP, SP, #4
  1628. ADD SP, SP, #72 ; adjust SP & remove PAF
  1629. LDR R0, [R11, #64] ; load 'State.PSR'
  1630. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1631. LDR R0, [R11, #60] ; load 'State.PC'...
  1632. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1633. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1634. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1635. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1636. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1637. LDR R11, [R11, #44]
  1638. MOVS PC, LR ; SPSR -> CPSR & return
  1639. ; Data section
  1640. state: d32 stateTag ; address of stateTag
  1641. END IRQGlue;
  1642. (** Calls all handlers for all pending IRQs.
  1643. Is called by IRQGlue.
  1644. *)
  1645. PROCEDURE IRQCaller(VAR state: State);
  1646. VAR i, reg, irq, ack, count: LONGINT; handler: Handler; icip: SET;
  1647. BEGIN
  1648. ack := SYSTEM.GET32(Platform.ICCIAR);
  1649. (* service this irq *)
  1650. irq := ack MOD 1024;
  1651. IF irq # 1023 THEN (* not a spurious IRQ *)
  1652. state.INT := irq;
  1653. IF (MinIRQ <= irq) & (irq<= MaxIRQ) THEN
  1654. count := 0;
  1655. handler := irqHandler[irq, count];
  1656. WHILE (handler # NIL) & (count < MaxIRQHandlers - 1) DO
  1657. handler(state);
  1658. DisableInterrupts; (* handler may have reactivated interrupts *)
  1659. INC(count);
  1660. handler := irqHandler[irq, count];
  1661. END;
  1662. SYSTEM.PUT32(Platform.ICCEOIR, ack);
  1663. END;
  1664. END;
  1665. (* service pending IRQs *)
  1666. FOR reg := 0 TO 2 DO
  1667. SYSTEM.GET( Platform.ICDISPR+reg*4, icip );
  1668. i := 0;
  1669. WHILE (i <= 31) & (icip # {}) DO
  1670. IF (i IN icip) THEN
  1671. icip := icip - {i};
  1672. irq := i+reg*32;
  1673. (* Do not service pending interrupts that are disabled: this allows state triggered interrupts to be
  1674. * handled by software in an interrupt process. *)
  1675. IF IsIRQEnabled(irq) & (irq # PrivateTimerIRQ) THEN
  1676. (*Trace.String("Pending IRQ "); Trace.Int(irq, 0); Trace.Ln;*)
  1677. count := 0;
  1678. state.INT := irq;
  1679. handler := irqHandler[irq, count];
  1680. WHILE (handler # NIL) & (count < MaxIRQHandlers - 1) DO
  1681. handler(state);
  1682. DisableInterrupts; (* handler may have reactivated interrupts *)
  1683. INC(count);
  1684. handler := irqHandler[irq, count]
  1685. END;
  1686. SYSTEM.PUT32(Platform.ICCEOIR, irq); (* end of interrupt *)
  1687. SYSTEM.PUT32(Platform.ICDICPR+reg*4, {i}); (* clear pending bit *)
  1688. END
  1689. END;
  1690. INC( i )
  1691. END
  1692. END;
  1693. END IRQCaller;
  1694. (** Undefined Exception Handler. Saves the processor state and calls the registered handler. *)
  1695. PROCEDURE {NOPAF} undefGlue;
  1696. CODE
  1697. CLREX
  1698. SUB SP, SP, #72 ; Room for the State record
  1699. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1700. MOV R0, R0
  1701. ADD SP, SP, #60
  1702. SUB R0, LR, #4 ; return address = LR-4
  1703. STR R0, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1704. MRS R0, SPSR ; get saved PSR
  1705. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1706. LDR R0, [PC, #undefined-8-$] ; save -Undef in the INT field
  1707. STR R0, [SP], #4
  1708. SUB SP, SP, #72
  1709. MOV R11, SP
  1710. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1711. STR R5, [SP, #-4]! ; push value (type tag)
  1712. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1713. LDR R0, [PC,#handler-8-$]
  1714. LDR R0, [R0, #0]
  1715. BLX R0
  1716. LDR R11, [SP], #4
  1717. ADD SP, SP, #4
  1718. ADD SP, SP, #72 ; adjust SP & remove PAF
  1719. LDR R0, [R11, #64] ; load 'State.PSR'
  1720. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1721. LDR R0, [R11, #60] ; load 'State.PC'...
  1722. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1723. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1724. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1725. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1726. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1727. LDR R11, [R11, #44]
  1728. MOVS PC, LR ; SPSR -> CPSR & return
  1729. ; Data section
  1730. state: d32 stateTag ; address of stateTag
  1731. handler: d32 undefHandler ; handler
  1732. undefined: d32 -Undef ; INT number for undefined instructions
  1733. END undefGlue;
  1734. (**
  1735. * Software Interrupt Handler. Saves the processor state and calls the registered handler.
  1736. * The SWI number is stored into the INT field of the state record.
  1737. *)
  1738. PROCEDURE {NOPAF} SWIGlue;
  1739. CODE
  1740. SUB SP, SP, #72 ; Room for the State record
  1741. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1742. MOV R0, R0
  1743. ADD SP, SP, #60
  1744. SUB R1, LR, #4 ; return address = LR-4
  1745. STR R1, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1746. MRS R0, SPSR ; get saved PSR
  1747. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1748. LDR R0, [R1, #0] ; Load SWI instruction
  1749. LDR R2, [PC, #HFFFFFF-8-$]
  1750. AND R0, R0, R2 ; R0 MOD 1000000 = SWI number
  1751. STR R0, [SP], #4 ; push SWI number as INT. SP points to offset 72
  1752. SUB SP, SP, #72 ; Update SP to correct location
  1753. MOV R11, SP
  1754. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1755. STR R5, [SP, #-4]! ; push value (type tag)
  1756. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1757. LDR R0, [PC,#handler-8-$]
  1758. LDR R0, [R0, #0]
  1759. BLX R0
  1760. LDR R11, [SP], #4
  1761. ADD SP, SP, #4
  1762. ADD SP, SP, #72 ; adjust SP & remove PAF
  1763. LDR R0, [R11, #64] ; load 'State.PSR'
  1764. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1765. LDR R0, [R11, #60] ; load 'State.PC'...
  1766. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1767. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1768. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1769. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1770. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1771. LDR R11, [R11, #44]
  1772. MOVS PC, LR ; SPSR -> CPSR & return
  1773. ; Data section
  1774. state: d32 stateTag ; address of stateTag
  1775. HFFFFFF: d32 0FFFFFFH ; SWI number mask
  1776. handler: d32 swiHandler ; swiHandler
  1777. END SWIGlue;
  1778. (**
  1779. * Prefetch Abort Handler. Saves the processor state and calls the registered handler.
  1780. * The PC field of the state record holds the address at which the prefetch fault occurred.
  1781. *)
  1782. PROCEDURE {NOPAF} prefetchGlue;
  1783. CODE
  1784. CLREX
  1785. SUB SP, SP, #72 ; Room for the State record
  1786. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1787. MOV R0, R0
  1788. ADD SP, SP, #60
  1789. SUB R0, LR, #4 ; return address = LR-4
  1790. STR R0, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1791. MRS R0, SPSR ; get saved PSR
  1792. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1793. LDR R0, [PC, #prefetchAbort-8-$] ; save -Data in the INT field
  1794. STR R0, [SP], #4
  1795. SUB SP, SP, #72
  1796. MOV R11, SP
  1797. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1798. STR R5, [SP, #-4]! ; push value (type tag)
  1799. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1800. LDR R0, [PC,#handler-8-$]
  1801. LDR R0, [R0, #0]
  1802. BLX R0
  1803. LDR R11, [SP], #4
  1804. ADD SP, SP, #4
  1805. ADD SP, SP, #72 ; adjust SP & remove PAF
  1806. LDR R0, [R11, #64] ; load 'State.PSR'
  1807. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1808. LDR R0, [R11, #60] ; load 'State.PC'...
  1809. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1810. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1811. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1812. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1813. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1814. LDR R11, [R11, #44]
  1815. MOVS PC, LR ; SPSR -> CPSR & return
  1816. ; Data section
  1817. state: d32 stateTag ; address of stateTag
  1818. handler: d32 prefetchHandler ; handler
  1819. prefetchAbort: d32 -Prefetch ; prefetch INT number
  1820. END prefetchGlue;
  1821. (**
  1822. * Data Abort Handler. Saves the processor state and calls the registered handler.
  1823. * Use procedure GetPageFault to get abort status and address.
  1824. *)
  1825. PROCEDURE {NOPAF} dataGlue;
  1826. CODE
  1827. CLREX
  1828. SUB SP, SP, #72 ; Room for the State record
  1829. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1830. MOV R0, R0
  1831. ADD SP, SP, #60
  1832. SUB R0, LR, #8 ; return address = LR-8
  1833. STR R0, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1834. MRS R0, SPSR ; get saved PSR
  1835. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1836. LDR R0, [PC, #dataAbort-8-$] ; save -Data in the INT field
  1837. STR R0, [SP], #4
  1838. SUB SP, SP, #72
  1839. MOV R11, SP
  1840. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1841. STR R5, [SP, #-4]! ; push value (type tag)
  1842. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1843. LDR R0, [PC,#handler-8-$]
  1844. LDR R0, [R0, #0]
  1845. BLX R0
  1846. LDR R11, [SP], #4
  1847. ADD SP, SP, #4
  1848. ADD SP, SP, #72 ; adjust SP & remove PAF
  1849. LDR R0, [R11, #64] ; load 'State.PSR'
  1850. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1851. LDR R0, [R11, #60] ; load 'State.PC'...
  1852. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1853. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1854. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1855. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1856. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1857. LDR R11, [R11, #44]
  1858. MOVS PC, LR ; SPSR -> CPSR & return
  1859. ; Data section
  1860. state: d32 stateTag ; address of stateTag
  1861. handler: d32 dataHandler ; address of the handler variable
  1862. dataAbort: d32 -Data
  1863. END dataGlue;
  1864. (** Fast Interrupt Handler. Saves the processor state and calls the registered handler *)
  1865. PROCEDURE {NOPAF} fiqGlue;
  1866. CODE
  1867. CLREX
  1868. SUB SP, SP, #72 ; Room for the State record
  1869. STMIA SP, {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, FP, SP, LR}^
  1870. MOV R0, R0
  1871. ADD SP, SP, #60
  1872. SUB R0, LR, #4 ; return address = LR-4
  1873. STR R0, [SP], #4 ; push ('PC' in 'State'). SP points to offset 64
  1874. MRS R0, SPSR ; get saved PSR
  1875. STR R0, [SP], #4 ; push ('PSR' in 'State'). SP points to offset 68
  1876. SUB SP, SP, #68
  1877. MOV R11, SP
  1878. LDR R5, [pc, #state-$-8] ; load address of stateTag constant
  1879. STR R5, [SP, #-4]! ; push value (type tag)
  1880. STR R11, [SP, #-4]! ; push parameter (address of 'State' parameter)
  1881. BL fiqHandler
  1882. LDR R11, [SP], #4
  1883. ADD SP, SP, #4
  1884. ADD SP, SP, #72 ; adjust SP & remove PAF
  1885. LDR R0, [R11, #64] ; load 'State.PSR'
  1886. MSR SPSR_cxsf, R0 ; and store it into SPSR
  1887. LDR R0, [R11, #60] ; load 'State.PC'...
  1888. MOV LR, R0 ; ...into LR (because we will return to LR, not PC)
  1889. ADD R0, R11, #48 ; R0 points to 'State.SP'
  1890. LDMIA R0, { FP, SP, LR }^ ; load 'State.SP' & 'State.LR' into user mode registers
  1891. MOV R0, R0 ; nop, to not access banked registers after LDM ^
  1892. LDMIA R11, { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10 } ; restore unbanked regs
  1893. LDR R11, [R11, #44]
  1894. MOVS PC, LR ; SPSR -> CPSR & return
  1895. ; Data section
  1896. state: d32 stateTag ; address of stateTag
  1897. END fiqGlue;
  1898. (** Initializes IRQ handling. *)
  1899. PROCEDURE InitInterrupts*;
  1900. CONST
  1901. EnableSecure=0;
  1902. EnableNonSecure=1;
  1903. NumberIRQs = 96;
  1904. VAR p: PROCEDURE; i: LONGINT;
  1905. BEGIN
  1906. Acquire(Interrupts);
  1907. IRQMask := {};
  1908. p := IRQGlue;
  1909. SYSTEM.PUT32(InterruptVector + Irq, SYSTEM.VAL(LONGINT, p)); (* install new IRQ handler *)
  1910. SYSTEM.PUT32(Platform.ICDDCR, 0);
  1911. FOR i := 32 DIV 16 TO (NumberIRQs-1) DIV 16 (* 2 bits per IRQ *) DO
  1912. SYSTEM.PUT32(Platform.ICDICFR+i*4, 0);
  1913. END;
  1914. FOR i := 0 TO (NumberIRQs-1) DIV 4 (* 8 bits per IRQ *) DO
  1915. SYSTEM.PUT32(Platform.ICDIPR+i*4, LONGINT(0A0A0A0A0H)); (* set priority of each interrupt to 160 *)
  1916. END;
  1917. FOR i := (32 DIV 4) TO (NumberIRQs-1) DIV 4 (* 8 bits per IRQ *) DO
  1918. SYSTEM.PUT32(Platform.ICDIPTR+i*4, 1010101H); (* reset interrupt targets to processor 0 *)
  1919. END;
  1920. (* disable all interrupt forwardings *)
  1921. FOR i := 0 TO (NumberIRQs-1) DIV 32 (* 1 bit per IRQ *) DO
  1922. SYSTEM.PUT32(Platform.ICDICER+i*4, LONGINT(0FFFFFFFFH));
  1923. END;
  1924. SYSTEM.PUT32(Platform.ICCPMR, 0F0H);
  1925. SYSTEM.PUT32(Platform.ICCICR, {0,1,2});
  1926. SYSTEM.PUT32(Platform.ICCBPR, 0);
  1927. SYSTEM.PUT32(Platform.ICDDCR, {EnableSecure, EnableNonSecure});
  1928. Release(Interrupts);
  1929. (*InvalidateDCache(dCacheBase);*)
  1930. (*EnableIRQ(PrivateTimerIRQ);*)
  1931. END InitInterrupts;
  1932. (** Restore silent, infinitly-looping exception handlers *)
  1933. PROCEDURE EndInterrupts;
  1934. BEGIN
  1935. SYSTEM.PUT32(InterruptVector + Undef, InterruptVector + Undef);
  1936. SYSTEM.PUT32(InterruptVector + Swi, InterruptVector + Swi);
  1937. SYSTEM.PUT32(InterruptVector + Prefetch, InterruptVector + Prefetch);
  1938. SYSTEM.PUT32(InterruptVector + Data, InterruptVector + Data);
  1939. SYSTEM.PUT32(InterruptVector + Irq, InterruptVector + Irq);
  1940. SYSTEM.PUT32(InterruptVector + Fiq, InterruptVector + Fiq);
  1941. END EndInterrupts;
  1942. (* GetExceptionState *)
  1943. PROCEDURE GetExceptionState*(VAR int: State; VAR exc: ExceptionState);
  1944. BEGIN
  1945. (* save all state information while interrupts are still disabled *)
  1946. exc.locks := BreakAll();
  1947. IF int.INT = -Undef THEN
  1948. exc.halt := 17;
  1949. exc.instn := SYSTEM.GET32(int.PC)
  1950. ELSIF int.INT = -Prefetch THEN
  1951. exc.pf := int.PC;
  1952. exc.status := -1;
  1953. exc.halt := 19
  1954. ELSIF int.INT = -Data THEN
  1955. GetPageFault(exc.pf, exc.status);
  1956. IF exc.pf < 4 * k THEN
  1957. (* NIL pointer *)
  1958. exc.halt := 18
  1959. ELSE
  1960. exc.halt := 19
  1961. END
  1962. ELSE
  1963. (* SWI *)
  1964. exc.halt := int.INT
  1965. END
  1966. END GetExceptionState;
  1967. PROCEDURE GetPageFault * (VAR adr: ADDRESS; VAR status: LONGINT);
  1968. CODE
  1969. MRC p15, 0, R0, C5, C0 ; load fault status register (FSR)
  1970. AND R0, R0, #0FFH ; only bits 7:0 are valid
  1971. LDR R1, [FP, #status]
  1972. STR R0, [R1, #0]
  1973. MRC p15, 0, R0, C6, C0 ; load fault address (FAR)
  1974. LDR R1, [FP, #adr]
  1975. STR R0, [R1, #0]
  1976. END GetPageFault;
  1977. (* FAR - returns the Fault Address Register. *)
  1978. PROCEDURE -FAR*(): LONGINT;
  1979. CODE
  1980. MRC p15, 0, R0, C6, C0 ; FAR is co-processor 15 register 6
  1981. END FAR;
  1982. (** Init global timer *)
  1983. PROCEDURE InitGlobalTimer;
  1984. CONST
  1985. TimerEnable=0;
  1986. BEGIN
  1987. (* disable first *)
  1988. SYSTEM.PUT32(Platform.GlobalTimerControlRegister, {});
  1989. (* reset global counter *)
  1990. SYSTEM.PUT32(Platform.GlobalTimerCounterRegister0, 0);
  1991. SYSTEM.PUT32(Platform.GlobalTimerCounterRegister1, 0);
  1992. SYSTEM.PUT32(Platform.GlobalTimerControlRegister, {TimerEnable});
  1993. END InitGlobalTimer;
  1994. (** Init private timer *)
  1995. PROCEDURE InitTicks;
  1996. CONST
  1997. TimerEnable=0;
  1998. AutoReload=1;
  1999. IRQEnable=2;
  2000. VAR
  2001. (* time slot in private timer counts; take into account that private timer clock frequency is equal to half of the CPU clock frequency *)
  2002. delay: LONGINT;
  2003. BEGIN
  2004. delay := ENTIER( ( LONGREAL(TimerPeriod) * 0.5D0 * LONGREAL(BootConfig.GetIntValue("CpuClockHz")) ) / 1.0D6 + 0.5D0 );
  2005. (* disable first *)
  2006. SYSTEM.PUT32(Platform.PrivateTimerControlRegister, {});
  2007. (*SYSTEM.PUT32(Platform.PrivateTimerCounterRegister, Delay);*)
  2008. SYSTEM.PUT32(Platform.PrivateLoadValueRegister, delay);
  2009. SYSTEM.PUT32(Platform.PrivateTimerControlRegister, {TimerEnable, AutoReload, IRQEnable});
  2010. END InitTicks;
  2011. PROCEDURE StopTicks;
  2012. BEGIN
  2013. SYSTEM.PUT32(Platform.PrivateTimerControlRegister, {});
  2014. END StopTicks;
  2015. (** Handle multiprocessor timer interrupt. *)
  2016. PROCEDURE HandleMPTimer*(VAR state: State);
  2017. BEGIN (* {interrupts off} *)
  2018. timer(ID(), state); (* rarely used *)
  2019. (* Clear timer interrupt *)
  2020. SYSTEM.PUT32(Platform.GlobalTimerInterruptStatusRegister, 1);
  2021. EnableInterrupts; (* enable interrupts before acquiring locks below - to avoid deadlock with StopAll. *)
  2022. Timeslice(state); (* fixme: check recursive interrupt *)
  2023. END HandleMPTimer;
  2024. (** Handle uniprocessor timer interrupt. *)
  2025. PROCEDURE HandleUPTimer(VAR state: State);
  2026. BEGIN (* {interrupts off} *)
  2027. timer(ID(), state);
  2028. SYSTEM.PUT32(Platform.PrivateTimerInterruptStatusRegister, 1);
  2029. (* Shutdown if requested *)
  2030. IF ~(ID() IN allProcessors) THEN ShutdownSecondary END;
  2031. IF enableWatchdog THEN PrivateWatchdog.Feed(Second) END;
  2032. Timeslice(state)
  2033. END HandleUPTimer;
  2034. (** Install a processor timer event handler. *)
  2035. PROCEDURE InstallEventHandler* (h: EventHandler);
  2036. BEGIN
  2037. IF h # NIL THEN timer := h ELSE timer := DummyEvent END
  2038. END InstallEventHandler;
  2039. PROCEDURE DummyEvent*(id: LONGINT; CONST state: State);
  2040. BEGIN
  2041. END DummyEvent;
  2042. PROCEDURE DummyTimeslice*(VAR state: State);
  2043. BEGIN
  2044. END DummyTimeslice;
  2045. PROCEDURE DummyIRQ*;
  2046. BEGIN
  2047. END DummyIRQ;
  2048. PROCEDURE IRQBeginPrinter;
  2049. BEGIN
  2050. Trace.StringLn("IRQ BEGIN");
  2051. END IRQBeginPrinter;
  2052. PROCEDURE IRQEndPrinter;
  2053. BEGIN
  2054. Trace.StringLn("IRQ END");
  2055. END IRQEndPrinter;
  2056. (* Timer interrupt handler. *)
  2057. PROCEDURE TimerInterruptHandler(VAR state: State);
  2058. BEGIN
  2059. IF ID() = 0 THEN
  2060. INC(ticks);
  2061. DEC(eventCount);
  2062. IF eventCount = 0 THEN
  2063. eventCount := eventMax; event(state)
  2064. END;
  2065. END
  2066. END TimerInterruptHandler;
  2067. (* Set timer upcall. The handler procedure will be called at a rate of Second/divisor Hz. *)
  2068. PROCEDURE InstallTickHandler(handler: Handler; divisor: LONGINT);
  2069. BEGIN
  2070. eventMax := divisor; event := handler;
  2071. eventCount := eventMax
  2072. END InstallTickHandler;
  2073. (* ===== Low-Level Locks ===== *)
  2074. (* Initializes spinlocks. This is not exported in Intel version. *)
  2075. PROCEDURE InitLocks;
  2076. VAR
  2077. i: LONGINT;
  2078. BEGIN
  2079. FOR i := 0 TO MaxLock - 1 DO
  2080. lock[i].locked := FALSE
  2081. END;
  2082. END InitLocks;
  2083. PROCEDURE AcquirePreemption*(): LONGINT;
  2084. VAR
  2085. id: LONGINT;
  2086. BEGIN
  2087. id := ID();
  2088. INC(proc[id].preemptCount);
  2089. RETURN id
  2090. END AcquirePreemption;
  2091. PROCEDURE ReleasePreemption*;
  2092. VAR
  2093. id: LONGINT;
  2094. BEGIN
  2095. id := ID();
  2096. IF StrongChecks THEN
  2097. ASSERT(proc[id].preemptCount > 0);
  2098. END;
  2099. DEC(proc[id].preemptCount);
  2100. END ReleasePreemption;
  2101. PROCEDURE PreemptCount*(id: LONGINT): LONGINT;
  2102. BEGIN
  2103. IF StrongChecks THEN
  2104. ASSERT(id = ID());
  2105. END;
  2106. RETURN proc[id].preemptCount;
  2107. END PreemptCount;
  2108. (* Acquire lock. Disables interrupts. *)
  2109. PROCEDURE Acquire*(level: LONGINT);
  2110. VAR
  2111. id: LONGINT;
  2112. enabled: BOOLEAN;
  2113. BEGIN
  2114. enabled := AreInterruptsEnabled();
  2115. DisableInterrupts();
  2116. id := AcquirePreemption();
  2117. IF proc[id].locksHeld = {} THEN
  2118. proc[id].intStatus := enabled
  2119. END;
  2120. IF StrongChecks THEN
  2121. ASSERT(~AreInterruptsEnabled());
  2122. ASSERT((~enabled) OR (proc[id].locksHeld = {})); (* interrupts enabled => no locks held *)
  2123. ASSERT(~(level IN proc[id].locksHeld)) (* recursive locks not allowed *)
  2124. END;
  2125. AcquireObject(lock[level].locked);
  2126. (* Now, we hold the lock *)
  2127. INCL(proc[id].locksHeld, level);
  2128. IF StrongChecks THEN (* no lower-level locks currently held by this processor *)
  2129. ASSERT((level = 0) OR (proc[id].locksHeld * {0..level-1} = {}));
  2130. END;
  2131. END Acquire;
  2132. (* Release lock. Enables interrupts if last lock held. *)
  2133. PROCEDURE Release*(level: LONGINT);
  2134. VAR
  2135. id: LONGINT;
  2136. BEGIN
  2137. id := ID();
  2138. IF StrongChecks THEN
  2139. ASSERT(~AreInterruptsEnabled());
  2140. ASSERT(level IN proc[id].locksHeld);
  2141. ASSERT(lock[level].locked # FALSE)
  2142. END;
  2143. EXCL(proc[id].locksHeld, level);
  2144. ReleaseObject(lock[level].locked);
  2145. ReleasePreemption;
  2146. IF (proc[id].locksHeld = {}) & proc[id].intStatus THEN
  2147. EnableInterrupts
  2148. END;
  2149. END Release;
  2150. PROCEDURE AcquireAll*;
  2151. VAR
  2152. i: LONGINT;
  2153. BEGIN
  2154. FOR i := MaxLock - 1 TO 0 BY -1 DO
  2155. Acquire(i)
  2156. END
  2157. END AcquireAll;
  2158. PROCEDURE ReleaseAll*;
  2159. VAR
  2160. i: LONGINT;
  2161. BEGIN
  2162. FOR i := 0 TO MaxLock - 1 DO
  2163. Release(i)
  2164. END
  2165. END ReleaseAll;
  2166. (** Acquire a fine-grained lock on an active object. *)
  2167. (* Based on the code from "Barrier Litmus Tests and Cookbook" by Richard Grisenthwaite, ARM, 26.11.2009 *)
  2168. PROCEDURE AcquireObject*(VAR locked: BOOLEAN);
  2169. CODE
  2170. CLREX ; ensure that the local monitor is in the Open Access state after a context switch
  2171. LDR R1, [FP, #locked]
  2172. MOV R0, #1
  2173. Loop:
  2174. LDREXB R5, R1 ; read lock
  2175. CMP R5, #0 ; check if 0
  2176. WFENE ; sleep if the lock is held
  2177. STREXBEQ R5, R0, R1 ; attempt to store new value
  2178. CMPEQ R5, #0 ; test if store suceeded
  2179. BNE Loop ; retry if not
  2180. DMB ; ensures that all subsequent accesses are observed after the gaining of the lock is observed
  2181. ; loads and stores in the critical region can now be performed
  2182. END AcquireObject;
  2183. (** Release an active object lock. *)
  2184. (* Based on the code from "Barrier Litmus Tests and Cookbook" by Richard Grisenthwaite, ARM, 26.11.2009 *)
  2185. PROCEDURE ReleaseObject*(VAR locked: BOOLEAN);
  2186. CODE
  2187. LDR R1, [FP, #locked]
  2188. MOV R0, #0
  2189. DMB ; ensure all previous accesses are observed before the lock is cleared
  2190. STRB R0, [R1, #0] ; clear the lock.
  2191. DSB ; ensure completion of the store that cleared the lock before sending the event
  2192. SEV
  2193. END ReleaseObject;
  2194. (** Break all locks held by current processor (for exception handling). Returns levels released. *)
  2195. PROCEDURE BreakAll*(): SET;
  2196. VAR id, level: LONGINT; released: SET;
  2197. BEGIN
  2198. id := AcquirePreemption();
  2199. released := {};
  2200. FOR level := 0 TO MaxLock-1 DO
  2201. IF level IN proc[id].locksHeld THEN
  2202. lock[level].locked := FALSE; (* break the lock *)
  2203. EXCL(proc[id].locksHeld, level);
  2204. INCL(released, level)
  2205. END
  2206. END;
  2207. (*IF released = {} THEN
  2208. ASSERT(proc[id].nestCount = 0) (* no locks held *)
  2209. ELSE
  2210. ASSERT(proc[id].nestCount > 0); (* some locks held *)
  2211. proc[id].nestCount := 0 (* interrupt state will be restored later *)
  2212. END;*)
  2213. IF proc[id].preemptCount > 1 THEN INCL(released, Preemption) END;
  2214. proc[id].preemptCount := 0; (* clear preemption flag *)
  2215. RETURN released
  2216. END BreakAll; (* !!! interrupts are still off !!! *)
  2217. (* ===== Atomic Operations ===== *)
  2218. (* Atomic INC(x) *)
  2219. PROCEDURE -AtomicInc*(VAR x: LONGINT);
  2220. CODE
  2221. ;loop:
  2222. ; ADD R0, SP, #x ; R0 := ADR(x)
  2223. ; LDREX R1, R0 ; R1 := x
  2224. ; ADD R1, R1, #1 ; increment x
  2225. ; STREX R2, R1, R0
  2226. ; CMP R2, #0
  2227. ; BEQ loop ; if store failed, try again, else exit
  2228. ; ADD SP, SP, #4
  2229. LDR R0, [SP], #4
  2230. loop:
  2231. LDREX R1, R0
  2232. ADD R1, R1, #1
  2233. STREX R2, R1, R0
  2234. CMP R2, #0
  2235. BNE loop
  2236. END AtomicInc;
  2237. (* Atomic INC(x) *)
  2238. PROCEDURE -AtomicDec*(VAR x: LONGINT);
  2239. CODE
  2240. LDR R0, [SP], #4
  2241. loop:
  2242. LDREX R1, R0
  2243. SUB R1, R1, #1
  2244. STREX R2, R1, R0
  2245. CMP R2, #0
  2246. BNE loop
  2247. END AtomicDec;
  2248. PROCEDURE -AtomicAdd * (VAR x: LONGINT; y: LONGINT);
  2249. CODE
  2250. LDR R3, [SP, #y] ; R3 := y
  2251. LDR R0, [SP, #x] ; R0 := ADR(x)
  2252. loop:
  2253. LDREX R1, R0 ; R1 := x
  2254. ADD R1, R1, R3 ; increment x
  2255. STREX R2, R1, R0
  2256. CMP R2, #0
  2257. BNE loop ; if store failed, try again, else exit
  2258. ADD SP, SP, #8
  2259. END AtomicAdd;
  2260. (* Atomic compare-and-swap. Set x = new if x = old and return old value of x *)
  2261. PROCEDURE -AtomicCAS * (VAR x: LONGINT; old, new: LONGINT): LONGINT;
  2262. CODE
  2263. LDR R3, [SP, #x] ; R0 := ADDRESSOF(x)
  2264. LDR R1, [SP, #old] ; R1 := old
  2265. LDR R2, [SP, #new] ; R2 := new
  2266. ADD SP, SP, #12 ; pop variable from stack
  2267. loop:
  2268. LDREX R0, R3 ; load excl x
  2269. CMP R0, R1
  2270. BNE exit ; x # old -> exit
  2271. STREX R4, R2, R3 ; x = old -> store excl new -> x
  2272. CMP R4, #0
  2273. BNE loop ; store exclusive failed: retry
  2274. exit:
  2275. END AtomicCAS;
  2276. (* ===== Virtual Memory Management ===== *)
  2277. PROCEDURE Ensure32BitAddress*(adr: ADDRESS): LONGINT;
  2278. BEGIN
  2279. RETURN adr
  2280. END Ensure32BitAddress;
  2281. PROCEDURE GetSecondLevelEntry(virtualAddress: ADDRESS): ADDRESS;
  2282. VAR
  2283. ptIdx, basePT, entry: ADDRESS;
  2284. BEGIN
  2285. IF (PS <= virtualAddress) & (virtualAddress < M) THEN
  2286. (* First 256 entries *)
  2287. basePT := sysSecondLvlPtStart
  2288. ELSIF (4 * G - M <= virtualAddress) THEN
  2289. (* Entries 256 to 511 *)
  2290. basePT := sysSecondLvlPtStart + 400H
  2291. ELSIF (memStackStart <= virtualAddress) & (virtualAddress < memStackStop) THEN
  2292. basePT := sysSecondLvlPtStart + 800H + virtualAddress DIV M * k - memStackStart DIV k
  2293. ELSIF (memConfigStart <= virtualAddress) & (virtualAddress < memConfigStop) THEN
  2294. basePT := sysSecondLvlPtStop - (memConfigStop DIV k - virtualAddress DIV M * k)
  2295. END;
  2296. ptIdx := SHR(virtualAddress MOD M, PSlog2);
  2297. ASSERT(basePT + 4 * ptIdx >= sysSecondLvlPtStart);
  2298. ASSERT(basePT + 4 * ptIdx < sysSecondLvlPtStop);
  2299. entry := SYSTEM.GET32(basePT + 4 * ptIdx);
  2300. RETURN entry
  2301. END GetSecondLevelEntry;
  2302. PROCEDURE SetSecondLevelEntry(virtualAddress, physicalAddress, flags: ADDRESS);
  2303. VAR ptIdx, basePT, entry: ADDRESS;
  2304. firstLvlEntry: ADDRESS;
  2305. BEGIN
  2306. IF (PS <= virtualAddress) & (virtualAddress < M) THEN
  2307. (* First 256 entries *)
  2308. basePT := sysSecondLvlPtStart
  2309. ELSIF (4 * G - M <= virtualAddress) THEN
  2310. (* Entries 256 to 511 *)
  2311. basePT := sysSecondLvlPtStart + 400H
  2312. ELSIF (memStackStart <= virtualAddress) & (virtualAddress < memStackStop) THEN
  2313. basePT := sysSecondLvlPtStart + 800H + virtualAddress DIV M * k - memStackStart DIV k
  2314. ELSIF (memConfigStart <= virtualAddress) & (virtualAddress < memConfigStop) THEN
  2315. basePT := sysSecondLvlPtStop - (memConfigStop DIV k - virtualAddress DIV M * k)
  2316. END;
  2317. ptIdx := SHR(virtualAddress MOD M, PSlog2);
  2318. IF physicalAddress = NilAdr THEN
  2319. entry := slFault
  2320. ELSE
  2321. ASSERT(physicalAddress MOD PS = 0);
  2322. ASSERT((flags DIV PS = 0) & (flags MOD 4 = 0));
  2323. entry := physicalAddress + flags + slSmall
  2324. END;
  2325. ASSERT(basePT + 4 * ptIdx >= sysSecondLvlPtStart);
  2326. ASSERT(basePT + 4 * ptIdx < sysSecondLvlPtStop);
  2327. SYSTEM.PUT32(basePT + 4 * ptIdx, entry);
  2328. END SetSecondLevelEntry;
  2329. PROCEDURE UnmapPhysical*(viartAdr: ADDRESS; size: SIZE);
  2330. BEGIN
  2331. END UnmapPhysical;
  2332. (* Unmap a virtual page and deallocate the corresponding physical page *)
  2333. PROCEDURE DeallocatePage(virtualAdr: ADDRESS);
  2334. VAR memoryAdr: LONGINT;
  2335. BEGIN
  2336. (* unmap the page *)
  2337. memoryAdr := GetSecondLevelEntry(virtualAdr);
  2338. ASSERT(memoryAdr MOD 4 = slSmall); (* page must be mapped *)
  2339. SYSTEM.PUT32(virtualAdr, freePage); (* link freePage list (must be done as long as the page is still mapped !) *)
  2340. SetSecondLevelEntry(virtualAdr, NilAdr, 0);
  2341. InvalidateTLBEntry(SHRL(virtualAdr, PSlog2));
  2342. (* free the page *)
  2343. memoryAdr := SHRL(memoryAdr, 12);
  2344. freePage := memoryAdr;
  2345. INC(memory.free, PS)
  2346. END DeallocatePage;
  2347. (* AllocatePage - allocates and maps one memory page to [virtualAdr...virtualAdr+PageSize]. Returns TRUE iff successful *)
  2348. PROCEDURE AllocatePage(virtualAdr, accessPermissions, flags: ADDRESS): BOOLEAN;
  2349. VAR memoryAdr, entry: ADDRESS;
  2350. BEGIN
  2351. (* Use 1:1 Mapping for stack *)
  2352. (* map the page *)
  2353. entry := GetSecondLevelEntry(virtualAdr);
  2354. IF entry MOD 4 # slFault THEN
  2355. Acquire(TraceOutput);
  2356. Trace.String("Allocate Page: entry = ");
  2357. Trace.Address(entry);
  2358. Trace.String("; vadr = ");
  2359. Trace.Address(virtualAdr);
  2360. Trace.String("; CPU = ");
  2361. Trace.Int(ID(), 0);
  2362. Trace.Ln;
  2363. Release(TraceOutput)
  2364. END;
  2365. ASSERT(entry MOD 4 = slFault); (* page must not be mapped *)
  2366. SetSecondLevelEntry(virtualAdr, (*memoryAdr*) virtualAdr, accessPermissions + flags);
  2367. InvalidateTLBEntry(SHRL(virtualAdr, PSlog2));
  2368. RETURN TRUE
  2369. END AllocatePage;
  2370. (** PhysicalAdr - returns the (real) physical address of the specified range of memory, or NilAdr if the range is not contiguous.
  2371. It is the caller's responsiblilty to assure the range remains allocated during the time it is in use.
  2372. *)
  2373. PROCEDURE PhysicalAdr*(adr, size: LONGINT): LONGINT;
  2374. VAR physAdr: ARRAY 400H OF Range; num, i, end: LONGINT;
  2375. BEGIN
  2376. TranslateVirtual(adr, size, num, physAdr);
  2377. IF (num > 0) THEN
  2378. FOR i := 1 TO num-1 DO
  2379. IF (physAdr[i].adr # (physAdr[i-1].adr + physAdr[i-1].size)) THEN
  2380. RETURN NilAdr
  2381. END
  2382. END;
  2383. RETURN physAdr[0].adr
  2384. ELSE
  2385. RETURN NilAdr
  2386. END
  2387. END PhysicalAdr;
  2388. (** TranslateVirtual - translates a virtual address range to num ranges of (real) physical addresses. num returns 0 on error.*)
  2389. PROCEDURE TranslateVirtual*(virtAdr: ADDRESS; size: LONGINT; VAR num: LONGINT; VAR physAdr: ARRAY OF Range);
  2390. VAR entry, base, ofs, len: LONGINT; endAdr: ADDRESS; abort: BOOLEAN;
  2391. BEGIN
  2392. Acquire(Memory);
  2393. endAdr := virtAdr + size;
  2394. IF ((memHeapStart <= virtAdr) & (endAdr <= memHeapStop)) OR ((memStackStart <= virtAdr) & (endAdr <= memStackStop)) OR ((memIOStart <= virtAdr) & (endAdr <= memIOStop)) THEN
  2395. (* Optimizations: we know that heap, stacks and I/O regions are mapped 1:1. *)
  2396. (*! 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 *)
  2397. num := 1;
  2398. physAdr[0].adr := virtAdr;
  2399. physAdr[0].size := size;
  2400. ELSE
  2401. abort := FALSE;
  2402. num := 0;
  2403. WHILE (size > 0) & (num < LEN(physAdr)) & ~abort DO
  2404. entry := (*SYSTEM.GET32(pageTable.virtual + 4*SHR(virtAdr, LogM));*)GetFirstLevelEntry(virtAdr - virtAdr MOD M);
  2405. IF (entry MOD 4 = flSection) THEN
  2406. ofs := virtAdr MOD M;
  2407. len := MIN(size, M - ofs);
  2408. physAdr[num].adr := SHRL(entry, LogM) + ofs;
  2409. physAdr[num].size := len;
  2410. INC(num);
  2411. INC(virtAdr, len); DEC(size, len)
  2412. ELSIF (entry MOD 4 = flCoarse) THEN
  2413. base := SHRL(entry, 10);
  2414. WHILE (size > 0) & (num < LEN(physAdr)) & ~abort DO
  2415. entry := GetSecondLevelEntry(virtAdr);
  2416. IF (entry MOD 4 = slSmall) THEN
  2417. ofs := virtAdr MOD PS;
  2418. len := MIN(size, PS - ofs);
  2419. physAdr[num].adr := SHRL(entry, 12) + ofs;
  2420. physAdr[num].size := len;
  2421. INC(num);
  2422. INC(virtAdr, len); DEC(size, len)
  2423. ELSE
  2424. num := 0;
  2425. abort := TRUE
  2426. END
  2427. END
  2428. ELSE
  2429. num := 0; abort := TRUE
  2430. END;
  2431. END;
  2432. IF (size > 0) & (num = LEN(physAdr)) THEN num := 0 END; (* array 'physAdr' was too small *)
  2433. END;
  2434. Release(Memory)
  2435. END TranslateVirtual;
  2436. PROCEDURE SetFirstLevelEntry (virtual, physical: ADDRESS; permissions, flags, type: LONGINT);
  2437. VAR
  2438. index, entry: LONGINT;
  2439. BEGIN
  2440. index := SHR(virtual, LogM) * 4;
  2441. ASSERT(index >= 0);
  2442. ASSERT(sysFirstLvlPtStart + index < sysFirstLvlPtStop);
  2443. entry := physical + permissions * 400H + flags + type;
  2444. (*Trace.Address(virtual); Trace.String(" "); Trace.Address(physical); Trace.String(" "); Trace.Address(SysFirstLvlPtStart(*pageTable.virtual*) + index); Trace.String(" "); Trace.Address(entry); Trace.Ln;*)
  2445. SYSTEM.PUT32(sysFirstLvlPtStart + index, entry)
  2446. END SetFirstLevelEntry;
  2447. PROCEDURE GetFirstLevelEntry (virtual: ADDRESS): LONGINT;
  2448. VAR
  2449. index: LONGINT;
  2450. BEGIN
  2451. index := LSH(virtual, -(LogM)) * 4;
  2452. ASSERT(index >= 0);
  2453. ASSERT(sysFirstLvlPtStart + index < sysFirstLvlPtStop);
  2454. RETURN SYSTEM.GET32(sysFirstLvlPtStart + index)
  2455. END GetFirstLevelEntry;
  2456. (* AllocateHeap - allocates and maps [physicalAddress...physicalAddress+size] to [virtualAddress...virtualAddress+size] *)
  2457. PROCEDURE AllocateHeap(virtualAddress, physicalAddress, size: ADDRESS; accessPermissions, flags: LONGINT);
  2458. VAR i, entry: LONGINT;
  2459. BEGIN
  2460. ASSERT(size MOD M = 0);
  2461. FOR i := 0 TO (size DIV M) - 1 DO
  2462. entry := GetFirstLevelEntry(virtualAddress + i * M);
  2463. ASSERT(entry = 0);
  2464. SetFirstLevelEntry(virtualAddress + i * M, physicalAddress + i * M, accessPermissions, flags, flSection)
  2465. END
  2466. END AllocateHeap;
  2467. (** Enable Memory Management and virtual memory. *)
  2468. PROCEDURE EnableMM(translationBase, tbFlags, mmuFlags: ADDRESS);
  2469. BEGIN
  2470. InvalidateTLB;
  2471. CODE
  2472. ; Disable AFE (special permission mode) and TRE (special memory mode)
  2473. ldr r0, [pc, #pattern-$-8]
  2474. mrc p15, 0, r1, c1, c0, 0
  2475. and r1, r0, r1
  2476. mcr p15, 0, r1, c1, c0, 0
  2477. isb
  2478. ;mrc p15, 0, r0, c2, c0, 2
  2479. ;ldr r1, [pc, #TLBCRPattern-$-8]
  2480. ;and r0, r0, r1
  2481. ;mcr p15, 0, r0, c2, c0, 2
  2482. ldr r0, [FP, #translationBase]
  2483. ldr r1, [fp, #tbFlags]
  2484. orr r0, r0, r1
  2485. mcr p15, 0, r0, c2, c0, 0
  2486. isb
  2487. ;mvn r0, #0 ; mmu domains: 16 x 11 = manager on all domains
  2488. ldr r0, [pc, #domains-$-8]
  2489. mcr p15, 0, r0, c3, c0, 0
  2490. isb
  2491. ldr r0, [FP, #mmuFlags]
  2492. ldr r1, [FP, #sctlr-$-8]
  2493. orr r0, r0, r1 ; 1 bits in SCTLR
  2494. mcr p15, 0, r0, c1, c0, 0
  2495. isb
  2496. ;dsb
  2497. ;isb
  2498. b exit
  2499. domains: d32 55555555H ; Client on each domain
  2500. pattern: d32 0CFFFFFFFH ; NOT(AFE+TRE)
  2501. sctlr: d32 0C50078H
  2502. TLBCRPattern: d32 0FFFFFFF8H
  2503. exit:
  2504. END;
  2505. proc[ID()].mmu := TRUE
  2506. END EnableMM;
  2507. PROCEDURE InitMemory;
  2508. VAR
  2509. cr1: SET;
  2510. i: LONGINT;
  2511. base: ADDRESS;
  2512. coarseFlags, fineFlags, tbFlags: LONGINT;
  2513. trace: BOOLEAN;
  2514. val: ARRAY 8 OF CHAR;
  2515. BEGIN
  2516. BootConfig.GetValue("TraceMemory", val);
  2517. trace := val = '1';
  2518. IF trace THEN
  2519. (* Debug Tracing *)
  2520. Trace.String("Memory Layout");
  2521. IF ~enableCaching THEN Trace.String(" - WARNING: Caching Disabled") END;
  2522. Trace.Ln;
  2523. Trace.String("System Start: "); Trace.Address(memSysLowStart); Trace.Ln;
  2524. Trace.String("System Stop: "); Trace.Address(memSysLowStop); Trace.Ln;
  2525. Trace.String("System Size: "); Trace.Address(memSysLowStop - memSysLowStart); Trace.Ln;
  2526. Trace.String(" Interrupt Stack Start: "); Trace.Address(sysIntStackStart); Trace.Ln;
  2527. Trace.String(" Interrupt Stack Stop: "); Trace.Address(sysIntStackStop); Trace.Ln;
  2528. Trace.String(" Interrupt Stack Size: "); Trace.Address(sysIntStackStop - sysIntStackStart); Trace.Ln;
  2529. Trace.String(" First Page Table Start: "); Trace.Address(sysFirstLvlPtStart); Trace.Ln;
  2530. Trace.String(" First Page Table Stop: "); Trace.Address(sysFirstLvlPtStop); Trace.Ln;
  2531. Trace.String(" First Page Table Size: "); Trace.Address(sysFirstLvlPtStop - sysFirstLvlPtStart); Trace.Ln;
  2532. Trace.String(" Second Page Table Start: "); Trace.Address(sysSecondLvlPtStart); Trace.Ln;
  2533. Trace.String(" Second Page Table Stop: "); Trace.Address(sysSecondLvlPtStop); Trace.Ln;
  2534. Trace.String(" Second Page Table Size: "); Trace.Address(sysSecondLvlPtStop - sysSecondLvlPtStart); Trace.Ln;
  2535. Trace.String("Heap Start: "); Trace.Address(memHeapStart); Trace.Ln;
  2536. Trace.String("Heap Stop: "); Trace.Address(memHeapStop); Trace.Ln;
  2537. Trace.String("Heap Size: "); Trace.Address(memHeapStop - memHeapStart); Trace.Ln;
  2538. Trace.String("Stack Start: "); Trace.Address(memStackStart); Trace.Ln;
  2539. Trace.String("Stack Stop: "); Trace.Address(memStackStop); Trace.Ln;
  2540. Trace.String("Stack Size: "); Trace.Address(memStackStop - memStackStart); Trace.Ln;
  2541. Trace.String("Config Start: "); Trace.Address(memConfigStart); Trace.Ln;
  2542. Trace.String("Config Stop: "); Trace.Address(memConfigStop); Trace.Ln;
  2543. Trace.String("Config Size: "); Trace.Address(memConfigStop - memConfigStart); Trace.Ln;
  2544. Trace.String("I/O Start: "); Trace.Address(memIOStart); Trace.Ln;
  2545. Trace.String("I/O Stop: "); Trace.Address(memIOStop); Trace.Ln;
  2546. Trace.String("I/O Size: "); Trace.Address(memIOStop - memIOStart); Trace.Ln;
  2547. Trace.String("SysHigh Start: "); Trace.Address(memSysHighStart); Trace.Ln;
  2548. Trace.String("SysHigh Stop: "); Trace.Hex(memSysHighStop - 1, -8); Trace.Ln;
  2549. Trace.String(" Interrupt Vector Start: "); Trace.Address(sysVectorStart); Trace.Ln;
  2550. Trace.String(" Interrupt Vector Stop: "); Trace.Address(sysVectorStop); Trace.Ln;
  2551. Trace.String(" Interrupt Vector Size: "); Trace.Address(sysVectorStop - sysVectorStart); Trace.Ln;
  2552. Trace.String(" Cache References Start: "); Trace.Address(sysCacheRefStart); Trace.Ln;
  2553. Trace.String(" Cache References Stop: "); Trace.Address(sysCacheRefStop); Trace.Ln;
  2554. Trace.String(" Cache References Size: "); Trace.Address(sysCacheRefSize); Trace.Ln;
  2555. Trace.String(" Cache References Stack Offset: "); Trace.Address(sysCacheStackOfs); Trace.Ln;
  2556. END;
  2557. (* disable caching & buffering globally *)
  2558. cr1 := GetControlRegister();
  2559. SetControlRegister(cr1 - {DCache, ICache});
  2560. (*InvalidateDCache(dCacheBase);*)
  2561. (*InvalidateDCacheRange(0, MemStackStop);*)
  2562. InvalidateICache;
  2563. DrainWriteBuffer;
  2564. (* initialize memory ranges *)
  2565. heapLow.physical := memHeapStart;
  2566. heapLow.virtual := memHeapStart;
  2567. heapHigh.physical := memHeapStop;
  2568. heapHigh.virtual := memHeapStart;
  2569. stackHigh.physical := memStackStop;
  2570. stackHigh.virtual := memStackStop;
  2571. stackLow.physical := memStackStop;
  2572. stackLow.virtual := memStackStart;
  2573. (* initialize global variables *)
  2574. pageTable.virtual := sysFirstLvlPtStart;
  2575. pageTable.memory := sysFirstLvlPtStart;
  2576. stackPT := sysSecondLvlPtStart + 2 * k;
  2577. freePage := NilAdr;
  2578. (* Determine global caching parameter *)
  2579. IF enableCaching THEN
  2580. coarseFlags := Cacheable + Shareable;
  2581. fineFlags := CB
  2582. ELSE
  2583. coarseFlags:= Shareable;
  2584. fineFlags := 0;
  2585. END;
  2586. (* Clear first level page table *)
  2587. Fill32(sysFirstLvlPtStart, sysFirstLvlPtStop - sysFirstLvlPtStart, 0);
  2588. (* Clear second level page table *)
  2589. Fill32(sysSecondLvlPtStart, sysSecondLvlPtStop - sysSecondLvlPtStart, 0);
  2590. (* Map system area *)
  2591. SetFirstLevelEntry(0, sysSecondLvlPtStart, 0, 0, flCoarse);
  2592. FOR i := 1 TO 0FFH DO
  2593. SetSecondLevelEntry(PS * i, PS * i, FullAccess + fineFlags);
  2594. END;
  2595. (* Map page for high part of OCM *)
  2596. AllocateHeap(memSysHighStart, memSysHighStart, MAX(M, LONGINT(memSysHighStop - memSysHighStart)), SrwUrw, coarseFlags);
  2597. (* Map heap area *)
  2598. AllocateHeap(memHeapStart, memHeapStart, memHeapStop - memHeapStart, SrwUrw, coarseFlags);
  2599. (* Map I/O area, device-type, shared memory *)
  2600. AllocateHeap(memIOStart, memIOStart, memIOStop - memIOStart, SrwUrw, Shareable + B);
  2601. (* initialize stack & config page tables (excluding the last MB that is already initalized) *)
  2602. base := SHR(memStackStart, LogM);
  2603. FOR i := memStackStart TO memConfigStop - 1 BY M DO
  2604. SetFirstLevelEntry(i, sysSecondLvlPtStart + 2 * k + PTSize * (SHR(i, LogM) - base), 0, 0, flCoarse)
  2605. END;
  2606. (* Map config region directly *)
  2607. FOR i := 0 TO SHR(memConfigStop - memConfigStart, PSlog2) - 1 DO
  2608. SetSecondLevelEntry(memConfigStart + PS * i, memConfigStart + PS * i, FullAccess + fineFlags)
  2609. END;
  2610. (* flush all caches & the write buffer and invalidate both TLBs *)
  2611. FlushDCacheRange(0, SYSTEM.VAL(ADDRESS, LastAddress));
  2612. InvalidateICache;
  2613. DrainWriteBuffer;
  2614. InvalidateTLB;
  2615. (* get memory size *)
  2616. memory.size := memHeapStop - memHeapStart;
  2617. memory.free := memory.size;
  2618. (* get heap size (check how many MBs are allocated) *)
  2619. heapLow.physical := 1*M; heapLow.virtual := memHeapStart;
  2620. heapHigh.physical := 1*M;
  2621. i := SHR(memHeapStart, LogM);
  2622. WHILE (SYSTEM.GET32(pageTable.virtual + i*4) MOD 4 = flSection) DO
  2623. INC(heapHigh.physical, M);
  2624. DEC(memory.free, M);
  2625. INC(i)
  2626. END;
  2627. heapHigh.virtual := heapLow.virtual + heapHigh.physical - heapLow.physical;
  2628. (* allocate empty memory block with enough space for at least one free block *)
  2629. memBlockHead := SYSTEM.VAL (MemoryBlock, ADDRESSOF (initialMemBlock));
  2630. memBlockTail := memBlockHead;
  2631. initialMemBlock.beginBlockAdr := SYSTEM.VAL (ADDRESS, LastAddress);
  2632. initialMemBlock.endBlockAdr := heapHigh.virtual;
  2633. initialMemBlock.size := initialMemBlock.endBlockAdr - initialMemBlock.beginBlockAdr;
  2634. initialMemBlock.next := NIL;
  2635. freeStackIndex := 0;
  2636. (* init stack bitmap *)
  2637. FOR i := 0 TO (maxUserStacks) DIV 32 - 1 DO
  2638. freeStack[i] := {0..31};
  2639. END;
  2640. freeStack[(maxUserStacks) DIV 32] := {0 .. (LONGINT(maxUserStacks) MOD 32) - 1};
  2641. freeStackIndex := 0;
  2642. (* Init cache ref counts *)
  2643. cacheRefs := sysCacheRefStart;
  2644. Fill32(sysCacheRefStart, sysCacheRefSize, 0);
  2645. IF enableCaching THEN
  2646. tbFlags := 7BH
  2647. ELSE
  2648. tbFlags := 0
  2649. END;
  2650. (* Copy interrupt vector *)
  2651. SYSTEM.MOVE(0, 0FFFF0000H, 4096);
  2652. EnableMM(sysFirstLvlPtStart, tbFlags, 2000H + 1007H);
  2653. END InitMemory;
  2654. (** GetFreeK - returns information on free memory in Kbytes.*)
  2655. PROCEDURE GetFreeK*(VAR total, lowFree, highFree: SIZE);
  2656. BEGIN
  2657. Acquire(Memory);
  2658. total := SHR(memory.size, 10);
  2659. lowFree := 0;
  2660. highFree := SHR(memory.free, 10);
  2661. Release(Memory)
  2662. END GetFreeK;
  2663. (* ===== Stack Management ===== *)
  2664. (** Extend stack to address. Returns TRUE iff done.
  2665. * If a procedure that holds Memory needs triggers a stack extension, this procedure is called by the interrupt handler:
  2666. * we get a trap because Acquire is not reentrant. To solve this, we do not acquire memory iff:
  2667. * - we are in interrupt mode
  2668. * - the current processor holds Memory already
  2669. *)
  2670. PROCEDURE ExtendStack*(VAR s: Stack; virtAdr: ADDRESS): BOOLEAN;
  2671. VAR
  2672. ok, doLock: BOOLEAN;
  2673. access, psr, flags: LONGINT;
  2674. BEGIN
  2675. IF enableCaching THEN
  2676. flags := CB
  2677. ELSE
  2678. flags := 0
  2679. END;
  2680. SYSTEM.STPSR(0, psr);
  2681. (* Need to acquire Memory: if we are not in interrupt mode or if we do not hold this lock yet. *)
  2682. doLock := ~(Memory IN proc[ID()].locksHeld);
  2683. IF doLock THEN Acquire(Memory) END;
  2684. ok := FALSE;
  2685. IF (virtAdr < s.high) & (virtAdr >= s.low) THEN
  2686. (* Get page boundary *)
  2687. DEC(virtAdr, virtAdr MOD PS);
  2688. (* Check if page is mapped *)
  2689. (*InvalidateDCacheRange(memSysLowStart, memSysLowStop - memSysLowStart);*)
  2690. Initializer.InvalidateDCache;
  2691. IF (GetSecondLevelEntry(virtAdr) MOD 4 = slSmall) THEN
  2692. InvalidateTLBEntry(virtAdr);
  2693. Acquire(TraceOutput);
  2694. Trace.String("Stack address already mapped: ");
  2695. Trace.Address(virtAdr); Trace.Ln;
  2696. Release(TraceOutput)
  2697. ELSE
  2698. (* Allocate page: set different permissions for last stack page. *)
  2699. (*IF (virtAdr <= s.low) THEN HALT(100) ELSE access := FullAccess END;*)
  2700. access := FullAccess;
  2701. ok := AllocatePage(virtAdr, access, flags);
  2702. IF virtAdr < s.adr THEN
  2703. s.adr := virtAdr
  2704. END
  2705. END
  2706. ELSE
  2707. Acquire(TraceOutput);
  2708. Trace.StringLn("Address not in stack");Trace.Address(virtAdr);
  2709. Release(TraceOutput);
  2710. ok := FALSE
  2711. END;
  2712. IF doLock THEN Release(Memory) END;
  2713. RETURN ok
  2714. END ExtendStack;
  2715. (** Create a new stack s, for process with the initial stack pointer initSP. *)
  2716. PROCEDURE NewStack*(VAR s: Stack; process: ANY; VAR initSP: ADDRESS);
  2717. VAR
  2718. old, flags: LONGINT;
  2719. adr: ADDRESS;
  2720. free: SET;
  2721. b: BOOLEAN;
  2722. BEGIN
  2723. Acquire(Memory);
  2724. old := freeStackIndex;
  2725. IF enableCaching THEN
  2726. flags := CB
  2727. ELSE
  2728. flags := 0
  2729. END;
  2730. LOOP
  2731. free := freeStack[freeStackIndex];
  2732. IF free # {} THEN
  2733. (* Find the free stack space in that region and mark it as allocated *)
  2734. adr := 0;
  2735. WHILE ~(adr IN free) DO INC(adr) END;
  2736. EXCL(freeStack[freeStackIndex], SIZE(adr));
  2737. adr := memStackStart + (freeStackIndex * 32 + adr) * maxUserStackSize;
  2738. EXIT
  2739. END;
  2740. INC(freeStackIndex);
  2741. IF freeStackIndex = LEN(freeStack) THEN freeStackIndex := 0 END;
  2742. IF freeStackIndex = old THEN HALT(1503) END
  2743. END;
  2744. s.high := adr + maxUserStackSize; s.low := adr + StackGuardSize;
  2745. s.adr := s.high - InitStackSize; (* at the top of the virtual area *)
  2746. initSP := s.high;
  2747. b := AllocatePage(s.adr, FullAccess, flags); (* allocate one physical page first *)
  2748. ASSERT(b);
  2749. FlushDCacheRange(sysSecondLvlPtStart, sysSecondLvlPtStop - sysSecondLvlPtStart);
  2750. Release(Memory)
  2751. END NewStack;
  2752. PROCEDURE DisposeStack*(s: Stack);
  2753. VAR
  2754. adr: ADDRESS;
  2755. BEGIN
  2756. Acquire(Memory);
  2757. adr := s.adr;
  2758. WHILE adr # s.high DO
  2759. DeallocatePage(adr);
  2760. INC(adr, PS)
  2761. END;
  2762. adr := (adr - maxUserStacks - memStackStart) DIV maxUserStackSize;
  2763. INCL(freeStack[adr DIV 32], SIZE(adr MOD 32));
  2764. Release(Memory)
  2765. END DisposeStack;
  2766. (** Check if the specified stack is valid. *)
  2767. PROCEDURE ValidStack*(CONST s: Stack; sp: ADDRESS): BOOLEAN;
  2768. VAR valid: BOOLEAN;
  2769. BEGIN
  2770. Acquire(Memory);
  2771. valid := (sp MOD 4 = 0) & (sp >= s.adr) & (sp <= s.high);
  2772. WHILE valid & (sp < s.high) DO
  2773. valid := GetSecondLevelEntry(sp) MOD 4 = slSmall;
  2774. INC(sp, PS)
  2775. END;
  2776. Release(Memory);
  2777. RETURN valid
  2778. END ValidStack;
  2779. PROCEDURE GetStack(adr: ADDRESS; VAR s: Stack): BOOLEAN;
  2780. BEGIN
  2781. IF (adr < memStackStart) OR (adr > memStackStop) THEN
  2782. RETURN FALSE
  2783. END;
  2784. s.high := adr - PS;
  2785. s.low := adr - 4;
  2786. s.adr := adr;
  2787. RETURN TRUE
  2788. END GetStack;
  2789. (* ===== Heap ===== *)
  2790. PROCEDURE ValidHeapAddress*(p: ADDRESS): BOOLEAN;
  2791. BEGIN
  2792. RETURN (memHeapStart <= p) & (p < memHeapStop) & (p MOD 4 = 0)
  2793. END ValidHeapAddress;
  2794. (* Free unused memory block *)
  2795. PROCEDURE FreeMemBlock*(memBlock: MemoryBlock);
  2796. BEGIN
  2797. HALT(515) (* impossible to free heap *)
  2798. END FreeMemBlock;
  2799. (** Set memory block end address *)
  2800. PROCEDURE SetMemoryBlockEndAddress*(memBlock: MemoryBlock; endBlockAdr: ADDRESS);
  2801. BEGIN
  2802. ASSERT(endBlockAdr >= memBlock.beginBlockAdr);
  2803. memBlock.endBlockAdr := endBlockAdr
  2804. END SetMemoryBlockEndAddress;
  2805. (* Policy decision for heap expansion. NewBlock for the same block has failed try times. *)
  2806. (*PROCEDURE ExpandNow(try: LONGINT): BOOLEAN;
  2807. VAR size: SIZE;
  2808. BEGIN
  2809. size := LSH(memBlockTail.endBlockAdr - memBlockHead.beginBlockAdr, -10); (* heap size in KB *)
  2810. RETURN (~ODD(try) OR (size < heapMinKB)) & (size < heapMaxKB)
  2811. END ExpandNow;*)
  2812. (** 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). *)
  2813. (*PROCEDURE SetHeapEndAdr(VAR endAdr: ADDRESS);
  2814. VAR n, m: SIZE;
  2815. BEGIN
  2816. HALT(100);
  2817. Acquire(Memory);
  2818. (*
  2819. n := LSH(endAdr+(PS-1), -PSlog2) - LSH(heapEndAdr, -PSlog2); (* pages requested *)
  2820. m := LSH(pageHeapAdr, -PSlog2) - LSH(heapEndAdr, -PSlog2) - ReservedPages; (* max pages *)
  2821. IF n > m THEN n := m END;
  2822. IF n > 0 THEN INC(heapEndAdr, n*PS); DEC(freeHighPages, n) END;
  2823. endAdr := heapEndAdr;
  2824. *)
  2825. Release(Memory)
  2826. END SetHeapEndAdr;*)
  2827. (* Try to expand the heap by at least "size" bytes *)
  2828. PROCEDURE ExpandHeap*(try: LONGINT; size: SIZE; VAR memBlock: MemoryBlock; VAR beginBlockAdr, endBlockAdr: ADDRESS);
  2829. BEGIN
  2830. (*IF ExpandNow(try) THEN
  2831. IF size < expandMin THEN size := expandMin END;
  2832. beginBlockAdr := memBlockHead.endBlockAdr;
  2833. endBlockAdr := beginBlockAdr;
  2834. INC(endBlockAdr, size);
  2835. SetHeapEndAdr(endBlockAdr); (* in/out parameter *)
  2836. memBlock := memBlockHead;
  2837. (* 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 *)
  2838. ELSE*)
  2839. beginBlockAdr := memBlockHead.endBlockAdr;
  2840. endBlockAdr := memBlockHead.endBlockAdr;
  2841. memBlock := NIL
  2842. (*END*)
  2843. END ExpandHeap;
  2844. (** GetStaticHeap - get page range (beginAdr..endAdr-1) and first and last block of static heap.*)
  2845. PROCEDURE GetStaticHeap*(VAR beginBlockAdr, endBlockAdr, freeBlockAdr: ADDRESS);
  2846. BEGIN
  2847. beginBlockAdr := initialMemBlock.beginBlockAdr;
  2848. endBlockAdr := initialMemBlock.endBlockAdr;
  2849. freeBlockAdr := beginBlockAdr;
  2850. END GetStaticHeap;
  2851. (* ===== Caches, TLB & other ===== *)
  2852. (** SHR - logical shift right *)
  2853. PROCEDURE SHR(value, shift: ADDRESS): LONGINT;
  2854. CODE
  2855. LDR R0, [FP, #value]
  2856. LDR R1, [FP, #shift]
  2857. MOV R0, R0, LSR R1
  2858. END SHR;
  2859. (** SHRL - shift right and left. Mask out 'shift' lowest bits *)
  2860. PROCEDURE SHRL(value, shift: LONGINT): LONGINT;
  2861. (*CODE
  2862. LDR R0, [FP, #value]
  2863. LDR R1, [FP, #shift]
  2864. MOV R0, R0, LSR R1
  2865. MOV R0, R0, LSL R1*)
  2866. BEGIN
  2867. value := LSH(value, -shift);
  2868. value := LSH(value, shift);
  2869. RETURN value
  2870. END SHRL;
  2871. (** Fills 'size' bytes with 'filler', from 'destAdr' on. size must be multiple of 4 *)
  2872. PROCEDURE Fill32*(destAdr: ADDRESS; size: SIZE; filler: LONGINT);
  2873. CODE
  2874. LDR R0, [FP, #filler]
  2875. LDR R1, [FP, #size]
  2876. LDR R3, [FP, #destAdr]
  2877. ADD R4, R1, R3 ; R4 = size + destAdr
  2878. AND R5, R3, #3 ; R5 := R3 MOD 4
  2879. CMP R5, #0 ; ASSERT(R5 = 0)
  2880. BEQ CheckSize
  2881. SWI #8
  2882. CheckSize:
  2883. AND R5, R1, #3 ; R5 := R1 MOD 4
  2884. CMP R5, #0 ; ASSERT(R5 = 0)
  2885. BEQ Loop
  2886. SWI #8
  2887. Loop:
  2888. CMP R4, R3
  2889. BLS Exit
  2890. STR R0, [R3, #0] ; put(destAdr + counter, filler)
  2891. ADD R3, R3, #4 ; R3 := R3 + 4
  2892. B Loop
  2893. Exit:
  2894. END Fill32;
  2895. (* GetPageTableBase - returns the memory address of the first level page table *)
  2896. PROCEDURE -GetPageTableBase(): LONGINT;
  2897. CODE
  2898. MRC p15, 0, R0, c2, c0, 0
  2899. MOV R0, R0, LSR #14 ; clear bits 13..0
  2900. MOV R0, R0, LSL #14
  2901. END GetPageTableBase;
  2902. (** GC Initialization -- Set machine-dependent parameters gcThreshold, expandMin, heapMinKB and heapMaxKB *)
  2903. PROCEDURE SetGCParams*;
  2904. VAR size, t: SIZE;
  2905. BEGIN
  2906. GetFreeK(size, t, t); (* size is total memory size in KB *)
  2907. heapMinKB := size * HeapMin DIV 100;
  2908. heapMaxKB := size * HeapMax DIV 100;
  2909. expandMin := size * ExpandRate DIV 100 * 1024;
  2910. IF expandMin < 0 THEN expandMin := MAX(LONGINT) END;
  2911. gcThreshold := size * Threshold DIV 100 * 1024;
  2912. IF gcThreshold < 0 THEN gcThreshold := MAX(LONGINT) END
  2913. END SetGCParams;
  2914. (** Called when spinning, just does a NOP *)
  2915. PROCEDURE -SpinHint*;
  2916. CODE
  2917. MOV R0, R0
  2918. END SpinHint;
  2919. (** 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. *)
  2920. PROCEDURE StrToInt* (VAR i: LONGINT; CONST s: ARRAY OF CHAR): LONGINT;
  2921. VAR vd, vh, sgn, d: LONGINT; hex: BOOLEAN;
  2922. BEGIN
  2923. vd := 0; vh := 0; hex := FALSE;
  2924. IF s[i] = "-" THEN sgn := -1; INC (i) ELSE sgn := 1 END;
  2925. LOOP
  2926. IF (s[i] >= "0") & (s[i] <= "9") THEN d := ORD (s[i])-ORD ("0")
  2927. ELSIF (CAP (s[i]) >= "A") & (CAP (s[i]) <= "F") THEN d := ORD (CAP (s[i]))-ORD ("A") + 10; hex := TRUE
  2928. ELSE EXIT
  2929. END;
  2930. vd := 10*vd + d; vh := 16*vh + d;
  2931. INC (i)
  2932. END;
  2933. IF CAP (s[i]) = "H" THEN hex := TRUE; INC (i) END; (* optional H *)
  2934. IF hex THEN vd := vh END;
  2935. RETURN sgn * vd
  2936. END StrToInt;
  2937. (** Read Non Volatile memory. Not implemented. Required by clock. *)
  2938. PROCEDURE GetNVByte* (ofs: LONGINT): CHAR;
  2939. BEGIN
  2940. RETURN 10X
  2941. END GetNVByte;
  2942. (** Write Non Volatile memory. Not implemented. Required by clock. *)
  2943. PROCEDURE PutNVByte* (ofs: LONGINT; val: CHAR);
  2944. END PutNVByte;
  2945. (* empty section allocated at end of bootfile *)
  2946. PROCEDURE {NOPAF, ALIGNED(32)} LastAddress;
  2947. CODE
  2948. END LastAddress;
  2949. PROCEDURE GetConfig*(CONST name: ARRAY OF CHAR; VAR res: ARRAY OF CHAR);
  2950. BEGIN
  2951. BootConfig.GetValue(name, res)
  2952. END GetConfig;
  2953. PROCEDURE MulH * (x, y: HUGEINT): HUGEINT;
  2954. BEGIN
  2955. RETURN LONGINT(x) * LONGINT(y)
  2956. END MulH;
  2957. PROCEDURE DivH * (x, y: HUGEINT): HUGEINT;
  2958. BEGIN
  2959. RETURN x DIV y
  2960. END DivH;
  2961. (** Not implemented yet *)
  2962. PROCEDURE Portin8*(port: LONGINT; VAR val: CHAR);
  2963. END Portin8;
  2964. PROCEDURE Portout8*(port: LONGINT; val: CHAR);
  2965. END Portout8;
  2966. PROCEDURE TraceState * (CONST state: State);
  2967. BEGIN
  2968. Trace.StringLn("General Purpose Registers");
  2969. Trace.String("R0 "); Trace.Address(state.R[0]); Trace.Ln;
  2970. Trace.String("R1 "); Trace.Address(state.R[1]); Trace.Ln;
  2971. Trace.String("R2 "); Trace.Address(state.R[2]); Trace.Ln;
  2972. Trace.String("R3 "); Trace.Address(state.R[3]); Trace.Ln;
  2973. Trace.String("R4 "); Trace.Address(state.R[4]); Trace.Ln;
  2974. Trace.String("R5 "); Trace.Address(state.R[5]); Trace.Ln;
  2975. Trace.String("R6 "); Trace.Address(state.R[6]); Trace.Ln;
  2976. Trace.String("R7 "); Trace.Address(state.R[7]); Trace.Ln;
  2977. Trace.String("R8 "); Trace.Address(state.R[8]); Trace.Ln;
  2978. Trace.String("R9 "); Trace.Address(state.R[9]); Trace.Ln;
  2979. Trace.String("R10 "); Trace.Address(state.R[10]); Trace.Ln;
  2980. Trace.String("R11 "); Trace.Address(state.R[11]); Trace.Ln;
  2981. Trace.StringLn("Stack");
  2982. Trace.String("SP "); Trace.Address(state.SP); Trace.Ln;
  2983. Trace.String("FP "); Trace.Address(state.BP); Trace.Ln;
  2984. Trace.StringLn("Code");
  2985. Trace.String("LR "); Trace.Address(state.LR); Trace.Ln;
  2986. Trace.String("PC "); Trace.Address(state.PC); Trace.Ln;
  2987. Trace.Ln;
  2988. Trace.String("PSR "); Trace.Address(state.PSR); Trace.Ln;
  2989. Trace.Ln;
  2990. Trace.String("int "); Trace.Address(state.INT); Trace.Ln;
  2991. END TraceState;
  2992. PROCEDURE ReadMemLayout;
  2993. VAR
  2994. value: ARRAY 64 OF CHAR;
  2995. i: LONGINT;
  2996. BEGIN
  2997. memSysLowStart := Platform.OCMStart;
  2998. memSysLowStop := memSysLowStart + Platform.OCMSize;
  2999. GetConfig("KernelLoadAdr", value);
  3000. i := 0;
  3001. memHeapStart := StrToInt(i, value);
  3002. GetConfig("HeapSize", value);
  3003. i := 0;
  3004. memHeapStop := memHeapStart + StrToInt(i, value);
  3005. GetConfig("DDRSize", value);
  3006. i := 0;
  3007. memConfigStop := Platform.DDRStart + StrToInt(i, value);
  3008. GetConfig("ConfigSize", value);
  3009. i := 0;
  3010. memConfigStart := memConfigStop - StrToInt(i, value);
  3011. memStackStart := memHeapStop;
  3012. memStackStop := memConfigStart;
  3013. memIOStart := Platform.IOStart;
  3014. memIOStop := memIOStart + Platform.IOSize;
  3015. memSysHighStart := ADDRESS(4 * G - M);
  3016. memSysHighStop := 4 * G - 1;
  3017. (* System Parameters *)
  3018. sysIntStackStart := memSysLowStart + 1000H;
  3019. sysIntStackStop := memSysLowStart + Platform.MaxCpuNb * 4 * 4 * k;
  3020. (* The first level page table is always 16 k large, to map all 4 G of virtual memory space *)
  3021. sysFirstLvlPtStop := memSysLowStop;
  3022. sysFirstLvlPtStart := sysFirstLvlPtStop - 16 * k;
  3023. (*
  3024. * Second Level Page Table:
  3025. * - 2 * 256 entries for the system area (first and last MB of VMem)
  3026. * - 256 entries for each MB of virtual stack space
  3027. * 256 entries take 1kB memory space.
  3028. *)
  3029. sysSecondLvlPtStop := sysFirstLvlPtStart;
  3030. sysSecondLvlPtStart := sysSecondLvlPtStop - (2 + (memStackStop - memStackStart + memConfigStop - memConfigStart) DIV M) * k;
  3031. (*
  3032. * Interrupt Vector. Located at 0FFFFFFF0H
  3033. *)
  3034. sysVectorStart := 0FFFF0000H;
  3035. sysVectorStop := sysVectorStart + PS;
  3036. sysCacheRefStart := 0FFFF1000H;
  3037. (*
  3038. * Number of ref counters: 1 per 1st level heap page, 1 per 2nd level stack page.
  3039. * This memory region is organized as follows: the first part [0 .. SysCacheStackOfs) is used for heap pages,
  3040. * the second part, [SysCacheStackOfs .. SysCacheRefSize) is used for stack pages.
  3041. *)
  3042. sysCacheRefSize := (memHeapStop - memHeapStart) DIV M + (memStackStop - memStackStart) DIV PS;
  3043. INC(sysCacheRefSize, 4 - sysCacheRefSize MOD 4);
  3044. (* Offset in the ref count table for stack pages. *)
  3045. sysCacheStackOfs := (memHeapStop - memHeapStart) DIV M;
  3046. sysCacheRefStop := sysCacheRefStart + sysCacheRefSize;
  3047. (* Process stack system *)
  3048. GetConfig("StackSize", value);
  3049. i := 0;
  3050. maxUserStackSize := StrToInt(i, value);
  3051. maxUserStacks := (memStackStop - memStackStart) DIV maxUserStackSize;
  3052. GetConfig("EnableCaching", value);
  3053. enableCaching := value[0] # '0';
  3054. traceInterrupts := BootConfig.GetBoolValue("TraceInterrupts")
  3055. END ReadMemLayout;
  3056. PROCEDURE GetProcessorNumber;
  3057. VAR
  3058. value: ARRAY 64 OF CHAR;
  3059. i: LONGINT;
  3060. BEGIN
  3061. FOR i := 0 TO 63 DO value[i] := 0X END;
  3062. GetConfig("CpuNb", value);
  3063. i := 0;
  3064. numProcessors := StrToInt(i, value)
  3065. END GetProcessorNumber;
  3066. (** Analyse reasons for reset, print and record them. *)
  3067. PROCEDURE ResetAnalysis;
  3068. CONST
  3069. (* We need these constants as Platform.slcr is not initialized yet *)
  3070. SLCR_REBOOT_STATUS = ADDRESS(0F8000258H);
  3071. SLCR_LOCK = ADDRESS(0F8000004H);
  3072. SLCR_UNLOCK = ADDRESS(0F8000008H);
  3073. Lock = LONGINT(767BH);
  3074. Unlock = LONGINT(0DF0DH);
  3075. VAR
  3076. val: SET;
  3077. error: LONGINT;
  3078. BEGIN
  3079. SYSTEM.GET(SLCR_REBOOT_STATUS, val);
  3080. IF 16 IN val THEN
  3081. lastReboot := RebootSystemWatchdog;
  3082. Trace.StringLn("Starting after system watchdog reset")
  3083. END;
  3084. IF 17 IN val THEN
  3085. lastReboot := RebootWatchdogCPU0;
  3086. Trace.StringLn("Starting after private watchdog reset on CPU0")
  3087. END;
  3088. IF 18 IN val THEN
  3089. lastReboot := RebootWatchdogCPU1;
  3090. Trace.StringLn("Starting after private watchdog reset on CPU1")
  3091. END;
  3092. IF 19 IN val THEN
  3093. lastReboot := RebootSoftReset;
  3094. Trace.StringLn("Starting after software reboot")
  3095. END;
  3096. IF 20 IN val THEN
  3097. lastReboot := RebootDebug;
  3098. Trace.StringLn("Starting after debug reset")
  3099. END;
  3100. IF 21 IN val THEN
  3101. lastReboot := RebootHardReset;
  3102. Trace.StringLn("Starting after hard reset")
  3103. END;
  3104. IF 22 IN val THEN
  3105. lastReboot := RebootPowerOn;
  3106. Trace.StringLn("Starting after power on")
  3107. END;
  3108. error := SYSTEM.VAL(INTEGER, val);
  3109. IF error # 0 THEN
  3110. Trace.String("BootROM error code: "); Trace.Int(error, 0); Trace.Ln
  3111. END;
  3112. SYSTEM.PUT(SLCR_UNLOCK, Unlock);
  3113. SYSTEM.PUT(SLCR_REBOOT_STATUS, LONGINT(0));
  3114. SYSTEM.PUT(SLCR_LOCK, Lock)
  3115. END ResetAnalysis;
  3116. PROCEDURE InitWatchdog;
  3117. VAR val: ARRAY 32 OF CHAR;
  3118. BEGIN
  3119. GetConfig("EnableKernelWatchdog", val);
  3120. enableWatchdog := val = '1';
  3121. IF enableWatchdog THEN
  3122. PrivateWatchdog.Init(BootConfig.GetIntValue("CpuClockHz") DIV 2);
  3123. PrivateWatchdog.Start(PrivateWatchdog.Reset, Second)
  3124. END
  3125. END InitWatchdog;
  3126. PROCEDURE Init;
  3127. BEGIN
  3128. BootConfig.Init;
  3129. ReadMemLayout;
  3130. sp := SYSTEM.GetStackPointer();
  3131. fp := SYSTEM.GetFramePointer();
  3132. SYSTEM.LDPSR( 0, Platform.IRQMode + Platform.FIQDisabled + Platform.IRQDisabled );
  3133. SYSTEM.SETSP(sysIntStackStart + 1000H);
  3134. SYSTEM.LDPSR( 0, Platform.UndefMode + Platform.FIQDisabled + Platform.IRQDisabled );
  3135. SYSTEM.SETSP(sysIntStackStart + 1000H * 2);
  3136. SYSTEM.LDPSR( 0, Platform.AbortMode + Platform.FIQDisabled + Platform.IRQDisabled );
  3137. SYSTEM.SETSP(sysIntStackStart + 1000H * 3);
  3138. SYSTEM.LDPSR( 0, Platform.SVCMode + Platform.FIQDisabled + Platform.IRQDisabled );
  3139. SYSTEM.SETSP(sysIntStackStart + 1000H * 4);
  3140. SYSTEM.LDPSR( 0, Platform.SystemMode + Platform.FIQDisabled + Platform.IRQDisabled ); (* Disable interrupts, init SP, FP *)
  3141. SYSTEM.SETSP(sp);
  3142. SYSTEM.SETFP(fp);
  3143. TraceDevice.Install;
  3144. Trace.String("Machine: "); Trace.StringLn (Version);
  3145. version := Version;
  3146. InitProcessor;
  3147. InstallDefaultInterrupts;
  3148. DisableInterrupts;
  3149. ResetAnalysis;
  3150. (* Ensure memory layout consistency *)
  3151. ASSERT(sysIntStackStart >= 4 * k);
  3152. ASSERT(sysIntStackStop <= sysSecondLvlPtStart);
  3153. ASSERT(sysFirstLvlPtStart MOD (16 * k) = 0);
  3154. ASSERT(memStackStop <= memIOStart);
  3155. ASSERT(memIOStop <= memSysHighStart);
  3156. ASSERT(sysVectorStop <= sysCacheRefStart);
  3157. ASSERT(sysCacheRefStop <= memSysHighStop);
  3158. InitMemory;
  3159. GetProcessorNumber;
  3160. InitLocks;
  3161. InitGlobalTimer
  3162. END Init;
  3163. PROCEDURE {INITIAL} Initial;
  3164. BEGIN
  3165. Init;
  3166. END Initial;
  3167. END Machine.