The virtual memory is a memory management system that translate, on the fly, some "ideal" memory address to some real physical memory address.
It's well described on, for example, [wikipedia](https://en.wikipedia.org/wiki/Virtual_memory).
Here we choose to implement Virtual memory using pagination only. So we keep segmentation configured as a single `flat` model (c.f. `core/gdt.c`).
The paging is mainly implemented in `arch/ARCH/paging.c`.
## x86 and mirroring
We need a way to access and modify the record doing the translation `virtual memory -> physical memory` for the MMU.
On x86, this register is called the `PD` or Page Directory.
Once the paging is enabled on the CPU, we use a trick call `mirroring` to access and modify the PD and its content.
So now, we have a way to map a physical memory page to any given virtual page.
### PD implementation details
In a virtual addr(Vaddr), 10 first bit (MSB) are the index in the Page Directory.
A Page Directory Entry point to a Page Table. The 10 next bits are then an index in this Page Table. A Page Table entry then point to a physical address at which is added the remaining 12 bits.
So they are 1024 entry in the PD, each of them pointing to a PT of 1024 entry.
Each PTE pointing to 4K page.
First address (up to pageDesc from mem.c) are mapped such as Paddr == Vaddr. To make PD always accessible a (x86?) trick is used : The mirroring.
A given entry N in the PD point to the PD (this is possible because PDE very looks like PTE in x86). So N << (10 + 12 = 4Mo) point to the Paddr of PD.
Then, accessing N * 4Mo + I * 4Ko is accessing the PT of the Ieme entry in the PD (as MMU take the PD pointed by the PDE number N like a PT).
More particularly, accessing N * 4Mo + N * 4ko is accessing the PD.
*`allocArea` for large memory area of several PAGE_SIZE size
*`alloc` for object of any size
With each needing the other (`allocArea` need `alloc` to allocate `struct memArea` to keep track of the area and `alloc` need `allocArea` to allocate large memory size) we need to make sure that there is no forever loop.
### `AllocArea`
An area is represented by `struct memArea` and basically consist of a virtual memory address and a size if number of page.
This is a simple allocator keeping 2 linked list of used/free area.
Allocating a new area (thanks to `areaAlloc()`) consist of:
Freeing an area (thank to `areaFree()`) consist of trying to find adjacent free area and merge them with this one or just adding the area to the free one.
### `Alloc`
For large object allocation ( > PAGE_SIZE), this a basically a call to `areaAlloc()`.
For smaller object, this is a more complex allocator based on the concept of slab.
The allocator is configured at startup to maintain a collection of slabs, each of them configured for allocating object of a given size.
So a slab is described by `struct slabDesc` and contains a linked list of `struct slabEntry`.
Each of the `struct slabEntry` entry point to a memory area that is divided in chunk of the slab configured size.
It's a linked list so it is easy to add a new `struct slabEntry` when one is full.
Inside a `struct slabEntry` the `freeEl` attribute point to the next free chunk (of the slab configured size) in the allocated page(s). At this address is also a pointer to the next free area in this area.