[tip:efi/core] efi/arm32-stub: Allow boot-time allocations in the vmlinux region

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  318532bf63cfab779d763527d8b93e48c4a96dba
Gitweb: http://git.kernel.org/tip/318532bf63cfab779d763527d8b93e48c4a96dba
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:44 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:27:26 +0200

efi/arm32-stub: Allow boot-time allocations in the vmlinux region

The arm32 kernel decompresses itself to the base of DRAM unconditionally,
and so it is the EFI stub's job to ensure that the region is available.

Currently, we do this by creating an allocation there, and giving up if
that fails. However, any boot services regions occupying this area are
not an issue, given that the decompressor executes strictly after the
stub calls ExitBootServices().

So let's try a bit harder to proceed if the initial allocation fails,
and check whether any memory map entries occupying the region may be
considered safe.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Leif Lindholm 
Reviewed-by: Eugene Cohen 
Reviewed-by: Roy Franz 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-11-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm32-stub.c | 148 ++
 1 file changed, 128 insertions(+), 20 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm32-stub.c 
b/drivers/firmware/efi/libstub/arm32-stub.c
index e1f0b28..18a8b5e 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -63,6 +63,132 @@ void free_screen_info(efi_system_table_t *sys_table_arg, 
struct screen_info *si)
efi_call_early(free_pool, si);
 }
 
