High Memory Mapping
From The Linux Memory Wiki
We have learned that the linear address space is normally have 1GB/3GB split between kernel address space and process address space. The first 896MB memory is mapped directly to the physical address and any physical address higher than that are called high memory.
When the kernel allocate contiguous physical memory through functions such as __get_free_pages(), it can specify through the flags to obtain memory resides in high memory zone. The memory cannot be directly used after allocation because it doesn't have any linear address to refer to. The kernel thus has to do high memory mapping onto the page descriptor that was returned by __get_free_pages().
kmap()
void * kmap(struct page *page)
The kmap() function search for a suitable high memory linear address for the specified page descriptor and returns the linear address of the mapping. If the page descriptor contains a page that is not in high memory zone, the linear address of that page is returned directly without mapping. kmap() will block if no mapping is available.
kmap() is also refered to as permanent mapping, because the mapping remains there until we call kunmap() to release the mapping. This could be dangerous as we know that only 128MB of linear address is available for mapping, we will run out of memory if all address is used and not released. Hence it is important to release the mapping using kunmap() as soon as possible.
kmap_atomic()
void * kmap_atomic(struct page * page, enum km_type type)
The kmap_atomic() function does the same thing as kmap, but it does not block. This is typically used in interrupt handlers where kernel preemption is disabled.
kmap_atomic is also refered to as temporaly mapping, because the mapping will be released automatically on next call of kmap_atomic(). Hence it is optional to call the kunmap_atomic function. Hence we should also note that because of this the mapping shouldn't be reused after the deferrable function because the mapping may be used by other already.
Address Space Splitting
Conventional Linux has 1GB/3GB split between kernel and process address space. As the amount of physical memory increases beyond 1GB, kernel developers find the kernel being insufficient to manage all physical memory in just 1GB kernel address space. Hence there were some other splitting scheme like 2GB/2GB and 3GB/1GB been made to allow the kernel to have more memory resides in normal zone than high memory. This, of course have some down side. For instance, in 2GB/2GB split this means that processes may not have more than 2GB of memory, which is even more insufficient for applications such as database. However this scheme may works well for other types of applications which don't need so much memory.
A 4GB/4GB split patch was introduced in 2003 by kernel developer Ingo Molnar to resolve the high memory problem. The system works by completely switch from all the page tables in process address space to the kernel's own page tables. By doing this the kernel is able to map all 4GB memory directly because it has different set of page tables than the process.
This patch however is not so popular. The catch is that the TLB has to be flushed everytime a process switch into kernel mode, because the page tables has changed. And because a process would make system calls frequently, the flush may in fact become very inefficient. Note that in normal 1GB/3GB split no TLB flush is needed because the page tables remain the same when process switch to kernel mode, thats also why the kernel cannot use the other 3GB address space. So even though we may use more memory in this patch, we traded it with performance speed.
More information about the 4GB/4GB split can be found at the original article http://lwn.net/Articles/39283/.
