For embedded system, memory management varies from system to system, as you have your custom address space and custom peripheral devices and memory chips. Sometime, the porting of kernel may fail if the memory management is not carefully handled.
Years ago, uclinux was well-known as a linux operating system without MMU, which is more suitable for embedded systems back at that time. As FPGA has become more and more powerful, embedded OS can support MMU now. And for Linux running on Xilinx FPGA with microblaze or PPC, the MMU is required, as said in the documentation.
In this blog series, I am going to tell the story about memory management of Linux OS line by line. The story begins by introducing the MMU of microblaze.
MMU of Microblaze on Xilinx FPGA\
Memory Management Unit (MMU) is a piece of hardware, which bonded closely with CPU (microblaze/PPC here) to provide memory management functionality for softwares, especially operating systems.
MMU can function in two modes:
1. Real Mode: effective address are used to access physical memory directly.
2. Virtual Mode: effective address are translated into physical address to access physical memory by the virtual-memory management hardware in microblaze.
The mode is controlled by the 18th bit (VM) of rmsr (Machine Status Register), as shown in fig. 1.
fig. 1 Machine Status Register
At the very beginning, the MMU runs in real mode, as the reset value of VM is 0. After OS properly set the first several entry in TLB (Translation Look-aside Buffer), the MMU will switch into Virtual Mode.
In virtual mode, whenever an address is requested, it goes through the following procedure:
To understand this procedure, we need to know so-called Translation Look-aside Buffer (TLB). TLB can be viewed as a cache for address translation. The translation between virtual address and physical address in virtual mode is done via a kind of mechanism called 2-level page table translation. In microblaze, the translation goes as follows:
There are certain addresses that are frequently accessed, the translation is stored in TLB, the same we do for data cache. If the requested data is not found in TLB, a TLB miss (similar as cache miss) is generated, followed by the page table translation and TLB update operation.
There are four registers used for accessing TLB from software: TLBLO, TLBHI, TLBX, and TLBSX.
TLBLO: Translation Look-Aside Buffer Low Register
TLBHI: Translation Look-Aside Buffer High Register
TLBX: Translation Look-Aside Buffer Index Register
TLBSX: Translation Look-Aside Buffer Search Index Register
All these registers are accessed via MFS and MTS instructions.
Access TLB Entries
First of all, we need to know the TLB entry structure. A TLB entry can be accessed via TLBLO and TLBHI registers, with an index set at TLBX.
RPN (Real Page Number or Physical Page Number) is used to form physical address. Depending on the value of page size, certain bits of RPN are not used in physical address.
TAG (TLB-entry tag) is compared with the virtual memory address under control of SIZE.
SIZE (page Size) specifies page size.
There are 64 entries in the unified TLB in microblaze MMU architecture. So the INDEX field (bit 26 to 31, as shown below) of TLBX register is used as index of MMU entries. The field is also updated when TLBSX register is written with a virtual address and the virtual address is found in TLB entries.
Software can read and write unified TLB entries by using the TLBX register index (numbered 0 to 63) corresponding to one of the 64 entries in the TLB. The tag and data portions are read and written separately, so software must execute two MFS or MTS instructions to completely access an entry. The TLB is searched for a specific translation using the TLBSX register. TLBSX locates a translation using an effective address and loads the corresponding UTLB index into the TLBX register.
All the above are the story about MMU architecture of microblaze. You may refer to xilinx document: MicroBlaze Processor Reference Guide for more detail explanation on microblaze and its instructions. The figures and information in this blog comes from the document directly. Linux kernel set up memory page mapping in arch/microblaze/head.S. I am going to talk about the codes in head.S in next blog in this series.