5 Answers
5

On a 32-bit architecture, the address space range for addressing RAM is:

0x00000000 - 0xffffffff

or 4'294'967'295 (4 GB).

The linux kernel splits that up 3/1 (could also be 2/2, or 1/3 1) into user space (high memory) and kernel space (low memory) respectively.

The user space range:

0x00000000 - 0xbfffffff

Every newly spawned user process gets an address (range) inside this area. User processes are generally untrusted and therefore are forbidden to access the kernel space. Further, they are considered non-urgent, as a general rule, the kernel tries to defer the allocation of memory to those processes.

The kernel space range:

0xc0000000 - 0xffffffff

A kernel processes gets its address (range) here. The kernel can directly access this 1 GB of addresses (well, not the full 1 GB, there are 128 MB reserved for high memory access).

Every kernel process can also access the user space range if it wishes to. And to achieve this, the kernel maps an address from the user space (the high memory) to its kernel space (the low memory), the 128 MB mentioned above are especially reserved for this.

1 Whether the split is 3/1, 2/2, or 1/3 is controlled by the CONFIG_VMSPLIT_... option; you can probably check under /boot/config* to see which option was selected for your kernel.

This is old and I'm not sure you're around here. But I want to ask one thing: the reserved 128MB in kernel space (for high memory access), is it all the references of user-space memory area? So, a kernel process can access any user space by refer to this area, right?
–
AmumuJul 2 '12 at 4:37

Why is it always in 1/4's? I.e. why couldn't it split it 5/1 or something?
–
mgalgsAug 29 '12 at 23:48

I believe that what you say about high/low memory is wrong: I believe that in a pure 32bit system, the kernel can access the full 3GB of user space directly (kernel can access kernel space and user space). However when you have a PAE kernel things get more complex, now you have more than 3GB of RAM, each process can be 3GB, and you can not access the whole of user space directly. This is where high mem and that 128MB of memory in kernel space, comes in. With a 64bit kernel it gets simpler again, no high men, as all user space is accessible from the kernel.
–
richardDec 2 '14 at 22:00

This is relevant to the Linux kernel; I'm not sure how any Unix kernel handles this.

The High Memory is the segment of memory that user-space programs can address. It cannot touch Low Memory.

Low Memory is the segment of memory that the Linux kernel can address directly. If the kernel must access High Memory, it has to map it into its own address space first.

There was a patch introduced recently that lets you control where the segment is. The tradeoff is that you can take addressable memory away from user space so that the kernel can have more memory that it does not have to map before using.

The first reference to turn to is Linux Device Drivers (available both online and in book form), particularly chapter 15 which has a section on the topic.

In an ideal world, every system component would be able to map all the memory it ever needs to access. And this is the case for processes on Linux and most operating systems: a 32-bit process can only access a little less than 2^32 bytes of virtual memory (in fact about 3GB on a typical Linux 32-bit architecture). It gets difficult for the kernel, which needs to be able to map the full memory of the process whose system call it's executing, plus the whole physical memory, plus any other memory-mapped hardware device.

So when a 32-bit kernel needs to map more than 4GB of memory, it must be compiled with high memory support. High memory is memory which is not permanently mapped in the kernel's address space. (Low memory is the opposite: it is always mapped, so you can access it in the kernel simply by dereferencing a pointer.)

When you access high memory from kernel code, you need to call kmap first, to obtain a pointer from a page data structure (struct page). Calling kmap works whether the page is in high or low memory. There is also kmap_atomic which has added constraints but is more efficient on multiprocessor machines because it uses finer-grained locking. The pointer obtained through kmap is a resource: it uses up address space. Once you've finished with it, you must call kunmap (or kunmap_atomic) to free that resource; then the pointer is no longer valid, and the contents of the page can't be accessed until you call kmap again.

HIGHMEM is a range of kernel's memory space, but it is NOT memory you access but it's a place where you put what you want to access.

A typical 32bit Linux virtual memory map is like:

0x00000000-0xbfffffff: user process (3GB)

0xc0000000-0xffffffff: kernel space (1GB)

(CPU-specific vector and whatsoever are ignored here).

Linux splits the 1GB kernel space into 2 pieces, LOWMEM and HIGHMEM. The split varies from installation to installation.

If an installation chooses, say, 512MB-512MB for LOW and HIGH mems, the 512MB LOWMEM (0xc0000000-0xdfffffff) is statically mapped at the kernel boot time; usually the first so many bytes of the physical memory is used for this so that virtual and physical addresses in this range have a constant offset of, say, 0xc0000000.

On the other hand, the latter 512MB (HIGHMEM) has no static mapping (although you could leave pages semi-permanently mapped there, but you must do so explicitly in your driver code). Instead, pages are temporarily mapped and unmapped here so that virtual and physical addresses in this range have no consistent mapping. Typical uses of HIGHMEM include single-time data buffers.