arm64/efi: prefer AllocatePages() over efi_low_alloc() for vmlinux
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/1 arm64/efi: prefer AllocatePages() over efi_low_alloc() for vmlinux
Hello Haojian,
Could you please try this patch?
Signature · 14 lines
Ard. -------8<-------- When allocating memory for the kernel image, try the AllocatePages() boot service to obtain memory at the preferred offset of 'dram_base + TEXT_OFFSET', and only revert to efi_low_alloc() if that fails. This is the only way to allocate at the base of DRAM if DRAM starts at 0x0, since efi_low_alloc() refuses to allocate at 0x0. Signed-off-by: Ard Biesheuvel <[email protected]> --- arch/arm64/kernel/efi-stub.c | 45 ++++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-)
arch/arm64/kernel/efi-stub.c +37 -8
@@ -13,7 +13,7 @@#include <asm/efi.h> #include <asm/sections.h> -efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table, +efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg, unsigned long *image_addr, unsigned long *image_size, unsigned long *reserve_addr,
@@ -23,21 +23,50 @@ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table, {efi_status_t status;unsigned long kernel_size, kernel_memsize =0 ; +unsigned long pgnum;/* Relocate the image, if required. */ kernel_size = _edata - _text;if (*image_addr != (dram_base +TEXT_OFFSET )) { kernel_memsize = kernel_size + (_end - _edata); - status =efi_low_alloc (sys_table, kernel_memsize +TEXT_OFFSET , -SZ_2M , reserve_addr); + +// +// First, try a straight allocation at the preferred offset. +// This will work around the issue where, if dram_base == 0x0, +// efi_low_alloc() refuses to allocate at 0x0 (to prevent the +// address of the allocation to be mistaken for a FAIL return +// value or a NULL pointer). It will also ensure that, on +// platforms where the [dram_base, dram_base + TEXT_OFFSET) +// interval is partially occupied by the firmware (like on APM +// Mustang), we can still place the kernel at the address +// 'dram_base + TEXT_OFFSET'. +// + pgnum =round_up (kernel_memsize,EFI_PAGE_SIZE ) /EFI_PAGE_SIZE ; + status =efi_call_early (allocate_pages,EFI_ALLOCATE_ADDRESS , +EFI_LOADER_DATA , pgnum, + (efi_physical_addr_t *)reserve_addr); +if (status ==EFI_SUCCESS ) { +memcpy ((void *)*reserve_addr, (void *)*image_addr, + kernel_size); + *image_addr = *reserve_addr; + *reserve_size = kernel_memsize; + }else { + status =efi_low_alloc (sys_table_arg, + kernel_memsize +TEXT_OFFSET , +SZ_2M , reserve_addr); + +if (status ==EFI_SUCCESS ) { +memcpy ((void *)*reserve_addr +TEXT_OFFSET , + (void *)*image_addr, + kernel_size); + *image_addr = *reserve_addr +TEXT_OFFSET ; + *reserve_size = kernel_memsize +TEXT_OFFSET ; + } + }if (status !=EFI_SUCCESS ) { -pr_efi_err (sys_table,"Failed to relocate kernel\n" ); +pr_efi_err (sys_table_arg,"Failed to relocate kernel\n" );return status; } -memcpy ((void *)*reserve_addr +TEXT_OFFSET , (void *)*image_addr, - kernel_size); - *image_addr = *reserve_addr +TEXT_OFFSET ; - *reserve_size = kernel_memsize +TEXT_OFFSET ; }
Signature · 1 line
1.9.1
Quoted 4 lines · Ard Biesheuvel
Hello Haojian,
Could you please try this patch?
Ehm, never mind, please wait for the v2. This patch is incorrect.
Signature · 1 line
Ard.
Quoted 87 lines
-------8<--------
When allocating memory for the kernel image, try theAllocatePages()boot service to obtain memory at the preferred offset of 'dram_base+TEXT_OFFSET', and only revert toefi_low_alloc()if that fails. This is the only way to allocate at the base of DRAM if DRAM starts at0x0, sinceefi_low_alloc()refuses to allocate at0x0.Signed-off-by Ard Biesheuvel <[email protected]>--- arch/arm64/kernel/efi-stub.c | 45 ++++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-)arch/arm64/kernel/efi-stub.c +37
-9@@ -13,7 +13,7 @@#include <asm/efi.h> #include <asm/sections.h> -efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table, +efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg, unsigned long *image_addr, unsigned long *image_size, unsigned long *reserve_addr,@@ -23,21 +23,50 @@ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table, {efi_status_t status;unsigned long kernel_size, kernel_memsize =0 ; +unsigned long pgnum;/* Relocate the image, if required. */ kernel_size = _edata - _text;if (*image_addr != (dram_base +TEXT_OFFSET )) { kernel_memsize = kernel_size + (_end - _edata); - status =efi_low_alloc (sys_table, kernel_memsize +TEXT_OFFSET , -SZ_2M , reserve_addr); + +// +// First, try a straight allocation at the preferred offset. +// This will work around the issue where, if dram_base == 0x0, +// efi_low_alloc() refuses to allocate at 0x0 (to prevent the +// address of the allocation to be mistaken for a FAIL return +// value or a NULL pointer). It will also ensure that, on +// platforms where the [dram_base, dram_base + TEXT_OFFSET) +// interval is partially occupied by the firmware (like on APM +// Mustang), we can still place the kernel at the address +// 'dram_base + TEXT_OFFSET'. +// + pgnum =round_up (kernel_memsize,EFI_PAGE_SIZE ) /EFI_PAGE_SIZE ; + status =efi_call_early (allocate_pages,EFI_ALLOCATE_ADDRESS , +EFI_LOADER_DATA , pgnum, + (efi_physical_addr_t *)reserve_addr); +if (status ==EFI_SUCCESS ) { +memcpy ((void *)*reserve_addr, (void *)*image_addr, + kernel_size); + *image_addr = *reserve_addr; + *reserve_size = kernel_memsize; + }else { + status =efi_low_alloc (sys_table_arg, + kernel_memsize +TEXT_OFFSET , +SZ_2M , reserve_addr); + +if (status ==EFI_SUCCESS ) { +memcpy ((void *)*reserve_addr +TEXT_OFFSET , + (void *)*image_addr, + kernel_size); + *image_addr = *reserve_addr +TEXT_OFFSET ; + *reserve_size = kernel_memsize +TEXT_OFFSET ; + } + }if (status !=EFI_SUCCESS ) { -pr_efi_err (sys_table,"Failed to relocate kernel\n" ); +pr_efi_err (sys_table_arg,"Failed to relocate kernel\n" );return status; } -memcpy ((void *)*reserve_addr +TEXT_OFFSET , (void *)*image_addr, - kernel_size); - *image_addr = *reserve_addr +TEXT_OFFSET ; - *reserve_size = kernel_memsize +TEXT_OFFSET ; } --1.9.1
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH v2 1/1 arm64/efi: prefer AllocatePages() over efi_low_alloc() for vmlinux
Hello Haojian,
Could you please try this version instead?
Signature · 17 lines
Ard. -------8<--------- When allocating memory for the kernel image, try the AllocatePages() boot service to obtain memory at the preferred offset of 'dram_base + TEXT_OFFSET', and only revert to efi_low_alloc() if that fails. This is the only way to allocate at the base of DRAM if DRAM starts at 0x0, since efi_low_alloc() refuses to allocate at 0x0. Signed-off-by: Ard Biesheuvel <[email protected]> --- v2: - set *reserve_addr before calling AllocatePages() arch/arm64/kernel/efi-stub.c | 45 ++++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-)
arch/arm64/kernel/efi-stub.c +37 -8
@@ -13,7 +13,7 @@#include <asm/efi.h> #include <asm/sections.h> -efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table, +efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg, unsigned long *image_addr, unsigned long *image_size, unsigned long *reserve_addr,
@@ -23,21 +23,50 @@ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table, {efi_status_t status;unsigned long kernel_size, kernel_memsize =0 ; +unsigned long pgnum;/* Relocate the image, if required. */ kernel_size = _edata - _text;if (*image_addr != (dram_base +TEXT_OFFSET )) { kernel_memsize = kernel_size + (_end - _edata); - status =efi_low_alloc (sys_table, kernel_memsize +TEXT_OFFSET , -SZ_2M , reserve_addr); + +// +// First, try a straight allocation at the preferred offset. +// This will work around the issue where, if dram_base == 0x0, +// efi_low_alloc() refuses to allocate at 0x0 (to prevent the +// address of the allocation to be mistaken for a FAIL return +// value or a NULL pointer). It will also ensure that, on +// platforms where the [dram_base, dram_base + TEXT_OFFSET) +// interval is partially occupied by the firmware (like on APM +// Mustang), we can still place the kernel at the address +// 'dram_base + TEXT_OFFSET'. +// + pgnum =round_up (kernel_memsize,EFI_PAGE_SIZE ) /EFI_PAGE_SIZE ; + status =efi_call_early (allocate_pages,EFI_ALLOCATE_ADDRESS , +EFI_LOADER_DATA , pgnum, + (efi_physical_addr_t *)reserve_addr); +if (status ==EFI_SUCCESS ) { +memcpy ((void *)*reserve_addr, (void *)*image_addr, + kernel_size); + *image_addr = *reserve_addr; + *reserve_size = kernel_memsize; + }else { + status =efi_low_alloc (sys_table_arg, + kernel_memsize +TEXT_OFFSET , +SZ_2M , reserve_addr); + +if (status ==EFI_SUCCESS ) { +memcpy ((void *)*reserve_addr +TEXT_OFFSET , + (void *)*image_addr, + kernel_size); + *image_addr = *reserve_addr +TEXT_OFFSET ; + *reserve_size = kernel_memsize +TEXT_OFFSET ; + } + }if (status !=EFI_SUCCESS ) { -pr_efi_err (sys_table,"Failed to relocate kernel\n" ); +pr_efi_err (sys_table_arg,"Failed to relocate kernel\n" );return status; } -memcpy ((void *)*reserve_addr +TEXT_OFFSET , (void *)*image_addr, - kernel_size); - *image_addr = *reserve_addr +TEXT_OFFSET ; - *reserve_size = kernel_memsize +TEXT_OFFSET ; }
Signature · 1 line
1.9.1
PATCH v3 1/1 arm64/efi: prefer AllocatePages() over efi_low_alloc() for vmlinux
In reply to a message not in the archiveHello Haojian,
Apologies for the noise ...
Could you please try *this* version v3 instead? v2 is just the same patch as before ...
Signature · 17 lines
Ard. -------8<--------- When allocating memory for the kernel image, try the AllocatePages() boot service to obtain memory at the preferred offset of 'dram_base + TEXT_OFFSET', and only revert to efi_low_alloc() if that fails. This is the only way to allocate at the base of DRAM if DRAM starts at 0x0, since efi_low_alloc() refuses to allocate at 0x0. Signed-off-by: Ard Biesheuvel <[email protected]> --- v3: - set *reserve_addr before calling AllocatePages() arch/arm64/kernel/efi-stub.c | 47 ++++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-)
arch/arm64/kernel/efi-stub.c +39 -8
@@ -13,7 +13,7 @@#include <asm/efi.h> #include <asm/sections.h> -efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table, +efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg, unsigned long *image_addr, unsigned long *image_size, unsigned long *reserve_addr,
@@ -23,21 +23,52 @@ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table, {efi_status_t status;unsigned long kernel_size, kernel_memsize =0 ; +unsigned long nr_pages;/* Relocate the image, if required. */ kernel_size = _edata - _text;if (*image_addr != (dram_base +TEXT_OFFSET )) { kernel_memsize = kernel_size + (_end - _edata); - status =efi_low_alloc (sys_table, kernel_memsize +TEXT_OFFSET , -SZ_2M , reserve_addr); + +// +// First, try a straight allocation at the preferred offset. +// This will work around the issue where, if dram_base == 0x0, +// efi_low_alloc() refuses to allocate at 0x0 (to prevent the +// address of the allocation to be mistaken for a FAIL return +// value or a NULL pointer). It will also ensure that, on +// platforms where the [dram_base, dram_base + TEXT_OFFSET) +// interval is partially occupied by the firmware (like on APM +// Mustang), we can still place the kernel at the address +// 'dram_base + TEXT_OFFSET'. +// + *reserve_addr = dram_base +TEXT_OFFSET ; + nr_pages =round_up (kernel_memsize,EFI_ALLOC_ALIGN ) / +EFI_PAGE_SIZE ; + status =efi_call_early (allocate_pages,EFI_ALLOCATE_ADDRESS , +EFI_LOADER_DATA , nr_pages, + (efi_physical_addr_t *)reserve_addr); +if (status ==EFI_SUCCESS ) { +memcpy ((void *)*reserve_addr, (void *)*image_addr, + kernel_size); + *image_addr = *reserve_addr; + *reserve_size = kernel_memsize; + }else { + status =efi_low_alloc (sys_table_arg, + kernel_memsize +TEXT_OFFSET , +SZ_2M , reserve_addr); + +if (status ==EFI_SUCCESS ) { +memcpy ((void *)*reserve_addr +TEXT_OFFSET , + (void *)*image_addr, + kernel_size); + *image_addr = *reserve_addr +TEXT_OFFSET ; + *reserve_size = kernel_memsize +TEXT_OFFSET ; + } + }if (status !=EFI_SUCCESS ) { -pr_efi_err (sys_table,"Failed to relocate kernel\n" ); +pr_efi_err (sys_table_arg,"Failed to relocate kernel\n" );return status; } -memcpy ((void *)*reserve_addr +TEXT_OFFSET , (void *)*image_addr, - kernel_size); - *image_addr = *reserve_addr +TEXT_OFFSET ; - *reserve_size = kernel_memsize +TEXT_OFFSET ; }
Signature · 1 line
1.9.1
A message that is not in the archive (sent off-list or not yet received): 1437657906-20034-1-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org
Quoted 10 lines · Ard Biesheuvel
Hello Haojian,
Apologies for the noise ...
Could you please try *this* version v3 instead? v2 is just the same patch as before ...
Signature · 1 line
Ard.
Hi Ard,
Thanks for your patch. It fixes the issue when DRAM_BASE is 0x0.
Best Regards
Haojian
Quoted 89 lines
-------8<---------
When allocating memory for the kernel image, try the
AllocatePages()boot service to obtain memory at the preferred offset of 'dram_base+TEXT_OFFSET', and only revert toefi_low_alloc()if that fails. This is the only way to allocate at the base of DRAM if DRAM starts at0x0, sinceefi_low_alloc()refuses to allocate at0x0.Signed-off-by Ard Biesheuvel <[email protected]>---
v3:
- set*reserve_addrbefore callingAllocatePages()arch/arm64/kernel/efi-stub.c | 47 ++++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-)arch/arm64/kernel/efi-stub.c +39
-8@@ -13,7 +13,7 @@#include <asm/efi.h> #include <asm/sections.h> -efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table, +efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg, unsigned long *image_addr, unsigned long *image_size, unsigned long *reserve_addr,@@ -23,21 +23,52 @@ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table, {efi_status_t status;unsigned long kernel_size, kernel_memsize =0 ; +unsigned long nr_pages;/* Relocate the image, if required. */ kernel_size = _edata - _text;if (*image_addr != (dram_base +TEXT_OFFSET )) { kernel_memsize = kernel_size + (_end - _edata); - status =efi_low_alloc (sys_table, kernel_memsize +TEXT_OFFSET , -SZ_2M , reserve_addr); + +// +// First, try a straight allocation at the preferred offset. +// This will work around the issue where, if dram_base == 0x0, +// efi_low_alloc() refuses to allocate at 0x0 (to prevent the +// address of the allocation to be mistaken for a FAIL return +// value or a NULL pointer). It will also ensure that, on +// platforms where the [dram_base, dram_base + TEXT_OFFSET) +// interval is partially occupied by the firmware (like on APM +// Mustang), we can still place the kernel at the address +// 'dram_base + TEXT_OFFSET'. +// + *reserve_addr = dram_base +TEXT_OFFSET ; + nr_pages =round_up (kernel_memsize,EFI_ALLOC_ALIGN ) / +EFI_PAGE_SIZE ; + status =efi_call_early (allocate_pages,EFI_ALLOCATE_ADDRESS , +EFI_LOADER_DATA , nr_pages, + (efi_physical_addr_t *)reserve_addr); +if (status ==EFI_SUCCESS ) { +memcpy ((void *)*reserve_addr, (void *)*image_addr, + kernel_size); + *image_addr = *reserve_addr; + *reserve_size = kernel_memsize; + }else { + status =efi_low_alloc (sys_table_arg, + kernel_memsize +TEXT_OFFSET , +SZ_2M , reserve_addr); + +if (status ==EFI_SUCCESS ) { +memcpy ((void *)*reserve_addr +TEXT_OFFSET , + (void *)*image_addr, + kernel_size); + *image_addr = *reserve_addr +TEXT_OFFSET ; + *reserve_size = kernel_memsize +TEXT_OFFSET ; + } + }if (status !=EFI_SUCCESS ) { -pr_efi_err (sys_table,"Failed to relocate kernel\n" ); +pr_efi_err (sys_table_arg,"Failed to relocate kernel\n" );return status; } -memcpy ((void *)*reserve_addr +TEXT_OFFSET , (void *)*image_addr, - kernel_size); - *image_addr = *reserve_addr +TEXT_OFFSET ; - *reserve_size = kernel_memsize +TEXT_OFFSET ; }
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 8 lines · Haojian Zhuang
Quoted 7 lines · Ard Biesheuvel
Hello Haojian,
Apologies for the noise ...
Could you please try *this* version v3 instead? v2 is just the same patch as before ...
Quoted 8 lines
Quoted 3 lines
--
Ard.Hi Ard,
Thanks for your patch. It fixes the issue when
DRAM_BASEis0x0.
Thanks for verifying. May I add your Tested-by ?
Signature · 1 line
Ard.
Quoted 95 lines
Quoted 79 lines
-------8<---------
When allocating memory for the kernel image, try the
AllocatePages()boot service to obtain memory at the preferred offset of 'dram_base+TEXT_OFFSET', and only revert toefi_low_alloc()if that fails. This is the only way to allocate at the base of DRAM if DRAM starts at0x0, sinceefi_low_alloc()refuses to allocate at0x0.Signed-off-by Ard Biesheuvel <[email protected]>---
v3:
- set*reserve_addrbefore callingAllocatePages()arch/arm64/kernel/efi-stub.c | 47 ++++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-)arch/arm64/kernel/efi-stub.c +38
-4@@ -13,7 +13,7 @@#include <asm/efi.h> #include <asm/sections.h> -efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table, +efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg, unsigned long *image_addr, unsigned long *image_size, unsigned long *reserve_addr,@@ -23,21 +23,52 @@ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table, {efi_status_t status;unsigned long kernel_size, kernel_memsize =0 ; +unsigned long nr_pages;/* Relocate the image, if required. */ kernel_size = _edata - _text;if (*image_addr != (dram_base +TEXT_OFFSET )) { kernel_memsize = kernel_size + (_end - _edata); - status =efi_low_alloc (sys_table, kernel_memsize +TEXT_OFFSET , -SZ_2M , reserve_addr); + +// +// First, try a straight allocation at the preferred offset. +// This will work around the issue where, if dram_base == 0x0, +// efi_low_alloc() refuses to allocate at 0x0 (to prevent the +// address of the allocation to be mistaken for a FAIL return +// value or a NULL pointer). It will also ensure that, on +// platforms where the [dram_base, dram_base + TEXT_OFFSET) +// interval is partially occupied by the firmware (like on APM +// Mustang), we can still place the kernel at the address +// 'dram_base + TEXT_OFFSET'. +// + *reserve_addr = dram_base +TEXT_OFFSET ; + nr_pages =round_up (kernel_memsize,EFI_ALLOC_ALIGN ) / +EFI_PAGE_SIZE ; + status =efi_call_early (allocate_pages,EFI_ALLOCATE_ADDRESS , +EFI_LOADER_DATA , nr_pages, + (efi_physical_addr_t *)reserve_addr); +if (status ==EFI_SUCCESS ) { +memcpy ((void *)*reserve_addr, (void *)*image_addr, + kernel_size); + *image_addr = *reserve_addr; + *reserve_size = kernel_memsize; + }else { + status =efi_low_alloc (sys_table_arg, + kernel_memsize +TEXT_OFFSET , +SZ_2M , reserve_addr); + +if (status ==EFI_SUCCESS ) { +memcpy ((void *)*reserve_addr +TEXT_OFFSET , + (void *)*image_addr, + kernel_size); + *image_addr = *reserve_addr +TEXT_OFFSET ; + *reserve_size = kernel_memsize +TEXT_OFFSET ; + } + }if (status !=EFI_SUCCESS ) { -pr_efi_err (sys_table,"Failed to relocate kernel\n" );arch/arm64/kernel/efi-stub.c efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table, · line 74
Quoted 10 lines
arch/arm64/kernel/efi-stub.c +1
-4+pr_efi_err (sys_table_arg,"Failed to relocate kernel\n" );return status; } -memcpy ((void *)*reserve_addr +TEXT_OFFSET , (void *)*image_addr, - kernel_size); - *image_addr = *reserve_addr +TEXT_OFFSET ; - *reserve_size = kernel_memsize +TEXT_OFFSET ; }_______________________________________________
edk2-devel mailing list [email protected]
https://lists.01.org/mailman/listinfo/edk2-devel
A message that is not in the archive (sent off-list or not yet received): CAKv+Gu-vLtVQmHT+0BzBh0wq2AKDWxJZdJNBHFStd-AbMb0u9g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Quoted 13 lines · Ard Biesheuvel
Quoted 12 lines · Haojian Zhuang
Quoted 10 lines · Ard Biesheuvel
Hello Haojian,
Apologies for the noise ...
Could you please try *this* version v3 instead? v2 is just the same patch as before ...
--
Ard.
Quoted 7 lines
Quoted 4 lines
Hi Ard,
Thanks for your patch. It fixes the issue when
DRAM_BASEis0x0.Thanks for verifying. May I add your Tested-by ?
Of course. Please feel free to add my Tested-by.
Best Regards
Haojian