All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v4 4/7] efi_loader: Track size of pool allocations to allow freeing
       [not found] <20161001213229.19522-5-stefan.bruens@rwth-aachen.de>
@ 2016-10-09 20:17 ` Stefan Brüns
  2016-10-10 11:39   ` Alexander Graf
  2016-10-13 14:34   ` [U-Boot] [U-Boot, v4, " Alexander Graf
  0 siblings, 2 replies; 3+ messages in thread
From: Stefan Brüns @ 2016-10-09 20:17 UTC (permalink / raw)
  To: u-boot

We need a functional free_pool implementation, as otherwise each
allocate_pool causes growth of the memory descriptor table.

Different to free_pages, free_pool does not provide the size for the
to be freed allocation, thus we have to track the size ourselves.

As the only EFI requirement for pool allocation is an alignment of
8 bytes, we can keep allocating a range using the page allocator,
reserve the first 8 bytes for our bookkeeping and hand out the
remainder to the caller. This saves us from having to use any
independent data structures for tracking.

To simplify the conversion between pool allocations and the corresponding
page allocation, we create an auxiliary struct efi_pool_allocation.

Given the allocation size free_pool size can handoff freeing the page
range, which was indirectly allocated by a call to allocate_pool,
to free_pages.

Signed-off-by: Stefan Br?ns <stefan.bruens@rwth-aachen.de>
---
 include/efi_loader.h          |  2 ++
 lib/efi_loader/efi_boottime.c |  6 +++---
 lib/efi_loader/efi_memory.c   | 42 +++++++++++++++++++++++++++++++++++++++---
 3 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index f0473ab..3dad24e 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -122,6 +122,8 @@ efi_status_t efi_free_pages(uint64_t memory, unsigned long pages);
 /* EFI memory allocator for small allocations */
 efi_status_t efi_allocate_pool(int pool_type, unsigned long size,
 			       void **buffer);
+/* EFI pool memory free function. */
+efi_status_t efi_free_pool(void *buffer);
 /* Returns the EFI memory map */
 efi_status_t efi_get_memory_map(unsigned long *memory_map_size,
 				struct efi_mem_desc *memory_map,
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index eb74cb0..8274d8e 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -141,12 +141,12 @@ static efi_status_t EFIAPI efi_allocate_pool_ext(int pool_type,
 	return EFI_EXIT(r);
 }
 
-static efi_status_t EFIAPI efi_free_pool(void *buffer)
+static efi_status_t EFIAPI efi_free_pool_ext(void *buffer)
 {
 	efi_status_t r;
 
 	EFI_ENTRY("%p", buffer);
-	r = efi_free_pages((ulong)buffer, 0);
+	r = efi_free_pool(buffer);
 	return EFI_EXIT(r);
 }
 
@@ -736,7 +736,7 @@ static const struct efi_boot_services efi_boot_services = {
 	.free_pages = efi_free_pages_ext,
 	.get_memory_map = efi_get_memory_map_ext,
 	.allocate_pool = efi_allocate_pool_ext,
-	.free_pool = efi_free_pool,
+	.free_pool = efi_free_pool_ext,
 	.create_event = efi_create_event,
 	.set_timer = efi_set_timer,
 	.wait_for_event = efi_wait_for_event,
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index be642f1..de28db6 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -34,6 +34,19 @@ void *efi_bounce_buffer;
 #endif
 
 /*
+ * U-Boot services each EFI AllocatePool request as a separate
+ * (multiple) page allocation.  We have to track the number of pages
+ * to be able to free the correct amount later.
+ * EFI requires 8 byte alignment for pool allocations, so we can
+ * prepend each allocation with an 64 bit header tracking the
+ * allocation size, and hand out the remainder to the caller.
+ */
+struct efi_pool_allocation {
+	u64 num_pages;
+	char data[];
+};
+
+/*
  * Sorts the memory list from highest address to lowest address
  *
  * When allocating memory we should always start from the highest
@@ -332,11 +345,34 @@ efi_status_t efi_allocate_pool(int pool_type, unsigned long size,
 {
 	efi_status_t r;
 	efi_physical_addr_t t;
-	u64 num_pages = (size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+	u64 num_pages = (size + sizeof(u64) + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
+
+	if (size == 0) {
+		*buffer = NULL;
+		return EFI_SUCCESS;
+	}
 
 	r = efi_allocate_pages(0, pool_type, num_pages, &t);
-	if (r == EFI_SUCCESS)
-		*buffer = (void *)(uintptr_t)t;
+
+	if (r == EFI_SUCCESS) {
+		struct efi_pool_allocation *alloc = (void *)(uintptr_t)t;
+		alloc->num_pages = num_pages;
+		*buffer = alloc->data;
+	}
+
+	return r;
+}
+
+efi_status_t efi_free_pool(void *buffer)
+{
+	efi_status_t r;
+	struct efi_pool_allocation *alloc;
+
+	alloc = container_of(buffer, struct efi_pool_allocation, data);
+	/* Sanity check, was the supplied address returned by allocate_pool */
+	assert(((uintptr_t)alloc & EFI_PAGE_MASK) == 0);
+
+	r = efi_free_pages((uintptr_t)alloc, alloc->num_pages);
 
 	return r;
 }
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [U-Boot] [PATCH v4 4/7] efi_loader: Track size of pool allocations to allow freeing
  2016-10-09 20:17 ` [U-Boot] [PATCH v4 4/7] efi_loader: Track size of pool allocations to allow freeing Stefan Brüns
