From 5511064708688375cd9d2114d3ec5255da4e10c4 Mon Sep 17 00:00:00 2001 From: Stefan Naumann Date: Sat, 29 Jul 2017 23:31:31 +0200 Subject: [PATCH 1/6] Delete README --- mmu/README | 863 ----------------------------------------------------- 1 file changed, 863 deletions(-) delete mode 100644 mmu/README diff --git a/mmu/README b/mmu/README deleted file mode 100644 index 5924ff0..0000000 --- a/mmu/README +++ /dev/null @@ -1,863 +0,0 @@ - -See the top level README file for more information on documentation -and how to run these programs. - -This example demonstrates ARM MMU basics. - -You will need the ARM ARM (ARM Architectural Reference Manual) for -ARMv5. I have a couple of pages included in this repo, but you still -will need the ARM ARM. - -This code so far does not work on the Raspberry pi 2 yet, will get -that working at some point, the knowledge here still applies, I expect -the differences to be subtle between ARMv6 and 7 but will see. - - - --- NEED TO RE-WRITE THIS AGAIN, SUBPAGES ENABLED, COARSE 1KB TABLES -- - - - - -So what an MMU does or at least what an MMU does for us is it -translates virtual addresses into physical addresses as well as -checking access permissions, and gives us control over cachable -regions. - -So what does all of that mean? - -There is a boundary inside the chip around the ARM core, part of that -boundary is the memory interface for the ARM for lack of a better term -how the ARM accesses the world. Nothing special, all processors have -some sort of address and data based interface between the processor and -the ram and peripherals. That boundary uses physical addresses, that -boundary is on the memory side or "world side" of the ARM's mmu. -Within the ARM core there is the "processor side" of the mmu, and all -load and store (and fetch) accesses to the world go through the mmu. - -When the ARM powers up the mmu is disabled, which means all accesses -pass through unmodified making the "processor side" or virtual address -space equal to the world side physical address space. All of my -examples thus far, blinkers and such are based on physical addresses. -We already know that elswhere in the chip is another address -translation of some sort, because the manual is written for 0x7Exxxxxx -based adresses, but the ARM's physical addresses for those same things -is 0x20xxxxxx for the raspi 1 and 0x3Fxxxxxx for the raspi 2. For this -discussion we only care about that other mystery address translation -we care about the ARM and the ARM mmu. - -So when I say the mmu translates virtual addresses into physical -addresses. What that means is on the processor side there is an address -you are accessing, but that does not have to be the same address on -the physical address side of the mmu. Lets say for example I am -running a program on an operating system, Linux lets say, and I need -to compile that program before I can use it and I need to link it for -an address space so lets say that I link it to enter at address 0x8000 -and use memory from 0x0000 to whatever I need and/or whatever is -available. So that is all fine, except what if I have two programs -and I want both running "at the same time" how can both use the same -address space without clobbering each other? The answer is neither is -at that address space the virtual address WHEN RUNNING one of them is -in the virtual address space 0x00000000 to some number, but in reality -program 1 might have that mapped to the physical address 0x01000000 and -program 2 might have its 0x00000000 to some number mapped to 0x02000000. -So when program 1 thinks it is writing to address 0xABCDE it is really -writing to 0x010ABCDE and when program 2 thinks it is writing to -address 0xABCDE it is really writing to 0x020ABCDE. - -If you think about it it doesnt make any sense to allow any virtual -address to map to any physical address, for example from 0x12345678 -to 0xAABBCCDD. Think about it, we are talking about a 32 bit address -space or 4Giga addresses. If we allowed any address to convert to -any other address we would need a 4Giga to 4Giga map, we would actually -need 16Gigabytes just to hold the 4Giga physical adresses worst case. -To cut to the chase ARM has one option where the top 12 bits of the -virtual get translated to 12 bits of physical, the lower 20 bits in -that case are the same between the virtual and physical. This means -we can control 1MByte of address space with one definition, and have -4096 entries in some table somewhere to convert from virtual to -physical. That is quite managable. The minimum we would need to -store are the 12 replacement bits per table entry, but ARM uses a full -32 bit entry, which for this 1MB flavor, has the 12 physical bits plus -some other control bits. - -What does cachable regions mean? The mmu also gives you the feature -of being able to choose per descriptor whether or not you want to -enable caching on that block. One obvious reason would be for the -peripherals. Think about a timer, ideally you read the current timer -tick and each time you read it you get the current timer tick and -as it changes you see it change. But what if when we turned on the -data cache it covered all addresses, all loads and stores? Then you -read the timer once, get a value, read it again, now you get the -cached value over and over again you dont see the real timer value -in the peripheral. That is not good, you cannot manage a peripheral -if you cannot read its status register or read the data coming out -of it, etc. So at a minimum your peripherals need to be in non-cached -blocks. Likewise, if you have some ram that is shared by more than -one resource, say the GPU and the ARM or for the raspberry pi 2 shared -between multiple ARM cores, you have a similar situation, another -resource may change the ram on the far side of your cache but your -cache assumes it has a copy of what is in ram. Basically a cache -only helps you if whatever on the far side of it is only modified by -writes through the cache, if there are ways to change the data on -the far side you should not cache that area. The mmu gives you -the ability to control cached and non-cahced spaces. - -What is meant by access permissions? Lets think about those two -programs running "at the same time" on some operating system (Linux -for example) you dont want to allow one program to gain access to -the operating systems data nor some other programs data. Some -operating systems sure that are meant for only running trusted and -well mannered programs. But you dont want some video game on your -home computer to have access to your banking account data in another -window/program? The mechanisms vary across processor families but -an important job for the mmu is to provide a protection mechanism. -Such that when a particular program has a time slice on the processor -there is some mechanism to allow or restrict memory spaces. If some -code accesses an address that it does not have permission for then -an abort happens and the processor is notified. An interesting -side effect of this is that this doesnt have to be fatal, in fact it -could be by design. Think of a virtual machine, you could let the -virtual machine software run on the processor, and when it accesses -one of its peripherals the real operating system gets an abort but -instead of killing the virtual machine it actually simulates the -peripheral and lets the virtual machine keep running. Another one -that you have probably run into is when you run out of ram in your -computer, the notion of virtual memory which is differen than virtual -address space. Virtual memory in this case is when your program -ventures off the end of its allowed address space into ram it thinks -it has. The operating system gets an abort, finds some ram from -some other program, swaps that ram to disk for example, then allows -the program that was running to have a little more ram by mapping it -back in and allowing it to run. Later when the program whose data -got swapped to disk needs it it swaps back and whatever was in the -ram it swaps with then goes to disk. The term swap comes from the -idea that these blocks of ram are swapped back and forth to disk, -program A's ram goes to disk and is swapped with program T's, then -program T's is swapped with program K's and so on. This is why -starting right after you venture off that edge from real ram to -virtual, your computers performance drops dramatically and disk -activity goes way up, the more things running the more swapping going -on and disk is significantly slower than ram. - -As with all baremetal programming, wading through documentation is -the bulk of the job. Definitely true here, with the unfortunate -problem that ARM's docs dont all look the same from one Archtectural -Reference Manual to an other. We have this other problem that we -are techically using an ARMv6 (architecture version 6)(for the raspi 1) -but when you go to ARM's website there is an ARMv5 and then ARMv7 and -ARMv8, but no ARMv6. Well the ARMv5 manual is actually the original -ARM ARM, that I assume they realized couldnt maintain all the -architecture variations forever in one document, so they perhaps -wisely went to one ARM ARM per rev. With respect to the MMU, the ARMv5 -reference manual covers the ARMv4 (I didnt know there was an mmu option -there) ARMv5 and ARMv6, and there is mode such that you can have the -same code/tables and it works on all three, meaning you dont have to -if-then-else your code based on whatever architecture you find. This -raspi 1 example is based on subpages enabled which is this legacy or -compatibility mode across the three. - -I am mostly using the ARMv5 Architectural Reference Manual. -ARM DDI0100I. - -The 1MB sections mentioned above are called...sections...The ARM -mmu also has blobs that are smaller sizes 4096 byte pages for -example, will touch on those two sizes. The 4096 byte one is called -a small page. - -As mentioned above, 32 bit address space, 1MB is 20 bits so 32-20 is -12 bits or 4096 possible combinations or the address space is broken -up into 4096 1MB sections. The top 12 bits of the virtual address -get translated to 12 bits of physical. No rules on the translation -you can have virtual = physical or have any combination, or have -a bunch of virtual sections point at the same physical space, whatever -you want/need. - -ARM uses the term Virtual Memory System Architecture or VMSA and -they say things like VMSAv6 to talk about the ARMv6 VMSA. There -is a section in the ARM ARM titled Virtual Memory System Architecture. -In there we see the coprocessor registers, specifically CP15 register -2 is the translation table base register. - - -So the ARMv5 ARM ARM (ARM Architectural Reference Manual) is what -we need now. See the top level README for finding this document, -I have included a few pages in the form of postscript, any decent pdf -viewer should be able to handle these files. Before the pictures -though, the section in quesiton is titled Virtual Memory System -Architecture. In the CP15 subsection register 2 is the the translation -table base register. There are three opcodes which give us access to -three things, TTBR0, TTBR1 and the control register. - -First we read this comment - -If N = 0 always use TTBR0. When N = 0 (the reset case), the translation -table base is backwards compatible with earlier versions of the -architecture. - -That is the one we want, we will leave that as N = 0 and not touch it -and use TTBR0 - -Now what the TTBR0 description initially is telling me that bit 31 -down to 14-n or 14 in our case since n = 0 is the base address, in -PHYSICAL address space. Note the mmu cannot possibly go through the -mmu to figure out how to go through the mmu, the mmu itself only -operates on physical space and has direct access to it. In a second -we are going to see that we need the base address for the mmu table -to be aligned to 16384 bytes. (2 to the power 14, the lower 14 bits -of our TLB base address needs to be all zeros). - -We write that register using - - mcr p15,0,r0,c2,c0,0 ;@ tlb base - -TLB = Translation Lookaside Buffer. As far as we are concerned think -of it as an array of 32 bit integers, each integer (descriptor) being -used to completely or partially convert from virtual to physical and -describe permissions and caching. - -My example is going to have a define called MMUTABLEBASE which will -be where we start our TLB table. - -Here is the reality of the world. Some folks struggle with bit -manipulation, orring and anding and shifting and such, some dont. The -MMU is logic so it operates on these tables in the way that logic would, -meaning from a programmers perspective it is a lot of bit manipulation -but otherwise is relatively simple to something a program could do. As -programmers we need to know how the logic uses portsion of the virtual -address to look into this descriptor table or TLB, and then extracts -from those bits the next thing it needs to do. We have to know this so -that for a particular virtual address we can place the descriptor we -want in the place where the hardware is going to find it. So we need -a few lines of code plus some basic understanding of what is going on. -Just like bit manipulation causes some folks to struggle, reading -a chapter like this mmu chapter is equally daunting. It is nice to -have somehone hold your hand through it. Hopefully I am doing more -good than bad in that respect. - -There is a file, section_translation.ps in this repo, you should be -able to use a pdf viewer to open this file. The figure on the -second page shows just the address translation from virtual to physical -for a 1MB section. This picture uses X instead of N, we are using an -N = 0 so that means X = 0. The translation table base at the top -of the diagram is our MMUTABLEBASE, the address in physical space -of the beginning of our first level TLB or descriptor table. The -first thing we need to do is find the table entry for the virtual -address in question (the Modified virtual address in this diagram, -as far as we are concerned it is unmodified it is the virtual -address we intend to use). The first thing we see is the lower -14 bits of the translation table base are SBZ = should be zero. -Basically we need to have the translation table base aligned on a -16Kbyte boundary (2 to the 14th is 16K). It would not make sense -to use all zeros as the translation table base, we have our reset -and interrupt vectors at and near address zero in the arms address -space so the first sane address would be 0x00004000. The first -level descriptor is based on the top 12 bits of the virtual address -or 4096 entries, that is 16KBytes (not a coincidence), 0x4000 + 0x4000 -is 0x8000, where our arm programs entry point is, so we have space -there if we want to use it. But any address with the lower 14 bits -being zero will work so long as you have enough memory at that address -and you are not clobbering anything else that is using that memory -space. - -So what this picture is showing us is that we take the top 12 bits -of the virtual address, multiply by 4 or shift left 2, and add tat -to the translation table base, this gives the address for the first -level descriptor for that virtual address. The diagram shows the -first level fetch which returns a 32 bit value that we have placed -in the table. If the lower 2 bits of that first level descriptor are -0b10 then this is a 1MB Section. If a 1MB section then the top 12 -bits of the first level descriptor replace the top 12 bits of the -virtual address to convert it into a physical address. Understand -here first and foremost so long as we do the N = 0 thing, the first -level descriptor or the first thing the mmu does is look at the top -12 bits of the virtual address, always. If the lower two bits of -the first level descriptor are not 0b10 then we get into -a second level descriptor and more virtual bits come into play, but -for now if we start by learning just 1MB sections, the conversion -from virtual to physical only cares about the top 12 bits of the -address. So for 1MB sections we dont have to concentrate on every -actual address we are going to access we only need to think about -the 1MB aligned ranges. The uart for example on the raspi 1 has -a number of registers that start with 0x202150xx, if we use a 1MB -section for those we only care about the 0x202xxxxx part of the -address. To not have to change our code we would want to have -the virtual = physical for that and do not mark it as cacheable. - -So if my MMUTABLEBASE was 0x00004000 and I had a virtual address of -0x12345678 then the hardware is going to take the top 12 bits of that -address 0x123, multiply by 4 and add that to the MMUTABLEBASE. -0x4000+(0x123<<2) = 0x448C. and that is the address the mmu is going -to use for the first-level lookup. Ignoring the other bits in the -descriptor for now, if the first-level descriptor has the value -0xABC00002, the lower two bits are 0x10, a 1MB section, so the top -12 bits replace the virtual addresses top 12 bits and our 0x12345678 -is converted to the physical address 0xABC45678. - - -Now they have this optional thing called a supersection which is a 16MB -sized thing rather than 1MB and one might think that that would make -life easier, right? Wrong. No matter what, assuming the N = 0 thing -the first level descriptor is found using the top 12 bits of the -virtual address, so in order to do some 16MB thing you need 16 entries -one for each of the possible 1MB sections. If you are already -generating 16 descriptors might as well just make them 1MB sections, -you can read up on the differences between super sections and sections -and try them if you want. For what I am doing here dont need them, -just wanted to point out you still need 16 entries per super section. - -Hopefully I have not lost you yet with this address manipulation, -and maybe you are one step ahead of me, yes EVERY load and store with -the mmu enabled requires at least one mmu table lookup, the mmu when it -accesses this memory does not go through itself, but EVERY other fetch -and load and store. Which does have a performance hit, they do have -a bit of a cache in the mmu to store the last so many tlb lookups. -That helps, but you cannot avoid the mmu having to do the conversion -on every address. - -In the ARM ARM I am looking at the subsection on first-level descriptors -has a table: -Table B4-1 First-level descriptor format (VMSAv6, subpages enabled) -What this is telling us is that if the first-level descriptor, the -32 bit number we place in the right place in the TLB, has the lower -two bits 0b10 then that entry defines a 1MB section and the mmu can get -everything it needs from that first level descriptor. But if the -lower two bits are 0b01 then this is a coarse page table entry and -we have to go to a second level descriptor to complete the -conversion from virtual to physical. Not every address will need -this only the address ranges we want to be more coarsely divided than -1MB. Or the other way of saying it is of we want to control an -address range in chunks smaller than 1MB then we need to use pages -not sections. You can certainly use pages for the whole world, but -if you do the math, 4096Byte pages would mean your mmu table needs -to be 4MB+16K worst case. And you have to do more work to set that -all up. - -The coarse_translation.ps file I have included in this repo starts -off the same way as a section, has to the logic doesnt know what -you want until it sees the first level descriptor. If it sees a -0b01 as the lower 2 bits of the first level descriptor then this is -a coarse page table entry and it needs to do a second level fetch. -The second level fetch does not use the mmu tlb table base address -bits 31:10 of the second level address plus bits 19:12 of the -virtual address (times 4) are where the second level descriptor lives. -Note that is 8 more bits so the section is divided into 256 parts, this -page table address is similar to the mmu table address, but it needs -to be aligned on a 1K boundry (lower 10 bits zeros) and can be worst -case 1KBytes in size. - -The second level descriptor format defined in the ARM ARM (small pages -are most interesting here, subpages enabled) is a little different -than a first level section, we had a domain in the first level -descriptor to get here, but now have direct access to four sets of -AP bits you/I would have to read more to know what the difference -is between the domain defined AP and these additional four, for now -I dont care this is bare metal, set them to full access (0b11) and -move on (see below about domain and ap bits). - -So lets take the virtual address 0x12345678 and the MMUTABLEBASE of -0x4000 again. The first level descriptor address is the top three -bits of the virtual address 0x123, times 4, added to the MMUTABLEBASE -0x448C. But this time when we look it up we find a value in the -table that has the lower two bits being 0b01. Just to be crazy lets -say that descriptor was 0xABCDE001 (ignoring the domain and other -bits just talking address right now). That means we take 0xABCDE000 -the picture shows bits 19:12 (0x45) of the virtual address (0x12345678) -so the address to the second level descriptor in this crazy case is -0xABCDE000+(0x45<<2) = 0xABCDE114 why is that crazy? because I -chose an address where we in theory dont have ram on the raspberry pi -maybe a mirrored address space, but a sane address would have been -somewhere close to the MMUTABLEBASE so we can keep the whole of the -mmu tables in a confined area. Used this address simply for -demonstration purposes not based on a workable solution. - -The "other" bits in the descriptors are the domain, the TEX bits, -the C and B bits, domain and AP. - -The C bit is the simplest one to start with that means Cacheable. For -peripherals we absolutely dont want them to be cached. For ram, maybe. - -The b bit, means bufferable, as in write buffer. Something you may -not have heard about or thought about ever. It is kind of like a cache -on the write end of things instead of read end. I digress, when -a processor writes something everything is known, the address and -data. So the next level of logic, could, if so designed, accept -that address and data at that level and release the processor to -keep doing what it was doing (ideally fetch some more instructions -and keep running) in parallel that logic could then continue to perform -the write to the slower peripheral or really slow dram (or faster cache). -Giving us a small to large performance gain. But, what happens if while -we are doing that first write another write happens. Well if we only -have storage for one transaction in this little feature then the -processor has to wait for us to finish the first write however long -that takes, then we can grab the information for the second write and -then release the processor. I call writes "fire and forget" because -ideally the processor hands off the info to the memory controller -and keeps going, the memory controller has all the info it needs to -complete the task. For a read the processor needs that data back so -basically has to wait. Well a write buffer can store up to some number -of addresses and data. It can still fill up and have to hold the -processor off. But it is similar to a cache is to reading, it has -some faster ram that stages writes so the processor, sometimes, can -keep on going. - -Now the TEX bits you just have to look up and there is the rub there -are likely more than one set of tables for TEX C and B, I am going -to stick with a TEX of 0b000 and not mess with any fancy features -there. Now depending on whether this is considered an older arm -(ARMv5) or an ARMv6 or newer the combination of TEX, C and B have -some subtle differences. The cache bit in particular does enable -or disable this space as cacheable. That simply asserts bits on -the AMDA/AXI (memory) bus that marks the transaction as cacheable, -you still need a cache and need it setup and enabled for the -transaction to actually get cached. If you dont have the cache for -that transaction type enabled then it just does a normal memory (or -peripheral) operation. So we set TEX to zeros to keep it out of the -way. - -Lastly the domain and AP bits. Now you will see a 4 bit domain thing -and a 2 bit domain thing. These are related. There is a register in -the MMU right next to the translation table base address register this -one is a 32 bit register that contains 16 different domain definitions. - -The two bit domain controls are defined as such (these are AP bits) - -0b00 No access Any access generates a domain fault -0b01 Client Accesses are checked against the access permission bits in the TLB entry -0b10 Reserved Using this value has UNPREDICTABLE results -0b11 Manager Accesses are not checked against the access permission bits in the TLB -entry, so a permission fault cannot be generated - -For starters we are going to set all of the domains to 0b11 dont check -cant fault. What are these 16 domains though? Notice it takes 4 bits -to describe one of 16 things. The different domains have no specific -meaning other than that we can have 16 different definitions that we -control for whatever reason. You might allow for 16 different -threads running at once in your operating system, or 16 different -types of software running (kernel, application, ...) you can mark -a bunch of sections as belonging to one parituclar domain, and with a -simple change to that domain control register, a whole domain might -go from one type of permission to another, from no checking to -no access for example. By just writing this domain register you can -quickly change what address spaces have permission and which ones dont -without necessarily changing the mmu table. - -Since I usually use the MMU in bare metal to enable data caching on ram -I set my domain controls to 0b11, no checking and I simply make all -the MMU sections domain number 0. - -So we end up with this simple function that allows us to add first level -descriptors in the MMU translation table. - -unsigned int mmu_section ( unsigned int vadd, unsigned int padd, unsigned int flags ) -{ - unsigned int ra; - unsigned int rb; - unsigned int rc; - - ra=vadd>>20; - rb=MMUTABLEBASE|(ra<<2); - ra=padd>>20; - rc=(ra<<20)|flags|2; - PUT32(rb,rc); - return(0); -} - -So what you have to do to turn on the MMU is to first figure out all -the memory you are going to access, and make sure you have entries -for that. This is important, if you forget something, and dont have -a valid entry there, then you fault, your fault handler, if you have -chosen to write it, may also fault if it isnt placed write or something -it accesses also faults...(I would assume the fault handler is also -behind the mmu but would have to read up on that). - -So the smallest amount of ram on a raspi is 256MB or 0x10000000 bytes. - -Our program enters at address 0x8000, so that is within the first -section 0x000xxxxx so we should make that section cacheable and -bufferable. - - mmu_section(0x00000000,0x00000000,0x0000|8|4); - -This is saying map the virtual 0x000xxxxx to the physical 0x000xxxxx -enable the cache and write buffer. 0x8 is the C bit and 0x4 is the B -bit. tex, domain, etc are zeros. - -If we want to use all 256mb we would need to do this for all the -sections from 0x000xxxxx to 0x100xxxxx. Maybe do that later. - -We know that for the raspi1 the peripherals, uart and such are in -arm physical space at 0x20xxxxxx. To allow for more ram on the raspi 2 -they needed to move that and moved it to 0x3Fxxxxxx. So we either need -16 1MB section sized entries to cover that whole range or we look at -specific sections for specific things we care to talk to and just add -those. The uart and the gpio it is associated with is in the 0x202xxxxx -space. There are a couple of timers in the 0x200xxxxx space so one -entry can cover those. - -if we didnt want to allow those to be cached or write buffered then - - mmu_section(0x20000000,0x20000000,0x0000); //NOT CACHED! - mmu_section(0x20200000,0x20200000,0x0000); //NOT CACHED! - mmu_section(0x3F000000,0x3F000000,0x0000); //NOT CACHED! - mmu_section(0x3F200000,0x3F200000,0x0000); //NOT CACHED! - -but we may play with that to demonstrate what caching a peripheral -can do to you, why we need to turn on the mmu if for no other reason -than to get some bare metal performance by using the d cache. - -Now you have to think on a system level here, there are a number -of things in play. We need to plan our memory space, where are we -putting the MMU table, where are our peripherals, where is our program. - -If the only reason for using the mmu is to allow the use of the d cache -then just map the whole world virtual = physical if you want with the -peripherals not cached and the rest cached. - -If you are on the raspi 2 with multiple arm cores and are using -the multiple arm cores you need to do more reading if you want one -core to talk to another by sharing some of the memory between -them. Same problem as peripherals basically with multiple masters -of the ram/peripheral on the far side of my cache, how do I insure -what is in my cache maches the far side? Easiest way is to not -cache that space. You need to read up on if the cores share a cache -or have their own (or if l2 if present is shared but l1 is not), -ldrex/strex were implemented specifically for multi core, but you -need to understand the cache effects on these instructions ( -not documented well, I have an example on just this one topic). - -So once our tables are setup then we need to actually turn the -MMU on. Now I cant figure out where I got this from, and I have -modified it in this repo. According to this manual it was with the -ARMv6 that we got the DSB feature which says wait for either cache -or MMU to finish something before continuing. In particular when -initializing a cache to start it up you want to clean out all the -entries in a safe way you dont want to evict them and hose memory -you want to invalidate everything, mark it such that the cache lines -are empty/available. Likewise that little bit of TLB caching the MMU -has, we want to invalidate that too so we dont start up the mmu -with entries in there that dont match our entries. - -Why are we invalidating the cache in mmu init code? Because first we -need the mmu to use the d cache (to protect the peripherals from -being cached) and second the controls that enable the mmu are in the -same register as the i and d controls so it made sense to do both -mmu and cache stuff in one function. - -So after the DSB we set our domain control bits, now in this example -I have done something different, 15 of the 16 domains have the 0b11 -setting which is dont fault on anything, manager mode. I set domain -1 such that it has no access, so in the example I will change one -of the descriptor table entries to use domain one, then I will access -it and then see the access violation. I am also programming both -translation table base addresses even though we are using the N = 0 -mode and only one is needed. Depends on which manual you read I guess -as to whether or not you see the N = 0 and the separate or shared -i and d mmu tables. (the reason for two is if you want your i and -d address spaces to be managed separately). - -Understand I have been running on ARMv6 systems without the DSB and it -just works, so maybe that is dumb luck... - -This code relies on the caller to pass in the MMU enable and I and D -cache enables. This is because this is derived from code where -sometimes I turn things on or dont turn things on and wanted it -generic. - - -.globl start_MMU -start_MMU: - mov r2,#0 - mcr p15,0,r2,c7,c7,0 ;@ invalidate caches - mcr p15,0,r2,c8,c7,0 ;@ invalidate tlb - mcr p15,0,r2,c7,c10,4 ;@ DSB ?? - - mvn r2,#0 - bic r2,#0xC - mcr p15,0,r2,c3,c0,0 ;@ domain - - mcr p15,0,r0,c2,c0,0 ;@ tlb base - mcr p15,0,r0,c2,c0,1 ;@ tlb base - - mrc p15,0,r2,c1,c0,0 - orr r2,r2,r1 - mcr p15,0,r2,c1,c0,0 - - bx lr - -I am going to mess with the translation tables after the MMU is started -so the easiest way to deal with the TLB cache is to invalidate it, but -dont need to mess with main L1 cache. ARMv6 introduces a feature to -help with this, but going with this solution. - -.globl invalidate_tlbs -invalidate_tlbs: - mov r2,#0 - mcr p15,0,r2,c8,c7,0 ;@ invalidate tlb - mcr p15,0,r2,c7,c10,4 ;@ DSB ?? - bx lr - -Something to note here. Debugging using the JTAG based on chip debugger -makes life easier, that removing sd cards or the old days pulling an -eeprom out and putting it it in an eraser then a programmer. BUT, -it is not completely without issue. When and where and if you hit this -depends heavily on the core you are using and the jtag tools and the -commands you remember/prefer. The basic problem is caches can and -often do separate instruction I fetches from data D reads and writes. -So if you have test run A of a program that has executed the instruction -at address 0xD000. So that instruction is in the I cache. You have -also executed the instruction at 0xC000 but it has been evicted, but -you dont actually know what is in the I cache or not, shouldnt even -try to assume. You stop the processor, you write a new program to -memory, now these are data D writes, and go through the D cache. Then -you set the start address and run again. Now there are a number of -combinations here and only one if them works, the rest can lead to -failure. - -For each instruction/address in the program, if the prior instruction -at that address was in the i cache, and since data writes do not go -through the i cache then the new instruction for that address is either -in the d cache or in main ram. When you run the new program you will -get the stale/old instruction from a prior run when you fetch that -address (unless an invalidate happens, if a flush happens then you -write back, but why would an I cache flush?), and if the new instruction -at that address is not the same as the old one unpredictable results -will occur. You can start to see the combinations, did the data -write go through to d cache or to ram, will it flush to ram and is the -i cache invalid for that address, etc. - -There is also the quesiton of are the I and D caches shared, they can -be but that is both specific to the core and your setup. Also does -the jtag debugger have the ability to disable the caches, has it done -it for you, can you do it manually. - -Any time you are using the i or d caches you need to be careful using -a jtag debugger or even a bootloader type approach depending on its -design as you might end up doing data writes of instructions and going -around the i cache or worse. So for this kind of work using a chip -reset and non volitle rom/flash based bootloader can/will save you -a lot of headaches. If you know your debugger is solving this for you, -great, but always make sure as you change from the raspi 2 back to -a raspi 1 for example it might not be doing it and it will drive you -nuts when you keep downloading a new program and it either crashes -in a strange way or simply just keeps running the old program and -not appearing to take your new changes. - -So the example is going to start with the mmu off and write to -addresses in four different 1MB address spaces. So that later we -can play with the section descriptors and demonstrate virtual to -physical address conversion. - -So write some stuff and print it out on the uart. - - PUT32(0x00045678,0x00045678); - PUT32(0x00145678,0x00145678); - PUT32(0x00245678,0x00245678); - PUT32(0x00345678,0x00345678); - - hexstring(GET32(0x00045678)); - hexstring(GET32(0x00145678)); - hexstring(GET32(0x00245678)); - hexstring(GET32(0x00345678)); - uart_send(0x0D); uart_send(0x0A); - -then setup the mmu with at least those four sections and the peripherals - - mmu_section(0x00000000,0x00000000,0x0000|8|4); - mmu_section(0x00100000,0x00100000,0x0000); - mmu_section(0x00200000,0x00200000,0x0000); - mmu_section(0x00300000,0x00300000,0x0000); - //peripherals - mmu_section(0x20000000,0x20000000,0x0000); //NOT CACHED! - mmu_section(0x20200000,0x20200000,0x0000); //NOT CACHED! - -and start the mmu with the I and D caches enabled - - start_mmu(MMUTABLEBASE,0x00000001|0x1000|0x0004); - -then if we read those four addresses again we get the same output -as before since we maped virtual = physical. - - hexstring(GET32(0x00045678)); - hexstring(GET32(0x00145678)); - hexstring(GET32(0x00245678)); - hexstring(GET32(0x00345678)); - uart_send(0x0D); uart_send(0x0A); - -but what if we swizzle things around. make virtual 0x001xxxxx = -physical 0x003xxxxx. 0x002 looks at 0x000 and 0x003 looks at 0x001 -(dont mess with the 0x00000000 section, that is where our program is -running) - - mmu_section(0x00100000,0x00300000,0x0000); - mmu_section(0x00200000,0x00000000,0x0000); - mmu_section(0x00300000,0x00100000,0x0000); - -and maybe we dont need to do this but do it anyway just in case - - invalidate_tlbs(); - -read them again. - - hexstring(GET32(0x00045678)); - hexstring(GET32(0x00145678)); - hexstring(GET32(0x00245678)); - hexstring(GET32(0x00345678)); - uart_send(0x0D); uart_send(0x0A); - -the 0x000xxxxx entry was not modifed so we get 000045678 as the output -but the 0x001xxxxx read is now coming from physical 0x003xxxxx so we -get the 00345678 output, 0x002xxxxx comes from the 0x000xxxxx space -so that read gives 00045678 and the 0x003xxxxx is mapped to 0x001xxxxx -physical giving 00145678 as the output. - -So up to this point the output looks like this. - -DEADBEEF -00045678 -00145678 -00245678 -00345678 - -00045678 -00145678 -00245678 -00345678 - -00045678 -00345678 -00045678 -00145678 - -first blob is without the mmu enabled, second with the mmu but -virtual = physical, third we use the mmu to show virtual != physical -for some ranges. - -Now for some small pages, I made this function to help out. - -unsigned int mmu_small ( unsigned int vadd, unsigned int padd, unsigned int flags, unsigned int mmubase ) -{ - unsigned int ra; - unsigned int rb; - unsigned int rc; - - ra=vadd>>20; - rb=MMUTABLEBASE|(ra<<2); - rc=(mmubase&0xFFFFFC00)/*|(domain<<5)*/|1; - //hexstrings(rb); hexstring(rc); - PUT32(rb,rc); //first level descriptor - ra=(vadd>>12)&0xFF; - rb=(mmubase&0xFFFFFC00)|(ra<<2); - rc=(padd&0xFFFFF000)|(0xFF0)|flags|2; - //hexstrings(rb); hexstring(rc); - PUT32(rb,rc); //second level descriptor - return(0); -} - -So before turning on the mmu some physical addresses were written -with some data. The function takes the virtual, physical, flags and -where you want the secondary table to be. Remember secondary tables -can be up to 1K in size and are aligned on a 1K boundary. - - - mmu_small(0x0AA45000,0x00145000,0,0x00000400); - mmu_small(0x0BB45000,0x00245000,0,0x00000800); - mmu_small(0x0CC45000,0x00345000,0,0x00000C00); - mmu_small(0x0DD45000,0x00345000,0,0x00001000); - mmu_small(0x0DD46000,0x00146000,0,0x00001000); - //put these back - mmu_section(0x00100000,0x00100000,0x0000); - mmu_section(0x00200000,0x00200000,0x0000); - mmu_section(0x00300000,0x00300000,0x0000); - invalidate_tlbs(); - -Now why did I use different secondary table addresses most of the -time but not all of the time? A secondary table lookup is the same -first level descriptor for the top 12 bits of the address, if the -top 12 bits of the address are different it is a different secondary -table. So to demonstrate that we actually have separation within a -section I have two small pages within a 1MB section that I point -at two different physical address spaces. So in short if the top -12 bits of the virtual address are the same then they share the same -coarse page table, the way the function works it writes both first -and second level descriptors so if you were to do this - - mmu_small(0x0DD45000,0x00345000,0,0x00001000); - mmu_small(0x0DD46000,0x00146000,0,0x00001400); - -Then both of those virtual addresses would go to the 0x1400 table, and -the first virtual address would not have a secondary entry its -secondary entry would be in a table at 0x1000 but the first level -no longer points to 0x1000 so the mmu would get whatever it finds -in the 0x1400 table. - - -The last example is just demonstrating an access violation. Changing -the domain to that one domain we did not set full access to - - //access violation. - - mmu_section(0x00100000,0x00100000,0x0020); - invalidate_tlbs(); - - hexstring(GET32(0x00045678)); - hexstring(GET32(0x00145678)); - hexstring(GET32(0x00245678)); - hexstring(GET32(0x00345678)); - uart_send(0x0D); uart_send(0x0A); - -The first 0x45678 read comes from that first level descriptor, with -that domain - -00045678 -00000010 - -How do I know what that means with that output. Well from my blinker07 -example we touched on exceptions (interrupts). I made a generic test -fixture such that anything other than a reset prints something out -and then hangs. In no way shape or form is this a complete handler -but what it does show is that it is the exception that is at address -0x00000010 that gets hit which is data abort. So figuring out it was -a data abort (pretty much expected) have that then read the data fault -status registers, being a data access we expect the data/combined one -to show somthing and the instruction one to not. Adding that -instrumentation resulted in. - -00045678 -00000010 -00000019 -00000000 -00008110 -E5900000 -00145678 - -Now I switched to the ARM1176JZF-S Technical Reference Manual for more -detail and that shows the 0x01 was domain 1, the domain we used for -that access. then the 0x9 means Domain Section Fault. - -The lr during the abort shows us the instruction, which you would need -to disassemble to figure out the address, or at least that is one -way to do it perhaps there is a status register for that. - -The instruction and the address match our expectations for this fault. - -This is simply a basic intro. Just enough to be dangerous. The MMU -is one of the simplest peripherals to program so long as bit -manipulation is not something that causes you to lose sleep. What makes -it hard is that if you mess up even one bit, or forget even one thing -you can crash in spectacular ways (often silently without any way of -knowing what happened). Debugging can be hard at best. - -The ARM ARM indicates that the ARMv6 adds the feature of separating -the I and D from an mmu perspective which is an interesting thought -(see the jtag debugging comments, and think about how this can affect -you re-loading a program into ram and running) you have enough ammo -to try that. The ARMv7 doesnt seem to have a legacy mode yet, still -reading, the descriptors and how they are addresses looks basically -the same but this code doesnt yet work on the raspi 2, so I will -continue to work on that and update this repo when I figure it out. - - - - - From 27ff157eea0fc47b9a816f17b1321cdef3fd0bd3 Mon Sep 17 00:00:00 2001 From: Stefan Naumann Date: Sat, 29 Jul 2017 23:32:41 +0200 Subject: [PATCH 2/6] added (partially)) reworked README --- mmu/README.md | 822 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 822 insertions(+) create mode 100644 mmu/README.md diff --git a/mmu/README.md b/mmu/README.md new file mode 100644 index 0000000..b19918c --- /dev/null +++ b/mmu/README.md @@ -0,0 +1,822 @@ +# MMU on Raspberry Pi + +See the top level README file for more information on documentation +and how to run these programs. + +## Preface + +This example demonstrates ARM MMU basics. + +You will need the [ARM ARM] (ARM Architectural Reference Manual) for +ARMv5. + +This code so far does not work on the Raspberry pi 2 yet, will get +that working at some point, the knowledge here still applies, I expect +the differences to be subtle between ARMv6 and 7 but will see. + +## Fundamentals + +A Memory Managment Unit (MMU) translates virtual addresses into physical +addresses, as well as checking access permissions and giving control over +marking regions cacheable. This allows the programmer to identify the memory +regions which may be cached for faster access in the CPU core, but leaving out +for example hardware registers, which are mapped into memory. + +There is a boundary inside the chip around the ARM-core. The ARM-core itself +uses virtual addresses for memory and hardware-accesses, which are translated +by the MMU to physical addresses when actually requesting a value in memory. +Every access to the memory or the "world side" has to go through the MMU. + +When the ARM-core powers up the MMU is disable, which means that every access +will pass through unmodified, making the virtual addresses (processor side) +equal to the physical addresses (world side). All of the example thus far in +this repository (e.g. blinkers) are based in physical addresses. + +We already know that somewhere else in the chip the used addresses are +different. The Raspberry Pi manual is written for 0x7Exxxxxx based addresses, +but for the ARM's physical addresses for the same things is 0x20xxxxxx for the +Raspberry Pi 2 and 0x3Fxxxxxx for the Raspberry Pi 2. For this discussion we +only care about the ARM and the ARM MMU, not for the other mystical translation +on the chip. + +### Motivation + +Let's say I am programming a program for let's say Linux. I would have to link +my program to use specific addresses (or a specific address space). Let's +assume, that our program is loaded into 0x8000 and it can use the memory from +0x0000 onwards. That would be fine for one program, but let's say another +program wants to be loaded to 0x8000 or maybe use this space as memory for +variables. So how can we run several program without the risk of them +clobbering each other? + +The answer is neither is actually loaded into 0x8000 when running. The programs +may assume, that they can use the addresses like stated above, but in reality +the addresses when requesting memory cells will be translated by the MMU. So +one program could be placed to 0x10008000, the other one at 0x20008000. When +program 1 thinks it accesses 0x0000abcd it is really accessing 0x1000abcd, the +other one 0x2000abcd. This translation is completely transparent to the +programs, i.e. they will never notice, that the addresses are translated for +them. + +Theoretically you could assign every virtual address a physical address to be +translated to, but that does not make much sense. The ARM-core used on the +Raspberry Pi is a 32-bit processor, i.e. it uses 32-bit addresses. This means +we have 4 Giga (2^32) addresses. A table containing the physical addresses +alone would be 16 GB big. + +The ARM has one option to translate the top 12 bits of the virtual address to +the top 12 bits of the physical address, leaving the lower 20 bits as they are +between the virtual and physical space. This means we can control 1 MB of +address space per definition and have 4096 entries in a table somewhere to +convert virtual to physical addresses. The ARM still uses all 32 Bits, 12 for +the top 12 address bits, the other ones as control flags. One of them indicates +whether a region is marked as cacheable. + +### About caching + +A cache is a (very small but) very fast memory inside the processor. It is used +by the processor transparently to remember data which is loaded and/or stored +by your program together with its address. This behaviour saves the processor +from having to request the value from RAM every time it is needed, having to +wait for the (slower) memory on every read/write. Caching can vastly increase +the speed of your program. Changes to values are written through the cache. + +But why is it disabled with the MMU disabled? Let's assume we want to read the +value register of a timer. This is done by reading from a specific address. +What we want would be, that we get the current value every time we read the +register. When caching is enabled for these memory regions we would read the +current value one time, but after that we will only get the cached value. This +is no good, because you cannot control peripherals if you are unable to get the +current state or value of a peripheral, because the cache only gives you the +last (old) values. + +Likewise, if you have some RAM, which is shared by more than one resource, like +the GPU and the ARM or several processor cores on the Raspberry Pi 2 or 3, you +will have a similar situation. In general you want to disable caching on every +region which can be modified by other means than through the cache. The MMU +let's you enable or disable caching on memory regions. + +### About access permissions + +Let's think back to our example with the two programs running "at the same +time". You don't want any of the programs to get access to the operating +systems data structures nor do you want any of the two modifying code or data +of the other program. You would not want a video game to get access to your +banking account open in another window, would you? + +The mechanisms vary by processor family but the MMU provides the security +mechanisms. When a particular program is running on the processor there are +mean to allow or restrict access to specific memory spaces. If some code +accesses an address it does not have the permissions for, then a Data +Abort-Exception happens, and the processor will stop running the code of that +application. The Operating System will be notified (by the means of an +Exception Handler / Interrupt Service Routine). + +This Data Abort does not have to be fatal for the application, but it could be +by design. Think of a virtual machine, running on the processor and when it +tries to access its peripherals, the real Operating System can be notified to +simulate the peripheral and keep the virtual machine running. + +### About virtual memory + +What happens when you run out of memory on your computer? Let's say the RAM is +use up completely, but an application uses for example `malloc` to request more +memory. The operating system will then find a block of memory of another +application and save that to disk. This space can then be used by the running +application as memory. When the other program then tries to use the swapped out +memory, it will trigger an Data Abort-Exception in the processor. This will +trigger the operating system to swap that memory block back into memory (maybe +substituting another block of another application). + +The term swap comes from the idea that these blocks of ram are swapped back and +forth to disk, program A's ram goes to disk and is swapped with program T's, +then program T's is swapped with program K's and so on. This is why starting +right after you venture off that edge from real RAM to virtual, your computers +performance drops dramatically and disk activity goes way up. The more things +run the more memory needs to be swapped onto the much slower disk. + +## Wading through the documentation + +I am mostly using the ARMv5 Architectural Reference Manual DDI0100I. ([ARM ARM]) + +Unfortunately the ARM ARM does not look the same from one to the next. With the +Raspberry Pi 1 and Zero we are technically using an ARMv6 (architecture version +6), but when we go to ARM's website, there is an ARMv5, ARMv7 and ARMv8-version, +but no ARMv6. The ARMv5 manual is actually the original ARM ARM, where they (I +assume) realized, that they could not maintain all the architecture variations +in one document forever. So they split them per revision. With respect to the +MMU the ARMv5 manual cover the ARMv4, ARMv5 and ARMv6. There is a mode where +you can have the same code and table to work on all three, so you don't have to +if-then-else your code based on whatever architecture you find. This example is +based on this legacy mode with subpages enables. + +The 1 MB sections mentioned above are called sections. The ARM MMU also has +blobs with a smaller size of 4096 bytes, which are called small page. I will +touch on those two sizes. + +As mentioned above the Raspberry Pi has a 32 bit address space. 1 MB sections +means 20 bits unaltered (bits 32 to 20) and 12 bits translated meaning 4096 +1 MB sections, i.e. 4096 entries in the table. The top 12 bits of the virtual +address get translated to the top 12 bits of the physical address. There are no +additional rules on the translation, you can have for example +- virtual = physical +- any combination you like +- have a bunch of virtual sections point to the same physical space. + +ARM uses the term Virtual Memory System Architecture or VMSA and +they say things like VMSAv6 to talk about the ARMv6 VMSA. There +is a section in the ARM ARM titled Virtual Memory System Architecture. +In there we see the coprocessor registers, specifically CP15 register +2 is the translation table base register. In the CP15 subsection register 2 is +the translation table base register. There are three opcodes which give us +access to three things: `TTBR0`, `TTBR1` and the control register. + +### Writing the Translation table base address + +First we read this comment (pg. 741, heading: Register 2: Translation table +base): +> If N = 0 always use `TTBR0`. When N = 0 (the reset case), the translation +> table base is backwards compatible with earlier versions of the +> architecture. + +So we want to leave N = 0 and use `TTBR0`. + +The `TTBR0`-register contains the base address in the physical address space. +The bits 31 down to 14-n (with n=0 in our case) are used as the base address. +Note that the MMU cannot go through the MMU to figure out how to go through the +MMU. It operates exclusively in physical address space and has direct access to +memory. In a second we are going to see, that the base address for the MMU table +has to be aligned to 16384 bytes (2^14), the lower 14 bits of our TLB base +address is all zeroes (TLB=Translation Look-Aside Buffer)). + +We write that register using + +```armasm + mcr p15,0,r0,c2,c0,0 ;@ tlb base +``` + +#### The co-processor + +Let me explain what that mnemonic does. `mcr` is a special instruction to write +to registers of the co-processor. This co-processor manages loads of functions +of the ARM-core, like unaligned data access or the MMU. You probably already +came across `msr` which is an instruction to store data into the status +register of the ARM-core (for example to set a new privilege mode or to enable +interrupts). You cannot access the status register or the co-processor +registers with the normal `mov` instruction. + +The co-processor has several registers, which can be accessed by the `mcr` or +the `mrc` instruction. The parameters are: + +```armasm + MCR{cond} P15,,,,, + MRC{cond} P15,,,,, +``` + +[co-processor] shows the list of registers plus their assignment to the +parameters for the two instructions. So the above statement will access the following parameters: +- Opcode_1: 0 +- Rd: r0 +- CRn: c2 (register number within CP15) +- CRm: c0 (operational register) +- Opcode_2: 0 + +r0 serves as source register of the value to be written to the Register +identified by (c2,c0,0,0). + +#### About TLB + +As far as we are concerned think of the TLB as an array of 32 bit integer, +each one being used to translate a virtual to a physical address and +describes permissions and caching. My example is going to have a define called +`MMUTABLEBASE` which will be where out TLB table starts. The TLB is used as +cache for the page tables. + +The MMU is completely realised in hardware, but you can configure it the way +you want. It will operate on the values we set into our page table with Or and +And-operations (i.e. bit-manipulations). It uses portions of the virtual +addresses to find the correct plane in the page table to find the according +physical address. From the next bits it will decide what to do next. We, as +programmers, need to know how the MMU calculates the place, so we can put our +descriptor into the correct space, so the MMU finds it. + +#### Translating virtual to physical addresses + +In the manual there is figure B4-4 (page B4-29), which shows a diagram of how +the addresses are translated. It uses X instead of N (which we want to be 0). +The modified virtual address in this diagram is, as far as we are concerned, +unmodified as we want to intend to use our virtual addresses. The first thing +we see, is that the lower 14 Bits of the translation table base (in my example +`MMUTABLEBASE`), i.e. the start address of the translation table are marked as +SBZ, i.e. should-be-zero. This means, that the translation table should be +aligned to 16 KiB (2^14 Bytes). Using 0x0000 as starting address would not make +much sense, as this is the place for the interrupt vector. The next good place +would be 0x00004000. Adding another 16 KiB to that address is (not a +coincidence) 0x8000, where we put our code. But any other address, which is +aligned to 16 KiB should work, as long as you have enough memory there and not +clobber anything else. + +The figure B4-4 shows, that we take the top 12 bits of the virtual address, +multiply by 4 (or shift left by 2) and add that to the translation table base, +which gives the address of the first level descriptor for that virtual address. +A multiplication by 4 is no coincidence, but rather takes the length of each +descriptor into account (which is exactly 32 bit, or 4 byte). The descriptor +is fetched and interpreted. As long as we leave N=0 the MMU will always look +into the first 12 bits, which replace the first 12 bits of the virtual address. +The last two bits of the descriptor are flags, if they are 0b10, then it is a +1 MB section. If it's something different, then a second level translation +will be triggered, but for now let's focus on the simpler part. + +##### An example + +``` + MMUTABLEBASE = 0x00004000 + virtual address = 0x12345678 + -> first 12 bit (moved to right): 0x00000123 + descriptor for the section: 0x000448c + let's assume the descriptor was 0xABC00002 + -> physical address 0xABC45678 +``` + +#### 16 MiB Supersections + +So the ARM ARM states, that you can have 16 MiB supersections. This would make +life easier, right? Well, no. You still have to generate 16 descriptors for +each of the possible 1 MiB sections, so you might as well make them 1 MiB big. +You can read up on the differences and try the supersections our, but I'm going +to use 1 MiB sections for now. + +Maybe you figured out a bit of a problem here. Every load and store with the MMU +enabled requires at least one MMU table lookup. The MMU memory accesses of +course don't have to go through the MMU, but every other store or load. This +does have a performance hit. Therefore the MMU caches the last TLB-lookups. +This helps but the conversion has to be done on every requested address. + +### Descriptor format + +I am looking on the subsection about First Level Descriptors in the ARM ARM, +especially the Table B4-1 (pg. B4-27, First-level descriptor format (VMSAv6, +subpages enabled)). + +This table identifies four different sets of last two bits [1:0]: +- `0b00` - this section is unmapped. Attempting to access these addresses will generate a translation fault (Data Abort). The bits [31:2] are ignored by the hardware, although it is recommended to keep valid permissions for the descriptor there. +- `0b01` - for coarse second level table, second level lookup required for translation; allows more fine grained sectioning of the section +- `0b10` - sections descriptor for its associated virtual addresses, no second level lookup +- `0b11` - reserved in VMSAv6 + +For now let's work with the `0b10`-entries. The format of the entry is as follows: + +| | Bits 31:20 | Bits 19:15 | 14,13,12 | 11,10 | 9 | 8:5 | 4 | 3 | 2 | 1,0 | +|---|------------|------------|----------|-------|---|-----|---|---|---|-----| +| Section | Section base address | SBZ | TEX | AP | IMP | Domain | SBZ | C | B | `10` | + +The **section base address** are the 12 top bits of the physical address, which +substitute the top 12 bits of the virtual address. The **C** bit marks the address +region as cacheable. We do absolute not want to cache peripheral regions, +RAM-regions maybe. The C-flag simply asserts bits on the AMDA/AXI (memory) bus +that marks the transaction as cacheable, you still need a cache setup and +enabled for the transaction to actually get cached. If you don't have the +cache for that transaction type enabled, then it just does a normal memory (or +peripheral) operation. + +The **B** bit, means bufferable, as in write buffer. This enables a "cache" +but for writing instead of reading. When writing a value to RAM (or peripheral) +everything is known, the data and the address. The buffer-bit allows some logic +at this level to accept the value and address and continue to write the data to +the slower RAM or peripheral (or cache) and let's the CPU go on executing it's +program. This may give us a performance boost. When a second write appears and +we only have a single place for a transaction, the processor gets stalled until +the first one is complete and the second write-command can be saved to the +buffer. The advantage is that for a number of writes the processor can hand the +needed data to the memory controller and carry on. + +You need to look up the **TEX** bits yourself. I will stick to them being 0b000 +and will not mess with any fancy features here. The combinations of TEX, C and +B bits make some subtle differences, look them up in Table B4-3 (CB + TEX +Encodings). + +The **AP** bits indicate the level of access permissions (see Table B4-1 MMU +access permissions, pg. B4-9), for page table formats, which don't support APX, +value 0 is assumed. The following AP-values are therefore valid: +- `0b00` - No access for anyone; will generate permission fault on every access +- `0b01` - Read/Write permission for privileged mode +- `0b10` - Read/write for privileged mode, read for user mode (writes in user mode trigger permission faults) +- `0b11` - Full access (R/W for everyone) + +The **domain** is a bit trickier to explain. There is a register right next to the translation table base address register which contains 16 different domain specifications. These definitions are 2 bit long each: +- `0b00` - **no access**, any access generates a domain fault +- `0b01` - **client**, accesses are checked against the access permission bits in the TLB entry +- `0b10` - **UNPREDICTABLE** behaviour +- `0b11` - **manager**, accesses are not checked and cannot generate a permission fault + +The domains basically are 16 different definitions which control the behaviour +on access. We can define for example 16 types of applications and assign them +sections. We assign sections to domains by setting the four **domain** bits of +the translation table entry to the number of the definition in the register. +With changing to bits in this register we can then put sections of a domain +into another permission mode, which is quite useful, because we don't need to +change the MMU table. + +For starters we are going to set all of the domains to `0b11` don't check and +all of our sections can have the domain number 0. + +## A simple implementation + +```c + /** + * \brief creates an translation table entry (for sections of size 1 MiB) + * \param[in] vadd the virtual address (only top 12 bits used) + * \param[in] padd the physical address (only top 12 bits used) + * \param[in] flags the flags for the section + **/ + uint32_t mmu_section ( uint32_t virtual, uint32_t physical, uint32_t flags ) + { + uint32_t offset = virtual >> 20; + // plus and or are the same thing here, as MMUTABLEBASE is 14 bit aligned + uint32_t* entry = MMUTABLEBASE | (offset<<2); + + // mask lower 20 bits of physical address then ORR flags and 0x02 for 1 MiB + physval = (physval & 0xfff00000) | (flags & 0x7ffa) | 0x02; + + *entry = physval; + return(0); + } + + #define CACHEABLE 0x08 + #define BUFFERABLE 0x04 +``` + +### Filling the table with sections + +Before enabling the MMU itself we need to make sure, that every section of +memory we want to use is defined with a valid entry in the table. If not, +access to that region will trigger a fault handler - if you decide to write +one. Which in turn can access to non mapped memory - which is not good. + +The smallest amount of RAM on a Raspberry Pi is 256 MiB or 0x10000000 bytes. +Our program enters at address 0x8000, so that is within the first +section 0x000xxxxx so we should make that section cacheable and +bufferable. + +```c + mmu_section( 0x00000000,0x00000000, CACHEABLE | BUFFERABLE ); +``` + +This statement will create an entry for the virtual address space 0x000xxxxx +to the physical addresses 0x000xxxxx enable the cache and write buffer. If we +want to use all 256mb we would need to do this for all the sections from +0x000xxxxx to 0x100xxxxx. + + + +We know that for the Raspberry Pi 1 the peripherals, like AUX / UART and such +are in ARM physical space at 0x20xxxxxx. To allow for more RAM on the Raspberry +Pi 2 they needed to that peripheral base address and moved it to 0x3Fxxxxxx. +We can either create 16 1 MiB section entries to cover the whole range of +peripherals or we only define the sections we care to talk to. The UART and the +GPIO are associated with the 0x202xxxxx space. There are a couple of timers +in the 0x200xxxxx space so one entry can cover those. + +``` c + mmu_section(0x20000000,0x20000000,0x0000); //NOT CACHED! + mmu_section(0x20200000,0x20200000,0x0000); //NOT CACHED! + mmu_section(0x3F000000,0x3F000000,0x0000); //NOT CACHED! + mmu_section(0x3F200000,0x3F200000,0x0000); //NOT CACHED! +``` + +These sections are not cached and not buffered, but but we may play with that +to demonstrate what caching a peripheral can do to you, why we need to turn on +the MMU if for no other reason than to get some bare metal performance by +using the cache. + +Now you have to think on a system level here, there are a number +of things in play. We need to plan our memory space, where are we +putting the MMU table, where are our peripherals, where is our program. + +If the only reason for using the MMU is to allow the use of the cache +then just map the whole world 1:1; if you want with the peripherals not cached +and the rest cached. + +### Cache invalidation + +So once our tables are setup then we need to actually turn the +MMU on. When initialising a cache to you want to clean out all the entries in a +safe way. You want to invalidate everyhting, mark every cache line as empty / +available. Likewise you want the TLB caching the MU does to be invalidated, +so the MMU starts up with no valid lines in the cache, that don't match our +entries. Also we want the CPU to do a Data Synchronization Barrier (DSB), so +every explicit memory transaction is finished before the next instruction begins. + +All of the above can be done using the C15 [co-processor]. So, to summarise: +1. Invalidate all caches (Instruction and data, write 0 to `0, c7, c7, 0`) +2. Invalidate the TLB entries (write 0 to `0, c8, c7, 0`) +3. Data synchronisation barrier (write 0 to `0, c7, c10, 4`) +4. Set the domain access controls (write 0xffffffff to `0, c3, c0, 0`, 0b11 for every domain) +5. Set the base address for the translation table (`0,c2,c0,0`) +6. Enable level 1 caches and the MMU in the control register (`0,c1,c0,0`) and some other useful things: + - bit 0 (M) enables MMU + - bit 2 (C) enables level 1 data cache + - bit 11 (Z) enabled branch prediction + - bit 12 (I) enables instruction cache + - bit 22 (U) enabled non-aligned data access as well as mixed big-/little-endian data access + +So simple example code implementing the the MMU-enabling process might be this: + +```armasm +.global mmu_init +mmu_init: + mov r1,#0 + // invalidate caches + mcr p15,0,r1,c7,c7,0 + // invalidate TLB entries + mcr p15,0,r1,c8,c7,0 + // data synchronisation barrier + mcr p15,0,r1,c7,c10,4 + + // set all domains to 0b11 + ldr r1, =0xffffffff + mcr p15,0,r1,c3,c0,0 + + // set the translation table base address (remember to align 16 KiB!) + mcr p15,0,r0,c2,c0,0 ;@ tlb base + + // set the bits mentioned above + ldr r1, =0x00401805 + mrc p15,0,r2,c1,c0,0 + orr r2,r2,r1 + mcr p15,0,r2,c1,c0,0 + + mov pc, lr +``` + +// TODO + +I am going to mess with the translation tables after the MMU is started +so the easiest way to deal with the TLB cache is to invalidate it, but +dont need to mess with main L1 cache. ARMv6 introduces a feature to +help with this, but going with this solution. + +.globl invalidate_tlbs +invalidate_tlbs: + mov r2,#0 + mcr p15,0,r2,c8,c7,0 ;@ invalidate tlb + mcr p15,0,r2,c7,c10,4 ;@ DSB ?? + bx lr + +Something to note here. Debugging using the JTAG based on chip debugger +makes life easier, that removing sd cards or the old days pulling an +eeprom out and putting it it in an eraser then a programmer. BUT, +it is not completely without issue. When and where and if you hit this +depends heavily on the core you are using and the jtag tools and the +commands you remember/prefer. The basic problem is caches can and +often do separate instruction I fetches from data D reads and writes. +So if you have test run A of a program that has executed the instruction +at address 0xD000. So that instruction is in the I cache. You have +also executed the instruction at 0xC000 but it has been evicted, but +you dont actually know what is in the I cache or not, shouldnt even +try to assume. You stop the processor, you write a new program to +memory, now these are data D writes, and go through the D cache. Then +you set the start address and run again. Now there are a number of +combinations here and only one if them works, the rest can lead to +failure. + +For each instruction/address in the program, if the prior instruction +at that address was in the i cache, and since data writes do not go +through the i cache then the new instruction for that address is either +in the d cache or in main ram. When you run the new program you will +get the stale/old instruction from a prior run when you fetch that +address (unless an invalidate happens, if a flush happens then you +write back, but why would an I cache flush?), and if the new instruction +at that address is not the same as the old one unpredictable results +will occur. You can start to see the combinations, did the data +write go through to d cache or to ram, will it flush to ram and is the +i cache invalid for that address, etc. + +There is also the quesiton of are the I and D caches shared, they can +be but that is both specific to the core and your setup. Also does +the jtag debugger have the ability to disable the caches, has it done +it for you, can you do it manually. + +Any time you are using the i or d caches you need to be careful using +a jtag debugger or even a bootloader type approach depending on its +design as you might end up doing data writes of instructions and going +around the i cache or worse. So for this kind of work using a chip +reset and non volitle rom/flash based bootloader can/will save you +a lot of headaches. If you know your debugger is solving this for you, +great, but always make sure as you change from the raspi 2 back to +a raspi 1 for example it might not be doing it and it will drive you +nuts when you keep downloading a new program and it either crashes +in a strange way or simply just keeps running the old program and +not appearing to take your new changes. + +So the example is going to start with the mmu off and write to +addresses in four different 1MB address spaces. So that later we +can play with the section descriptors and demonstrate virtual to +physical address conversion. + +So write some stuff and print it out on the uart. + + PUT32(0x00045678,0x00045678); + PUT32(0x00145678,0x00145678); + PUT32(0x00245678,0x00245678); + PUT32(0x00345678,0x00345678); + + hexstring(GET32(0x00045678)); + hexstring(GET32(0x00145678)); + hexstring(GET32(0x00245678)); + hexstring(GET32(0x00345678)); + uart_send(0x0D); uart_send(0x0A); + +then setup the mmu with at least those four sections and the peripherals + + mmu_section(0x00000000,0x00000000,0x0000|8|4); + mmu_section(0x00100000,0x00100000,0x0000); + mmu_section(0x00200000,0x00200000,0x0000); + mmu_section(0x00300000,0x00300000,0x0000); + //peripherals + mmu_section(0x20000000,0x20000000,0x0000); //NOT CACHED! + mmu_section(0x20200000,0x20200000,0x0000); //NOT CACHED! + +and start the mmu with the I and D caches enabled + + start_mmu(MMUTABLEBASE,0x00000001|0x1000|0x0004); + +then if we read those four addresses again we get the same output +as before since we maped virtual = physical. + + hexstring(GET32(0x00045678)); + hexstring(GET32(0x00145678)); + hexstring(GET32(0x00245678)); + hexstring(GET32(0x00345678)); + uart_send(0x0D); uart_send(0x0A); + +but what if we swizzle things around. make virtual 0x001xxxxx = +physical 0x003xxxxx. 0x002 looks at 0x000 and 0x003 looks at 0x001 +(dont mess with the 0x00000000 section, that is where our program is +running) + + mmu_section(0x00100000,0x00300000,0x0000); + mmu_section(0x00200000,0x00000000,0x0000); + mmu_section(0x00300000,0x00100000,0x0000); + +and maybe we dont need to do this but do it anyway just in case + + invalidate_tlbs(); + +read them again. + + hexstring(GET32(0x00045678)); + hexstring(GET32(0x00145678)); + hexstring(GET32(0x00245678)); + hexstring(GET32(0x00345678)); + uart_send(0x0D); uart_send(0x0A); + +the 0x000xxxxx entry was not modifed so we get 000045678 as the output +but the 0x001xxxxx read is now coming from physical 0x003xxxxx so we +get the 00345678 output, 0x002xxxxx comes from the 0x000xxxxx space +so that read gives 00045678 and the 0x003xxxxx is mapped to 0x001xxxxx +physical giving 00145678 as the output. + +So up to this point the output looks like this. + +DEADBEEF +00045678 +00145678 +00245678 +00345678 + +00045678 +00145678 +00245678 +00345678 + +00045678 +00345678 +00045678 +00145678 + +first blob is without the mmu enabled, second with the mmu but +virtual = physical, third we use the mmu to show virtual != physical +for some ranges. + +Now for some small pages, I made this function to help out. + +unsigned int mmu_small ( unsigned int vadd, unsigned int padd, unsigned int flags, unsigned int mmubase ) +{ + unsigned int ra; + unsigned int rb; + unsigned int rc; + + ra=vadd>>20; + rb=MMUTABLEBASE|(ra<<2); + rc=(mmubase&0xFFFFFC00)/*|(domain<<5)*/|1; + //hexstrings(rb); hexstring(rc); + PUT32(rb,rc); //first level descriptor + ra=(vadd>>12)&0xFF; + rb=(mmubase&0xFFFFFC00)|(ra<<2); + rc=(padd&0xFFFFF000)|(0xFF0)|flags|2; + //hexstrings(rb); hexstring(rc); + PUT32(rb,rc); //second level descriptor + return(0); +} + +So before turning on the mmu some physical addresses were written +with some data. The function takes the virtual, physical, flags and +where you want the secondary table to be. Remember secondary tables +can be up to 1K in size and are aligned on a 1K boundary. + + + mmu_small(0x0AA45000,0x00145000,0,0x00000400); + mmu_small(0x0BB45000,0x00245000,0,0x00000800); + mmu_small(0x0CC45000,0x00345000,0,0x00000C00); + mmu_small(0x0DD45000,0x00345000,0,0x00001000); + mmu_small(0x0DD46000,0x00146000,0,0x00001000); + //put these back + mmu_section(0x00100000,0x00100000,0x0000); + mmu_section(0x00200000,0x00200000,0x0000); + mmu_section(0x00300000,0x00300000,0x0000); + invalidate_tlbs(); + +Now why did I use different secondary table addresses most of the +time but not all of the time? A secondary table lookup is the same +first level descriptor for the top 12 bits of the address, if the +top 12 bits of the address are different it is a different secondary +table. So to demonstrate that we actually have separation within a +section I have two small pages within a 1MB section that I point +at two different physical address spaces. So in short if the top +12 bits of the virtual address are the same then they share the same +coarse page table, the way the function works it writes both first +and second level descriptors so if you were to do this + + mmu_small(0x0DD45000,0x00345000,0,0x00001000); + mmu_small(0x0DD46000,0x00146000,0,0x00001400); + +Then both of those virtual addresses would go to the 0x1400 table, and +the first virtual address would not have a secondary entry its +secondary entry would be in a table at 0x1000 but the first level +no longer points to 0x1000 so the mmu would get whatever it finds +in the 0x1400 table. + + +The last example is just demonstrating an access violation. Changing +the domain to that one domain we did not set full access to + + //access violation. + + mmu_section(0x00100000,0x00100000,0x0020); + invalidate_tlbs(); + + hexstring(GET32(0x00045678)); + hexstring(GET32(0x00145678)); + hexstring(GET32(0x00245678)); + hexstring(GET32(0x00345678)); + uart_send(0x0D); uart_send(0x0A); + +The first 0x45678 read comes from that first level descriptor, with +that domain + +00045678 +00000010 + +How do I know what that means with that output. Well from my blinker07 +example we touched on exceptions (interrupts). I made a generic test +fixture such that anything other than a reset prints something out +and then hangs. In no way shape or form is this a complete handler +but what it does show is that it is the exception that is at address +0x00000010 that gets hit which is data abort. So figuring out it was +a data abort (pretty much expected) have that then read the data fault +status registers, being a data access we expect the data/combined one +to show somthing and the instruction one to not. Adding that +instrumentation resulted in. + +00045678 +00000010 +00000019 +00000000 +00008110 +E5900000 +00145678 + +Now I switched to the ARM1176JZF-S Technical Reference Manual for more +detail and that shows the 0x01 was domain 1, the domain we used for +that access. then the 0x9 means Domain Section Fault. + +The lr during the abort shows us the instruction, which you would need +to disassemble to figure out the address, or at least that is one +way to do it perhaps there is a status register for that. + +The instruction and the address match our expectations for this fault. + +This is simply a basic intro. Just enough to be dangerous. The MMU +is one of the simplest peripherals to program so long as bit +manipulation is not something that causes you to lose sleep. What makes +it hard is that if you mess up even one bit, or forget even one thing +you can crash in spectacular ways (often silently without any way of +knowing what happened). Debugging can be hard at best. + +The ARM ARM indicates that the ARMv6 adds the feature of separating +the I and D from an mmu perspective which is an interesting thought +(see the jtag debugging comments, and think about how this can affect +you re-loading a program into ram and running) you have enough ammo +to try that. The ARMv7 doesnt seem to have a legacy mode yet, still +reading, the descriptors and how they are addresses looks basically +the same but this code doesnt yet work on the raspi 2, so I will +continue to work on that and update this repo when I figure it out. + +## Coarse paging (TODO) + +The coarse_translation.ps file I have included in this repo starts +off the same way as a section, has to the logic doesnt know what +you want until it sees the first level descriptor. If it sees a +0b01 as the lower 2 bits of the first level descriptor then this is +a coarse page table entry and it needs to do a second level fetch. +The second level fetch does not use the mmu tlb table base address +bits 31:10 of the second level address plus bits 19:12 of the +virtual address (times 4) are where the second level descriptor lives. +Note that is 8 more bits so the section is divided into 256 parts, this +page table address is similar to the mmu table address, but it needs +to be aligned on a 1K boundry (lower 10 bits zeros) and can be worst +case 1KBytes in size. + +The second level descriptor format defined in the ARM ARM (small pages +are most interesting here, subpages enabled) is a little different +than a first level section, we had a domain in the first level +descriptor to get here, but now have direct access to four sets of +AP bits you/I would have to read more to know what the difference +is between the domain defined AP and these additional four, for now +I dont care this is bare metal, set them to full access (0b11) and +move on (see below about domain and ap bits). + +So lets take the virtual address 0x12345678 and the MMUTABLEBASE of +0x4000 again. The first level descriptor address is the top three +bits of the virtual address 0x123, times 4, added to the MMUTABLEBASE +0x448C. But this time when we look it up we find a value in the +table that has the lower two bits being 0b01. Just to be crazy lets +say that descriptor was 0xABCDE001 (ignoring the domain and other +bits just talking address right now). That means we take 0xABCDE000 +the picture shows bits 19:12 (0x45) of the virtual address (0x12345678) +so the address to the second level descriptor in this crazy case is +0xABCDE000+(0x45<<2) = 0xABCDE114 why is that crazy? because I +chose an address where we in theory dont have ram on the raspberry pi +maybe a mirrored address space, but a sane address would have been +somewhere close to the MMUTABLEBASE so we can keep the whole of the +mmu tables in a confined area. Used this address simply for +demonstration purposes not based on a workable solution. + +### Raspberry Pi 2 + +If you are on the raspi 2 with multiple arm cores and are using +the multiple arm cores you need to do more reading if you want one +core to talk to another by sharing some of the memory between +them. Same problem as peripherals basically with multiple masters +of the ram/peripheral on the far side of my cache, how do I insure +what is in my cache maches the far side? Easiest way is to not +cache that space. You need to read up on if the cores share a cache +or have their own (or if l2 if present is shared but l1 is not), +ldrex/strex were implemented specifically for multi core, but you +need to understand the cache effects on these instructions ( +not documented well, I have an example on just this one topic). + + +[ARM ARM]: https://www.scss.tcd.ie/~waldroj/3d1/arm_arm.pdf +[co-processor]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0301h/index.html From f01c6fbb0182243ba69446158e6c473139ee341e Mon Sep 17 00:00:00 2001 From: Stefan Naumann Date: Sun, 30 Jul 2017 14:48:59 +0200 Subject: [PATCH 3/6] rewrote the Readme --- mmu/README.md | 655 ++++++++++++++++++++----------------- mmu/coarse_translation.ps | Bin 113969 -> 0 bytes mmu/notmain.c | 92 ++++-- mmu/novectors.s | 55 ++-- mmu/periph.c | 9 +- mmu/section_translation.ps | Bin 116370 -> 0 bytes 6 files changed, 447 insertions(+), 364 deletions(-) delete mode 100644 mmu/coarse_translation.ps delete mode 100644 mmu/section_translation.ps diff --git a/mmu/README.md b/mmu/README.md index b19918c..6eec5ad 100644 --- a/mmu/README.md +++ b/mmu/README.md @@ -270,12 +270,13 @@ will be triggered, but for now let's focus on the simpler part. ##### An example ``` - MMUTABLEBASE = 0x00004000 - virtual address = 0x12345678 + MMUTABLEBASE = 0x00004000 + virtual address = 0x12345678 -> first 12 bit (moved to right): 0x00000123 - descriptor for the section: 0x000448c - let's assume the descriptor was 0xABC00002 - -> physical address 0xABC45678 + -> multiplied by 4: 0x0000048c + descriptor for the section: 0x0000448c + let's assume the descriptor was 0xABC00002 + -> physical address 0xABC45678 ``` #### 16 MiB Supersections @@ -376,12 +377,12 @@ all of our sections can have the domain number 0. uint32_t* entry = MMUTABLEBASE | (offset<<2); // mask lower 20 bits of physical address then ORR flags and 0x02 for 1 MiB - physval = (physval & 0xfff00000) | (flags & 0x7ffa) | 0x02; + uint32_t physval = (physical & 0xfff00000) | (flags & 0x7ffa) | 0x02; *entry = physval; return(0); } - + #define CACHEABLE 0x08 #define BUFFERABLE 0x04 ``` @@ -456,367 +457,419 @@ All of the above can be done using the C15 [co-processor]. So, to summarise: 6. Enable level 1 caches and the MMU in the control register (`0,c1,c0,0`) and some other useful things: - bit 0 (M) enables MMU - bit 2 (C) enables level 1 data cache - - bit 11 (Z) enabled branch prediction + - bit 11 (Z) enables branch prediction - bit 12 (I) enables instruction cache - - bit 22 (U) enabled non-aligned data access as well as mixed big-/little-endian data access + - bit 22 (U) enables non-aligned data access as well as mixed big-/little-endian data access -So simple example code implementing the the MMU-enabling process might be this: +What bits of these you want to set is up to you. I would recommend M, C and I, +but I am going ahead and set them all. So simple example code implementing the +the MMU-enabling process might be this: ```armasm -.global mmu_init -mmu_init: - mov r1,#0 - // invalidate caches - mcr p15,0,r1,c7,c7,0 - // invalidate TLB entries - mcr p15,0,r1,c8,c7,0 - // data synchronisation barrier - mcr p15,0,r1,c7,c10,4 - - // set all domains to 0b11 - ldr r1, =0xffffffff - mcr p15,0,r1,c3,c0,0 - - // set the translation table base address (remember to align 16 KiB!) - mcr p15,0,r0,c2,c0,0 ;@ tlb base - - // set the bits mentioned above - ldr r1, =0x00401805 - mrc p15,0,r2,c1,c0,0 - orr r2,r2,r1 - mcr p15,0,r2,c1,c0,0 - - mov pc, lr + .global mmu_init + mmu_init: + mov r1,#0 + // invalidate caches + mcr p15,0,r1,c7,c7,0 + // invalidate TLB entries + mcr p15,0,r1,c8,c7,0 + // data synchronisation barrier + mcr p15,0,r1,c7,c10,4 + + // set all domains to 0b11 + ldr r1, =0xffffffff + mcr p15,0,r1,c3,c0,0 + + // set the translation table base address (remember to align 16 KiB!) + mcr p15,0,r0,c2,c0,0 + + // set the bits mentioned above + ldr r1, =0x00401805 + mrc p15,0,r2,c1,c0,0 + orr r2,r2,r1 + mcr p15,0,r2,c1,c0,0 + + mov pc, lr ``` -// TODO - -I am going to mess with the translation tables after the MMU is started -so the easiest way to deal with the TLB cache is to invalidate it, but -dont need to mess with main L1 cache. ARMv6 introduces a feature to -help with this, but going with this solution. - -.globl invalidate_tlbs -invalidate_tlbs: - mov r2,#0 - mcr p15,0,r2,c8,c7,0 ;@ invalidate tlb - mcr p15,0,r2,c7,c10,4 ;@ DSB ?? - bx lr - -Something to note here. Debugging using the JTAG based on chip debugger -makes life easier, that removing sd cards or the old days pulling an -eeprom out and putting it it in an eraser then a programmer. BUT, -it is not completely without issue. When and where and if you hit this -depends heavily on the core you are using and the jtag tools and the -commands you remember/prefer. The basic problem is caches can and -often do separate instruction I fetches from data D reads and writes. -So if you have test run A of a program that has executed the instruction -at address 0xD000. So that instruction is in the I cache. You have -also executed the instruction at 0xC000 but it has been evicted, but -you dont actually know what is in the I cache or not, shouldnt even -try to assume. You stop the processor, you write a new program to -memory, now these are data D writes, and go through the D cache. Then -you set the start address and run again. Now there are a number of -combinations here and only one if them works, the rest can lead to -failure. - -For each instruction/address in the program, if the prior instruction -at that address was in the i cache, and since data writes do not go -through the i cache then the new instruction for that address is either -in the d cache or in main ram. When you run the new program you will -get the stale/old instruction from a prior run when you fetch that -address (unless an invalidate happens, if a flush happens then you -write back, but why would an I cache flush?), and if the new instruction -at that address is not the same as the old one unpredictable results -will occur. You can start to see the combinations, did the data -write go through to d cache or to ram, will it flush to ram and is the -i cache invalid for that address, etc. - -There is also the quesiton of are the I and D caches shared, they can -be but that is both specific to the core and your setup. Also does -the jtag debugger have the ability to disable the caches, has it done -it for you, can you do it manually. - -Any time you are using the i or d caches you need to be careful using -a jtag debugger or even a bootloader type approach depending on its +For messing with the translation tables after the MMU is started, you will need +to invalidate the TLB cache again, so let's put this part into its own function. +We don't need to care about the L1 cache, this time. Also ARMv6 introduces a +feature to help with invlidating the TLB, but I'm going with this solution: + +```armasm + .globl tlb_invalidate + tlb_invalidate: + mov r2,#0 + // invalidate TLB entries + mcr p15,0,r1,c8,c7,0 + // data synchronisation barrier + mcr p15,0,r1,c7,c10,4 + mov pc,lr +``` + +#### (JTAG) Debugging and caching + +Something to note here. Debugging using the JTAG based on-chip-debugger +makes life easier. No SD-card swapping and no more EEPROM-flashing. BUT, +it is not completely without issue. The basic problem is that caches often +seperate instruction fetches from data reads and writes. Let's say you execute +instructions at 0xD0000 (which is cached) and an instruction 0xC000. So you +transfer your programm, set the start address and run again. + +For each instruction in the program the prior instruction in that address might +still be in the instruction cache and the new one in main RAM (or data cache). +So, when running the new program you might still be running the old +instructions, which are fetched back from the instruction cache, not the RAM, +unless an invalidate or flush happens). + +There is also the question of are the instruction and data caches shared? +They can be specific to the core and your setup. Is your JTAG-debugger able to +disable the caches, has it done that for you, or can you do it manually. + +Any time you are using the instruction or data caches you need to be careful +using a JTAG-debugger or even a bootloader type approach depending on its design as you might end up doing data writes of instructions and going -around the i cache or worse. So for this kind of work using a chip -reset and non volitle rom/flash based bootloader can/will save you -a lot of headaches. If you know your debugger is solving this for you, -great, but always make sure as you change from the raspi 2 back to -a raspi 1 for example it might not be doing it and it will drive you -nuts when you keep downloading a new program and it either crashes -in a strange way or simply just keeps running the old program and -not appearing to take your new changes. - -So the example is going to start with the mmu off and write to -addresses in four different 1MB address spaces. So that later we -can play with the section descriptors and demonstrate virtual to -physical address conversion. - -So write some stuff and print it out on the uart. +around the instruction cache or worse. This may be done by your JTAG debugger, +but keep in mind to change back to / from Raspberry Pi 2 when switching between +the Pis. Otherwise this might driver you mad, when you keep downloading new +code but the Pi crashes or behaves unexpectedly. + +## Having fun with address translation + +So the example is going to start with the MMU off and write to +addresses in four different 1MB address spaces, so we can play with the section +descriptors and demonstrate virtual to physical address conversion later. +```c + // write data to four different 1 MiB sections PUT32(0x00045678,0x00045678); PUT32(0x00145678,0x00145678); PUT32(0x00245678,0x00245678); PUT32(0x00345678,0x00345678); + // write the data back to UART hexstring(GET32(0x00045678)); hexstring(GET32(0x00145678)); hexstring(GET32(0x00245678)); hexstring(GET32(0x00345678)); - uart_send(0x0D); uart_send(0x0A); - -then setup the mmu with at least those four sections and the peripherals + // 0D CR '\r' (carriage ret) + uart_send(0x0D); + // 0A LF '\n' (new line) + uart_send(0x0A); - mmu_section(0x00000000,0x00000000,0x0000|8|4); + // Then setup the MMU with at least those four sections + mmu_section(0x00000000,0x00000000,CACHEABLE | BUFFERABLE); mmu_section(0x00100000,0x00100000,0x0000); mmu_section(0x00200000,0x00200000,0x0000); mmu_section(0x00300000,0x00300000,0x0000); - //peripherals + + // and the peripherals: mmu_section(0x20000000,0x20000000,0x0000); //NOT CACHED! mmu_section(0x20200000,0x20200000,0x0000); //NOT CACHED! -and start the mmu with the I and D caches enabled - - start_mmu(MMUTABLEBASE,0x00000001|0x1000|0x0004); - -then if we read those four addresses again we get the same output -as before since we maped virtual = physical. + // Start the MMU with the instruction and data caches enabled: + mmu_init ( MMUTABLEBASE ); + // when we read those four addresses back we get the same output + // as we wrote before because we mapped virtual = physical hexstring(GET32(0x00045678)); hexstring(GET32(0x00145678)); hexstring(GET32(0x00245678)); hexstring(GET32(0x00345678)); uart_send(0x0D); uart_send(0x0A); +``` -but what if we swizzle things around. make virtual 0x001xxxxx = -physical 0x003xxxxx. 0x002 looks at 0x000 and 0x003 looks at 0x001 -(dont mess with the 0x00000000 section, that is where our program is -running) +But what if we swizzle things around? Don't mess with the 0x00000000-section, +because that is where our code is. +```c + // change the table entries mmu_section(0x00100000,0x00300000,0x0000); mmu_section(0x00200000,0x00000000,0x0000); mmu_section(0x00300000,0x00100000,0x0000); -and maybe we dont need to do this but do it anyway just in case - + // invalidate the TLB invalidate_tlbs(); -read them again. - + // and read the addresses again, which we wrote to above hexstring(GET32(0x00045678)); hexstring(GET32(0x00145678)); hexstring(GET32(0x00245678)); hexstring(GET32(0x00345678)); uart_send(0x0D); uart_send(0x0A); +``` + +The 0x000xxxxx entry was not modified, so we get 0x000045678 as the output. The +section 0x001xxxxx will read from physical addresses 0x003xxxxx so we get the +0x00345678 output, 0x002xxxxx will translate to the 0x000xxxxx space +so that read gives 0x00045678 and the 0x003xxxxx is mapped to physical +0x001xxxxx giving 0x00145678 as the output. + +So up to this point the output looks like this: + +``` + 00045678 + 00145678 + 00245678 + 00345678 + + 00045678 + 00145678 + 00245678 + 00345678 + + 00045678 + 00345678 + 00045678 + 00145678 +``` + +The first block is with the MMU disabled, the second one with MMU enabled but +1:1 virtual to physical translation, the third one with the non 1:1 translation. + +## Coarse paging + +With coarse paging the logic does not know what kind of translation will be done +until the first level read, so the first step is identical to the translation +above. If it sees a `0b01` as the lower 2 bits of the first level descriptor, +then it knows, it's a coarse page entry and it needs as second level fetch. +Table B4-5 Accessing coarse page table second-level descriptors (pg. B4-30) +shows the logic fetching the second level descriptor. + +### Second level descriptor format + +There are two things to the two level translation. At first we need to set the +first level descriptors accordingly. The format is as follows Table B4-1 +(pg. B4-27, First-level descriptor format (VMSAv6, subpages enabled)). + +| | Bits 31:10 | 9 | 8:5 | 4,3,2 | 1,0 | +|---|------------|---|-----|-------|-----| +| Coarse Page Table | Coarse Page Table base Address | IMP | Domain | IMP | `01` | + +The bits 4:2 are implementation defined and should be zero (SBZ) for VMSAv6. +The domain-bits are used as above. The bits 31:10 are used as the base address +of the second level page table. This second level page table needs to be +aligned to 1 KiB in memory. + +So after fetching the first level descriptor the bits 31:10 of the entry will +be used as bits 31:10 of the second level descriptor, i.e. it will be used as +base address for the second level table. The virtual address bits 19:12 will be +used to navigate inside that second level table, i.e. shift completely to the +right, multiplied by 4 then used added onto the base address. The lowest 2 bits +of the address of the second level entry is always zero. Note that there are +256 possibilities to fill the bits 19:12 of the virtual address, i.e. the +section is divided into 256 parts, i.e. 4 KiB pages. + +The second level descriptor looks like this (for small pages, for more see +Table 4-3 Second level descriptor format (subpages enabled), pg. 4-31): + +| | Bits 31:12 | 11,10 | 9,8 | 7,6 | 5,4 | 3 | 2 | 1,0 | +|---|------------|-------|-----|-----|-----|---|---|-----| +| Small page | Small page base address | AP3 | AP2 | AP1 | AP0 | C | B | `10` | + +Note, that there are four **AP**-fields here. The small page is divided further +into four blocks of the same size (i.e. in the case of small pages 1 KiB), which +have their own AP-Access control. AP0 applies to the block with the lowest base +address. You can set them all to `0b11` - full access and not care, or have +fine grained access control over the blocks of that page. + +### An example + +This example is a bit crazy, as the address of the second level descriptor is +an address, where we don't even have RAM anymore on the Raspberry Pi. Normally +you want to keep your second level tables somewhere near the first level table, +so you have the memory managment information in a confined space. + +``` + MMUTABLEBASE = 0x00004000 + virtual address = 0x12345678 + -> bits 19:12 of the virtual address: 0x00000045 + address of the first level descriptor: 0x0000448c + let's assume a descriptor value of: 0xABCDE001 + base address of second level table: 0xABCDE000 + offset to the second level table: 0x00000114 + address of the second level descriptor: 0xABCDE114 +``` + +### A simple implementation -the 0x000xxxxx entry was not modifed so we get 000045678 as the output -but the 0x001xxxxx read is now coming from physical 0x003xxxxx so we -get the 00345678 output, 0x002xxxxx comes from the 0x000xxxxx space -so that read gives 00045678 and the 0x003xxxxx is mapped to 0x001xxxxx -physical giving 00145678 as the output. - -So up to this point the output looks like this. - -DEADBEEF -00045678 -00145678 -00245678 -00345678 - -00045678 -00145678 -00245678 -00345678 - -00045678 -00345678 -00045678 -00145678 - -first blob is without the mmu enabled, second with the mmu but -virtual = physical, third we use the mmu to show virtual != physical -for some ranges. - -Now for some small pages, I made this function to help out. - -unsigned int mmu_small ( unsigned int vadd, unsigned int padd, unsigned int flags, unsigned int mmubase ) -{ - unsigned int ra; - unsigned int rb; - unsigned int rc; - - ra=vadd>>20; - rb=MMUTABLEBASE|(ra<<2); - rc=(mmubase&0xFFFFFC00)/*|(domain<<5)*/|1; - //hexstrings(rb); hexstring(rc); - PUT32(rb,rc); //first level descriptor - ra=(vadd>>12)&0xFF; - rb=(mmubase&0xFFFFFC00)|(ra<<2); - rc=(padd&0xFFFFF000)|(0xFF0)|flags|2; - //hexstrings(rb); hexstring(rc); - PUT32(rb,rc); //second level descriptor - return(0); -} - -So before turning on the mmu some physical addresses were written -with some data. The function takes the virtual, physical, flags and -where you want the secondary table to be. Remember secondary tables -can be up to 1K in size and are aligned on a 1K boundary. +```c + /** + * \brief creates an translation table entry (for sections of size 1 MiB) + * \param[in] virtual the virtual address (only top 12 bits used) + * \param[in] physical the physical address (only top 12 bits used) + * \param[in] flags the flags for the section + **/ + uint32_t mmu_page ( uint32_t virtual, uint32_t physical, uint32_t flags, uint32_t secondbase ) + { + uint32_t offset = virtual >> 20; + // plus and or are the same thing here, as MMUTABLEBASE is 14 bit aligned + uint32_t* entry = MMUTABLEBASE | (offset<<2); + // mask lower 20 bits of physical address then ORR flags and 0x01 for coarse translation + uint32_t entryval = (secondbase & 0xfffffc00) | (flags & 0xf0) | 0x01; + // set first level descriptor + *entry = entryval; + + // mask everything except bits 19:12 + offset = (virtual >> 12) & 0xff; + // form the second level + uint32_t* secondLevelEntry = (secondbase & 0xfffffc00) | (offset << 2); + + // form the value of the second level descriptor + // bytes 31:12 are the page base address, flags contain B,C, AP_x = 0b11 + // for all and the 0x02 at the end to identify the entry as small page + uint32_t physval = (physical & 0xfffff000) | 0xff0 | (flags & 0xc) | 0x02; + + // set the second level descriptor + *secondLevelEntry = physval; + return(0); + } +``` + +So let's assign some sections to coarse translation: +```c mmu_small(0x0AA45000,0x00145000,0,0x00000400); mmu_small(0x0BB45000,0x00245000,0,0x00000800); mmu_small(0x0CC45000,0x00345000,0,0x00000C00); mmu_small(0x0DD45000,0x00345000,0,0x00001000); mmu_small(0x0DD46000,0x00146000,0,0x00001000); - //put these back - mmu_section(0x00100000,0x00100000,0x0000); - mmu_section(0x00200000,0x00200000,0x0000); - mmu_section(0x00300000,0x00300000,0x0000); - invalidate_tlbs(); + + invalidate_tlb(); +``` -Now why did I use different secondary table addresses most of the -time but not all of the time? A secondary table lookup is the same -first level descriptor for the top 12 bits of the address, if the -top 12 bits of the address are different it is a different secondary -table. So to demonstrate that we actually have separation within a -section I have two small pages within a 1MB section that I point -at two different physical address spaces. So in short if the top -12 bits of the virtual address are the same then they share the same -coarse page table, the way the function works it writes both first -and second level descriptors so if you were to do this +Let's look in the last two `mmu_small`-statements here. you will notice, that +the `secondbase`-parameter is the same here. This is in fact wanted, as I want +to add an entry into the secondary table I assigned before, not set a new one, +i.e. orphaning the old one. So let's assume I would set a new secondary table +base address like this: +```c mmu_small(0x0DD45000,0x00345000,0,0x00001000); mmu_small(0x0DD46000,0x00146000,0,0x00001400); +``` -Then both of those virtual addresses would go to the 0x1400 table, and -the first virtual address would not have a secondary entry its -secondary entry would be in a table at 0x1000 but the first level -no longer points to 0x1000 so the mmu would get whatever it finds -in the 0x1400 table. - +When I try to access an address in the page 0x0DD45xxx, then the MMU would look +inside a secondary table located at 0x00001400, which of course does not contain +our previously set entry for the small page. But it will definitely find +something there, and probably behave unexpected, if we are not aware of our +mistake here. So always make sure the secondary table base addresses of the +pages in the same section are the same. -The last example is just demonstrating an access violation. Changing -the domain to that one domain we did not set full access to +## Access violation - //access violation. +First we want to set a domain to 0x00, so accessing a section with that domain +will definitely trigger an access violation. I will assume we wrote that to +domain number 1. +```c + // set the domain of a section to 0x01 mmu_section(0x00100000,0x00100000,0x0020); - invalidate_tlbs(); + invalidate_tlb(); + // then read the data from the sections hexstring(GET32(0x00045678)); hexstring(GET32(0x00145678)); hexstring(GET32(0x00245678)); hexstring(GET32(0x00345678)); uart_send(0x0D); uart_send(0x0A); +``` + +I expect that second read-statement to trigger a Data Abort-Exception, so I +want to write an exception handler, to read the status information of that +exception. We need to following registers of the C15 co-processor: +- `0,c5,c0,0` - Data Fault Status Register +- `0,c5,c0,1` - Instruction Fault Status Register + +### Data Fault Status Register + +This register holds the source of the last data fault. The bits have the +following functions: + +| Bit 31:13 | 12 | 11 | 10 | 9 | 8 | 7:4 | 3:0 | +|-----|----------|----|----|---|---|-----|-----| +| SBZ | SD | RW | S | 0 | 0 | Domain | Status | + +**SD** indicates an AXI Decode or Slave error caused the abort (only valid for +external aborts, for all other should be zero). **RW** indicates whether a read +(0) or a write (1) access caused the abort. The **S**-flag is part of the status +field. The **Domain** bits indicate the domain which was accessed when the abort +occurred. The **Status** bits show the type of fault generated. See the +[Data Fault Status Register]-manual for a list. + +### Instruction Fault Status Register + +This register holds the source of the last instruction fault. The bits have the following functions: + +| Bit 31:13 | 12 | 11 | 10 | 9 :4 | 3:0 | +|-----|----------|----|----|------|-----| +| SBZ | SD | SBZ | 0 | SBZ | Status | + +See the [Instruction Fault Status Register]-manual for the list of status combinations. + +### Reading the status registers + +```armasm + data_abort: + // save the link-register + mov r6,lr + // get the last executed instruction + ldr r8,[r6,#-8] + + // reading the status register + mrc p15,0,r4,c5,c0,0 ;@ data/combined + mrc p15,0,r5,c5,c0,1 ;@ instruction + mov sp,#0x00004000 + + // print data fault status register + mov r0,r4 + bl hexstring + + // print instruction fault status register + mov r0,r5 + bl hexstring + + // print the link register + mov r0,r6 + bl hexstring + + // print the bit-representation of the last executed instruction + mov r0,r8 + bl hexstring + + b hang +``` + +Running the code results in: + +``` + 00045678 + 00000019 + 00000000 + 00008110 + E5900000 + 00145678 +``` + +The first line is the one correct data-read we do in our code above. The +next value is the data fault status register, which indicates that the domain +0x01 was accessed and aborted with an 0x09 fault, i.e. a Domain Section fault. + +# Conclusion -The first 0x45678 read comes from that first level descriptor, with -that domain - -00045678 -00000010 - -How do I know what that means with that output. Well from my blinker07 -example we touched on exceptions (interrupts). I made a generic test -fixture such that anything other than a reset prints something out -and then hangs. In no way shape or form is this a complete handler -but what it does show is that it is the exception that is at address -0x00000010 that gets hit which is data abort. So figuring out it was -a data abort (pretty much expected) have that then read the data fault -status registers, being a data access we expect the data/combined one -to show somthing and the instruction one to not. Adding that -instrumentation resulted in. - -00045678 -00000010 -00000019 -00000000 -00008110 -E5900000 -00145678 - -Now I switched to the ARM1176JZF-S Technical Reference Manual for more -detail and that shows the 0x01 was domain 1, the domain we used for -that access. then the 0x9 means Domain Section Fault. - -The lr during the abort shows us the instruction, which you would need -to disassemble to figure out the address, or at least that is one -way to do it perhaps there is a status register for that. - -The instruction and the address match our expectations for this fault. - -This is simply a basic intro. Just enough to be dangerous. The MMU -is one of the simplest peripherals to program so long as bit -manipulation is not something that causes you to lose sleep. What makes -it hard is that if you mess up even one bit, or forget even one thing -you can crash in spectacular ways (often silently without any way of -knowing what happened). Debugging can be hard at best. - -The ARM ARM indicates that the ARMv6 adds the feature of separating -the I and D from an mmu perspective which is an interesting thought -(see the jtag debugging comments, and think about how this can affect -you re-loading a program into ram and running) you have enough ammo -to try that. The ARMv7 doesnt seem to have a legacy mode yet, still -reading, the descriptors and how they are addresses looks basically -the same but this code doesnt yet work on the raspi 2, so I will -continue to work on that and update this repo when I figure it out. - -## Coarse paging (TODO) - -The coarse_translation.ps file I have included in this repo starts -off the same way as a section, has to the logic doesnt know what -you want until it sees the first level descriptor. If it sees a -0b01 as the lower 2 bits of the first level descriptor then this is -a coarse page table entry and it needs to do a second level fetch. -The second level fetch does not use the mmu tlb table base address -bits 31:10 of the second level address plus bits 19:12 of the -virtual address (times 4) are where the second level descriptor lives. -Note that is 8 more bits so the section is divided into 256 parts, this -page table address is similar to the mmu table address, but it needs -to be aligned on a 1K boundry (lower 10 bits zeros) and can be worst -case 1KBytes in size. - -The second level descriptor format defined in the ARM ARM (small pages -are most interesting here, subpages enabled) is a little different -than a first level section, we had a domain in the first level -descriptor to get here, but now have direct access to four sets of -AP bits you/I would have to read more to know what the difference -is between the domain defined AP and these additional four, for now -I dont care this is bare metal, set them to full access (0b11) and -move on (see below about domain and ap bits). - -So lets take the virtual address 0x12345678 and the MMUTABLEBASE of -0x4000 again. The first level descriptor address is the top three -bits of the virtual address 0x123, times 4, added to the MMUTABLEBASE -0x448C. But this time when we look it up we find a value in the -table that has the lower two bits being 0b01. Just to be crazy lets -say that descriptor was 0xABCDE001 (ignoring the domain and other -bits just talking address right now). That means we take 0xABCDE000 -the picture shows bits 19:12 (0x45) of the virtual address (0x12345678) -so the address to the second level descriptor in this crazy case is -0xABCDE000+(0x45<<2) = 0xABCDE114 why is that crazy? because I -chose an address where we in theory dont have ram on the raspberry pi -maybe a mirrored address space, but a sane address would have been -somewhere close to the MMUTABLEBASE so we can keep the whole of the -mmu tables in a confined area. Used this address simply for -demonstration purposes not based on a workable solution. - -### Raspberry Pi 2 - -If you are on the raspi 2 with multiple arm cores and are using -the multiple arm cores you need to do more reading if you want one -core to talk to another by sharing some of the memory between -them. Same problem as peripherals basically with multiple masters -of the ram/peripheral on the far side of my cache, how do I insure -what is in my cache maches the far side? Easiest way is to not -cache that space. You need to read up on if the cores share a cache -or have their own (or if l2 if present is shared but l1 is not), -ldrex/strex were implemented specifically for multi core, but you -need to understand the cache effects on these instructions ( -not documented well, I have an example on just this one topic). +This is just a simple intro to MMUs, just enough to be dangerous. The MMU is one +of the simplest peripherals to program so long as bit manipulations are not +something that causes you to lose sleep. But if you mess it up even a bit, or +forget something, you can crash in spectacular ways (often silently without any +way of knowing what really happened. Debugging can be hard at best. +The ARM ARM indicates that ARMv6 adds a feature of separating the data from the +instructions from the MMUs perspective, which is an interesting thought (see the +JTAG-debugging comments). [ARM ARM]: https://www.scss.tcd.ie/~waldroj/3d1/arm_arm.pdf -[co-processor]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0301h/index.html +[co-processor]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0301h/ch03s02s01.html +[Data Fault Status Register]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0301h/Bgbiaghh.html +[Instruction Fault Status Register]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0301h/Bgbccfgi.html diff --git a/mmu/coarse_translation.ps b/mmu/coarse_translation.ps deleted file mode 100644 index 234265d4389ce39a51cbc943c5c12210172c2982..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 113969 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 ?OsjhKML06k=0$uJ9Tixq{f<@F_x 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 #define MMUTABLEBASE 0x00004000 -//------------------------------------------------------------------- -unsigned int mmu_section ( unsigned int vadd, unsigned int padd, unsigned int flags ) +#define CACHEABLE 0x08 +#define BUFFERABLE 0x04 + +/** + * \brief creates an translation table entry (for sections of size 1 MiB) + * \param[in] vadd the virtual address (only top 12 bits used) + * \param[in] padd the physical address (only top 12 bits used) + * \param[in] flags the flags for the section + **/ +uint32_t mmu_section ( uint32_t virtual, uint32_t physical, uint32_t flags ) { - unsigned int ra; - unsigned int rb; - unsigned int rc; - - ra=vadd>>20; - rb=MMUTABLEBASE|(ra<<2); - rc=(padd&0xFFF00000)|0xC00|flags|2; - //hexstrings(rb); hexstring(rc); - PUT32(rb,rc); + uint32_t offset = virtual >> 20; + // plus and or are the same thing here, as MMUTABLEBASE is 14 bit aligned + uint32_t* entry = MMUTABLEBASE | (offset<<2); + + // mask lower 20 bits of physical address then ORR flags and 0x02 for 1 MiB + physval = (physval & 0xfff00000) | (flags & 0x7ffa) | 0x02; + + *entry = physval; return(0); } -//------------------------------------------------------------------- -unsigned int mmu_small ( unsigned int vadd, unsigned int padd, unsigned int flags, unsigned int mmubase ) + + +/** + * \brief creates an translation table entry (for sections of size 1 MiB) + * \param[in] virtual the virtual address (only top 12 bits used) + * \param[in] physical the physical address (only top 12 bits used) + * \param[in] flags the flags for the section + **/ +uint32_t mmu_page ( uint32_t virtual, uint32_t physical, uint32_t flags, uint32_t secondbase ) { - unsigned int ra; - unsigned int rb; - unsigned int rc; - - ra=vadd>>20; - rb=MMUTABLEBASE|(ra<<2); - rc=(mmubase&0xFFFFFC00)/*|(domain<<5)*/|1; - //hexstrings(rb); hexstring(rc); - PUT32(rb,rc); //first level descriptor - ra=(vadd>>12)&0xFF; - rb=(mmubase&0xFFFFFC00)|(ra<<2); - rc=(padd&0xFFFFF000)|(0xFF0)|flags|2; - //hexstrings(rb); hexstring(rc); - PUT32(rb,rc); //second level descriptor + uint32_t offset = virtual >> 20; + // plus and or are the same thing here, as MMUTABLEBASE is 14 bit aligned + uint32_t* entry = MMUTABLEBASE | (offset<<2); + // mask lower 20 bits of physical address then ORR flags and 0x01 for coarse translation + uint32_t entryval = (secondbase & 0xfffffc00) | (flags & 0xf0) | 0x01; + + // set first level descriptor + *entry = entryval; + + // mask everything except bits 19:12 + offset = (virtual >> 12) & 0xff; + // form the second level + uint32_t* secondLevelEntry = (secondbase & 0xfffffc00) | (offset << 2); + + // form the value of the second level descriptor + // bytes 31:12 are the page base address, flags contain B,C, AP_x = 0b11 + // for all and the 0x02 at the end to identify the entry as small page + uint32_t physval = (physical & 0xfffff000) | 0xff0 | (flags & 0xc) | 0x02; + + // set the second level descriptor + *secondLevelEntry = physval; return(0); } + + //------------------------------------------------------------------------ int notmain ( void ) { @@ -95,7 +117,7 @@ int notmain ( void ) mmu_section(0x20000000,0x20000000,0x0000); //NOT CACHED! mmu_section(0x20200000,0x20200000,0x0000); //NOT CACHED! - start_mmu(MMUTABLEBASE,0x00000001|0x1000|0x0004); //[23]=0 subpages enabled = legacy ARMv4,v5 and v6 + mmu_init( MMUTABLEBASE ); hexstring(GET32(0x00045678)); hexstring(GET32(0x00145678)); @@ -106,7 +128,7 @@ int notmain ( void ) mmu_section(0x00100000,0x00300000,0x0000); mmu_section(0x00200000,0x00000000,0x0000); mmu_section(0x00300000,0x00100000,0x0000); - invalidate_tlbs(); + invalidate_tlb(); hexstring(GET32(0x00045678)); hexstring(GET32(0x00145678)); @@ -123,7 +145,7 @@ int notmain ( void ) mmu_section(0x00100000,0x00100000,0x0000); mmu_section(0x00200000,0x00200000,0x0000); mmu_section(0x00300000,0x00300000,0x0000); - invalidate_tlbs(); + invalidate_tlb(); hexstring(GET32(0x0AA45678)); hexstring(GET32(0x0BB45678)); @@ -139,7 +161,7 @@ int notmain ( void ) //access violation. mmu_section(0x00100000,0x00100000,0x0020); - invalidate_tlbs(); + invalidate_tlb(); hexstring(GET32(0x00045678)); hexstring(GET32(0x00145678)); diff --git a/mmu/novectors.s b/mmu/novectors.s index deaf533..efc758f 100644 --- a/mmu/novectors.s +++ b/mmu/novectors.s @@ -74,22 +74,32 @@ handler: b hang data_abort: + // save the link-register mov r6,lr + // get the last executed instruction ldr r8,[r6,#-8] + + // reading the status register mrc p15,0,r4,c5,c0,0 ;@ data/combined mrc p15,0,r5,c5,c0,1 ;@ instruction mov sp,#0x00004000 - bl hexstring + + // print data fault status register mov r0,r4 bl hexstring + + // print instruction fault status register mov r0,r5 bl hexstring + + // print the link register mov r0,r6 bl hexstring + + // print the bit-representation of the last executed instruction mov r0,r8 bl hexstring - mov r0,r7 - bl hexstring + b hang .globl PUT32 @@ -106,25 +116,30 @@ GET32: dummy: bx lr -.globl start_mmu -start_mmu: - mov r2,#0 - mcr p15,0,r2,c7,c7,0 ;@ invalidate caches - mcr p15,0,r2,c8,c7,0 ;@ invalidate tlb - mcr p15,0,r2,c7,c10,4 ;@ DSB ?? - - mvn r2,#0 - bic r2,#0xC - mcr p15,0,r2,c3,c0,0 ;@ domain - +.global mmu_init +mmu_init: + mov r1,#0 + // invalidate caches + mcr p15,0,r1,c7,c7,0 + // invalidate TLB entries + mcr p15,0,r1,c8,c7,0 + // data synchronisation barrier + mcr p15,0,r1,c7,c10,4 + + // set all domains to 0b11 + ldr r1, =0xffffffff + mcr p15,0,r1,c3,c0,0 + + // set the translation table base address (remember to align 16 KiB!) mcr p15,0,r0,c2,c0,0 ;@ tlb base - mcr p15,0,r0,c2,c0,1 ;@ tlb base - + + // set the bits mentioned above + ldr r1, =0x00401805 mrc p15,0,r2,c1,c0,0 orr r2,r2,r1 mcr p15,0,r2,c1,c0,0 - - bx lr + + mov pc, lr .globl stop_mmu stop_mmu: @@ -135,8 +150,8 @@ stop_mmu: mcr p15,0,r2,c1,c0,0 bx lr -.globl invalidate_tlbs -invalidate_tlbs: +.globl invalidate_tlb +invalidate_tlb: mov r2,#0 mcr p15,0,r2,c8,c7,0 ;@ invalidate tlb mcr p15,0,r2,c7,c10,4 ;@ DSB ?? diff --git a/mmu/periph.c b/mmu/periph.c index 2e0d49b..a2489a4 100644 --- a/mmu/periph.c +++ b/mmu/periph.c @@ -6,7 +6,6 @@ extern void PUT32 ( unsigned int, unsigned int ); extern void PUT16 ( unsigned int, unsigned int ); extern void PUT8 ( unsigned int, unsigned int ); extern unsigned int GET32 ( unsigned int ); -extern void BRANCHTO ( unsigned int ); extern void dummy ( unsigned int ); #define SYSTIMERCLO (0x20003004) @@ -120,13 +119,7 @@ void uart_init ( void ) PUT32(GPPUDCLK0,0); PUT32(AUX_MU_CNTL_REG,3); } -//------------------------------------------------------------------------- -unsigned int system_timer_low ( void ) -{ - return(GET32(SYSTIMERCLO)); -} -//------------------------------------------------------------------------- -//------------------------------------------------------------------------- + //------------------------------------------------------------------------- diff --git a/mmu/section_translation.ps b/mmu/section_translation.ps deleted file mode 100644 index d81ebdc398ac45871568dae7f75d1112b4d41afc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 116370 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%0DqgTd6BFPj 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 z zy`eXf_KJ2ulFSm5Nqi-?DzM6-S%M#{y^10|;bRcaEWQg+Kgt*lVr=dxo+l{=3P@mi zy-*(s3`{y?3Q!oQUxKJ3FE#m5cE_x6bWD+&&1lTP`No-$Btlvbzz9N!9T^=Vn!%%B zvDz%?z^$W|irphhX50Qrg17J|!~4IL;qCh=!|T&OVtC^#|7M0a%AP7|(QF#%@%IqC z|LU@*|L-!qe=@XxGPM6HhE~c)Br43%%>*6{&em5_q7lGRAdEauV5*Xx2$B(eATh9? zlnj9k$u8<@(lzNb9tzF1rqva+<74GLM8n3_@VSG`y6jYN) z&o2d(9SZgk(18*XMh49r>S1a*eot5~%M`mPf6y?}(K5=XAq`}#q7dpTAc@KV;w{k{ z)JTE{#MfgjBK4%z8a4@VOfV~G@L$*n6if0a<`*ajA&Hg@#1qN>1ZOUSxvVot7l%hkMo;a{C@DeQjI8ln!*TN~p=1`8W zT{?amfGIkbn_C~Ee|lhRE^zfwBr5ar+ISSVAYzQ3IPNWk!^r7(1>N(Sice}F8cIVM z7FqzZ5sWRE13w~8lnj92?33uHqrgiZ8bX9PtVS{-Zwfjl8U%n<P&ah>T5z)tEMh^IfwW}=0i8I1xMqw{fWLQvPvA=8LQV(E=h36gi% zKCG2|!Hk(K*ouHwA2HoI#l?ZNqH_$qp>nJr zcFe-T5GBVbOR;0JgPI|P4U|!j73x)?tBI0wBV1#b0&nSW!B((es~cS(2Z%)iWY=2C zI&MTn9;l!e2{``%0YbGJvRe)0Y#(`p0N6ycH}ZXA#g#2(nX$s7fiX5tfx&!RT>0n-#VWatgd`ZMu4SnEb+PH9NCnz)2)&O(M zS$2xYkdJ^#B9o0qbMVcm00B8Ee?bnJOPP{otk6bdRmuREiLf6JApey4!J{cX@CG_) zM4bW%DoR~!QK}2e)N2R+DrFP(E2D}fuD%MHjFTfy&|m`L5~A*CYO5U)3l@EHq&`?` zYZC!vS=iGUbykL;fdz=VBnZ4VSN=*b1KCSt+KG0XFdXEqI5VnF6>!0`;V761Nw=#* znq=ePH$5fE|E*{#k{h$Vzyd9BJ*K3`23DKnv1}oED>NXII+P=g4EBblr$-K!#u4e1 zGST^opNKj<4L2D7gi7iib4Q!OW8fSvBU@kx=PugrX<+buzNNNi4DUa4ZJKW$+JO5J4cBsQwSc86Vz-a zV4XaWGRbKZgcm4+Akl&^No4F6O|+B=;wlbI)Ds4-fj44vpsjK6qPhCeugE4L{#v=H zC1Fu4L*s$niMkYQJ|0x17$JfT*0m(?mSOZ~#0(qO$gv@}stzde!$PvQz%}kT;1-V2 zBS~k&3c<+3d`G35oZbTv-5BenOcT|HOhj%_YEZNXokc+;4G(=3u{om`y>L>z9zZ78 zRfFPXNVSNReJZN3W~0ECnF$@DTW}^0Hj!rFm7mOKq7%YaN`bO4^5jiox_78#Ha%Z%|;wc z$arDbm`Z*Tn-gdKYMp2n$fDeiE*^veL14ydbeL6K6i5n1j}pS6IL zRMckSTU1Afex4bKgNiva)DMjslS<4XL`x~$gePMH>={8AnH5VL*b0&_wmLo}&e@9s zu{gV&xQ)C*3`keN)dkRErG-)@>2=Qph#v_TqB#t=5iuVfl~^&VXFOS8S(sYF0KArv zEZRUBHDMEwTde|h0PaTR060gRFL0r~faF&Tj*5dm!rdrDtQTtlK?qj;6FK=4{ILd7 z7k9O@m$%3JvzOacOUv{_b))wB`2NE3x3o;uuIdk8|2~kuB!{Phuly7_@#!BSC-Iek zJ91J;GdF)XZt^d081r92PX5F+{=_u?HJAnoU2rT4%xLIR5&BC!#i$Y_oI#YoON3EY zYWbw3(TJCyCWYcMwJVIHz7ZElYzio0RveQfV~}l=SAxr4&BJ!3Bhr>kEEbbN7zO<>0Ypp%;RkJ{_l%UlvFE4}W1u%j96$sy39Y;MnSO*y zGg?qUlVoes3vC?mNy&K?PJpI!rpgsqO5BL0hzroR2*PO3faG&O`VS5I$RANu#xWZI z34svc5ptQi=waa<1m?lqhQL{O3}fnH#M#yZmARTk(JcH&Xh?IRKMU=V^en=SINkx! zL)~lXL?OF$F?#Dnzg7x(bdE&YV@i85Z6G5x;uHlcya7p~ML9B+mLErh5G<42z$=pP zTcOrXBuXMAmoom4BY{s$rVJ`9 z<*|r3`KVBhgqmcOrZA1~)4JoNft!B^ z3-vE4(Hux<16|2w-Z+6-5rok>gXe9DyP7 z`oJ#o6b<#E+u$p*8)y$OH)`knFQwv!{)HBa8qr0B4&<~VI`jqw3s0^MS_Ejw8UzCP zj?fNg!XuNa(PYv;p*4u{pVxql#untgsObLOr(D|bz#^6OmXwZC|yb^LdtXF8{ z;F8fITP+I}oaQd7U<@%WH0V#r7|J_zn}|U*oVMr)B0@tL9o4NMjHVM*4%8A`M}s3W zBlv$*hls1AVu0k2+SVy-bW0)PK{aU#h-nJAJ47)C5$ppcrIA9EMQ@cvY7Yhy2P@`? zmh6fzXz`-@Or_nWGm}E~3m=VEC=h1oc~o{8LXsV#&gjGwv;ia%xNNB)O3+0fDnx<&s&xn4~eXdZHTTAnbGAT z1nHKRvI;$FLVYO~3waYvP%Q*e8-4+u0|lmdM0msza2nar5hs-qMhaQt6S_R)B+-4m zwlYQHMdD@Ih&JSOTruddQCNC3t8(iom7$15kvW%vMl5RL0;N_Ai)~TjpxR9+Xy!v8 z=5(x3E@COHGGn1nhJZUN!<-Be__QO01*S3#(JD5=eP{?(0Rd`V5U87^3sx%7)BeE~ zr<|ZgpQ)_Yaz=_^XB3gx03m=@CP1ue_xZ6f*nr2WRZ)^8P&R$hP)O>gRD@ns19f?f zhsN;&t6d1UM4(0a8Rt?shz$U%-j0TfXj~MI9xAOL2_#9pXgPg;j~0W`m-0HpQU2t|)SjRTozQ$l_pw7Bg4yZg?L3r}GW) zZjmWj$BqtCvkAe*STi^3I06IL{)l85Z-q{ZN<0Zf7zF@0;!lF1pu)Hc?V~=5V32&5 zoH(itnVkdyrpJcynpgY`!JbSJ1m7O5t; zV?X@W_GQ_kKrqr%+l!>pqCwnQm2!8=bu&PppdwMa%W@GyMwdecO!j*iDa4(Ppy*Q` zsKOS_8i&-Vl0sJCZxmb81cx|U57lVTsI(n~9S3BhO$#L_CvqyFd*+@7nJO@jJq@F& zLnulBh)wPHG-j;E;wAogVr|OBJBIuw$h=Y!z@v6b}(wG!V*4TPb{~!W!GJ(0X+XNtviwaQP zojhg8Ib_c^wEELv+srfvMDAhcT{qfODRgliou{lcl1S78O45dQq>C{Nut43bm0--7 zT`WFABF?42Rjb4ZDF^qS31?3SAA$v3RgkrECtlL5-_|p3dm3( z8{=e#AZndW$fXCm75p%{tOZChAkwnrQ0HL|T?v>3fN)X`fdhgwx|o7%l$l}SX}9Uu z@%gkTPP31wg6qc)^KO8zkk_lw0Lp1{73G6~8Li1U2jL9FBsqH>Ji@qOlVN^35(c8C zVI5D#WwA@_xq}Q;TnlIPgH)WCH04#%jEGG3NEENYUU)GY8}SO>PV5y20cj$oxLFmF zA|aGj9PtA6it~@yz|aJNB$a{KzoHdpMMLH&{v}feUvUu1$pK*M@Kg%J_l$z_QvE`E zO1e1fKP!+krXoxPC0R1!k|N84C|3^2ij5H+0Alys6u>E(j3^|F24mI@)W_F>L&|Wh z9BWg_FVaxCr4Z7iP_hevW7$A;qRgBxftjg%Mt&Pnp&nVaib7_Ei4rBifZ{X`!K_$A zH6m9>Lmf;dp3TI=?t;+=f0Ag307FT{`6{T68g0WJ4f3M%V05*DdV~=%3xA3 zi4mW-**RX-DqrsZpNsTcx5WFQfycy*r$0Eij{$x3Z{DHd#a4^HJCiW2g77LhoF zGDkg`L$EAHjWDSVB0SKMKtLQ#jrAs_DbN`+nEiKEhyTxqCdqNt5`5_TZ$ow z=gFexkJE-t>uQ3^r#O^0@TDRkYA$ICb(A7f&1X1f&un;|K(5rwK8je%I+h7JW=ef9 z#F*?xplkgI7^0P@_$zwSMf%CL^eH%C2C)#)iB+vh$n^*#L_H!L`($ScIvQYH(fd8%`lk?Tnt(LGrVh3a;58 zF3PhJRe)+aF3)C5j#dzn=NGV+wDBv*^W2nPsF4&&7&-L{Zg2F-Qw4pJWnjPdpa zcN7N(T(029mVHTw520aHWk=miluUu+nQQVtt!l`&1oH$g`UgaBL`s)v5JS7=fLL*} zSreb@u@i^)(PCjBSSl;r%=v9GUI>b0J;;hMp(G^H{lSFBJ&+Euj-q>~da=k#gcv5D z){T#$)59%Eb0{F_C&cNbUy5glNf<;WwrUKmxHt<+fD=Xek{|Yx158pNXWfX0)Lqd* zs@BoyKubezIGW&youg}s@*G2Ft6EM>ia4A)Mw=SBnea1&d|H1*6Xn^9kD9LRe_ozkk5j|oCp zLkbZ7H{wMml>R6B23gW7uDFbNCKXE8=?4@nf;t5S+RGv}9$1PM2T}&`X~OCh4?5T%JCP=gWONxhz+Q2sz>Czxf*G$Qp~nJub|hE6yY zhc;O@0tX8&4qZcUdR+yBk-aq>|oXM1i%U4XgsEw3TN>?kTY$c9Xs^F0N(r^1@enORdbCuJ zlN`)ooE-ocz_2pgDdwD)@eN){cma`$e^_1WF_DoWS(Xz7z69Bmj0@kZ!NZHcIWTbu z3YAEna4>KJN6tCY7l}_yC%w~J&C=9_g43}R_&qUAwAyDI5#(X_8Eogu``rBEwOP7Y zFQNvybvcD##Zx1D*)IvdmEn)RFX)dg&mAV0z4p>hz?wua7U2O#_7>SwSj84tn4qsjA+&EqW$WsqkUc~&dAl_%VkKT zp6~3RZkB=f;FXh2x)HgTEJ46EHPM8 zl*8l59C#qBg>;-}cT_9LOOrbpp+42ZIriG*23lqMB|?tXaCu0J^&3C}b&F~hU`_;( zcBIIGgBJEM4srvLW3(1 zA!rcEdlCmmDKF4u_{rN4ld{VWzo^IUSNzD zi4!CLssH>bFZlnzynt+Tv-bA>M6TjRFxLm8&&j!*L9aIe|gL1dNS{4cj;`dyO3F~ z-9N?$FMmsK{w@CS`c}J-f2YS^F0SJb^|#tZ{QK?wrI!34n>yNBi0gKLy)NBDUop>N z_oTO~smw%gu2{)#-Tdm_*&L(Oo0)ukip%`%#p!*?b<>B4)2v_V%gBn#@tJ1L*<637 zztZU`doo44IsV<5E*7#WKPdEm`#~vwkRIPyPA|ou>i6~J1#8uOdOSY3yGy^+;}6aX zd`-UlQcM0_d-=;@DtV)7KKtu8I>^KW^%OJX*-~c1lV_IGQ&aQF?~7>T;R^G~Z%uDO z+VdWqKA|tq1f>gk07E)g$SX#EsigynH!YUe=g;|?JZa(g-!PN?`TlY;lgS@GW)iO# zSN>%ti(g0lATtrq(woioX7cf;zW9ef^=1r6bkE3a#$PO$bbPn=55r-_1!WQ+vsFcV}K>zDpUaJ^tmJ7De)^Ud?~|)1Jzz18?LbJ^HrHdVYDh z`OEY~{q6Ojd!Uf*&m1L_SbMhUJchsYW`q;jN~T~I-RRmNWxFexdbT(7^7@wZrMp_T zr#qGTOSZcwlg!awy6UI3*Nd0>)7#^ViPozC}?9lY%i%*lgoEh_F zKb=S)ru??Iti62wmhV)*T`pTL8oXEprp;pOCgh2we303U-${lbxw@-7xNA@5EN)VZ zKRrIhUE?cfcloq8k3YU=`(mg)akVr3cAZW6Q@rBe;y0L&hu6EaH@{xa^b~XF^|yGD z`^ReiGFvQU>a}X}_Kl^lq<*+0L{T*Pr=#tuvd#CFK0sqDf4Ku2%hc50~(J zmgVK+-Q8pS{I9PAACGNH^4h5+Cgvb>2%4}(W1(-kr6m-vpNyo3`M7fJt{M+viNqbd zzfQR5KN+$5gFE?htUph@v%EQ;t&}r=DaYT~x?*qUFZEYX7B3f1^m2dp<`4Pgw>N8k z>(gxX{<89o&`h?sH&cH}R)DMLd}KL$(7)8I;*T}who;WWVDVT*qHCl1#rH`BI=5eu(l z0DJqHYZu5B`@UJhz#csLce05;F46t%60z!B z;_P!~841?o7vtbHAAa-rxnC~)+YzY@lz!(Gk`ehZ5jLP@(3AO(x7tJ1kjFCY$$Y;* zVh^Ts1A`I`SP zO>%Ev1BbXB}(K7ywoE@wLnPQJe@EHS+Gk6$~;OvNpx zU37*w%FMfCZ}QivAMODm$QOS5%Q1!5Ojuv$uQ7?4dnS-+<^lZ0OxHhbXF8emzV9d9 zH$H7vPs$FrRGyv$oe|O`H_mmJ@?x!?WO%{WAG`BAi@535-!13<#AkhMpT112`uDrU zihtPks!FD?g|W->AHiJ+S$}S9KV~l5Q%bz=&t|V!NyA{i3l096*{kHszq;DbCa;he zWdHi6Q&!0|12K~=_Qc%9)EU=b&s}%E@atO~guORy*EOzzf$j}E`z>^^0h18GNG6V~ zFY}nVo6FiuvZKR3`Tepu>M#`%iSdpP`aa_ge|>uMY!Srx)`wg92+QJ2PqxNOJ$@L2 zo9h-k0*}9U2Qh1{XP@( zeXi73S4_SXe=nzE>H4WaBsOf4G!!degO0e=_rZmiN!GH6?e$gsmiVIXk5NhqrLSra z@##zAL}RF2%G`g)v0X}{N zUWqf0;NrVTkvI4FNf`Mgf|AO;3PxNzT)%&QgaITdahKPRA+Q-PM0F9YJ$^>5u9`gh zSwyR5*(8WCeC73H4rBt|va*lp7*mt46w^++%qPyg93gX(4SZ&9KgRpO>Ab`+QiCWb z{uWbz^PUF`n=It0`mWd-5z|-+rOn=OBFynN)?Txv#$(oUf)P zxovOes&0tC=0p;a%K3KRETxIn|}Cicl_SBE>m%( z*dbr9_OV38{dt0q@7LyfdOgKz{Wap)PuOK3Z6Ek^QiJ;ojPe2S{8JcC`4hvb{1-5s zufO|uVmK7Q;gS9b#CeY;94TG7ABGcu2^@!|6JPk~6U#Bh3`VY!xld<7FXJ*<+rWam zu79LH$!{{fK7LPr_)Ajr4c*E0^yNcF`2)yv5Dq9UK$411&8HJgMEvl9iC9A4VNQXh zF!hs({dx-AC;2Ujm^@Sfy(;XegwALIRr%T(Yp zOM&?$c+W3bPy8ah$I9c0eE;Pyu`NIM$+tHPlm{jy1+oQt8JcpY*#FhOmPJ4e>sQo< z`Rw^&0s1+={Po8Ps8fa;`~v%YXFc(l`99{oEV%t0JSRN1=?aXE94eABBfxQQe&7yC z3;`?ofDU3_!*<3CeYzc;@ACvjX{|Mq4cOP8Y&``@U>c}Y;(N%SJV##|u_G)lrtj17 ziGqVP!at9qPT%>YlqZz={*$6TT`KuRpyl6psWh@7PrvZPm-_M~1HbtsZpOE<332Hk zZ|_2cr7}-UT$;wx*E|yXmoJRl87-%^-T4F#<_h0^5;3>d;Y(#; z&X2$5QQ|x9h3-x+{lnewJP32q`kZV;1)BT; zEyvbfL0C|R>A$jL5v|;$4vze|kglc-W4SlIoc_Z*Y$moc83<`f%ogtXb7%-i(|UQC z?EcT8iJAQF6GKDJ6E*$9V#Ak86Po1J4*&2aLnA)<{?|-9TpEKI@048HJbZWiWVRqK zrb4#UU;JD_-#%d`kVJkFkM%LiKYT(}ltvyUA%{yLhD?{o{FwImt-{9wieaxLm-+fZ zDNmacpO|9GM!zFW^3vZvNhQytW;yxj$0v*_HBJBdeEH44(hmIioA++``NG8i_?hmF{2>#c<=Te)=<|niNc0chu<=FSP`yB87 zvcNt%jxxLc-S_dz|G;CZ)cS)fd|CmtLF}uqcf!plbi+SzD`LPuy2QtuCuWb`(55M@ zP1#tpgP$L;!=E1*6q4(h{I90++b7qluV4D*GJRo3?Al+h^YxQ&zxMT)zJ2hM>wF9c z>YFX&o<6Vku^>v{&(I(3_rK#3n?bJiT4^>+kRI_z=8`lete=xay*SCEZScvlCFh(5 zW;!GkDvrRHiU3?^lK5p9Rhqdr>zOQj#Ambt)wN@Vs<=_6A$u`-~IM|HKt77*ZqRX6EUdD`fs}}Z>7E}jV%DsevWZe zTP8c{w+4l)k=Tag7RaiYAf5?>GW79%VK3qsbNv18O0I;s`Szn!FuK<2UQ zyttr6`M^)D)=yT>Z26EiwZ4Xa43CiV(i0L2`0We zNlwdVh?qUTCUsB_{QdX-$SJV*za2TE@H`q_Pak2$A6(*hJbk=o6hC`U)KG}}zWRvoX8zO5awoFxKuQze`_-g= z=S=?CkA6So0(A`|L)VjB?{{~#5L^XSS|t)=69-}bHWvBUuFZeVuKqsS$rUX=wQ!L? zYjXMV!vA+3`or=5#%TT2_52q$+iz`u51uqIaBgp1v z0-K7hjqLiq7TH$pJcRj75g_m z2ABD>=ZNGTVFE5$gkY}4o4T{Lh69MEruoV-}pmvZ!m2FPWPmb(zwryv$s^&RP8VIi`vF)sO#P?9`7Ds zLLF91Rnpb^#alYsGMz`q(^NX$l|0AR-=1p3rj$DI(Qdu^cCEAM*T2uvkiq?-_+LMn ze;}KEdQ8-CmuGjcwXZ*zpnh4ay-YsdKRrI6Y}0P}anY&T#bdRW_6~0J_5VlTetPzH zwwZKeO<%mfy!g$_`duyEHNH7HKVK<*{<6>9H{CT8H~#Un&$}dVvwZgUQvVOPiW?>N zp^!ZM$KA+yQuP@8)a-d{~;xM(PCzf~W{_O7=tieK7BPMT(STDJ=Mv2t~K z`mlAkduwO1)W1;bSQ&llJt)mT?Cl<1^ex=HZf_g2p{thN*X+vmVDrG;`0CL}sdzur zv)o*qJn!n<=&fJ(K8{X3uXN8H)TVA{GCc>kL&GooD=Ui~3rEGKzJu(_@YB|V;+ypR z@oLk;!|wh3*ld4hvVDH9_js_avoQO3F}T)oyYsl%bKWvsp4snwZ*4z)9yp&mZq~_Y zfAm_5fb09_)q}A%#l)?t^ycm2+4AA;&D`Bf@7Z*9WImHUE4>_--|{y@gDX89&$HQ% z-oBUF+vmRRi=Es2djG(2=ki>4@8fCxarW}Ky*IbEc72sfkKQh=_f$s)59W^Uma`*E zJ1y0Q=7s*}uK8;J%|h35xnuCP_jY)+z5Vj2;du6Xb7-%5dZ6=S>G|xn)^=OGKRZ9Z z=Oe%dpJh@d^-dNjNyO|rm%T=3q3zL(jk9a5 z*S^2@HnGru*ty!?zOa6H{yg{oP&r-N9az6>U!EJhoto|4y1C1~rqXkV69#VV@@lBR zp}TKr@ZnhPRej*GwYqdZ(?2(QHuAiAJ#gQ&_qg>|c~;MUIs5k5Qp|0iEae;5Zg2AM zhqKGItyFqt=5%LcdF1*1Zs}_EV!7>0$I1HL+Vnzxr#+W_8=GxkYaP9OI-MWA7$4bc zE%rXmz3ui4FAcTj`s$ng#g@Ch$=inQrBr&Ry)id)wzYJ!dwqX=SSc(HJk8JCw=~~8 zj-0hFwC|U$mp8vCBqB9GuPfc3*F_u4g-Q%TqV=YZKQGtD9}D*SYJN{qxb`%ynt_ZT04O zV{vkOy)e-l&x6?O+&o=-dXCUa}0t<~w( zsrOv(a?9${-pESN{+Fw@v&Qk)TH(Dm^d&d9R;)aYElsp8e6g~tot^dCO77@wbo1$; zJkxOboL{_uZfb1b&2~(w4{jZTARL^Y;Eh zcmCCaY~LR#Z(kL1ZJp&@{j_1{dh{)SFu68$Gx)N)zj9kzz1=*xyzYHz>Kr*)-@4ds z%(UDetn3%N4|ld69(FtT`&t`vcfF~!8Jt|%-&Tyd*mK=HnJe!tERR=5OY<%Hh3S0P z{NUos{?z+Z?qTL}uRihE|FoOGTd7@MjaH9K(=G20b4$+)BlDZ~+QLh1a-=%8y*abh zw4KYWt!+=PJ$7^)^$y&$zm`UhoBHmiPDkf1J5JgUhL;9fR#qps274c-YuEM3!ue|F z;Y|1J)j}%$Jb(SrHnqP!@VYWwo6W5am0COI?nZmQR5m8dBeN3&n=NZ6a|ex2wU)<+ zm7V_U!&2K&eSPd~x?Xu~KCaAP_bwMMn^WnVeBa*N-Tg$*cBbX=adNF={I>h1Wv_eV zc=v37sj|CLSvt;*?k$}cuZCam2KVkq?wb1+mWxfVca?$r#V>hEr>=2(t!HF>c-%m~ zR99{WW~!U@mx1}g^Y)IB^|77D?Bh!AaeS@TzL#C@E!?*>TvreCmHLdHO0)%uS|Qt7ql{)5BmgXVnh@}YLsu~vR+t6%LttTsRQ z4VH%sQ@fip8@EkO+dAlUE$mNL8a6N9 zj^5@M7Hhlj=c)8#)7#+cdSmm|% zMjnQ5ho{?K$L2Rj=WhqMkB_%+x+lI&6dqnrW>V?ZmX+ej`220_-RAg0?yYpu^zwLl zHMM!Rwv;*D95`qjYHVrkdR(r&oGo8Zj$O1B2WrEkTg9oR=JEZJtJQ_&rnk(@v;|px z?{2txKP_}-nkx%;oAv5^?q%ex^KPqU{bX0S+tSeG^lSC5det_XdzmQLt3B_v#fk0Z zzP{7a##qN*{h+8VfD^F9BI8eY{XYwz7 z4F~0w#_f^r>|pM;yu8!c+kV+lTwKVGAKzSNR$FE_npnuwuFU#i)A8EL^YHuS|1*+W z|0Tc_l}CWt{j2!$*B}2U;iWA7GrWw8{1{!zr%JyQT%zkj`S9-#E=yk{!T))oWl7{6 z;pY#5EluTa8kY~&YK<-Jn=9L^J99h7E%Vvup0&}w z)8(G0j;H+X!q(pV%GrKtY;wX9NPjK@>W+Ycf4vBP`ti>eL3~k;@eeP8j~o2%BA9(S z``f=X#rQ9*f^S*M4++M9Ut;k)v)}$&oEyy@4vsZ6m2-VfzuL~_WG3aaKjw=)zyADZ zbNQJsLQ6h3baI&=ceGTw-1pNhP4)7j1^xGLX$qVFxtls3{wLeIuzOh?x!P=-XO1Lb zs?N?rhsuSmh%;-_y`xD>X*0@xAEYupFSLW}sr+0S)t=%o< zt5bpA@=|BlNcka~-_AA^vKMVH2agXocjp&v+e=6NCtIsahbNnFqc`WB9o>y*ZTDA$ z)!NAVXm7q{{O-MPdA;;lc$#j=iiQg7Z(GB6bAwlq%4ReQWRF`TgEw-(YriXZU8gW$b0doHb5$)@L4OPOs~;Ew4je zlgk}VcaLkcgZp!9PirSz_2a_eeE-JQPAWa!vwo3zFAY5mS9^{wXU4XRtxxr#>fP*Q zcYo_?v)iuE4OAM|M+UmaR*z0^o9ABc7F(M3vmKAyUpA_lo6=zR;85uKbh%nwYp8Z@ zcP=iC9qe=;T`hGjt*!1Itv=nPa+PPcaeH&b=q|yfsrOBR-*~0SB;mvgEe5vtaqviB2 z({Pd>+L>9MdnvE%uqWGav^^-)LS@M%)NJ&PmbqK_gg1hOUKgf0 z!$r0Ix>RnioxQE>w_Y`GEp-l`cFT85&AkV!^QrVe{pzTp`DJx%urhg&-)`+W>^^F( zPn~rxc4rP-7AHDps!g+dTU|>Ny`$rIjceO8w@-&n&ok5Yx!s$ag~^4T$=2T1T`}zP zeD!86JJMJy*RFexTQ_!_&bnL2N-z20_v!1A1M%(Y-oZv|2)FLPbzkIk#Mv%80b_50h^o`;3{)Whh; z#?C^^@#43eJ8I^9V<%{uX7#y+ii2# z=jG$wi=F&jGJL7ZZp7xu8`KRONo7u*e;pwr5GE+ZXY#F`G zTzBrxtv6Jk&aWQoi`CKnceD0fet-VvHHiVlKfm^l&s3;C`}}8KGrk!S&_C`q<2V2G znjgsPAEB(j=QVdKYo}{>nd9-to7UTzzJ~enM*G-Rm8yk}Ym0WITJvY-awtqPL zGIF=o(K=IUs&3c5bXT`8zU*Huos2NksdU5Z$!Yger-QFoXn1|7pHGu4lbv@H1?fN3=fRvdq#J5=6U()E86dinPHV7At@x_-R2Gh3)_O_#b4`j!V9+B(|D%e(CF?bXhBezE)PVEldl zZM38Hve+`Z(y&%rc%QB|XE)d0_cFEHT=!(-`{v>E{NhRWp|?7GInjH2v$3|lv9omi zWofUwb32uO8_F$q?N81w4|MOI4Rnj=hyb5?tzZQuFCaJ_j_M% zyKgYJ-SpmB?VitkIURYs9IdvFoK>e9>WtJm3)s@!@;X@W?ijxqzr}lJXDYAbqkS*) zt+}?^PFHi=*3NtO{k-`q)A;Z>TVKB$Z@Ia7xVgIAzwRoX?lzYfK#>i7Yv9JKy`I-x zb^Bm#{QxF>UGc3?!n^x{%WS9xqbO<;%cLL^{CoC%xo?l-t27M&y|{w zCl9J8vv0FEQ)4?TZC#@$!#(2<8-3Z`+UpF!;{9Z1Xr}$>YNxz;Jf7`tEidsi^Ar3` z^Wn~Vr&sIEAGSQUOcr1FheW2+`K|eEb9wc$bi0%Na@6#oa3a&ZJ2?1KT{v&Lzr86P zb-fI=Y&uqGd3Aet^l`lKrFQJd%=FuMQ&a7EsQqNOR%~xy+;0&vuJn~ozid79c8u1x zOO3N%To%i`IMzKdG1E3zm|8d-x*yvwj(%BenC{A#o^}`FiAG*$3&rW4iS3rV<&)dh z=KI{p##Qt4%}{>4{My#Cc6`=wygs}7)ZRYUx4i%G<>h|ta^Pm6v{bnGvQ->D`m*(U z_y!x_?3x?T9=^X{U7c-Qx1FA!Ez};DXU3LB-pdycEyMR`U3X6#8(mk!7aOb16NSP3 z>k$OianEJTWyj;i%hArxdSlZQENWuCWubWZvRc~#Vf7CjU3I>+<*wG}U!VIMYOBwg zmdo%KUcI&Vf5zdf&9o#gIEHy^I6 zeS4y>;(7Z}rlVtjYi(y}uDkd+csw`y@^ZVf(zpD!H##`n&{V%#*($c)Oq`DPK3}YC zHkVHp8}5(09|tC0&zfGJrf)iK*7oET)z-y@!Q9dI>*Dy;``OJNXk zZEohSr_Y~X8}{c4=WYAdqu2e7QqS`J=J9U1siCsfRqw4&p6-nsqx$OM{WtIXfdc&2 z`~Lj%pLyS}_`^T$ed9O(^uGU`_g$YTZH^ygZl9iKN?(rW*Jcm9FW$G7E*nNq8)y1P zMxTrG%gcp_wc;Eu#g#Bf2l9@6`FchA7)nFQ(m)Z^QD=gQ$}eWUc;_~l^zey6%!_|jM?K9q(JhFh89Ht$b-(m=-E6O1|toK~(_vOwf*G2}8?@Q&o`@QAm35|*e+jH*& zPu2F(%j*4gNA_%FzhQl?_%?Fz@P5Crm8s4wFJ}tHxpHsz^cp&Sy1kzr>|1Cg9Bf`_ z8QkdT+OAwZ-S?k&wl-WZy)X6OA%eSRuJ@hGEeATub|9acFP7cHOvhUprdtd%G#DH1RC!qaC@BXIq07_ zeEhifaKmHQsKAemE$fc@^Smv0!0 zPmOO^1lH?SO4`jK>weo&*=Us+%{kBZf?75$PDi_5A?LIx9DlUJ>2kCy~xbo_pI+7 z9*$Q#UOP6Hk4E+yOP3v8onuW~JNeg@@BSf{eZIcWE+2IqeOnO9pLi9eb)h`#`DI1? z{PUkJiTI{`l795B!>&TL6PNjMP3Uy&FpA%-isU8~&;K4~C0Z!oYr;`(lVZz`Led^@h66$c;klc!tvle7evy$3Vrm9B*&d0?@7Jypz&ep>~^%?yLfuD z^j>Jlwr5xKmA0|s``Z4}_1f@JYl~3u`EmWdvVGJywK};s*S|jYcwODzD$HMAmwJ{q z+r~RK@AKKW-I;?@{=L%KdwR6n^fc8!ayWCjvQ>B*z1n)f)?dwtyC-)~a*qRu&z1G9 z+3PRa!<%CMWd8ALYGJPbax^zTQ=c5Z{PHj`dA)wnJEQN%%zf$0%Gu)XU4N~u_PjmV zP@XD{@%zusL&L94CzJKgy_4+1d1dIJ_i(qV^L(!VY^1YtJvKM6abF(VT-t5UdzfH83=9;_4&-xcGE~lnvF0NXqx~FPAS4Ypgn-6b29VNNReqZ+WYN4Yv zTpV8CyQ@#$RqOM+)wT83%fsXK{`Zr)#=`4s`{lvy);yY8Fa0Wr_LZaqy@$Tzx9rq(-WE3?C=6DOx{4TYtS)4sdj_O-j|o65w)RDbn! z`(&hf>X4VpKP}G;4Ucy}Zw%zGcY78tJNW(5`(w*t-&=lXZghV9>FH&$Fk0$vINIv# zy4YT8e^sD=IMF-Me3rl6o1R~|**cr;slLds3uAA$N0pbBow@Du+95Lex~XEa2~)w32I) zO8GS6@6pI{rmH8nS|fTZL%$|+5|f!!H)ViW$s;2H13l&!M)!!~hga2Yo@cic%A!WO zi7v;hWU?-F124tZ;IKQKa3Rk>*#bFvGeTzELp=%_Ri`iDb@xa725|VOSM$)KwQR_iu*1~d&7~ZomGP%&_$3{^>y9f;@ST&v+K8Or&=4`H2c*ptb z+if<_m>M2I!l5P94rt`(hcmgw4Fc`HI``0tLpj-eG8myeN5wgO(?DAdDq4Aq0D!F2 zaF|kSolNU?$~&8(JHDc@O%$z=^Li*>q4!L&cnYW8)$laA8PT)f9v8RKq!Et6nv0=V+YkF#)Gx~^9?w#%{rfUCX`FG!VuuoH%j1YE zUDLGQa!q96)fW~J5K5hvp+j-K*#k^8Pi%D;ObWI&EejwOap+%b{Ai~vF+5sTCu}Y| z$LOaNyMEp`3Lc}tW9b}H)M592mCEfw>>~Hb0nk_t+FNz(#*5WdAKX<%||{E zGPgE304tj!nJ)26Ypx%z+y1#QaB1Y_G=jNV8`Yj0HF%()p~X)>_Ybd!spa3TockPK ze2(y@WHOo{36ZFNuWuo(u1~c^*4s2asvWuRFz`FhSjmFA;<3VKHq53at?45J zJfoZ^xYv>e{kW*m9>7sDPy>(8Lq3e0k>txf_)TlI4CQJ6}zAs#m zD|Mu86-lT)15@j(C->%M;LyxpO{+}!6#iTcC&l6vN(VhLJhwFRyhbFt_7v5bVO_V@ zkiYu7u(Y;T4^hp%pF^R<)1%AzZCf1Jw0yBzb(mnvjOOl&#k#E=(6_j9w_G|rQkh}* zQJZG4@fHaWjfIge3SODA5vk!O>)Yks#Iq!&cLy&J1=KW0nE-X1#DeGl>+=VKAlQVf z_KI(0_ELS?IB+@8?S*R}TkXniTUrpRmXkpn#Jo+kqpY)yx+8FFPrf#-Y+Ej4AVPF$ ziI2VQOiq_=WhhzEM!DE@%i0l1)#W~Iu7K}4AQbh(%b$M!KmYwN{}r6sKhFM_KmFZj zL0;(Vullb}2BOJZ_&>Yve`T_te*V8a#J@TjU|W56qyG=L2}1XO>CaxOFiHkwfo74JHgBW})oosz##t<-+xIIK>$yB+p|{bu_c;~S-Cc*TRtL(} zW|faLH+_NbC(uQ~oO@mH!KC9$9cSGH=;bmDDzC1Nl<&b=v#JSF)7usuay0rhZu2+rLg?yJXxrx z87Xco29+uCUaW7MMSV;Mx;6#ystvW>%Yd8}jlzNyV?iIUKyNU5e}{Q9Xaj3JXN$$F zA(WAJJ3pV~8p~GL)Oxp~ulkSf;J#2N_eKjujEbP0DSwMqV{m|LVcV=i#qTfp32QhgA44e*ecLe{}n6pyNpWheP0-*Z+$U-@l!F^`qAhlokHl z27|zN|H9`-&pUdxZ0CZK)+%niPRBnbIO!5xx|X`=o1*P&i*jP+v104l-_cBEFD0oS z+eLR#hw&cowv^8RNQ05|8g&ChLiBSPR5U!uf}LZ@haH&-G^h47p)g$6Z(pb5x^om- zDTz&%+|Bi5Sb>j9Ash8cKP&*gE}3noh#7aHpR!Pq5A1!Ax;19)cc~AGkY}-esciKj zQaO3E;dxje?4Qk7qcP!fXe9t4P=lyRIYRFN-gmbAkaoq4{ce7a*6%abytS&l%=fLQ z3~zQ)rEo0D{#9vTTSdcqU-7gclt9U7KIqrWZgDy@QNWqm?(}IxL1vh+wkyif=>*gP zT@E~mk6BX;N8^_uu8IPi)HzgQo=J4{G$wHrd}oDo>vc|0t_4Wz;MOhy$?9{NZQfy2 z^v$zRRF5M#WF3v;y%7Ur*)t?=fmvsm84W|p@bFV3oAb{6E3jAwgf zA^2Sk{98U-etXV&C-F+puv6~GOLGj=0DIU;D(4V&xgF44#Yu@9(SN&Jw^& zkdR7my3+y-yLka=oac9#-Q!cNXTIL%Z+jcm$$oC)PYr?ZHuu-#U+wOXcm4r-3*-@d&;C(mDZ^DjZYf8O@SlvOCRJw)9poWLD=t!DYO zy~S*HW<#epM-{n6o5`~GB0k=7!Ei?BW7<=irxdb2mA3tUKG*4kipHW;Rcg1?*i8q6 zX(75E=*!dX@|X1MAx@sxXF8*nxlB%Ha4+7&4b!kM$zgVWW^}8(+D?*wVZ&UXfbAFM z^LtaB!23pee)E#P)tvQsb(iI!I#E2Xce!T9wqngYuWwt8jNri$l9@TdZuc9|$`&&3 z@(Tp$fQfgr$7*IE)N|4*dr$Z!GH%cJP0GqkP?ySuO*HQ;+eNuvC~9UMOZA@hE-15c zoJLerxQ{8mO#ra(U!9^4y~KO^uukd0`nTQj%>V(ZI1uyxZgYG&{MFw0#qt3o`CqYo z9};pOZ72TiTjPI(413<=GW`6S$?rjEyReK}(QAiC@U3jzDoMiW` zsnnXAR;U!}Mv+P$mmxw+Rlt=!tI*mAu)S^_Ye_)_lpdqEed-}F1l#1G6p2=E`^dVA zxZ?L2G#l9T`${Z|Mq4pQ%LHj)C+w~eNu}R($hUZak8}TyU4#;#RCb<7H@!vFFu&<~ zm)k@>jl7nv`f`p;*HpRFW6r61_ZdPktH29!xO?fgTRUw6ML(r7tF*=oGcE+FqG;x@ z!eD-~D@^`Y3cCJ~ynuYRZI=n?eX)Qg+dGYl(X<==HqttL^@cFbOn+KXRUpFD)Su;`$NieqP{j+wDIjxBhu{5JhM= ze8yS6UT{R{+yW^A8Zre%UDqTdsOM@$e7DVA-P?Y5J>62J+QVLCt%fTXrD;JVSFQC! z1e9K;=bXnh)-F=F<2D7omUV~B2TwPfT*G&{pXY)H6 zWqrqKny(`SK&9ok&0a}#5bbfTZAxb>$S%kmR>{21LhnYzEoKW?=$LlyU~|ymnikT9 z$_A9YHNgR+wio0R6>l4V06^u@Uo19brBR7bRd>j=wr%K6K6`g%cWWo|(D!}HK-cgr7GAU(7uf6b70b zm(Ug$gJH+;{3+!l8N4L3(7h)v8SW4PnGmx&_Gk6|B}aO2QqPeaSK`^mJY7L&P*_KH z`SSdypY1!E5NWT#8}cN3xorA9qfXUVL%fOdhqb?N`&U$6in|p9soOJgIiDKDxubLU zI!q0lF@)6>@lpd>J43_Fl{WINV^ro_IA$HIx-_j=!8L3ug~Dt}46&g$vG-Yy8b(r9 zzwNzo^l%;`i+A6WnLS^_Py%rUfv{#55v)<_x+|6Ey*N#j%qW@Nl^mmvwRr6qY99j^ zGKLtUtU*0X`&OaIxPiyj`S~bGqY1gh0K!Y1!;lR6f(*6laTu3#p}7I7fuURkiGrre zEZwql;ig;I$+V=B?M-D{r2~6*=ttdynU+$LYj0j4Kw&gGf~z&W2_~R)ho}88wH;*L ztH`m$c`%zOy_M29K6{0c(ktuv+xeQR_w6H1!#-1lww6p?8wvrUK}KA_8hR+83vQz& z+Z5LC_EJz4K_d-Q45i*Z8FJ2B2DUMw%1#5=;1(H^!^#lox|!GDK2d7D0|WBWspgHV z%F(Gxp6gt(b~g-!rw+(#_x-ON!{~Nld_ZP0Bb3;*{Q< zvUwhgy=f(N$Mpvr;^*|c?v?NRuDMFA-|fVQ)AV5{K7`l4!-d}*nm>vRhG0DiD$&pi&KPc{)_4kMnkljAQ%JnV`YCKA%?% zH_0@3=#E}+Kx8(u4k^T5tI_STt=j!o(H`&Sod0e8fBHWFMSQqL-`7`v1O)#){MG9J z)hz;A#ovfPKh{@+e!5@OSASjr=oJ4g_0>OmMgN7;+TUUhe<-c}|F7NiWr;1uw==jX zz&2D0SD7g#KDO;%N~jR;vA42Jq}-$`;xc4fgE`>4r)N;Xs(_SZ%C~M3rbyA_w-xXW zv3@iK_`?eLa`>wi@GDaOSOK3%`NtLT(YF1^kkLnB5s-cVdse^?Nco?(06>L3N+%#+ z@~Y6_3OTq7lt?3sKuo`D38TusgT)GK1U+7vKtX0x3I{Jdooj<6L3M5 zB?t2UCLLg$U1zGkQ<3>ybROFA{=!6k^tWa5nZ*Mq!k>f~z8wB)nS9G10ujECW%8l( z_0=-@LWtqp1^%vO@pjVA1mMz~``_n!n4@1hnuho^Ub}HNH z#yf30r3NHW$4%aK($7@y5pYtA!OxTNvf8{mCo#Z4jl5>6*E{~$Ke65Ra;$2{g<~N2 zY|N%u6*;fq!p_E-MZriq8-uzXgq)u{2^8^oGFv~TySUOKn)m2%-oq9B!vTr=DNTlWjg=yYmqoI|dQY!Vu3R(q?nx>nJB}5pFZFmY}XEsas};-tJ$yJia(#qDs@(#Z|Nqh4QsL zqnQq1`K7qoaZvPntHfA$Jf1L5Nz+LA_KLn6(R^0KB|s3&b*$26*_s5bopBdo>mc^= zPGisQ$+p+#_pdS_Fm@B~y^)?^`_9nW~+Ha-a4iUQ-3p06sI3RKvNf|VAm24MiEyw}k8qluTPt#yvvyxuz zwWJ=jw!SHu<>P!-t++{VeRxDuy>d&pmd*3^*y>#B+}+9y2hYLlEjqxD zT#DPbPb{A9gnB9~9aC3pXKWiTn*wnHau8c%^1*JljDKkM$~g#r)Pd*iU6f63i?}!7 z_jG?8UZyRp;ICRX6_cKU63usges)1#1raHD2z!WU<=(jf!DRKS=Qj)plTuutar&W@MG_3EP3Zx;%>{QhI9?HAxL-*ISXDE}7K6ENtOr zw96n4eNZdYyYO~*yaRP6R72XOxe@TqCk@@e_inF!c>DPz4oazulA+ckjKv}OJ(1Tm zjAt90Jkhwr#Z_N?Om(-~uXRV8+}hK&l}$5qO)(&i zG6MHbySQy782-e$dQU$^voy!AwZ2&!pLQ=z?;2BQr_2S?ia;teyH4ohs`;{%1WUE9 z+)iusqPNJSv%H)^nw$VAaBjbP6#D3_Tpu^gwtjmw#zhcwaUW45yP{P-Pl4#UbXWq- zF=t$`*NHr6AM5!JU}*FTuhibJxg9)`f>hCNW zaTdt)iECoJfJsosJexPOP~{qv#?U_r8|ob&Hj9<8=$>wbGQB%z^bzLPbWO4E<=sq- zwMqKYuo)1VoYNQzL&a>T6IVbXCy&;|dKby3#t8C&hnE6u-a55$zB@Xq z<^D2%$|9Ab!uKjK$m?~v@&pR?%#%1Tl$OuzLtT%W!5pk?sD8RB1UAp-VQRu1v^gT? z@)K!u%IDTZiF{C3(Y%zJ4t6HaoN=VpRio;^vZ5?7y>7$wPv(fh@JqSG_u4g$AusZI^6^=ib_pmIho6FQ5#Zp`!ChCiUW0%mK9vqWb=YEPA%^0nHoKSqmb2#i;IQ3mZ@MY90Qcx7g9 zmMNcIF-6e*($P^Wze|(6v~Nv^Iv`OWgYN2ZO4Hd#O6XS0$7f)QL_5<#cyOMs#K#@f z3m!H;L`|!CSUlh%2KAabd8aOXMGy`4`pCUO9QR%ZwKcwcqo)R-09S!pU*wR>Qetk~ z0kF#?)`mNQ4hn17p5?Ow-ygYV9C<`)Dnk4C+yk8iQMoBcjB-Dxk&O=D>)OfxxI?Up z)AL<6%oUn|qbxLB3Wj;5Uq3&kOKQr!cxqcMdg+CEdrnqoa9YI2-Q_XKb;IoaWywQG zsi->I5HJlu3VE83gU0NG8C1^~I!w2MIj_tFnZ4$)aTC#*KJ7133J4B^mz5f6YyF!xCvfVSTEbl^`_4+6nR6@Fs~K}L30|O7c0qenouiHg0_kU-R|q6YXnVjO zH=0P*RtSOCi7An#=q)nh>7h+*H0`k$HkOZqFV08-Npv5_sRP*er*y&{vUC|vDsS)Z zm$lWnQ76K|s_&e7n>EF)s@q*F_7Q(Fvbc$v_Y=2S1F6b^M*Ed_alT3`IiSC2G0(+} zlY=Zfi^Ad2sPHn5`k*5axv7nOBN|o0dZjQp_fDeeq5YPcDvCLJ$K<0-3wP70(fhV& k`Jh7K*j{M;evGQ6Uyi&#bQskhTOcI;0R2UW(&(rE4VgPpYybcN From 8ebb646d43f81e46fe82d1e6c83a444d0c9c7880 Mon Sep 17 00:00:00 2001 From: Stefan Naumann Date: Sun, 30 Jul 2017 15:03:29 +0200 Subject: [PATCH 4/6] tested and fixed some code --- mmu/Makefile | 6 ------ mmu/README.md | 25 ++++++++++++++++++------- mmu/notmain.c | 31 ++++++++++++++----------------- mmu/novectors.s | 5 +++++ 4 files changed, 37 insertions(+), 30 deletions(-) diff --git a/mmu/Makefile b/mmu/Makefile index 537efe6..ce2dc2a 100644 --- a/mmu/Makefile +++ b/mmu/Makefile @@ -30,9 +30,3 @@ notmain.hex : memmap novectors.o periph.o notmain.o $(ARMGNU)-objdump -D notmain.elf > notmain.list $(ARMGNU)-objcopy notmain.elf -O ihex notmain.hex - - - - - - diff --git a/mmu/README.md b/mmu/README.md index 6eec5ad..789d97f 100644 --- a/mmu/README.md +++ b/mmu/README.md @@ -366,8 +366,8 @@ all of our sections can have the domain number 0. ```c /** * \brief creates an translation table entry (for sections of size 1 MiB) - * \param[in] vadd the virtual address (only top 12 bits used) - * \param[in] padd the physical address (only top 12 bits used) + * \param[in] virtual the virtual address (only top 12 bits used) + * \param[in] physical the physical address (only top 12 bits used) * \param[in] flags the flags for the section **/ uint32_t mmu_section ( uint32_t virtual, uint32_t physical, uint32_t flags ) @@ -845,17 +845,28 @@ See the [Instruction Fault Status Register]-manual for the list of status combin Running the code results in: ``` - 00045678 - 00000019 - 00000000 - 00008110 + 00045678 + 00000019 + 00000000 + 00008104 E5900000 - 00145678 ``` The first line is the one correct data-read we do in our code above. The next value is the data fault status register, which indicates that the domain 0x01 was accessed and aborted with an 0x09 fault, i.e. a Domain Section fault. +The third line is the value of the instruction fault status register, which +indicates a status of 0x0, i.e. "no function, reset value". That probably means +no fault happened. + +The fourth line is the link register, i.e. the address to the instruction which +would have been executed next, and the last line is the binary representation +of the instruction which caused the fault. Use a disassembler to view the +instruction in all its mnemonic glory: + +``` + 80fc: e5900000 ldr r0, [r0] +``` # Conclusion diff --git a/mmu/notmain.c b/mmu/notmain.c index 45aa3bf..46fd6c2 100644 --- a/mmu/notmain.c +++ b/mmu/notmain.c @@ -1,12 +1,11 @@ - -//------------------------------------------------------------------------- -//------------------------------------------------------------------------- +#include extern void PUT32 ( unsigned int, unsigned int ); extern void PUT16 ( unsigned int, unsigned int ); extern unsigned int GET32 ( unsigned int ); extern void mmu_init ( uint32_t ); +extern void mmu_domain ( uint32_t ); extern void stop_mmu ( void ); extern void invalidate_tlb ( void ); @@ -16,8 +15,6 @@ extern void uart_send ( unsigned int ); extern void hexstrings ( unsigned int ); extern void hexstring ( unsigned int ); -#include - #define MMUTABLEBASE 0x00004000 #define CACHEABLE 0x08 @@ -25,18 +22,18 @@ extern void hexstring ( unsigned int ); /** * \brief creates an translation table entry (for sections of size 1 MiB) - * \param[in] vadd the virtual address (only top 12 bits used) - * \param[in] padd the physical address (only top 12 bits used) + * \param[in] virtual the virtual address (only top 12 bits used) + * \param[in] physical the physical address (only top 12 bits used) * \param[in] flags the flags for the section **/ uint32_t mmu_section ( uint32_t virtual, uint32_t physical, uint32_t flags ) { uint32_t offset = virtual >> 20; // plus and or are the same thing here, as MMUTABLEBASE is 14 bit aligned - uint32_t* entry = MMUTABLEBASE | (offset<<2); + uint32_t* entry = (uint32_t*) (MMUTABLEBASE | (offset<<2)); // mask lower 20 bits of physical address then ORR flags and 0x02 for 1 MiB - physval = (physval & 0xfff00000) | (flags & 0x7ffa) | 0x02; + uint32_t physval = (physical & 0xfff00000) | (flags & 0x7ffa) | 0x02; *entry = physval; return(0); @@ -53,7 +50,7 @@ uint32_t mmu_page ( uint32_t virtual, uint32_t physical, uint32_t flags, uint32_ { uint32_t offset = virtual >> 20; // plus and or are the same thing here, as MMUTABLEBASE is 14 bit aligned - uint32_t* entry = MMUTABLEBASE | (offset<<2); + uint32_t* entry = (uint32_t*) (MMUTABLEBASE | (offset<<2)); // mask lower 20 bits of physical address then ORR flags and 0x01 for coarse translation uint32_t entryval = (secondbase & 0xfffffc00) | (flags & 0xf0) | 0x01; @@ -63,7 +60,7 @@ uint32_t mmu_page ( uint32_t virtual, uint32_t physical, uint32_t flags, uint32_ // mask everything except bits 19:12 offset = (virtual >> 12) & 0xff; // form the second level - uint32_t* secondLevelEntry = (secondbase & 0xfffffc00) | (offset << 2); + uint32_t* secondLevelEntry = (uint32_t*) ((secondbase & 0xfffffc00) | (offset << 2)); // form the value of the second level descriptor // bytes 31:12 are the page base address, flags contain B,C, AP_x = 0b11 @@ -136,11 +133,11 @@ int notmain ( void ) hexstring(GET32(0x00345678)); uart_send(0x0D); uart_send(0x0A); - mmu_small(0x0AA45000,0x00145000,0,0x00000400); - mmu_small(0x0BB45000,0x00245000,0,0x00000800); - mmu_small(0x0CC45000,0x00345000,0,0x00000C00); - mmu_small(0x0DD45000,0x00345000,0,0x00001000); - mmu_small(0x0DD46000,0x00146000,0,0x00001000); + mmu_page(0x0AA45000,0x00145000,0,0x00000400); + mmu_page(0x0BB45000,0x00245000,0,0x00000800); + mmu_page(0x0CC45000,0x00345000,0,0x00000C00); + mmu_page(0x0DD45000,0x00345000,0,0x00001000); + mmu_page(0x0DD46000,0x00146000,0,0x00001000); //put these back mmu_section(0x00100000,0x00100000,0x0000); mmu_section(0x00200000,0x00200000,0x0000); @@ -159,7 +156,7 @@ int notmain ( void ) uart_send(0x0D); uart_send(0x0A); //access violation. - + mmu_domain ( 0xffffff03 ); mmu_section(0x00100000,0x00100000,0x0020); invalidate_tlb(); diff --git a/mmu/novectors.s b/mmu/novectors.s index efc758f..a1e36fd 100644 --- a/mmu/novectors.s +++ b/mmu/novectors.s @@ -116,6 +116,11 @@ GET32: dummy: bx lr +.global mmu_domain +mmu_domain: + mcr p15, 0, r0, c3, c0, 0 + mov pc, lr + .global mmu_init mmu_init: mov r1,#0 From 917f8cc71426d23b27935124cc5b1571ab60a451 Mon Sep 17 00:00:00 2001 From: Stefan Naumann Date: Sun, 30 Jul 2017 15:06:07 +0200 Subject: [PATCH 5/6] changed armasm to c syntax highlighting --- mmu/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mmu/README.md b/mmu/README.md index 789d97f..f54b2b7 100644 --- a/mmu/README.md +++ b/mmu/README.md @@ -191,7 +191,7 @@ address is all zeroes (TLB=Translation Look-Aside Buffer)). We write that register using -```armasm +```c mcr p15,0,r0,c2,c0,0 ;@ tlb base ``` @@ -208,7 +208,7 @@ registers with the normal `mov` instruction. The co-processor has several registers, which can be accessed by the `mcr` or the `mrc` instruction. The parameters are: -```armasm +```c MCR{cond} P15,,,,, MRC{cond} P15,,,,, ``` @@ -465,7 +465,7 @@ What bits of these you want to set is up to you. I would recommend M, C and I, but I am going ahead and set them all. So simple example code implementing the the MMU-enabling process might be this: -```armasm +```c .global mmu_init mmu_init: mov r1,#0 @@ -497,7 +497,7 @@ to invalidate the TLB cache again, so let's put this part into its own function. We don't need to care about the L1 cache, this time. Also ARMv6 introduces a feature to help with invlidating the TLB, but I'm going with this solution: -```armasm +```c .globl tlb_invalidate tlb_invalidate: mov r2,#0 @@ -811,7 +811,7 @@ See the [Instruction Fault Status Register]-manual for the list of status combin ### Reading the status registers -```armasm +```c data_abort: // save the link-register mov r6,lr From dbfc5f6985f4e2e95da3dd8844bb84d1358816d1 Mon Sep 17 00:00:00 2001 From: Stefan Naumann Date: Mon, 31 Jul 2017 14:27:28 +0200 Subject: [PATCH 6/6] Fixed a rather nasty bug in the Readme (flags-bitmask) --- mmu/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmu/README.md b/mmu/README.md index f54b2b7..8b66fcd 100644 --- a/mmu/README.md +++ b/mmu/README.md @@ -377,7 +377,7 @@ all of our sections can have the domain number 0. uint32_t* entry = MMUTABLEBASE | (offset<<2); // mask lower 20 bits of physical address then ORR flags and 0x02 for 1 MiB - uint32_t physval = (physical & 0xfff00000) | (flags & 0x7ffa) | 0x02; + uint32_t physval = (physical & 0xfff00000) | (flags & 0x7ffc) | 0x02; *entry = physval; return(0);