+static efi_status_t reserve_kernel_base(efi_system_table_t *sys_table_arg,
+   unsigned long dram_base,
+   unsigned long *reserve_addr,
+   unsigned long *reserve_size)
+{
+   efi_physical_addr_t alloc_addr;
+   efi_memory_desc_t *memory_map;
+   unsigned long nr_pages, map_size, desc_size, buff_size;
+   efi_status_t status;
+   unsigned long l;
+
+   struct efi_boot_memmap map = {
+   .map= _map,
+   .map_size   = _size,
+   .desc_size  = _size,
+   .desc_ver   = NULL,
+   .key_ptr= NULL,
+   .buff_size  = _size,
+   };
+
+   /*
+* Reserve memory for the uncompressed kernel image. This is
+* all that prevents any future allocations from conflicting
+* with the kernel. Since we can't tell from the compressed
+* image how much DRAM the kernel actually uses (due to BSS
+* size uncertainty) we allocate the maximum possible size.
+* Do this very early, as prints can cause memory allocations
+* that may conflict with this.
+*/
+   alloc_addr = dram_base + MAX_UNCOMP_KERNEL_SIZE;
+   nr_pages = MAX_UNCOMP_KERNEL_SIZE / EFI_PAGE_SIZE;
+   status = efi_call_early(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
+   EFI_BOOT_SERVICES_DATA, nr_pages, _addr);
+   if (status == EFI_SUCCESS) {
+   if (alloc_addr == dram_base) {
+   *reserve_addr = alloc_addr;
+   *reserve_size = MAX_UNCOMP_KERNEL_SIZE;
+   return EFI_SUCCESS;
+   }
+   /*
+* If we end up here, the allocation succeeded but starts below
+* dram_base. This can only occur if the real base of DRAM is
+* not a multiple of 128 MB, in which case dram_base will have
+* been rounded up. Since this implies that a part of the region
+* was already occupied, we need to fall through to the code
+* below to ensure that the existing allocations don't conflict.
+* For this reason, we use EFI_BOOT_SERVICES_DATA above and not
+* EFI_LOADER_DATA, which we wouldn't able to distinguish from
+* allocations that we want to disallow.
+*/
+   }
+
+   /*
+* If the allocation above failed, we may still be able to proceed:
+* if the only allocations in the region are of types that will be
+* released to the OS after ExitBootServices(), the decompressor can
+* safely overwrite them.
+*/
+   status = efi_get_memory_map(sys_table_arg, );
+   if (status != EFI_SUCCESS) {
+   pr_efi_err(sys_table_arg,
+  "reserve_kernel_base(): Unable to retrieve memory 

[tip:efi/core] efi/arm32-stub: Allow boot-time allocations in the vmlinux region

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  318532bf63cfab779d763527d8b93e48c4a96dba
Gitweb: http://git.kernel.org/tip/318532bf63cfab779d763527d8b93e48c4a96dba
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:44 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 12:27:26 +0200

efi/arm32-stub: Allow boot-time allocations in the vmlinux region

The arm32 kernel decompresses itself to the base of DRAM unconditionally,
and so it is the EFI stub's job to ensure that the region is available.

Currently, we do this by creating an allocation there, and giving up if
that fails. However, any boot services regions occupying this area are
not an issue, given that the decompressor executes strictly after the
stub calls ExitBootServices().

So let's try a bit harder to proceed if the initial allocation fails,
and check whether any memory map entries occupying the region may be
considered safe.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Leif Lindholm 
Reviewed-by: Eugene Cohen 
Reviewed-by: Roy Franz 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-11-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm32-stub.c | 148 ++
 1 file changed, 128 insertions(+), 20 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm32-stub.c 
b/drivers/firmware/efi/libstub/arm32-stub.c
index e1f0b28..18a8b5e 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -63,6 +63,132 @@ void free_screen_info(efi_system_table_t *sys_table_arg, 
struct screen_info *si)
efi_call_early(free_pool, si);
 }
 
+static efi_status_t reserve_kernel_base(efi_system_table_t *sys_table_arg,
+   unsigned long dram_base,
+   unsigned long *reserve_addr,
+   unsigned long *reserve_size)
+{
+   efi_physical_addr_t alloc_addr;
+   efi_memory_desc_t *memory_map;
+   unsigned long nr_pages, map_size, desc_size, buff_size;
+   efi_status_t status;
+   unsigned long l;
+
+   struct efi_boot_memmap map = {
+   .map= _map,
+   .map_size   = _size,
+   .desc_size  = _size,
+   .desc_ver   = NULL,
+   .key_ptr= NULL,
+   .buff_size  = _size,
+   };
+
+   /*
+* Reserve memory for the uncompressed kernel image. This is
+* all that prevents any future allocations from conflicting
+* with the kernel. Since we can't tell from the compressed
+* image how much DRAM the kernel actually uses (due to BSS
+* size uncertainty) we allocate the maximum possible size.
+* Do this very early, as prints can cause memory allocations
+* that may conflict with this.
+*/
+   alloc_addr = dram_base + MAX_UNCOMP_KERNEL_SIZE;
+   nr_pages = MAX_UNCOMP_KERNEL_SIZE / EFI_PAGE_SIZE;
+   status = efi_call_early(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
+   EFI_BOOT_SERVICES_DATA, nr_pages, _addr);
+   if (status == EFI_SUCCESS) {
+   if (alloc_addr == dram_base) {
+   *reserve_addr = alloc_addr;
+   *reserve_size = MAX_UNCOMP_KERNEL_SIZE;
+   return EFI_SUCCESS;
+   }
+   /*
+* If we end up here, the allocation succeeded but starts below
+* dram_base. This can only occur if the real base of DRAM is
+* not a multiple of 128 MB, in which case dram_base will have
+* been rounded up. Since this implies that a part of the region
+* was already occupied, we need to fall through to the code
+* below to ensure that the existing allocations don't conflict.
+* For this reason, we use EFI_BOOT_SERVICES_DATA above and not
+* EFI_LOADER_DATA, which we wouldn't able to distinguish from
+* allocations that we want to disallow.
+*/
+   }
+
+   /*
+* If the allocation above failed, we may still be able to proceed:
+* if the only allocations in the region are of types that will be
+* released to the OS after ExitBootServices(), the decompressor can
+* safely overwrite them.
+*/
+   status = efi_get_memory_map(sys_table_arg, );
+   if (status != EFI_SUCCESS) {
+   pr_efi_err(sys_table_arg,
+  "reserve_kernel_base(): Unable to retrieve memory 
map.\n");
+   return status;
+   }
+
+   for (l = 0; l < map_size; l += desc_size) {
+   efi_memory_desc_t *desc;
+   u64 start, end;
+
+   desc = (void *)memory_map + l;
+   start = 

[tip:efi/core] efi/arm32-stub: Allow boot-time allocations in the vmlinux region

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  0dee5fe386a3b51b63f5ac5aa3a23bc6ed385cae
Gitweb: http://git.kernel.org/tip/0dee5fe386a3b51b63f5ac5aa3a23bc6ed385cae
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:44 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:52 +0200

efi/arm32-stub: Allow boot-time allocations in the vmlinux region

The arm32 kernel decompresses itself to the base of DRAM unconditionally,
and so it is the EFI stub's job to ensure that the region is available.

Currently, we do this by creating an allocation there, and giving up if
that fails. However, any boot services regions occupying this area are
not an issue, given that the decompressor executes strictly after the
stub calls ExitBootServices().

So let's try a bit harder to proceed if the initial allocation fails,
and check whether any memory map entries occupying the region may be
considered safe.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Leif Lindholm 
Reviewed-by: Eugene Cohen 
Reviewed-by: Roy Franz 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-11-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm32-stub.c | 148 ++
 1 file changed, 128 insertions(+), 20 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm32-stub.c 
b/drivers/firmware/efi/libstub/arm32-stub.c
index e1f0b28..18a8b5e 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -63,6 +63,132 @@ void free_screen_info(efi_system_table_t *sys_table_arg, 
struct screen_info *si)
efi_call_early(free_pool, si);
 }
 
+static efi_status_t reserve_kernel_base(efi_system_table_t *sys_table_arg,
+   unsigned long dram_base,
+   unsigned long *reserve_addr,
+   unsigned long *reserve_size)
+{
+   efi_physical_addr_t alloc_addr;
+   efi_memory_desc_t *memory_map;
+   unsigned long nr_pages, map_size, desc_size, buff_size;
+   efi_status_t status;
+   unsigned long l;
+
+   struct efi_boot_memmap map = {
+   .map= _map,
+   .map_size   = _size,
+   .desc_size  = _size,
+   .desc_ver   = NULL,
+   .key_ptr= NULL,
+   .buff_size  = _size,
+   };
+
+   /*
+* Reserve memory for the uncompressed kernel image. This is
+* all that prevents any future allocations from conflicting
+* with the kernel. Since we can't tell from the compressed
+* image how much DRAM the kernel actually uses (due to BSS
+* size uncertainty) we allocate the maximum possible size.
+* Do this very early, as prints can cause memory allocations
+* that may conflict with this.
+*/
+   alloc_addr = dram_base + MAX_UNCOMP_KERNEL_SIZE;
+   nr_pages = MAX_UNCOMP_KERNEL_SIZE / EFI_PAGE_SIZE;
+   status = efi_call_early(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
+   EFI_BOOT_SERVICES_DATA, nr_pages, _addr);
+   if (status == EFI_SUCCESS) {
+   if (alloc_addr == dram_base) {
+   *reserve_addr = alloc_addr;
+   *reserve_size = MAX_UNCOMP_KERNEL_SIZE;
+   return EFI_SUCCESS;
+   }
+   /*
+* If we end up here, the allocation succeeded but starts below
+* dram_base. This can only occur if the real base of DRAM is
+* not a multiple of 128 MB, in which case dram_base will have
+* been rounded up. Since this implies that a part of the region
+* was already occupied, we need to fall through to the code
+* below to ensure that the existing allocations don't conflict.
+* For this reason, we use EFI_BOOT_SERVICES_DATA above and not
+* EFI_LOADER_DATA, which we wouldn't able to distinguish from
+* allocations that we want to disallow.
+*/
+   }
+
+   /*
+* If the allocation above failed, we may still be able to proceed:
+* if the only allocations in the region are of types that will be
+* released to the OS after ExitBootServices(), the decompressor can
+* safely overwrite them.
+*/
+   status = efi_get_memory_map(sys_table_arg, );
+   if (status != EFI_SUCCESS) {
+   pr_efi_err(sys_table_arg,
+  "reserve_kernel_base(): Unable to retrieve memory 

[tip:efi/core] efi/arm32-stub: Allow boot-time allocations in the vmlinux region

2017-04-05 Thread tip-bot for Ard Biesheuvel
Commit-ID:  0dee5fe386a3b51b63f5ac5aa3a23bc6ed385cae
Gitweb: http://git.kernel.org/tip/0dee5fe386a3b51b63f5ac5aa3a23bc6ed385cae
Author: Ard Biesheuvel 
AuthorDate: Tue, 4 Apr 2017 17:02:44 +0100
Committer:  Ingo Molnar 
CommitDate: Wed, 5 Apr 2017 09:27:52 +0200

efi/arm32-stub: Allow boot-time allocations in the vmlinux region

The arm32 kernel decompresses itself to the base of DRAM unconditionally,
and so it is the EFI stub's job to ensure that the region is available.

Currently, we do this by creating an allocation there, and giving up if
that fails. However, any boot services regions occupying this area are
not an issue, given that the decompressor executes strictly after the
stub calls ExitBootServices().

So let's try a bit harder to proceed if the initial allocation fails,
and check whether any memory map entries occupying the region may be
considered safe.

Signed-off-by: Ard Biesheuvel 
Reviewed-by: Leif Lindholm 
Reviewed-by: Eugene Cohen 
Reviewed-by: Roy Franz 
Cc: Linus Torvalds 
Cc: Matt Fleming 
Cc: Peter Zijlstra 
Cc: Thomas Gleixner 
Cc: linux-...@vger.kernel.org
Link: http://lkml.kernel.org/r/20170404160245.27812-11-ard.biesheu...@linaro.org
Signed-off-by: Ingo Molnar 
---
 drivers/firmware/efi/libstub/arm32-stub.c | 148 ++
 1 file changed, 128 insertions(+), 20 deletions(-)

diff --git a/drivers/firmware/efi/libstub/arm32-stub.c 
b/drivers/firmware/efi/libstub/arm32-stub.c
index e1f0b28..18a8b5e 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -63,6 +63,132 @@ void free_screen_info(efi_system_table_t *sys_table_arg, 
struct screen_info *si)
efi_call_early(free_pool, si);
 }
 
+static efi_status_t reserve_kernel_base(efi_system_table_t *sys_table_arg,
+   unsigned long dram_base,
+   unsigned long *reserve_addr,
+   unsigned long *reserve_size)
+{
+   efi_physical_addr_t alloc_addr;
+   efi_memory_desc_t *memory_map;
+   unsigned long nr_pages, map_size, desc_size, buff_size;
+   efi_status_t status;
+   unsigned long l;
+
+   struct efi_boot_memmap map = {
+   .map= _map,
+   .map_size   = _size,
+   .desc_size  = _size,
+   .desc_ver   = NULL,
+   .key_ptr= NULL,
+   .buff_size  = _size,
+   };
+
+   /*
+* Reserve memory for the uncompressed kernel image. This is
+* all that prevents any future allocations from conflicting
+* with the kernel. Since we can't tell from the compressed
+* image how much DRAM the kernel actually uses (due to BSS
+* size uncertainty) we allocate the maximum possible size.
+* Do this very early, as prints can cause memory allocations
+* that may conflict with this.
+*/
+   alloc_addr = dram_base + MAX_UNCOMP_KERNEL_SIZE;
+   nr_pages = MAX_UNCOMP_KERNEL_SIZE / EFI_PAGE_SIZE;
+   status = efi_call_early(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
+   EFI_BOOT_SERVICES_DATA, nr_pages, _addr);
+   if (status == EFI_SUCCESS) {
+   if (alloc_addr == dram_base) {
+   *reserve_addr = alloc_addr;
+   *reserve_size = MAX_UNCOMP_KERNEL_SIZE;
+   return EFI_SUCCESS;
+   }
+   /*
+* If we end up here, the allocation succeeded but starts below
+* dram_base. This can only occur if the real base of DRAM is
+* not a multiple of 128 MB, in which case dram_base will have
+* been rounded up. Since this implies that a part of the region
+* was already occupied, we need to fall through to the code
+* below to ensure that the existing allocations don't conflict.
+* For this reason, we use EFI_BOOT_SERVICES_DATA above and not
+* EFI_LOADER_DATA, which we wouldn't able to distinguish from
+* allocations that we want to disallow.
+*/
+   }
+
+   /*
+* If the allocation above failed, we may still be able to proceed:
+* if the only allocations in the region are of types that will be
+* released to the OS after ExitBootServices(), the decompressor can
+* safely overwrite them.
+*/
+   status = efi_get_memory_map(sys_table_arg, );
+   if (status != EFI_SUCCESS) {
+   pr_efi_err(sys_table_arg,
+  "reserve_kernel_base(): Unable to retrieve memory 
map.\n");
+   return status;
+   }
+
+   for (l = 0; l < map_size; l += desc_size) {
+   efi_memory_desc_t *desc;
+   u64 start, end;
+
+   desc = (void *)memory_map + l;
+   start =