4

I am familiar that the Linux kernel memory is usually 1:1 mapped (up to a certain limit of the zone). From what I understood is that to make this 1:1 mapping more efficient the array of struct page is virtually mapped.

I wanted to check if that is the case. Is there a way to test if - given an address (lets say that of a struct page) check if it is 1:1 mapped or virtually mapped?

wxz
  • 2,254
  • 1
  • 10
  • 31
anon
  • 188
  • 1
  • 13
  • 1
    Curious to know if there's a function specifically to test for this. But I suppose a roundabout way is to check how struct page was allocated. Depending how it's allocated should tell you if the address is logical or virtual. See [here](https://stackoverflow.com/a/5748589/13020139) and the comments [here](https://stackoverflow.com/questions/34516301/linux-kernel-virtual-to-physical-address-translation) – wxz Aug 26 '21 at 19:38
  • @wxz Thank you. After going thorough the links I have another slightly unrelated but crucial question to understand the core concepts. Can a virtual page (through page table) swap out a logical kernel page (the 1:1 mapped ones). Seems like it's possible because the same page frame can be used for another page. But then does the kernel know it will need to bring the 1:1 mapped page back when accessed by the kernel? Maybe the kernel makes all those 1:1 mapped pages unswappable? – anon Aug 28 '21 at 04:38
  • Can you include the source(s) of where you've seen this statement about "1:1 mapping" show up? I think I may have misunderstood your initial question, but if you show me where you've seen this statement before, I might have an answer to help. – wxz Aug 29 '21 at 04:06
  • Did you get an answer to this? Could you include the source for where you've seen 1:1 mapping? – wxz Sep 20 '21 at 16:25
  • @wxz still haven't found an answer to this but I think enumerating all struct page will show if the page logically mapped (1:1) or virtually. I don't have a source, I was just asking if the kernel can swap out logically mapped pages when running low on memory. – anon Sep 20 '21 at 16:33

1 Answers1

0

The notion of address space for a 64-bit machine emcompasses 2^64 addresses. This is far larger than any modern amount of physical memory in one machine. Therefore, it is possible to have the entire physical memory mapped into the address space with plenty of room to spare. As discussed in this post and shown here, Linux leaves 64 TB of the address space for the physical mapping. Therefore, if the kernel needed to iterate through all bytes in physical memory, it could just iterate through addresses 0+offset to total_bytes_of_RAM + offset, where offset is the address where the direct mapping starts (ffff888000000000 in the 64 bit memory layout linked above). Also, this direct mapping region is within the kernel address range that is "shared between all processes" so addresses in this range should always be logical.

Your post has two questions: one is how to test if an address is logical or virtual. As I mentioned, the answer is if the address falls within the direct mapping range, then it is logical. Otherwise it is virtual. If it is a virtual address, then obtaining the physical address through the page tables should allow you to access the address logically by following the physical_addr + offset math as mentioned above.

Additionally, kmalloc allocates/reserves memory directly using this logical mapping, so you immediately know that if the address you're using came from kmalloc, it is a logical address. However, vmalloc and any user-space memory allocations use virtual addresses that must be translated to get the logical equivalent.

Your second question is whether "logically mapped pages" can be swapped out. The question should be rephrased because technically all pages that are in RAM are logically mapped in that direct mapping region. And yes certain pages in main memory can be swapped out or kicked out to be used by another page in the same page frame. Now, if you're asking whether pages that are only mapped logically and not virtually (like with kmalloc, which gets memory from slab) can be swapped out, I think the answer is that they can be reclaimed if not being used, but aren't generally swapped out. Kernel pages are generally not swapped out, except for hibernation.

wxz
  • 2,254
  • 1
  • 10
  • 31
  • How do you do this in kernel? Given that you can run a kernel module. How can the module find these highmem and lowmem bounds? As a clarification. I mean in general if you are creating a kernel module how would you know the bounds. Of course if you expect to run only in 64 bit x86 machines then just look it up, but if you want to run on ARM 32 bit or powerpc or any other architecture you can't have a lookup table in your code during compilation (it will be too tedious). It will also need to be different for different linux kernel versions, so it's not at all practical. – anon Sep 20 '21 at 18:43
  • I just found [this document](https://www.kernel.org/doc/Documentation/arm/Porting) that contains kernel symbols like PHYS_OFFSET but it's specifically for ARM architectures I think. Not sure if there is a uniform way of figuring this out across all archs. – wxz Sep 20 '21 at 18:49
  • Actually, I think `PAGE_OFFSET` is typically used as the generic start address of the direct mapping section of RAM in kernel memory. See [this comment](https://elixir.bootlin.com/linux/latest/source/arch/arm64/include/asm/memory.h#L37) for ARM. In x86-64, `PAGE_OFFSET` goes to [this definition](https://elixir.bootlin.com/linux/latest/source/arch/x86/include/asm/page_64_types.h#L42) which matches the memory layout linked in my answer. – wxz Sep 21 '21 at 15:14
  • @anon Not sure if I have to tag you for you to get notified of comments. Did you see my latest comment? – wxz Sep 22 '21 at 15:26
  • yes I saw your answer. I don't think it answers my question. I don't get how memory holes fit in this explanation. Yes you can test if the address is in the range but that doesn't mean that the address will be valid. Also if kernel page can be swapped you don't know if it is in the RAM or its swapped, so if you test only address being in a range you will miss these 2 cases where the address is not valid. – anon Sep 22 '21 at 17:58
  • I think you misunderstood. My answer said kernel pages aren't swapped out (except for hibernation but you're not going to be checking addresses while hibernated so ignore that situation). Also, my answer isn't assuming that you're just looping through all addresses in the address space looking for valid ones. I assume you have a kernel address that is in use and are asking how to know if it's logical or not. If the address came from `kmalloc`, it's logical. If you don't know if it came from `kmalloc`, but it falls within the direct mapping range, it's logical. Anything else is non-logical. – wxz Sep 22 '21 at 18:12
  • @anon Also not sure what you're referring to with "memory holes". I didn't talk about memory holes at all. – wxz Sep 22 '21 at 18:13