1

I am creating a kernel for x64 which is booting with UEFI. While the kernel has to be loaded at a low-ish address (I believe, because UEFI requires identity mapped pages so it cannot be mapped higher than the highest physical address), I want to relocate up to the end of memory. During this process I intend on creating new paging structures and in order to reduce memory consumption, I wanted to reuse the page tables used to map the image in the lower half. However, these page tables will only exist if 4k paging is used by UEFI, so my question is whether or not UEFI is required to use 4k paging on x64. I believe the answer is no, but I hope otherwise and wanted to see if this is true.

Now I understand UEFI allocates memory via BootServices->AllocatePage in 4k chunks it refers to as pages, but is this required to translate to the actual mapping structure used? I noticed that in section 2.3.6 of the UEFI 2.8 specification, the section referring to AArch64 calling conventions, it states

MMU configuration: Implementations must use only 4k pages [...]

There is no similar denotation in section 2.3.4, on the x64 calling conventions, which is why I believe the answer is no.

EDIT: Based upon what I've already seen and the comment by Peter Cordes, I believe the standard does not specify exactly what it should be. Thus a revised version of the question is: Does the standard specify 4k translation granularity? If not, do most UEFI vendors on x64 use 4k pages?

brenden
  • 574
  • 3
  • 16
  • I think AArch64's alternate page sizes (or actually translation granularity) include 16k or 64k, which is a lot more "reasonable" than x86-64 2MiB large-pages. And I think the choice on AArch64 could affect interpretation / requirements of newly-created page-table entries ([Simultaneous existence of different-sized pages on Aarch64](https://stackoverflow.com/q/34269185)). Thus it's more important to nail it down for that reason than on x86-64, moreso than for how the existing UEFi-created page tables are set up. But yes, the end result is that the standard probably doesn't nail down x86-64. – Peter Cordes Feb 25 '21 at 02:15
  • @PeterCordes That makes sense and sort of what I was thinking. I'm going to edit my question to see if there is a de facto standard, or common pattern for UEFI implementors to follow. – brenden Feb 25 '21 at 02:18
  • Generally with legacy BIOS bootloaders, defensive coding has been necessary for wide portability: assume the as little as possible. I'd assume that would be a good idea for UEFI, too: expect some mobo vendor's firmware to violate any expectation, especially if it's not nailed down in the standard. Why not just map a 1G hugepage to cover the memory region you want to copy to? (e.g. read CR3 and parse the existing page table, and create new entries at the necessary levels.) – Peter Cordes Feb 25 '21 at 02:28
  • Thats a good point about defensive coding and I should stick to that. As I mentioned in the question, its not that I'm copy the data, but rather I wanted to reuse the page tables in the higher mapping to avoid extra memory allocation (although it would only be about 2M so not anything absurd). – brenden Feb 25 '21 at 02:31
  • Oh right, then yeah ideally just copy an existing page-directory entry at some level, so it points to the same subtree of PDEs / PTEs. Or a 1G hugepage, if that's what the firmware chose to set up. But even if you create your own mappings from scratch, it should only take a few 4k blocks of memory, one for each level with maybe a couple at the lowest level. Or use 2M largepages for contiguous regions. Remember that page directories (and thus the radix tree they form) can be sparse: not-present entries don't have to point at anything. – Peter Cordes Feb 25 '21 at 02:38
  • Yeah, my plan was to allocate up to 515 pages initially (1 pml4, 1 pdpt, 1 directory, and up to 512 tables). These pages will be used for the rest of the runtime, due to some architectural plans for the kernel, I want all mappings to have the same granularity of 4k, so I don't want to reuse a page directory that maps 2m pages instead if that makes sense. – brenden Feb 25 '21 at 02:44
  • My Kaby Lake test system seems to use 2M mappings for everything. – prl Feb 25 '21 at 05:27
  • I’m pretty sure that another system I use has some 1G mappings but I don’t have access to it at the moment to check. – prl Feb 25 '21 at 05:34
  • If you’re doing this prior to calling ExItBootServices, then you’re not allowed to change CR3, so you have to insert your new mappings into the existing PML4. If you’re doing it after calling ExitBootServices, then the page tables allocated by UEFI are free for your OS to reuse anyway. – prl Feb 25 '21 at 05:50
  • I am doing this all after exiting boot services. I want to reuse the tables, but I'm unsure if they even exist as the memory could be mapped using page directories which directly map 2M pages, or possibly even larger page sizes like the 1G you mentioned. With this question, I want to see if this concern is misplaced by hopefully finding that implementors are required to use 4k pages which use tables. To clarify, are those 1G and 2M mappings the ones given to a UEFI Application by the bios/uefi? – brenden Feb 25 '21 at 13:55

0 Answers0