kernel-memory
page - fixed length (PAGE_SIZE) block of virtual memory.
page frame - fixed-length block of physical memory (RAM)
page table - mappings between virtual addresses and physical addresses
---------------------------------------------------------------------------------
128 MB of the kernel address space is used to map a high memory of RAM on the fly when needed. Mapping to access high memory is created on the fly by the kernel and destroyed when
done. This makes high memory access slower. However, the concept of high memory does not exist on 64-bit systems, due to the huge address range (264 TB), where the 3 GB/1 GB
(or any similar split scheme) split does not make sense anymore.
On the other hand, 896 MB of kernel address space is permanently and linearly mapped to a low 896 MB of RAM. Addresses that result from that mapping are called logical addresses. These are virtual addresses but
can be translated into physical addresses by subtracting a fixed offset. the first 16 MB of LOWMEM is reserved for Direct Memory Access (DMA) usage.
The physical memory is also divided into ZONES
ZONE_DMA — From 0MB to 16MB
ZONE_NROMAL — From 16MB — 896 MB
ZONE_HIGHMEM — From 897MB to remaining physical memory.
The top 128 MB of the kernel address space is called a high-memory region. It is used by
the kernel to temporarily map physical memory above 1 GB (above 896 MB in reality).
When physical memory above 1 GB (or, more precisely, 896MB) needs to be accessed, the
kernel uses that 128 MB to create a temporary mapping to its virtual address space, thus
achieving the goal of being able to access all physical pages. You can define high memory
as being memory for which logical addresses do not exist and which is not mapped
permanently into a kernel address space. The physical memory above 896 MB is mapped
on demand to the 128 MB of the HIGHMEM region.
Mapping to access high memory is created on the fly by the kernel and destroyed when
done. This makes high memory access slower. However, the concept of high memory does
not exist on 64-bit systems, due to the huge address range (264 TB), where the 3 GB/1 GB
(or any similar split scheme) split does not make sense anymore.
memory returned by vmalloc() always comes from the HIGH_MEM zone. It returns memory
that is exclusively contiguous in the virtual address space, but not physically contiguous.
It is important to note that vmalloc() is slower than kmalloc() and page
allocator functions because it must both retrieve the memory and build the page tables, or
even remap into a virtually contiguous range, whereas kmalloc() never does that.
#include <linux/vmalloc.h>
void *vmalloc(unsigned long size);
---------------------------------------------------------------------------------
Process address:
each process in linux is a task struct which have its section mappings in mm_struct and task vma mappings in vm_area_struct.
struct task_struct {
struct mm_struct *mm, *active_mm; ===> struct vm_area_struct *mmap ===> unsigned long vm_start;
unsigned long vm_end;
struct vm_area_struct *vm_next, *vm_prev;
struct mm_struct *vm_mm;
pgprot_t vm_page_prot;
unsigned long vm_flags;
unsigned long vm_pgoff;
struct file * vm_file;
unsigned long start_code, end_code, start_data, end_data;
unsigned long start_brk, brk, start_stack;
unsigned long arg_start, arg_end, env_start, env_end;
};
---------------------------------------------------------------------------------
MMU
MMU does not only convert virtual addresses into physical ones but also protects memory from unauthorized access.
Given a process, any page that needs to be accessed from this process must exist in one of its VMAs and, thus, must live in the process's page table (every process has its own).
It is important to know that the MMU does not store any mapping. It is a data structure located in RAM. Instead, there is a special register in the CPU, called the Page Table Base
Register (PTBR) or the Translation Table Base Register 0 (TTBR0), which points to the base (entry 0) of the level-1 (top-level) page table (PGD) of the process. It is exactly where
the pdg field of struct mm_struct points: current->mm.pgd == TTBR0.
At context switch (when a new process is scheduled and given the CPU), the kernel immediately configures the MMU and updates the PTBR with the new process's pgd.
Now, when a virtual address is given to MMU, it uses the PTBR's content to locate the process's level-1 page table (PGD), and then it uses the level-1 index, extracted from the
Most-Significant Bits (MSBs) of the virtual address to find the appropriate table entry, which contains a pointer to the base address of the appropriate level-2 page table. Then,
from that base address, it uses the level-2 index to find the appropriate entry and so on, until it reaches the PTE. ARM architecture (i.MX6, in our case) has a two-level page table.
In this case, the level-2 entry is a PTE and points to the physical page (PFN). Only the physical page is found at this step. To access the exact memory location in the page, the
MMU extracts the memory offset, also part of the virtual address, and points to the same offset in the physical page
TLB
Before the MMU proceeds to address translation, there is another step involved. As there is a cache for recently accessed data, there is also a cache for recently translated
addresses.
On memory access, the CPU walks through the TLB trying to find the virtual page number of the page that is being accessed. This step is called a TLB lookup. When a TLB
entry is found (a match occurs), it is called TLB hit, and the CPU just keeps running and uses the PFN found in the TLB entry to calculate the target physical address. There is no
page fault when a TLB hit occurs. If a translation can be found in the TLB, virtual memory access will be as fast as physical access. If there is no TLB hit, it is called TLB miss.
On a TLB miss, there are two possibilities. Depending on the processor type, the TLB miss event can be handled by the software, the hardware, or through the MMU:
• Software handling: The CPU raises a TLB miss interrupt, caught by the OS. The OS then walks through the process's page table to find the right PTE. If there is a
matching and valid entry, then the CPU installs the new translation in the TLB. Otherwise, the page fault handler is executed.
----------------------------------------------------------------------------------------------------
Stage 2 translation
https://developer.arm.com/documentation/102142/0100/Stage-2-translation
Interrupt forwarding
https://developer.arm.com/documentation/102142/0100/Virtualizing-exceptions
non-cached memory
https://stackoverflow.com/questions/90204/why-would-a-region-of-memory-be-marked-non-cached
This is done so that the processor does not use stale values due to caching. When you access (regular) cached RAM, the processor can "remember" the value that you accessed.
The next time you look at that same memory location, the processor will return the value it remembers without looking in RAM. This is caching.
If the content of the location can change without the processor knowing as could be the case if you have a memory-mapped device
(an FPGA returning some data packets for example), the processor could return the value "remembered" from last time, which would be wrong.
To avoid this problem, you mark that address space as non-cacheable. This ensures the processor does not try to remember the value.
Comments
Post a Comment