@ 2016-10-10 11:39   ` Alexander Graf
  2016-10-13 14:34   ` [U-Boot] [U-Boot, v4, " Alexander Graf
  1 sibling, 0 replies; 3+ messages in thread
From: Alexander Graf @ 2016-10-10 11:39 UTC (permalink / raw)
  To: u-boot

On 10/09/2016 10:17 PM, Stefan Br?ns wrote:
> We need a functional free_pool implementation, as otherwise each
> allocate_pool causes growth of the memory descriptor table.
>
> Different to free_pages, free_pool does not provide the size for the
> to be freed allocation, thus we have to track the size ourselves.
>
> As the only EFI requirement for pool allocation is an alignment of
> 8 bytes, we can keep allocating a range using the page allocator,
> reserve the first 8 bytes for our bookkeeping and hand out the
> remainder to the caller. This saves us from having to use any
> independent data structures for tracking.
>
> To simplify the conversion between pool allocations and the corresponding
> page allocation, we create an auxiliary struct efi_pool_allocation.
>
> Given the allocation size free_pool size can handoff freeing the page
> range, which was indirectly allocated by a call to allocate_pool,
> to free_pages.
>
> Signed-off-by: Stefan Br?ns <stefan.bruens@rwth-aachen.de>

Reviewed-by: Alexander Graf <agraf@suse.de>


Alex

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [U-Boot] [U-Boot, v4, 4/7] efi_loader: Track size of pool allocations to allow freeing
  2016-10-09 20:17 ` [U-Boot] [PATCH v4 4/7] efi_loader: Track size of pool allocations to allow freeing Stefan Brüns
  2016-10-10 11:39   ` Alexander Graf
@ 2016-10-13 14:34   ` Alexander Graf
  1 sibling, 0 replies; 3+ messages in thread
From: Alexander Graf @ 2016-10-13 14:34 UTC (permalink / raw)
  To: u-boot

> We need a functional free_pool implementation, as otherwise each
> allocate_pool causes growth of the memory descriptor table.
> 
> Different to free_pages, free_pool does not provide the size for the
> to be freed allocation, thus we have to track the size ourselves.
> 
> As the only EFI requirement for pool allocation is an alignment of
> 8 bytes, we can keep allocating a range using the page allocator,
> reserve the first 8 bytes for our bookkeeping and hand out the
> remainder to the caller. This saves us from having to use any
> independent data structures for tracking.
> 
> To simplify the conversion between pool allocations and the corresponding
> page allocation, we create an auxiliary struct efi_pool_allocation.
> 
> Given the allocation size free_pool size can handoff freeing the page
> range, which was indirectly allocated by a call to allocate_pool,
> to free_pages.
> 
> Signed-off-by: Stefan Br?ns <stefan.bruens@rwth-aachen.de>
> Reviewed-by: Alexander Graf <agraf@suse.de>

Thanks, applied to 

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2016-10-13 14:34 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20161001213229.19522-5-stefan.bruens@rwth-aachen.de>
2016-10-09 20:17 ` [U-Boot] [PATCH v4 4/7] efi_loader: Track size of pool allocations to allow freeing Stefan Brüns
2016-10-10 11:39   ` Alexander Graf
2016-10-13 14:34   ` [U-Boot] [U-Boot, v4, " Alexander Graf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.