Page 1 of 1
kernel memory mapping
Posted: Tue Nov 10, 2015 1:58 pm
by Techel
So the address space of an user process consists of one half for the user's memory and one half for the kernel. For simple reasons the kernel's half is not mapped entirely, but what to do when the kernel needs to map some memory for eg. drivers, his heap etc? Should it iterate through all address spaces and update the kernel's half accordingly? How do you handle this?
Re: kernel memory mapping
Posted: Tue Nov 10, 2015 2:37 pm
by BASICFreak
I handle this by allocating all the Page Tables that the Kernel can use.
Usually empty Page Tables, but a way non the less to setup all the kernel space without actually mapping any of it.
Which allows me to modify every Page Directory at once, instead of having to update every process's PageDIR when the Kernel requires more data.
Without PAE and PSE, and assuming you are using 2GB virtual (way too much in my opinion) you only have to allocate 2MB of space for the whole structure.
Re: kernel memory mapping
Posted: Wed Nov 11, 2015 12:35 am
by Techel
That was my first idea, but then I have to allocate 2MB, which is not that little.
Re: kernel memory mapping
Posted: Wed Nov 11, 2015 12:39 am
by BASICFreak
Well don't use 2GB for the kernel, I only use 512MB
(>=E0000000) - which is much more manageable, IMO. Then you only have to allocate 1/2 MB.
Re: kernel memory mapping
Posted: Wed Nov 11, 2015 1:45 am
by Brendan
Hi,
Roflo wrote:So the address space of an user process consists of one half for the user's memory and one half for the kernel. For simple reasons the kernel's half is not mapped entirely, but what to do when the kernel needs to map some memory for eg. drivers, his heap etc? Should it iterate through all address spaces and update the kernel's half accordingly? How do you handle this?
First, understand that:
- If a page table is used by all virtual address spaces, you can add/remove/modify page table entries and the changes will automatically happen in all virtual address spaces.
- For PAE and long mode; if a page directory is used by all virtual address spaces, you can add/remove/modify page directory entries and the changes will automatically happen in all virtual address spaces.
- For long mode; if a page directory pointer table is used by all virtual address spaces, you can add/remove/modify PDPT entries and the changes will automatically happen in all virtual address spaces.
With this in mind, you can pre-allocate and don't have to worry about changing all virtual address spaces. For example, if your kernel space is 1 GiB and you're using PAE, then all virtual address spaces can use a single "pre-allocated" page directory for kernel space, and any changes you make to that page directory's entries will automatically happen in all virtual address spaces, and so will any changes you make to kernel's page table entries.
This means that (e.g.) if you are using PAE then it makes sense to sure kernel space is a multiple of 1 GiB so that you can efficiently pre-allocate page directories for kernel space and don't need to worry. In a similar way, if you're using long mode you might consider making kernel space a (relatively small) multiple of 512 GiB so you can pre-allocate Page Directory Pointer Tables.
However; sometimes pre-allocating isn't very nice. For example, if your kernel space is 1 GiB and you're using "plain 32-bit paging" you'd have to pre-allocate 256 page tables and it's going to cost you 1 MiB of RAM (which is a lot on old computers that don't support PAE and might only have 8 MiB of RAM to start with).
To avoid pre-allocating you have update something in all virtual address spaces. There are 2 main ways of doing this:
- Map whatever needs to be changed into kernel space so it can be accessed. For example (the same "plain 32-bit paging with 1 GiB of kernel space" example) you could map the page directory for every virtual address space as a normal page into kernel space, so that when you add/remove page tables for kernel space you can modify the page directory entry for all page directories (for all virtual address spaces).
- Don't update the other virtual address space until just before after you switch from one virtual address space to another. For example (the same "plain 32-bit paging with 1 GiB of kernel space" example) you could have a master list of 256 page directory entries in normal RAM (in a safe part of kernel space), and whenever you switch to a new virtual address space you can copy the data from that master list into the virtual address space's page directory before it's used.
Also note that for the second method you can get a little fancy. For example, you can have a "master list version number" and give each virtual address space a "version number when kernel space was last updated"; so that (when switching between virtual address spaces) you know if the virtual address space needs to be updated from the master list and can avoid updating it if/when nothing changed.
Note 1: For all of the above I've assumed that you're able to access all paging structures for the current virtual address space (e.g. using the recursive mapping trick).
Note 2: For all of the above I've ignored TLB invalidation. That's a different/complicated problem all on its own!
Cheers,
Brendan
Re: kernel memory mapping
Posted: Wed Nov 11, 2015 2:15 am
by Techel
I came up with an idea similar to your last point: Having one Pagedirectory with the lower half as kernel and when switching the upper half of the new pd gets copied to this one pd (plus cache flush).