Wiley.Symbian.OS.Internals.Real.time.Kernel.Programming.Dec.2005.eBook-DDU (779891), страница 56
Текст из файла (страница 56)
Instead they raise a CPU exceptionand expect that a software routine provided by the OS will look up thetranslation and set a TLB entry (if successful) before resuming the memoryaccess that caused the exception. Although EKA2 could support this typeof MMU, a reasonable implementation would require that the MMUprovides special support for the software walking routine.
For example,if the MMU reserved a region of the virtual address space to be directlymapped to physical memory without using the TLB, this would allowthe table walking algorithm to read the page directory and page tableswithout incurring additional ‘‘TLB miss’’ exceptions.7.2.1.2 Virtual address spacesEarlier, I said that there is only one page directory in the mapping. Thisis true at any given time as the MMU has only one TTBR register whichpoints to the base of the page directory. However, we can write to theTTBR and tell the MMU to use a different page directory when translatingvirtual addresses. This is one of the techniques that allows the samevirtual address to map onto different physical addresses at different times.Why would we want to do this?The format of the executable code in Symbian OS is the basis for one ofthe reasons – in particular the way in which code refers to data.
Symbianuses a relocated code format, in which the code has the actual (virtual)address of the data object. This is in contrast to relocatable code in whichdata references are all made relative to some external reference, usuallya reserved register. It is almost amusing to note that only relocated coderequires a set of relocation data in the executable file format so that theOS loader can correctly adjust all of the direct references within the code.Consider an application, TERCET.EXE for instance, that has a globalvariable, lasterror, used to record the last error encountered in the258MEMORY MODELSprogram. Once this program has been loaded, linked and relocated therewill be several memory blocks used for the program, and within them adirect reference from the program code to the address that the OS hasdecided to use for the lasterror variable (see Figure 7.4).00500000Static Variableslasterror00700000HeapF0000000CodeFigure 7.4Reference tolasterror ataddress 00500840Memory used to run TERCET.EXEThis seems fine, we have a memory block allocated at virtual address0xF0000000 for the program code, and another allocated at virtualaddress 0x00500000 for the program data, and in particular for thelasterror variable.
There will be others for the program execution stackand the dynamic memory pool, or heap; however, unlike lasterrorthese do not have direct references from the program code.Now suppose that the OS needs to run a second instance of TERCET.EXE at the same time as the first. One of the definitions of a processin the OS is an independent memory address space. So as a separateprocess, the second copy of TERCET.EXE must have its own thread andexecution stack, its own heap and its own copy of the global variables.One way to achieve this would be to make a second copy of theprogram code and relocate this for different code and data addresses tothe first instance (see Figure 7.5). Notice that this requires the code to beduplicated so that the second instance refers to a different location for thelasterror variable.
Symbian OS doesn’t do this for two reasons. Firstly,duplicating the code uses more RAM – which is already in short supply.Secondly, and more crucially, built-in software is usually executed inplace (XIP) from Flash memory and so it has already been relocatedfor just one code and data address. And worse – we have discarded therelocation data to save space in the Flash memory, so we cannot make acopy of the code and relocate it for a new address.MMUs AND CACHESFirst Instance0050000000700000259Second InstanceStatic VariablesStatic VariableslasterrorlasterrorHeap01500000Heap01700000CodeF1000000Reference tolasterror ataddress01500840F0000000CodeFigure 7.5Memory used to run TERCET.EXESo, in Symbian OS both instances of TERCET.EXE will share the samecode memory – but this also implies that the address for lasterror isthe same in both processes, 0x00500840 (see Figure 7.6).0050000000700000First InstanceSecond InstanceStatic VariablesStatic VariableslasterrorlasterrorHeapF0000000Reference tolasterror ataddress 00500840Heap00500000????????Shared CodeFigure 7.6 Running TERCET.EXE twice, sharing the codeWe still need the two instances of TERCET.EXE to have separatememory blocks for their variables, so that when an instance of the processis running it finds its own variable mapped to address 0x00500840.
Sowe need a way for the same virtual address to translate to two differentphysical addresses, depending on which process is currently running.The solution is for each process in the OS to have its own mappingfrom virtual to physical addresses, and this mapping is called the process260MEMORY MODELSmemory context. As I described in Chapter 3, Threads, Processes andLibraries, when we schedule a new thread to run, part of the work thathas to be done is to determine if the new thread runs in the same processas the old one.
When this is not the case, the memory context has to bechanged to ensure that the correct mapping is used for virtual addressesin the new thread and process.How this is achieved in Symbian OS depends on the type of MMU,and I describe this later in the chapter when I look at the differentmemory models.7.2.1.3 Memory protectionOne of the issues that an open OS must address is how to protect theoperating system from software which is flawed or even malicious. If allsoftware has direct access to the device memory, then it is not possibleto limit the adverse effects that new software might have on a device.We have already seen that the MMU provides an indirect mappingfrom the virtual address used by the software and the physical address ofthe memory provided by the OS.
For each of the pages mapped by theMMU, we can supply attributes that describe an access policy for thatmemory. When used correctly and consistently by an OS this is a verypowerful feature:• We can protect the kernel data from direct and indirect attacks fromuser-mode programs• We can protect the hardware that uses memory mapped I/O frombeing accessed directly by user-mode programs• We can allow a process to read and write its own memory, but denyit access to that of any other process• We can ensure that loaded software cannot be modified after loadingby marking it as read-only• When this is supported by the MMU, we can ensure that general heapand stack memory cannot be executed as program code, defendingagainst many buffer over-run type attacks• We can provide memory that can be shared by just some of therunning processes.Figure 7.7 illustrates these concepts by showing which memory shouldbe made accessible to a thread when running in user or supervisor modes.The memory used by the kernel and two user programs, A and B, is shownwhere A and B share some code and some data.
The left-hand imagesshow memory accessible to a thread in program A in both user andkernel mode – note that the kernel memory is inaccessible to user-modesoftware. The top right image shows that program B cannot accessMMUs AND CACHESKernel StacksKernel HeapKernel dataI/O memoryROMcode261Kernel StacksKernel HeapKernel dataI/O memoryROMcodeProgram AstacksCommonbufferProgram BstacksProgram AstacksCommonbufferProgram BstacksProgram AheapProgram AbufferProgram BheapProgram AheapProgram AbufferProgram BheapProgram AcodeShared codeProgram BcodeProgram AcodeShared codeProgram BcodeProgram A thread in user modeKernel StacksKernel HeapKernel dataI/O memoryProgram B thread in user modeROMcodeKernel StacksKernel HeapKernel dataI/O memoryROMcodeProgram AstacksCommonbufferProgram BstacksProgram AstacksCommonbufferProgram BstacksProgram AheapProgram AbufferProgram BheapProgram AheapProgram AbufferProgram BheapProgram AcodeShared codeProgram BcodeProgram AcodeShared codeProgram BcodeProgram A thread in kernel modeProgram C thread in user modeFigure 7.7 Memory accessible to a thread in user and kernel modesmemory used by program A except for memory that has been sharedbetween these programs.
The final image with program C, whose ownmemory is not shown, shows that this program has no access to any of thememory used by programs A and B. This demonstrates the ideal situation,and, as I will describe later, the different memory models sometimesprovide less restricted access than is shown here for certain situations. Ofcourse, any such relaxation is made very carefully to preserve the valueof providing the memory protection in the first place.7.2.1.4 Page faultsThe MMU allows us to map all of a device’s RAM, 16 MB say, intoa much larger 4 GB virtual address space. Clearly many of the virtualaddresses cannot map onto physical memory.
What happens if we try toaccess one of these?262MEMORY MODELSWhen walking through the page tables to translate an address, theMMU may find an entry that is marked as empty, or not present (in thepage directory or a page table). When this occurs, the MMU raises a CPUprefetch or data abort exception, depending on whether the memoryaccess was trying to read code or data.Something very similar will occur if the MMU detects that the CPU isnot permitted to access the page because it does not currently satisfy theaccess policy for the page.In EKA2, this will usually result in a user-side thread terminating withKERN-EXEC 3 (unhandled exception) or the OS rebooting in the case ofa kernel thread. I covered this in more detail in Chapter 6, Interrupts andExceptions.Operating systems designed for personal computers all use page faultsand the MMU mapping to achieve another goal: demand paging.
This isa scheme in which the operating system can effectively pretend that ithas more physical memory than is really available. It does this by savingto disk memory pages that have not been used recently, and allowinganother program to use the physical memory (for now).