New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
arm64: Use proper memory type for kernel allocation #101
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, thank you for testing and tracking that down!
@@ -389,7 +391,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), | |||
grub_loader_unset(); | |||
|
|||
kernel_alloc_pages = GRUB_EFI_BYTES_TO_PAGES (kernel_size + align - 1); | |||
kernel_alloc_addr = grub_efi_allocate_any_pages (kernel_alloc_pages); | |||
kernel_alloc_addr = grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if isn't better to instead make grub_efi_allocate_any_pages()
to use GRUB_EFI_LOADER_CODE
rather than open coding it the params that use it to call grub_efi_allocate_pages_real()
.
Since AFAICT is only used to allocate memory for the kernel image anyways, the memory for the initrd (that's data and not code) is already allocated using a different helper allocate_initrd_mem()
so that can continue to use GRUB_EFI_LOADER_DATA
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, by changing grub_efi_allocate_any_pages()
you will fix this not only for arm64 but also for x86.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that it's used in grub_efi_mm_init()
to allocate memory maps. How about a helper (perhaps grub_efi_allocate_executable_pages()
or grub_efi_allocate_kernel_pages()
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, probably grub_efi_allocate_kernel_pages()
then to be consistent with how the memory for the initrd is allocated ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i386 already has 8a2d168 (although that uses EFI_RUNTIME_SERVICES_CODE
instead). I assume that's also used for x86_64?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me, the EFI stub of the kernel seems more like a UEFI application than a runtime driver, but again, I don't know much about this stuff.
Yes, I agree with you here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fwiw: chainloader also seems to use GRUB_EFI_LOADER_CODE
:
grub2/grub-core/loader/efi/chainloader.c
Lines 1052 to 1054 in b1ce9c4
status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES, | |
GRUB_EFI_LOADER_CODE, | |
pages, &address); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that it's used in
grub_efi_mm_init()
to allocate memory maps. How about a helper (perhapsgrub_efi_allocate_executable_pages()
orgrub_efi_allocate_kernel_pages()
)?
Probably just move kernel_alloc() from the i386 loader to some common code and make the policy list be passed in?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems to depend on some interaction with the max_addresses
field, where parts of it are read in from the i386/x64 kernel header. I'm not sure how to adapt this for AArch64, but if you have some patches I'd be happy to test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably just move kernel_alloc() from the i386 loader to some common code and make the policy list be passed in?
So after having another look at this, the max_addresses
thing shouldn't be an issue. As you've said, this could just be passed in. However, I think using kernel_alloc()
here doesn't make that much sense to do this in this PR:
We could use it for the kernel image + command-line memory, passing in a policy array with a single entry. But given that it only uses a single entry and none of the re-try logic that's used on x86, this seems a bit too convoluted to me. Also, it's orthogonal to the change to GRUB_EFI_LOADER_CODE
, because that is still passed in to kernel_alloc()
. Further, adapting it for the initrd would need some changes (or workarounds) as the arm64 code relies on grub_efi_get_ram_base()
whereas the x86 code doesn't.
b8e58aa
to
b90ccf8
Compare
b90ccf8
to
4ba911f
Compare
cad2fc1
to
ecf3d74
Compare
b77167c
to
9e97e00
Compare
178d2c4
to
8a96f14
Compare
199a61d
to
7f8daed
Compare
Could we get this PR down to the one relevant patch for discussion, please? |
Sorry for the long silence. I will try to revisit this in the next couple of days. |
Currently, the kernel pages are allocated with type EFI_LOADER_DATA. While the vast majority of systems will happily execute code from those pages (i.e. don't care about memory protection), the Microsoft Surface Pro X stalls, as this memory is not designated as "executable". Therefore, allocate the kernel pages as EFI_LOADER_CODE to request memory that is actually executable. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
55b95a3
to
71402fa
Compare
The current version of this code also fixes the lenovo x13s, and presumably other machines based on the QC SoC/firmware. It also matches a bit of debugging/hacking I did last week before being pointed at this PR. My only reservations are that maybe it should only be done on machines that don't have the EFI_MEMORY_ATTRIBUTE_PROTOCOL. I have a slight worry there are some old/unsupported machines that have +Write turned off for EfiLoaderCode pages, but at the moment we have a known set of broken machines without this change. Is there a more concrete problem with it? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
Currently, the kernel pages are allocated with type EFI_LOADER_DATA.
While the vast majority of systems will happily execute code from those
pages (i.e. don't care about memory protection), the Microsoft Surface
Pro X stalls, as this memory is not designated as "executable".
Therefore, allocate the kernel pages as EFI_LOADER_CODE to request
memory that is actually executable.
Signed-off-by: Maximilian Luz luzmaximilian@gmail.com