2

I have gone through Robert Love's Linux Kernel Development, and other sources. And everywhere it mentions that on a 32 bit x86 system the kernel owns the top 1 GB of the virtual address space, out of that upto 896 MB is mapped contiguously onto physical memory (called ZONE_NORMAL) the rest is mapped into the remaining 128 MB space as required, and may not be contiguous (ZONE_HIGHMEM).

On 64 bit, the problem of not having enough virtual address space is eliminated. And the memory map is described as,

0xffffffffffffffff  +-----------+
                    |           |
                    |           | Kernelspace
                    |           |
0xffff800000000000  +-----------+
                    |           |
                    |           |
                    |   hole    |
                    |           |
                    |           |
0x00007fffffffffff  +-----------+
                    |           |
                    |           |  Userspace
                    |           |
0x0000000000000000  +———————————+

However, it is not clear, in this map how much of the kernelspace is required to be physically contiguous (as defined in ZONE_NORMAL). and how much is mapped as required.

Is the ZONE_HIGHMEM in 64 bit kernel always 0? Since all memory is quite within range of the virtual address space?

But the kernel's fixed contiguous memory (which is un-pageable) would also require to be small, since that chunk of physical memory would never be available to other user processes. So the kernel would require to use memory which need not be contiguous (like ZONE_HIGHMEM), as required. This conflicts with the ZONE_HIGHMEM being empty on 64-bit kernels.

So I am confused about how much of the kernelspace is fixed physically contiguous and how much is non-contiguous in case of 64 bit kernels.

4
  • Why would the chunk of memory never be available to user space processes? A physical page can have many mappings, the mapping is just a view from the virtual address space to physical memory. Not even the 32-bit kernel had ZONE_HIGHMEM from the start. It was introduced as a necessity when physical memory outgrew the virtual address space. The 1 GB area was not a problem when PCs had 256 MB of RAM. – Johan Myréen Aug 21 '20 at 14:12
  • I assumed it will never be available because 1. kernel memory is un-pageable, so if used, it will not be swapped out 2. It maps directly to a contiguous chunk of physical memory 3. kernel needs to keep some space available to satisfy the kmalloc requirements, which needs to be from this contiguous memory. it figures that since kernel will not be able to increase the contiguous memory region on demand, if a user process is mapping to the same memory, then if a kernel needs to use it, it will have to move them to swap when kernel needs it. – saketrp Aug 31 '20 at 10:19
  • but doing that is seems possible, so maybe my assumption was not correct. – saketrp Aug 31 '20 at 11:36
  • We have to distinguish between the memory the kernel is using internally and the pages it hands out to user space processes. The former includes the kernel's code and data structures, kmalloced memory, etc. This is typically only a small part of the total RAM. At startup, the kernel maps the whole physical RAM for its internal use, for example to be able to zero pages. (Memory can only be accessed through virtual addresses.) It is the kernel that implements the un-pageability of kernel memory, that's just how the kernel is implemented. – Johan Myréen Aug 31 '20 at 13:14
2

There’s no HIGHMEM on 64-bit x86 — CONFIG_HIGHMEM depends on X86_32.

There are two fixed mappings of physical memory on 64-bit x86:

ffff888000000000 | -119.5  TB | ffffc87fffffffff |   64 TB | direct mapping of all physical memory (page_offset_base)

and the area starting at

ffffffff80000000 |   -2    GB | ffffffff9fffffff |  512 MB | kernel text mapping, mapped to physical address 0

(negative addresses are offsets from the end of the address space).

The latter corresponds to what you’re thinking of, as far as I can tell, and tends to be small; see the “Memory” line shown during boot:

Memory: 20144992K/20660008K available (14339K kernel code, 2406K rwdata, 8340K rodata, 2488K init, 5116K bss, 515016K reserved, 0K cma-reserved)

(just under 30MiB) and any memory locked by modules loaded later on.

4
  • ok, so the kmalloc allocations (expected to be physically contiguous) happen directly by the allocator finding that much free contiguous space anywhere in the physical memory and returning the direct mapped address (in ffff888000000000 mapping) in the kernel space? – saketrp Aug 21 '20 at 12:05
  • Individual kmalloc allocations are physically contiguous, but successive allocations aren’t necessarily (especially with KASAN). As far as I’m aware, the returned address is a virtual address towards the end of the address space, normally not in the ffff888... mapping; the latter isn’t used for kernel allocations. Bear in mind that kmalloc is really intended for allocations smaller than a page, so finding appropriate memory isn’t difficult in most cases. – Stephen Kitt Aug 21 '20 at 12:19
  • The addresses that I've observed for objects allocated via kmem_cache_alloc do seem to be from ffff888... mapping, including even task_struct pointers. Wouldn't that mean it is used for kernel allocations? – saketrp Aug 21 '20 at 12:50
  • Ah, right, I stand corrected! So yes then, it does mean it is used for kernel allocations. (/me goes off to read the slab allocator code again...) – Stephen Kitt Aug 21 '20 at 12:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.