Pull in allocator fixes from upstream
Resolves: #2156419 Signed-off-by: Robbie Harwood <rharwood@redhat.com>
This commit is contained in:
parent
501956fdc0
commit
433335e50c
@ -1,74 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Jones <pjones@redhat.com>
|
||||
Date: Fri, 29 Jul 2022 15:57:57 -0400
|
||||
Subject: [PATCH] efi: make the default arena most of ram
|
||||
|
||||
Currently when populating the initial memory arena on EFI systems, we
|
||||
count the available regions below GRUB_EFI_MAX_ALLOCATION_ADDRESS from
|
||||
the EFI memory map and then allocates one quarter of that for our arena.
|
||||
|
||||
Because many systems come up without IOMMUs, we currently set
|
||||
GRUB_EFI_MAX_ALLOCATION_ADDRESS to 0x7fffffff, i.e. all addresses
|
||||
allocated must be below 2G[0]. Due to firmware and other
|
||||
considerations, this makes the most memory we can possibly have in our
|
||||
arena 512M.
|
||||
|
||||
Because our EFI loader doesn't get kernel and initrd memory from grub's
|
||||
allocator, but rather reserves it directly from UEFI and then simply
|
||||
marks those as allocated if they're within grub's arena, it was
|
||||
historically possible to have initrds that are larger than 512M, because
|
||||
we could use any memory region below 4G, without concern for grub's
|
||||
choice of arena size.
|
||||
|
||||
Unfortunately, when we switched to using the "verifiers" API (and thus
|
||||
the file_filter_t API) to do measurement of kernel and initrd, this
|
||||
introduced a pattern that allocates the entire file when we call
|
||||
grub_file_open(), and buffers it to pass to the filter. This results in
|
||||
needing to have enough space for the initramfs in the grub arena.
|
||||
|
||||
This is bad.
|
||||
|
||||
Since it's unlikely you're going to do anything *other* than loading a
|
||||
kernel and initramfs that takes much of the available free memory from
|
||||
UEFI, this patch introduces a workaround by changing the amount we give
|
||||
to the arena be three quarters of the available memory, rather than one
|
||||
quarter, thus changing our theoretical initrd limit to 1.5G. In
|
||||
practice, it may still be smaller than that depending on allocation
|
||||
fragmentation, but generally it will be most of it.
|
||||
|
||||
Note that this doesn't fix the underlying flaw, which is that there is
|
||||
no safe way to do the validation correctly using the "verifiers" system
|
||||
with the current file API without buffering the whole file before
|
||||
grub_file_read() is ever called, and thus you can't set an allocation
|
||||
policy for the initial buffer of the file at all, so unless we raise the
|
||||
allocation limit to >4G, it can't be allocated in the big region.
|
||||
|
||||
[0] I'm not sure there was a good reason not to pick 4G, but even if we
|
||||
had, at least one common firmware routes the first 2G of physical
|
||||
RAM to 0x0, and any additional memory starting at 0x100000000.
|
||||
|
||||
Related: rhbz#2112134
|
||||
|
||||
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||||
(cherry picked from commit 005a0aaaad2a00a1fa1e60d94cc4fd5407c22e7d)
|
||||
---
|
||||
grub-core/kern/efi/mm.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
|
||||
index 88364d764c..0288eab361 100644
|
||||
--- a/grub-core/kern/efi/mm.c
|
||||
+++ b/grub-core/kern/efi/mm.c
|
||||
@@ -738,10 +738,10 @@ grub_efi_mm_init (void)
|
||||
filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map,
|
||||
desc_size, memory_map_end);
|
||||
|
||||
- /* By default, request a quarter of the available memory. */
|
||||
+ /* By default, request three quarters of the available memory. */
|
||||
total_pages = get_total_pages (filtered_memory_map, desc_size,
|
||||
filtered_memory_map_end);
|
||||
- required_pages = (total_pages >> 2);
|
||||
+ required_pages = (total_pages >> 1) + (total_pages >> 2);
|
||||
if (required_pages < BYTES_TO_PAGES (MIN_HEAP_SIZE))
|
||||
required_pages = BYTES_TO_PAGES (MIN_HEAP_SIZE);
|
||||
else if (required_pages > BYTES_TO_PAGES (MAX_HEAP_SIZE))
|
184
0308-mm-Clarify-grub_real_malloc.patch
Normal file
184
0308-mm-Clarify-grub_real_malloc.patch
Normal file
@ -0,0 +1,184 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Thu, 25 Nov 2021 02:22:46 +1100
|
||||
Subject: [PATCH] mm: Clarify grub_real_malloc()
|
||||
|
||||
When iterating through the singly linked list of free blocks,
|
||||
grub_real_malloc() uses p and q for the current and previous blocks
|
||||
respectively. This isn't super clear, so swap to using prev and cur.
|
||||
|
||||
This makes another quirk more obvious. The comment at the top of
|
||||
grub_real_malloc() might lead you to believe that the function will
|
||||
allocate from *first if there is space in that block.
|
||||
|
||||
It actually doesn't do that, and it can't do that with the current
|
||||
data structures. If we used up all of *first, we would need to change
|
||||
the ->next of the previous block to point to *first->next, but we
|
||||
can't do that because it's a singly linked list and we don't have
|
||||
access to *first's previous block.
|
||||
|
||||
What grub_real_malloc() actually does is set *first to the initial
|
||||
previous block, and *first->next is the block we try to allocate
|
||||
from. That allows us to keep all the data structures consistent.
|
||||
|
||||
Document that.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
(cherry picked from commit 246ad6a44c281bb13486ddea0a26bb661db73106)
|
||||
(cherry picked from commit b590e0181a94b3d48ca0c537565c946fad8e6a4f)
|
||||
---
|
||||
grub-core/kern/mm.c | 76 +++++++++++++++++++++++++++++------------------------
|
||||
1 file changed, 41 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
|
||||
index d8c8377578..fb20e93acf 100644
|
||||
--- a/grub-core/kern/mm.c
|
||||
+++ b/grub-core/kern/mm.c
|
||||
@@ -178,13 +178,20 @@ grub_mm_init_region (void *addr, grub_size_t size)
|
||||
}
|
||||
|
||||
/* Allocate the number of units N with the alignment ALIGN from the ring
|
||||
- buffer starting from *FIRST. ALIGN must be a power of two. Both N and
|
||||
- ALIGN are in units of GRUB_MM_ALIGN. Return a non-NULL if successful,
|
||||
- otherwise return NULL. */
|
||||
+ * buffer given in *FIRST. ALIGN must be a power of two. Both N and
|
||||
+ * ALIGN are in units of GRUB_MM_ALIGN. Return a non-NULL if successful,
|
||||
+ * otherwise return NULL.
|
||||
+ *
|
||||
+ * Note: because in certain circumstances we need to adjust the ->next
|
||||
+ * pointer of the previous block, we iterate over the singly linked
|
||||
+ * list with the pair (prev, cur). *FIRST is our initial previous, and
|
||||
+ * *FIRST->next is our initial current pointer. So we will actually
|
||||
+ * allocate from *FIRST->next first and *FIRST itself last.
|
||||
+ */
|
||||
static void *
|
||||
grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
|
||||
{
|
||||
- grub_mm_header_t p, q;
|
||||
+ grub_mm_header_t cur, prev;
|
||||
|
||||
/* When everything is allocated side effect is that *first will have alloc
|
||||
magic marked, meaning that there is no room in this region. */
|
||||
@@ -192,24 +199,24 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
|
||||
return 0;
|
||||
|
||||
/* Try to search free slot for allocation in this memory region. */
|
||||
- for (q = *first, p = q->next; ; q = p, p = p->next)
|
||||
+ for (prev = *first, cur = prev->next; ; prev = cur, cur = cur->next)
|
||||
{
|
||||
grub_off_t extra;
|
||||
|
||||
- extra = ((grub_addr_t) (p + 1) >> GRUB_MM_ALIGN_LOG2) & (align - 1);
|
||||
+ extra = ((grub_addr_t) (cur + 1) >> GRUB_MM_ALIGN_LOG2) & (align - 1);
|
||||
if (extra)
|
||||
extra = align - extra;
|
||||
|
||||
- if (! p)
|
||||
+ if (! cur)
|
||||
grub_fatal ("null in the ring");
|
||||
|
||||
- if (p->magic != GRUB_MM_FREE_MAGIC)
|
||||
- grub_fatal ("free magic is broken at %p: 0x%x", p, p->magic);
|
||||
+ if (cur->magic != GRUB_MM_FREE_MAGIC)
|
||||
+ grub_fatal ("free magic is broken at %p: 0x%x", cur, cur->magic);
|
||||
|
||||
- if (p->size >= n + extra)
|
||||
+ if (cur->size >= n + extra)
|
||||
{
|
||||
- extra += (p->size - extra - n) & (~(align - 1));
|
||||
- if (extra == 0 && p->size == n)
|
||||
+ extra += (cur->size - extra - n) & (~(align - 1));
|
||||
+ if (extra == 0 && cur->size == n)
|
||||
{
|
||||
/* There is no special alignment requirement and memory block
|
||||
is complete match.
|
||||
@@ -222,9 +229,9 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
|
||||
| alloc, size=n | |
|
||||
+---------------+ v
|
||||
*/
|
||||
- q->next = p->next;
|
||||
+ prev->next = cur->next;
|
||||
}
|
||||
- else if (align == 1 || p->size == n + extra)
|
||||
+ else if (align == 1 || cur->size == n + extra)
|
||||
{
|
||||
/* There might be alignment requirement, when taking it into
|
||||
account memory block fits in.
|
||||
@@ -241,23 +248,22 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
|
||||
| alloc, size=n | |
|
||||
+---------------+ v
|
||||
*/
|
||||
-
|
||||
- p->size -= n;
|
||||
- p += p->size;
|
||||
+ cur->size -= n;
|
||||
+ cur += cur->size;
|
||||
}
|
||||
else if (extra == 0)
|
||||
{
|
||||
grub_mm_header_t r;
|
||||
|
||||
- r = p + extra + n;
|
||||
+ r = cur + extra + n;
|
||||
r->magic = GRUB_MM_FREE_MAGIC;
|
||||
- r->size = p->size - extra - n;
|
||||
- r->next = p->next;
|
||||
- q->next = r;
|
||||
+ r->size = cur->size - extra - n;
|
||||
+ r->next = cur->next;
|
||||
+ prev->next = r;
|
||||
|
||||
- if (q == p)
|
||||
+ if (prev == cur)
|
||||
{
|
||||
- q = r;
|
||||
+ prev = r;
|
||||
r->next = r;
|
||||
}
|
||||
}
|
||||
@@ -284,32 +290,32 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
|
||||
*/
|
||||
grub_mm_header_t r;
|
||||
|
||||
- r = p + extra + n;
|
||||
+ r = cur + extra + n;
|
||||
r->magic = GRUB_MM_FREE_MAGIC;
|
||||
- r->size = p->size - extra - n;
|
||||
- r->next = p;
|
||||
+ r->size = cur->size - extra - n;
|
||||
+ r->next = cur;
|
||||
|
||||
- p->size = extra;
|
||||
- q->next = r;
|
||||
- p += extra;
|
||||
+ cur->size = extra;
|
||||
+ prev->next = r;
|
||||
+ cur += extra;
|
||||
}
|
||||
|
||||
- p->magic = GRUB_MM_ALLOC_MAGIC;
|
||||
- p->size = n;
|
||||
+ cur->magic = GRUB_MM_ALLOC_MAGIC;
|
||||
+ cur->size = n;
|
||||
|
||||
/* Mark find as a start marker for next allocation to fasten it.
|
||||
This will have side effect of fragmenting memory as small
|
||||
pieces before this will be un-used. */
|
||||
/* So do it only for chunks under 64K. */
|
||||
if (n < (0x8000 >> GRUB_MM_ALIGN_LOG2)
|
||||
- || *first == p)
|
||||
- *first = q;
|
||||
+ || *first == cur)
|
||||
+ *first = prev;
|
||||
|
||||
- return p + 1;
|
||||
+ return cur + 1;
|
||||
}
|
||||
|
||||
/* Search was completed without result. */
|
||||
- if (p == *first)
|
||||
+ if (cur == *first)
|
||||
break;
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Thu, 25 Nov 2021 02:22:47 +1100
|
||||
Subject: [PATCH] mm: grub_real_malloc(): Make small allocs comment match code
|
||||
|
||||
Small allocations move the region's *first pointer. The comment
|
||||
says that this happens for allocations under 64K. The code says
|
||||
it's for allocations under 32K. Commit 45bf8b3a7549 changed the
|
||||
code intentionally: make the comment match.
|
||||
|
||||
Fixes: 45bf8b3a7549 (* grub-core/kern/mm.c (grub_real_malloc): Decrease cut-off of moving the)
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
(cherry picked from commit a847895a8d000bdf27ad4d4326f883a0eed769ca)
|
||||
(cherry picked from commit 16f329218ced9302554bde95084e6a2ad308733b)
|
||||
---
|
||||
grub-core/kern/mm.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
|
||||
index fb20e93acf..db7e0b2a5b 100644
|
||||
--- a/grub-core/kern/mm.c
|
||||
+++ b/grub-core/kern/mm.c
|
||||
@@ -306,7 +306,7 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align)
|
||||
/* Mark find as a start marker for next allocation to fasten it.
|
||||
This will have side effect of fragmenting memory as small
|
||||
pieces before this will be un-used. */
|
||||
- /* So do it only for chunks under 64K. */
|
||||
+ /* So do it only for chunks under 32K. */
|
||||
if (n < (0x8000 >> GRUB_MM_ALIGN_LOG2)
|
||||
|| *first == cur)
|
||||
*first = prev;
|
121
0310-mm-Document-grub_free.patch
Normal file
121
0310-mm-Document-grub_free.patch
Normal file
@ -0,0 +1,121 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Thu, 25 Nov 2021 02:22:48 +1100
|
||||
Subject: [PATCH] mm: Document grub_free()
|
||||
|
||||
The grub_free() possesses a surprising number of quirks, and also
|
||||
uses single-letter variable names confusingly to iterate through
|
||||
the free list.
|
||||
|
||||
Document what's going on.
|
||||
|
||||
Use prev and cur to iterate over the free list.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
(cherry picked from commit 1f8d0b01738e49767d662d6426af3570a64565f0)
|
||||
(cherry picked from commit 6fd181e46a16f0219b586ce0bd44928a3f58dec8)
|
||||
---
|
||||
grub-core/kern/mm.c | 63 ++++++++++++++++++++++++++++++++++-------------------
|
||||
1 file changed, 41 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
|
||||
index db7e0b2a5b..0351171cf9 100644
|
||||
--- a/grub-core/kern/mm.c
|
||||
+++ b/grub-core/kern/mm.c
|
||||
@@ -446,54 +446,73 @@ grub_free (void *ptr)
|
||||
}
|
||||
else
|
||||
{
|
||||
- grub_mm_header_t q, s;
|
||||
+ grub_mm_header_t cur, prev;
|
||||
|
||||
#if 0
|
||||
- q = r->first;
|
||||
+ cur = r->first;
|
||||
do
|
||||
{
|
||||
grub_printf ("%s:%d: q=%p, q->size=0x%x, q->magic=0x%x\n",
|
||||
- GRUB_FILE, __LINE__, q, q->size, q->magic);
|
||||
- q = q->next;
|
||||
+ GRUB_FILE, __LINE__, cur, cur->size, cur->magic);
|
||||
+ cur = cur->next;
|
||||
}
|
||||
- while (q != r->first);
|
||||
+ while (cur != r->first);
|
||||
#endif
|
||||
-
|
||||
- for (s = r->first, q = s->next; q <= p || q->next >= p; s = q, q = s->next)
|
||||
+ /* Iterate over all blocks in the free ring.
|
||||
+ *
|
||||
+ * The free ring is arranged from high addresses to low
|
||||
+ * addresses, modulo wraparound.
|
||||
+ *
|
||||
+ * We are looking for a block with a higher address than p or
|
||||
+ * whose next address is lower than p.
|
||||
+ */
|
||||
+ for (prev = r->first, cur = prev->next; cur <= p || cur->next >= p;
|
||||
+ prev = cur, cur = prev->next)
|
||||
{
|
||||
- if (q->magic != GRUB_MM_FREE_MAGIC)
|
||||
- grub_fatal ("free magic is broken at %p: 0x%x", q, q->magic);
|
||||
+ if (cur->magic != GRUB_MM_FREE_MAGIC)
|
||||
+ grub_fatal ("free magic is broken at %p: 0x%x", cur, cur->magic);
|
||||
|
||||
- if (q <= q->next && (q > p || q->next < p))
|
||||
+ /* Deal with wrap-around */
|
||||
+ if (cur <= cur->next && (cur > p || cur->next < p))
|
||||
break;
|
||||
}
|
||||
|
||||
+ /* mark p as free and insert it between cur and cur->next */
|
||||
p->magic = GRUB_MM_FREE_MAGIC;
|
||||
- p->next = q->next;
|
||||
- q->next = p;
|
||||
+ p->next = cur->next;
|
||||
+ cur->next = p;
|
||||
|
||||
+ /*
|
||||
+ * If the block we are freeing can be merged with the next
|
||||
+ * free block, do that.
|
||||
+ */
|
||||
if (p->next + p->next->size == p)
|
||||
{
|
||||
p->magic = 0;
|
||||
|
||||
p->next->size += p->size;
|
||||
- q->next = p->next;
|
||||
+ cur->next = p->next;
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
- r->first = q;
|
||||
+ r->first = cur;
|
||||
|
||||
- if (q == p + p->size)
|
||||
+ /* Likewise if can be merged with the preceeding free block */
|
||||
+ if (cur == p + p->size)
|
||||
{
|
||||
- q->magic = 0;
|
||||
- p->size += q->size;
|
||||
- if (q == s)
|
||||
- s = p;
|
||||
- s->next = p;
|
||||
- q = s;
|
||||
+ cur->magic = 0;
|
||||
+ p->size += cur->size;
|
||||
+ if (cur == prev)
|
||||
+ prev = p;
|
||||
+ prev->next = p;
|
||||
+ cur = prev;
|
||||
}
|
||||
|
||||
- r->first = q;
|
||||
+ /*
|
||||
+ * Set r->first such that the just free()d block is tried first.
|
||||
+ * (An allocation is tried from *first->next, and cur->next == p.)
|
||||
+ */
|
||||
+ r->first = cur;
|
||||
}
|
||||
}
|
||||
|
74
0311-mm-Document-grub_mm_init_region.patch
Normal file
74
0311-mm-Document-grub_mm_init_region.patch
Normal file
@ -0,0 +1,74 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Thu, 25 Nov 2021 02:22:49 +1100
|
||||
Subject: [PATCH] mm: Document grub_mm_init_region()
|
||||
|
||||
The grub_mm_init_region() does some things that seem magical, especially
|
||||
around region merging. Make it a bit clearer.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
(cherry picked from commit 246d69b7ea619fc1e77dcc5960e37aea45a9808c)
|
||||
(cherry picked from commit 1eb53ad7659ee1d8141fe31138d0df9873b09182)
|
||||
---
|
||||
grub-core/kern/mm.c | 31 ++++++++++++++++++++++++++++++-
|
||||
1 file changed, 30 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
|
||||
index 0351171cf9..1cbf98c7ab 100644
|
||||
--- a/grub-core/kern/mm.c
|
||||
+++ b/grub-core/kern/mm.c
|
||||
@@ -128,23 +128,52 @@ grub_mm_init_region (void *addr, grub_size_t size)
|
||||
if (((grub_addr_t) addr + 0x1000) > ~(grub_addr_t) size)
|
||||
size = ((grub_addr_t) -0x1000) - (grub_addr_t) addr;
|
||||
|
||||
+ /* Attempt to merge this region with every existing region */
|
||||
for (p = &grub_mm_base, q = *p; q; p = &(q->next), q = *p)
|
||||
+ /*
|
||||
+ * Is the new region immediately below an existing region? That
|
||||
+ * is, is the address of the memory we're adding now (addr) + size
|
||||
+ * of the memory we're adding (size) + the bytes we couldn't use
|
||||
+ * at the start of the region we're considering (q->pre_size)
|
||||
+ * equal to the address of q? In other words, does the memory
|
||||
+ * looks like this?
|
||||
+ *
|
||||
+ * addr q
|
||||
+ * |----size-----|-q->pre_size-|<q region>|
|
||||
+ */
|
||||
if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q)
|
||||
{
|
||||
+ /*
|
||||
+ * Yes, we can merge the memory starting at addr into the
|
||||
+ * existing region from below. Align up addr to GRUB_MM_ALIGN
|
||||
+ * so that our new region has proper alignment.
|
||||
+ */
|
||||
r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN);
|
||||
+ /* Copy the region data across */
|
||||
*r = *q;
|
||||
+ /* Consider all the new size as pre-size */
|
||||
r->pre_size += size;
|
||||
-
|
||||
+
|
||||
+ /*
|
||||
+ * If we have enough pre-size to create a block, create a
|
||||
+ * block with it. Mark it as allocated and pass it to
|
||||
+ * grub_free (), which will sort out getting it into the free
|
||||
+ * list.
|
||||
+ */
|
||||
if (r->pre_size >> GRUB_MM_ALIGN_LOG2)
|
||||
{
|
||||
h = (grub_mm_header_t) (r + 1);
|
||||
+ /* block size is pre-size converted to cells */
|
||||
h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2);
|
||||
h->magic = GRUB_MM_ALLOC_MAGIC;
|
||||
+ /* region size grows by block size converted back to bytes */
|
||||
r->size += h->size << GRUB_MM_ALIGN_LOG2;
|
||||
+ /* adjust pre_size to be accurate */
|
||||
r->pre_size &= (GRUB_MM_ALIGN - 1);
|
||||
*p = r;
|
||||
grub_free (h + 1);
|
||||
}
|
||||
+ /* Replace the old region with the new region */
|
||||
*p = r;
|
||||
return;
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Thu, 25 Nov 2021 02:22:45 +1100
|
||||
Subject: [PATCH] mm: Document GRUB internal memory management structures
|
||||
|
||||
I spent more than a trivial quantity of time figuring out pre_size and
|
||||
whether a memory region's size contains the header cell or not.
|
||||
|
||||
Document the meanings of all the properties. Hopefully now no-one else
|
||||
has to figure it out!
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
(cherry picked from commit a6c5c52ccffd2674d43db25fb4baa9c528526aa0)
|
||||
(cherry picked from commit 222eb8897c25581e63a352633528fc130d151a64)
|
||||
---
|
||||
include/grub/mm_private.h | 28 ++++++++++++++++++++++++++++
|
||||
1 file changed, 28 insertions(+)
|
||||
|
||||
diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h
|
||||
index c2c4cb1511..203533cc3d 100644
|
||||
--- a/include/grub/mm_private.h
|
||||
+++ b/include/grub/mm_private.h
|
||||
@@ -21,15 +21,27 @@
|
||||
|
||||
#include <grub/mm.h>
|
||||
|
||||
+/* For context, see kern/mm.c */
|
||||
+
|
||||
/* Magic words. */
|
||||
#define GRUB_MM_FREE_MAGIC 0x2d3c2808
|
||||
#define GRUB_MM_ALLOC_MAGIC 0x6db08fa4
|
||||
|
||||
+/* A header describing a block of memory - either allocated or free */
|
||||
typedef struct grub_mm_header
|
||||
{
|
||||
+ /*
|
||||
+ * The 'next' free block in this region's circular free list.
|
||||
+ * Only meaningful if the block is free.
|
||||
+ */
|
||||
struct grub_mm_header *next;
|
||||
+ /* The block size, not in bytes but the number of cells of
|
||||
+ * GRUB_MM_ALIGN bytes. Includes the header cell.
|
||||
+ */
|
||||
grub_size_t size;
|
||||
+ /* either free or alloc magic, depending on the block type. */
|
||||
grub_size_t magic;
|
||||
+ /* pad to cell size: see the top of kern/mm.c. */
|
||||
#if GRUB_CPU_SIZEOF_VOID_P == 4
|
||||
char padding[4];
|
||||
#elif GRUB_CPU_SIZEOF_VOID_P == 8
|
||||
@@ -48,11 +60,27 @@ typedef struct grub_mm_header
|
||||
|
||||
#define GRUB_MM_ALIGN (1 << GRUB_MM_ALIGN_LOG2)
|
||||
|
||||
+/* A region from which we can make allocations. */
|
||||
typedef struct grub_mm_region
|
||||
{
|
||||
+ /* The first free block in this region. */
|
||||
struct grub_mm_header *first;
|
||||
+
|
||||
+ /*
|
||||
+ * The next region in the linked list of regions. Regions are initially
|
||||
+ * sorted in order of increasing size, but can grow, in which case the
|
||||
+ * ordering may not be preserved.
|
||||
+ */
|
||||
struct grub_mm_region *next;
|
||||
+
|
||||
+ /*
|
||||
+ * A grub_mm_region will always be aligned to cell size. The pre-size is
|
||||
+ * the number of bytes we were given but had to skip in order to get that
|
||||
+ * alignment.
|
||||
+ */
|
||||
grub_size_t pre_size;
|
||||
+
|
||||
+ /* How many bytes are in this region? (free and allocated) */
|
||||
grub_size_t size;
|
||||
}
|
||||
*grub_mm_region_t;
|
@ -0,0 +1,57 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Thu, 21 Apr 2022 15:24:14 +1000
|
||||
Subject: [PATCH] mm: Assert that we preserve header vs region alignment
|
||||
|
||||
grub_mm_region_init() does:
|
||||
|
||||
h = (grub_mm_header_t) (r + 1);
|
||||
|
||||
where h is a grub_mm_header_t and r is a grub_mm_region_t.
|
||||
|
||||
Cells are supposed to be GRUB_MM_ALIGN aligned, but while grub_mm_dump
|
||||
ensures this vs the region header, grub_mm_region_init() does not.
|
||||
|
||||
It's better to be explicit than implicit here: rather than changing
|
||||
grub_mm_region_init() to ALIGN_UP(), require that the struct is
|
||||
explicitly a multiple of the header size.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Tested-by: Patrick Steinhardt <ps@pks.im>
|
||||
(cherry picked from commit 1df8fe66c57087eb33bd6dc69f786ed124615aa7)
|
||||
(cherry picked from commit f4d39686e773274e690ada441f5e128ac3c4ac06)
|
||||
---
|
||||
include/grub/mm_private.h | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h
|
||||
index 203533cc3d..a688b92a83 100644
|
||||
--- a/include/grub/mm_private.h
|
||||
+++ b/include/grub/mm_private.h
|
||||
@@ -20,6 +20,7 @@
|
||||
#define GRUB_MM_PRIVATE_H 1
|
||||
|
||||
#include <grub/mm.h>
|
||||
+#include <grub/misc.h>
|
||||
|
||||
/* For context, see kern/mm.c */
|
||||
|
||||
@@ -89,4 +90,17 @@ typedef struct grub_mm_region
|
||||
extern grub_mm_region_t EXPORT_VAR (grub_mm_base);
|
||||
#endif
|
||||
|
||||
+static inline void
|
||||
+grub_mm_size_sanity_check (void) {
|
||||
+ /* Ensure we preserve alignment when doing h = (grub_mm_header_t) (r + 1). */
|
||||
+ COMPILE_TIME_ASSERT ((sizeof (struct grub_mm_region) %
|
||||
+ sizeof (struct grub_mm_header)) == 0);
|
||||
+
|
||||
+ /*
|
||||
+ * GRUB_MM_ALIGN is supposed to represent cell size, and a mm_header is
|
||||
+ * supposed to be 1 cell.
|
||||
+ */
|
||||
+ COMPILE_TIME_ASSERT (sizeof (struct grub_mm_header) == GRUB_MM_ALIGN);
|
||||
+}
|
||||
+
|
||||
#endif
|
204
0314-mm-When-adding-a-region-merge-with-region-after-as-w.patch
Normal file
204
0314-mm-When-adding-a-region-merge-with-region-after-as-w.patch
Normal file
@ -0,0 +1,204 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Thu, 21 Apr 2022 15:24:15 +1000
|
||||
Subject: [PATCH] mm: When adding a region, merge with region after as well as
|
||||
before
|
||||
|
||||
On x86_64-efi (at least) regions seem to be added from top down. The mm
|
||||
code will merge a new region with an existing region that comes
|
||||
immediately before the new region. This allows larger allocations to be
|
||||
satisfied that would otherwise be the case.
|
||||
|
||||
On powerpc-ieee1275, however, regions are added from bottom up. So if
|
||||
we add 3x 32MB regions, we can still only satisfy a 32MB allocation,
|
||||
rather than the 96MB allocation we might otherwise be able to satisfy.
|
||||
|
||||
* Define 'post_size' as being bytes lost to the end of an allocation
|
||||
due to being given weird sizes from firmware that are not multiples
|
||||
of GRUB_MM_ALIGN.
|
||||
|
||||
* Allow merging of regions immediately _after_ existing regions, not
|
||||
just before. As with the other approach, we create an allocated
|
||||
block to represent the new space and the pass it to grub_free() to
|
||||
get the metadata right.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Tested-by: Patrick Steinhardt <ps@pks.im>
|
||||
(cherry picked from commit 052e6068be622ff53f1238b449c300dbd0a8abcd)
|
||||
(cherry picked from commit 9b7b9820e37b6828ea9b7da15f8da952a53a3df5)
|
||||
---
|
||||
grub-core/kern/mm.c | 128 +++++++++++++++++++++++++++++-----------------
|
||||
include/grub/mm_private.h | 9 ++++
|
||||
2 files changed, 91 insertions(+), 46 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
|
||||
index 1cbf98c7ab..7be33e23bf 100644
|
||||
--- a/grub-core/kern/mm.c
|
||||
+++ b/grub-core/kern/mm.c
|
||||
@@ -130,53 +130,88 @@ grub_mm_init_region (void *addr, grub_size_t size)
|
||||
|
||||
/* Attempt to merge this region with every existing region */
|
||||
for (p = &grub_mm_base, q = *p; q; p = &(q->next), q = *p)
|
||||
- /*
|
||||
- * Is the new region immediately below an existing region? That
|
||||
- * is, is the address of the memory we're adding now (addr) + size
|
||||
- * of the memory we're adding (size) + the bytes we couldn't use
|
||||
- * at the start of the region we're considering (q->pre_size)
|
||||
- * equal to the address of q? In other words, does the memory
|
||||
- * looks like this?
|
||||
- *
|
||||
- * addr q
|
||||
- * |----size-----|-q->pre_size-|<q region>|
|
||||
- */
|
||||
- if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q)
|
||||
- {
|
||||
- /*
|
||||
- * Yes, we can merge the memory starting at addr into the
|
||||
- * existing region from below. Align up addr to GRUB_MM_ALIGN
|
||||
- * so that our new region has proper alignment.
|
||||
- */
|
||||
- r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN);
|
||||
- /* Copy the region data across */
|
||||
- *r = *q;
|
||||
- /* Consider all the new size as pre-size */
|
||||
- r->pre_size += size;
|
||||
+ {
|
||||
+ /*
|
||||
+ * Is the new region immediately below an existing region? That
|
||||
+ * is, is the address of the memory we're adding now (addr) + size
|
||||
+ * of the memory we're adding (size) + the bytes we couldn't use
|
||||
+ * at the start of the region we're considering (q->pre_size)
|
||||
+ * equal to the address of q? In other words, does the memory
|
||||
+ * looks like this?
|
||||
+ *
|
||||
+ * addr q
|
||||
+ * |----size-----|-q->pre_size-|<q region>|
|
||||
+ */
|
||||
+ if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q)
|
||||
+ {
|
||||
+ /*
|
||||
+ * Yes, we can merge the memory starting at addr into the
|
||||
+ * existing region from below. Align up addr to GRUB_MM_ALIGN
|
||||
+ * so that our new region has proper alignment.
|
||||
+ */
|
||||
+ r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN);
|
||||
+ /* Copy the region data across */
|
||||
+ *r = *q;
|
||||
+ /* Consider all the new size as pre-size */
|
||||
+ r->pre_size += size;
|
||||
|
||||
- /*
|
||||
- * If we have enough pre-size to create a block, create a
|
||||
- * block with it. Mark it as allocated and pass it to
|
||||
- * grub_free (), which will sort out getting it into the free
|
||||
- * list.
|
||||
- */
|
||||
- if (r->pre_size >> GRUB_MM_ALIGN_LOG2)
|
||||
- {
|
||||
- h = (grub_mm_header_t) (r + 1);
|
||||
- /* block size is pre-size converted to cells */
|
||||
- h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2);
|
||||
- h->magic = GRUB_MM_ALLOC_MAGIC;
|
||||
- /* region size grows by block size converted back to bytes */
|
||||
- r->size += h->size << GRUB_MM_ALIGN_LOG2;
|
||||
- /* adjust pre_size to be accurate */
|
||||
- r->pre_size &= (GRUB_MM_ALIGN - 1);
|
||||
- *p = r;
|
||||
- grub_free (h + 1);
|
||||
- }
|
||||
- /* Replace the old region with the new region */
|
||||
- *p = r;
|
||||
- return;
|
||||
- }
|
||||
+ /*
|
||||
+ * If we have enough pre-size to create a block, create a
|
||||
+ * block with it. Mark it as allocated and pass it to
|
||||
+ * grub_free (), which will sort out getting it into the free
|
||||
+ * list.
|
||||
+ */
|
||||
+ if (r->pre_size >> GRUB_MM_ALIGN_LOG2)
|
||||
+ {
|
||||
+ h = (grub_mm_header_t) (r + 1);
|
||||
+ /* block size is pre-size converted to cells */
|
||||
+ h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2);
|
||||
+ h->magic = GRUB_MM_ALLOC_MAGIC;
|
||||
+ /* region size grows by block size converted back to bytes */
|
||||
+ r->size += h->size << GRUB_MM_ALIGN_LOG2;
|
||||
+ /* adjust pre_size to be accurate */
|
||||
+ r->pre_size &= (GRUB_MM_ALIGN - 1);
|
||||
+ *p = r;
|
||||
+ grub_free (h + 1);
|
||||
+ }
|
||||
+ /* Replace the old region with the new region */
|
||||
+ *p = r;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Is the new region immediately above an existing region? That
|
||||
+ * is:
|
||||
+ * q addr
|
||||
+ * |<q region>|-q->post_size-|----size-----|
|
||||
+ */
|
||||
+ if ((grub_uint8_t *) q + sizeof (*q) + q->size + q->post_size ==
|
||||
+ (grub_uint8_t *) addr)
|
||||
+ {
|
||||
+ /*
|
||||
+ * Yes! Follow a similar pattern to above, but simpler.
|
||||
+ * Our header starts at address - post_size, which should align us
|
||||
+ * to a cell boundary.
|
||||
+ *
|
||||
+ * Cast to (void *) first to avoid the following build error:
|
||||
+ * kern/mm.c: In function ‘grub_mm_init_region’:
|
||||
+ * kern/mm.c:211:15: error: cast increases required alignment of target type [-Werror=cast-align]
|
||||
+ * 211 | h = (grub_mm_header_t) ((grub_uint8_t *) addr - q->post_size);
|
||||
+ * | ^
|
||||
+ * It is safe to do that because proper alignment is enforced in grub_mm_size_sanity_check().
|
||||
+ */
|
||||
+ h = (grub_mm_header_t)(void *) ((grub_uint8_t *) addr - q->post_size);
|
||||
+ /* our size is the allocated size plus post_size, in cells */
|
||||
+ h->size = (size + q->post_size) >> GRUB_MM_ALIGN_LOG2;
|
||||
+ h->magic = GRUB_MM_ALLOC_MAGIC;
|
||||
+ /* region size grows by block size converted back to bytes */
|
||||
+ q->size += h->size << GRUB_MM_ALIGN_LOG2;
|
||||
+ /* adjust new post_size to be accurate */
|
||||
+ q->post_size = (q->post_size + size) & (GRUB_MM_ALIGN - 1);
|
||||
+ grub_free (h + 1);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
/* Allocate a region from the head. */
|
||||
r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN);
|
||||
@@ -195,6 +230,7 @@ grub_mm_init_region (void *addr, grub_size_t size)
|
||||
r->first = h;
|
||||
r->pre_size = (grub_addr_t) r - (grub_addr_t) addr;
|
||||
r->size = (h->size << GRUB_MM_ALIGN_LOG2);
|
||||
+ r->post_size = size - r->size;
|
||||
|
||||
/* Find where to insert this region. Put a smaller one before bigger ones,
|
||||
to prevent fragmentation. */
|
||||
diff --git a/include/grub/mm_private.h b/include/grub/mm_private.h
|
||||
index a688b92a83..96c2d816be 100644
|
||||
--- a/include/grub/mm_private.h
|
||||
+++ b/include/grub/mm_private.h
|
||||
@@ -81,8 +81,17 @@ typedef struct grub_mm_region
|
||||
*/
|
||||
grub_size_t pre_size;
|
||||
|
||||
+ /*
|
||||
+ * Likewise, the post-size is the number of bytes we wasted at the end
|
||||
+ * of the allocation because it wasn't a multiple of GRUB_MM_ALIGN
|
||||
+ */
|
||||
+ grub_size_t post_size;
|
||||
+
|
||||
/* How many bytes are in this region? (free and allocated) */
|
||||
grub_size_t size;
|
||||
+
|
||||
+ /* pad to a multiple of cell size */
|
||||
+ char padding[3 * GRUB_CPU_SIZEOF_VOID_P];
|
||||
}
|
||||
*grub_mm_region_t;
|
||||
|
72
0315-mm-Debug-support-for-region-operations.patch
Normal file
72
0315-mm-Debug-support-for-region-operations.patch
Normal file
@ -0,0 +1,72 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Thu, 21 Apr 2022 15:24:16 +1000
|
||||
Subject: [PATCH] mm: Debug support for region operations
|
||||
|
||||
This is handy for debugging. Enable with "set debug=regions".
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Tested-by: Patrick Steinhardt <ps@pks.im>
|
||||
(cherry picked from commit 8afa5ef45b797ba5d8147ceee85ac2c59dcc7f09)
|
||||
(cherry picked from commit 4eb79abc52d35f40afc21e241561cf1dd8251a7b)
|
||||
---
|
||||
grub-core/kern/mm.c | 19 ++++++++++++++++---
|
||||
1 file changed, 16 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
|
||||
index 7be33e23bf..38bfb01df9 100644
|
||||
--- a/grub-core/kern/mm.c
|
||||
+++ b/grub-core/kern/mm.c
|
||||
@@ -115,9 +115,8 @@ grub_mm_init_region (void *addr, grub_size_t size)
|
||||
grub_mm_header_t h;
|
||||
grub_mm_region_t r, *p, q;
|
||||
|
||||
-#if 0
|
||||
- grub_printf ("Using memory for heap: start=%p, end=%p\n", addr, addr + (unsigned int) size);
|
||||
-#endif
|
||||
+ grub_dprintf ("regions", "Using memory for heap: start=%p, end=%p\n",
|
||||
+ addr, (char *) addr + (unsigned int) size);
|
||||
|
||||
/* Exclude last 4K to avoid overflows. */
|
||||
/* If addr + 0x1000 overflows then whole region is in excluded zone. */
|
||||
@@ -142,8 +141,14 @@ grub_mm_init_region (void *addr, grub_size_t size)
|
||||
* addr q
|
||||
* |----size-----|-q->pre_size-|<q region>|
|
||||
*/
|
||||
+ grub_dprintf ("regions", "Can we extend into region above?"
|
||||
+ " %p + %" PRIxGRUB_SIZE " + %" PRIxGRUB_SIZE " ?=? %p\n",
|
||||
+ (grub_uint8_t *) addr, size, q->pre_size, (grub_uint8_t *) q);
|
||||
if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q)
|
||||
{
|
||||
+ grub_dprintf ("regions", "Yes: extending a region: (%p -> %p) -> (%p -> %p)\n",
|
||||
+ q, (grub_uint8_t *) q + sizeof (*q) + q->size,
|
||||
+ addr, (grub_uint8_t *) q + sizeof (*q) + q->size);
|
||||
/*
|
||||
* Yes, we can merge the memory starting at addr into the
|
||||
* existing region from below. Align up addr to GRUB_MM_ALIGN
|
||||
@@ -185,9 +190,15 @@ grub_mm_init_region (void *addr, grub_size_t size)
|
||||
* q addr
|
||||
* |<q region>|-q->post_size-|----size-----|
|
||||
*/
|
||||
+ grub_dprintf ("regions", "Can we extend into region below?"
|
||||
+ " %p + %" PRIxGRUB_SIZE " + %" PRIxGRUB_SIZE " + %" PRIxGRUB_SIZE " ?=? %p\n",
|
||||
+ (grub_uint8_t *) q, sizeof(*q), q->size, q->post_size, (grub_uint8_t *) addr);
|
||||
if ((grub_uint8_t *) q + sizeof (*q) + q->size + q->post_size ==
|
||||
(grub_uint8_t *) addr)
|
||||
{
|
||||
+ grub_dprintf ("regions", "Yes: extending a region: (%p -> %p) -> (%p -> %p)\n",
|
||||
+ q, (grub_uint8_t *) q + sizeof (*q) + q->size,
|
||||
+ q, (grub_uint8_t *) addr + size);
|
||||
/*
|
||||
* Yes! Follow a similar pattern to above, but simpler.
|
||||
* Our header starts at address - post_size, which should align us
|
||||
@@ -213,6 +224,8 @@ grub_mm_init_region (void *addr, grub_size_t size)
|
||||
}
|
||||
}
|
||||
|
||||
+ grub_dprintf ("regions", "No: considering a new region at %p of size %" PRIxGRUB_SIZE "\n",
|
||||
+ addr, size);
|
||||
/* Allocate a region from the head. */
|
||||
r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN);
|
||||
|
81
0316-mm-Drop-unused-unloading-of-modules-on-OOM.patch
Normal file
81
0316-mm-Drop-unused-unloading-of-modules-on-OOM.patch
Normal file
@ -0,0 +1,81 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Patrick Steinhardt <ps@pks.im>
|
||||
Date: Thu, 21 Apr 2022 15:24:17 +1000
|
||||
Subject: [PATCH] mm: Drop unused unloading of modules on OOM
|
||||
|
||||
In grub_memalign(), there's a commented section which would allow for
|
||||
unloading of unneeded modules in case where there is not enough free
|
||||
memory available to satisfy a request. Given that this code is never
|
||||
compiled in, let's remove it together with grub_dl_unload_unneeded().
|
||||
|
||||
Signed-off-by: Patrick Steinhardt <ps@pks.im>
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Tested-by: Patrick Steinhardt <ps@pks.im>
|
||||
(cherry picked from commit 139fd9b134a01e0b5fe0ebefafa7f48d1ffb6d60)
|
||||
(cherry picked from commit 81267ca5387486ede52e0462a71555bc6d181085)
|
||||
---
|
||||
grub-core/kern/dl.c | 20 --------------------
|
||||
grub-core/kern/mm.c | 8 --------
|
||||
include/grub/dl.h | 1 -
|
||||
3 files changed, 29 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
|
||||
index d5de80186f..ab9101a5ad 100644
|
||||
--- a/grub-core/kern/dl.c
|
||||
+++ b/grub-core/kern/dl.c
|
||||
@@ -998,23 +998,3 @@ grub_dl_unload (grub_dl_t mod)
|
||||
grub_free (mod);
|
||||
return 1;
|
||||
}
|
||||
-
|
||||
-/* Unload unneeded modules. */
|
||||
-void
|
||||
-grub_dl_unload_unneeded (void)
|
||||
-{
|
||||
- /* Because grub_dl_remove modifies the list of modules, this
|
||||
- implementation is tricky. */
|
||||
- grub_dl_t p = grub_dl_head;
|
||||
-
|
||||
- while (p)
|
||||
- {
|
||||
- if (grub_dl_unload (p))
|
||||
- {
|
||||
- p = grub_dl_head;
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- p = p->next;
|
||||
- }
|
||||
-}
|
||||
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
|
||||
index 38bfb01df9..1825dc8289 100644
|
||||
--- a/grub-core/kern/mm.c
|
||||
+++ b/grub-core/kern/mm.c
|
||||
@@ -444,14 +444,6 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
||||
count++;
|
||||
goto again;
|
||||
|
||||
-#if 0
|
||||
- case 1:
|
||||
- /* Unload unneeded modules. */
|
||||
- grub_dl_unload_unneeded ();
|
||||
- count++;
|
||||
- goto again;
|
||||
-#endif
|
||||
-
|
||||
default:
|
||||
break;
|
||||
}
|
||||
diff --git a/include/grub/dl.h b/include/grub/dl.h
|
||||
index 45ac8e339f..6bc2560bf0 100644
|
||||
--- a/include/grub/dl.h
|
||||
+++ b/include/grub/dl.h
|
||||
@@ -206,7 +206,6 @@ grub_dl_t EXPORT_FUNC(grub_dl_load) (const char *name);
|
||||
grub_dl_t grub_dl_load_core (void *addr, grub_size_t size);
|
||||
grub_dl_t EXPORT_FUNC(grub_dl_load_core_noinit) (void *addr, grub_size_t size);
|
||||
int EXPORT_FUNC(grub_dl_unload) (grub_dl_t mod);
|
||||
-extern void grub_dl_unload_unneeded (void);
|
||||
extern int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod);
|
||||
extern int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod);
|
||||
extern int EXPORT_FUNC(grub_dl_ref_count) (grub_dl_t mod);
|
131
0317-mm-Allow-dynamically-requesting-additional-memory-re.patch
Normal file
131
0317-mm-Allow-dynamically-requesting-additional-memory-re.patch
Normal file
@ -0,0 +1,131 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Patrick Steinhardt <ps@pks.im>
|
||||
Date: Thu, 21 Apr 2022 15:24:18 +1000
|
||||
Subject: [PATCH] mm: Allow dynamically requesting additional memory regions
|
||||
|
||||
Currently, all platforms will set up their heap on initialization of the
|
||||
platform code. While this works mostly fine, it poses some limitations
|
||||
on memory management on us. Most notably, allocating big chunks of
|
||||
memory in the gigabyte range would require us to pre-request this many
|
||||
bytes from the firmware and add it to the heap from the beginning on
|
||||
some platforms like EFI. As this isn't needed for most configurations,
|
||||
it is inefficient and may even negatively impact some usecases when,
|
||||
e.g., chainloading. Nonetheless, allocating big chunks of memory is
|
||||
required sometimes, where one example is the upcoming support for the
|
||||
Argon2 key derival function in LUKS2.
|
||||
|
||||
In order to avoid pre-allocating big chunks of memory, this commit
|
||||
implements a runtime mechanism to add more pages to the system. When
|
||||
a given allocation cannot be currently satisfied, we'll call a given
|
||||
callback set up by the platform's own memory management subsystem,
|
||||
asking it to add a memory area with at least "n" bytes. If this
|
||||
succeeds, we retry searching for a valid memory region, which should
|
||||
now succeed.
|
||||
|
||||
If this fails, we try asking for "n" bytes, possibly spread across
|
||||
multiple regions, in hopes that region merging means that we end up
|
||||
with enough memory for things to work out.
|
||||
|
||||
Signed-off-by: Patrick Steinhardt <ps@pks.im>
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Tested-by: Patrick Steinhardt <ps@pks.im>
|
||||
(cherry picked from commit 887f98f0db43e33fba4ec1f85e42fae1185700bc)
|
||||
(cherry picked from commit 8f3238a7dc482497e76b5ef6fbeb04f84d9a9aaa)
|
||||
---
|
||||
grub-core/kern/mm.c | 30 ++++++++++++++++++++++++++++++
|
||||
include/grub/mm.h | 18 ++++++++++++++++++
|
||||
2 files changed, 48 insertions(+)
|
||||
|
||||
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
|
||||
index 1825dc8289..f2e27f263b 100644
|
||||
--- a/grub-core/kern/mm.c
|
||||
+++ b/grub-core/kern/mm.c
|
||||
@@ -28,6 +28,9 @@
|
||||
- multiple regions may be used as free space. They may not be
|
||||
contiguous.
|
||||
|
||||
+ - if existing regions are insufficient to satisfy an allocation, a new
|
||||
+ region can be requested from firmware.
|
||||
+
|
||||
Regions are managed by a singly linked list, and the meta information is
|
||||
stored in the beginning of each region. Space after the meta information
|
||||
is used to allocate memory.
|
||||
@@ -81,6 +84,7 @@
|
||||
|
||||
|
||||
grub_mm_region_t grub_mm_base;
|
||||
+grub_mm_add_region_func_t grub_mm_add_region_fn;
|
||||
|
||||
/* Get a header from the pointer PTR, and set *P and *R to a pointer
|
||||
to the header and a pointer to its region, respectively. PTR must
|
||||
@@ -444,6 +448,32 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
||||
count++;
|
||||
goto again;
|
||||
|
||||
+ case 1:
|
||||
+ /* Request additional pages, contiguous */
|
||||
+ count++;
|
||||
+
|
||||
+ if (grub_mm_add_region_fn != NULL &&
|
||||
+ grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_CONSECUTIVE) == GRUB_ERR_NONE)
|
||||
+ goto again;
|
||||
+
|
||||
+ /* fallthrough */
|
||||
+
|
||||
+ case 2:
|
||||
+ /* Request additional pages, anything at all */
|
||||
+ count++;
|
||||
+
|
||||
+ if (grub_mm_add_region_fn != NULL)
|
||||
+ {
|
||||
+ /*
|
||||
+ * Try again even if this fails, in case it was able to partially
|
||||
+ * satisfy the request
|
||||
+ */
|
||||
+ grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_NONE);
|
||||
+ goto again;
|
||||
+ }
|
||||
+
|
||||
+ /* fallthrough */
|
||||
+
|
||||
default:
|
||||
break;
|
||||
}
|
||||
diff --git a/include/grub/mm.h b/include/grub/mm.h
|
||||
index d81623d226..7c6f925ffd 100644
|
||||
--- a/include/grub/mm.h
|
||||
+++ b/include/grub/mm.h
|
||||
@@ -20,6 +20,7 @@
|
||||
#ifndef GRUB_MM_H
|
||||
#define GRUB_MM_H 1
|
||||
|
||||
+#include <grub/err.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/err.h>
|
||||
@@ -29,6 +30,23 @@
|
||||
# define NULL ((void *) 0)
|
||||
#endif
|
||||
|
||||
+#define GRUB_MM_ADD_REGION_NONE 0
|
||||
+#define GRUB_MM_ADD_REGION_CONSECUTIVE (1 << 0)
|
||||
+
|
||||
+/*
|
||||
+ * Function used to request memory regions of `grub_size_t` bytes. The second
|
||||
+ * parameter is a bitfield of `GRUB_MM_ADD_REGION` flags.
|
||||
+ */
|
||||
+typedef grub_err_t (*grub_mm_add_region_func_t) (grub_size_t, unsigned int);
|
||||
+
|
||||
+/*
|
||||
+ * Set this function pointer to enable adding memory-regions at runtime in case
|
||||
+ * a memory allocation cannot be satisfied with existing regions.
|
||||
+ */
|
||||
+#ifndef GRUB_MACHINE_EMU
|
||||
+extern grub_mm_add_region_func_t EXPORT_VAR(grub_mm_add_region_fn);
|
||||
+#endif
|
||||
+
|
||||
void grub_mm_init_region (void *addr, grub_size_t size);
|
||||
void *EXPORT_FUNC(grub_calloc) (grub_size_t nmemb, grub_size_t size);
|
||||
void *EXPORT_FUNC(grub_malloc) (grub_size_t size);
|
104
0318-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch
Normal file
104
0318-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch
Normal file
@ -0,0 +1,104 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Patrick Steinhardt <ps@pks.im>
|
||||
Date: Thu, 21 Apr 2022 15:24:19 +1000
|
||||
Subject: [PATCH] kern/efi/mm: Always request a fixed number of pages on init
|
||||
|
||||
When initializing the EFI memory subsystem, we will by default request
|
||||
a quarter of the available memory, bounded by a minimum/maximum value.
|
||||
Given that we're about to extend the EFI memory system to dynamically
|
||||
request additional pages from the firmware as required, this scaling of
|
||||
requested memory based on available memory will not make a lot of sense
|
||||
anymore.
|
||||
|
||||
Remove this logic as a preparatory patch such that we'll instead defer
|
||||
to the runtime memory allocator. Note that ideally, we'd want to change
|
||||
this after dynamic requesting of pages has been implemented for the EFI
|
||||
platform. But because we'll need to split up initialization of the
|
||||
memory subsystem and the request of pages from the firmware, we'd have
|
||||
to duplicate quite some logic at first only to remove it afterwards
|
||||
again. This seems quite pointless, so we instead have patches slightly
|
||||
out of order.
|
||||
|
||||
Signed-off-by: Patrick Steinhardt <ps@pks.im>
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Tested-by: Patrick Steinhardt <ps@pks.im>
|
||||
(cherry picked from commit 938c3760b8c0fca759140be48307179b50107ff6)
|
||||
(cherry picked from commit 90e793a2ef3bc35609cb1b605ebd1fae15dd4b2d)
|
||||
---
|
||||
grub-core/kern/efi/mm.c | 35 +++--------------------------------
|
||||
1 file changed, 3 insertions(+), 32 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
|
||||
index 88364d764c..f574edabef 100644
|
||||
--- a/grub-core/kern/efi/mm.c
|
||||
+++ b/grub-core/kern/efi/mm.c
|
||||
@@ -38,9 +38,8 @@
|
||||
a multiplier of 4KB. */
|
||||
#define MEMORY_MAP_SIZE 0x3000
|
||||
|
||||
-/* The minimum and maximum heap size for GRUB itself. */
|
||||
-#define MIN_HEAP_SIZE 0x100000
|
||||
-#define MAX_HEAP_SIZE (1600 * 0x100000)
|
||||
+/* The default heap size for GRUB itself in bytes. */
|
||||
+#define DEFAULT_HEAP_SIZE 0x100000
|
||||
|
||||
static void *finish_mmap_buf = 0;
|
||||
static grub_efi_uintn_t finish_mmap_size = 0;
|
||||
@@ -514,23 +513,6 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
|
||||
return filtered_desc;
|
||||
}
|
||||
|
||||
-/* Return the total number of pages. */
|
||||
-static grub_efi_uint64_t
|
||||
-get_total_pages (grub_efi_memory_descriptor_t *memory_map,
|
||||
- grub_efi_uintn_t desc_size,
|
||||
- grub_efi_memory_descriptor_t *memory_map_end)
|
||||
-{
|
||||
- grub_efi_memory_descriptor_t *desc;
|
||||
- grub_efi_uint64_t total = 0;
|
||||
-
|
||||
- for (desc = memory_map;
|
||||
- desc < memory_map_end;
|
||||
- desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
|
||||
- total += desc->num_pages;
|
||||
-
|
||||
- return total;
|
||||
-}
|
||||
-
|
||||
/* Add memory regions. */
|
||||
static void
|
||||
add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
|
||||
@@ -695,8 +677,6 @@ grub_efi_mm_init (void)
|
||||
grub_efi_memory_descriptor_t *filtered_memory_map_end;
|
||||
grub_efi_uintn_t map_size;
|
||||
grub_efi_uintn_t desc_size;
|
||||
- grub_efi_uint64_t total_pages;
|
||||
- grub_efi_uint64_t required_pages;
|
||||
int mm_status;
|
||||
|
||||
grub_nx_init ();
|
||||
@@ -738,22 +718,13 @@ grub_efi_mm_init (void)
|
||||
filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map,
|
||||
desc_size, memory_map_end);
|
||||
|
||||
- /* By default, request a quarter of the available memory. */
|
||||
- total_pages = get_total_pages (filtered_memory_map, desc_size,
|
||||
- filtered_memory_map_end);
|
||||
- required_pages = (total_pages >> 2);
|
||||
- if (required_pages < BYTES_TO_PAGES (MIN_HEAP_SIZE))
|
||||
- required_pages = BYTES_TO_PAGES (MIN_HEAP_SIZE);
|
||||
- else if (required_pages > BYTES_TO_PAGES (MAX_HEAP_SIZE))
|
||||
- required_pages = BYTES_TO_PAGES (MAX_HEAP_SIZE);
|
||||
-
|
||||
/* Sort the filtered descriptors, so that GRUB can allocate pages
|
||||
from smaller regions. */
|
||||
sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end);
|
||||
|
||||
/* Allocate memory regions for GRUB's memory management. */
|
||||
add_memory_regions (filtered_memory_map, desc_size,
|
||||
- filtered_memory_map_end, required_pages);
|
||||
+ filtered_memory_map_end, BYTES_TO_PAGES (DEFAULT_HEAP_SIZE));
|
||||
|
||||
#if 0
|
||||
/* For debug. */
|
@ -0,0 +1,86 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Patrick Steinhardt <ps@pks.im>
|
||||
Date: Thu, 21 Apr 2022 15:24:20 +1000
|
||||
Subject: [PATCH] kern/efi/mm: Extract function to add memory regions
|
||||
|
||||
In preparation of support for runtime-allocating additional memory
|
||||
region, this patch extracts the function to retrieve the EFI memory
|
||||
map and add a subset of it to GRUB's own memory regions.
|
||||
|
||||
Signed-off-by: Patrick Steinhardt <ps@pks.im>
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Tested-by: Patrick Steinhardt <ps@pks.im>
|
||||
(cherry picked from commit 96a7ea29e3cb61b6c2302e260e8e6a6117e17fa3)
|
||||
[rharwood: backport around our nx]
|
||||
(cherry picked from commit 4a85c48111f5e516cbc000bf4a7bc989b36d623c)
|
||||
---
|
||||
grub-core/kern/efi/mm.c | 21 +++++++++++++++------
|
||||
1 file changed, 15 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
|
||||
index f574edabef..9c9f9ac0c5 100644
|
||||
--- a/grub-core/kern/efi/mm.c
|
||||
+++ b/grub-core/kern/efi/mm.c
|
||||
@@ -668,8 +668,8 @@ grub_nx_init (void)
|
||||
}
|
||||
}
|
||||
|
||||
-void
|
||||
-grub_efi_mm_init (void)
|
||||
+static grub_err_t
|
||||
+grub_efi_mm_add_regions (grub_size_t required_bytes)
|
||||
{
|
||||
grub_efi_memory_descriptor_t *memory_map;
|
||||
grub_efi_memory_descriptor_t *memory_map_end;
|
||||
@@ -684,7 +684,7 @@ grub_efi_mm_init (void)
|
||||
/* Prepare a memory region to store two memory maps. */
|
||||
memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
|
||||
if (! memory_map)
|
||||
- grub_fatal ("cannot allocate memory");
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for memory map");
|
||||
|
||||
/* Obtain descriptors for available memory. */
|
||||
map_size = MEMORY_MAP_SIZE;
|
||||
@@ -702,14 +702,14 @@ grub_efi_mm_init (void)
|
||||
|
||||
memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (map_size));
|
||||
if (! memory_map)
|
||||
- grub_fatal ("cannot allocate memory");
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for new memory map");
|
||||
|
||||
mm_status = grub_efi_get_memory_map (&map_size, memory_map, 0,
|
||||
&desc_size, 0);
|
||||
}
|
||||
|
||||
if (mm_status < 0)
|
||||
- grub_fatal ("cannot get memory map");
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "error fetching memory map from EFI");
|
||||
|
||||
memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size);
|
||||
|
||||
@@ -724,7 +724,7 @@ grub_efi_mm_init (void)
|
||||
|
||||
/* Allocate memory regions for GRUB's memory management. */
|
||||
add_memory_regions (filtered_memory_map, desc_size,
|
||||
- filtered_memory_map_end, BYTES_TO_PAGES (DEFAULT_HEAP_SIZE));
|
||||
+ filtered_memory_map_end, BYTES_TO_PAGES (required_bytes));
|
||||
|
||||
#if 0
|
||||
/* For debug. */
|
||||
@@ -742,6 +742,15 @@ grub_efi_mm_init (void)
|
||||
/* Release the memory maps. */
|
||||
grub_efi_free_pages ((grub_addr_t) memory_map,
|
||||
2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+grub_efi_mm_init (void)
|
||||
+{
|
||||
+ if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE) != GRUB_ERR_NONE)
|
||||
+ grub_fatal ("%s", grub_errmsg);
|
||||
}
|
||||
|
||||
#if defined (__aarch64__) || defined (__arm__) || defined (__riscv)
|
@ -0,0 +1,88 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Patrick Steinhardt <ps@pks.im>
|
||||
Date: Thu, 21 Apr 2022 15:24:21 +1000
|
||||
Subject: [PATCH] kern/efi/mm: Pass up errors from add_memory_regions()
|
||||
|
||||
The function add_memory_regions() is currently only called on system
|
||||
initialization to allocate a fixed amount of pages. As such, it didn't
|
||||
need to return any errors: in case it failed, we cannot proceed anyway.
|
||||
This will change with the upcoming support for requesting more memory
|
||||
from the firmware at runtime, where it doesn't make sense anymore to
|
||||
fail hard.
|
||||
|
||||
Refactor the function to return an error to prepare for this. Note that
|
||||
this does not change the behaviour when initializing the memory system
|
||||
because grub_efi_mm_init() knows to call grub_fatal() in case
|
||||
grub_efi_mm_add_regions() returns an error.
|
||||
|
||||
Signed-off-by: Patrick Steinhardt <ps@pks.im>
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Tested-by: Patrick Steinhardt <ps@pks.im>
|
||||
(cherry picked from commit 15a015698921240adc1ac266a3b5bc5fcbd81521)
|
||||
(cherry picked from commit c39acabc11d98ba18c6724eeb446508da7410c68)
|
||||
---
|
||||
grub-core/kern/efi/mm.c | 22 +++++++++++++++-------
|
||||
1 file changed, 15 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
|
||||
index 9c9f9ac0c5..29cf178aa9 100644
|
||||
--- a/grub-core/kern/efi/mm.c
|
||||
+++ b/grub-core/kern/efi/mm.c
|
||||
@@ -514,7 +514,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
|
||||
}
|
||||
|
||||
/* Add memory regions. */
|
||||
-static void
|
||||
+static grub_err_t
|
||||
add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
|
||||
grub_efi_uintn_t desc_size,
|
||||
grub_efi_memory_descriptor_t *memory_map_end,
|
||||
@@ -542,9 +542,9 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
|
||||
GRUB_EFI_ALLOCATE_ADDRESS,
|
||||
GRUB_EFI_LOADER_CODE);
|
||||
if (! addr)
|
||||
- grub_fatal ("cannot allocate conventional memory %p with %u pages",
|
||||
- (void *) ((grub_addr_t) start),
|
||||
- (unsigned) pages);
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
+ "Memory starting at %p (%u pages) marked as free, but EFI would not allocate",
|
||||
+ (void *) ((grub_addr_t) start), (unsigned) pages);
|
||||
|
||||
grub_mm_init_region (addr, PAGES_TO_BYTES (pages));
|
||||
|
||||
@@ -554,7 +554,11 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
|
||||
}
|
||||
|
||||
if (required_pages > 0)
|
||||
- grub_fatal ("too little memory");
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
+ "could not allocate all requested memory: %" PRIuGRUB_UINT64_T " pages still required after iterating EFI memory map",
|
||||
+ required_pages);
|
||||
+
|
||||
+ return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -677,6 +681,7 @@ grub_efi_mm_add_regions (grub_size_t required_bytes)
|
||||
grub_efi_memory_descriptor_t *filtered_memory_map_end;
|
||||
grub_efi_uintn_t map_size;
|
||||
grub_efi_uintn_t desc_size;
|
||||
+ grub_err_t err;
|
||||
int mm_status;
|
||||
|
||||
grub_nx_init ();
|
||||
@@ -723,8 +728,11 @@ grub_efi_mm_add_regions (grub_size_t required_bytes)
|
||||
sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end);
|
||||
|
||||
/* Allocate memory regions for GRUB's memory management. */
|
||||
- add_memory_regions (filtered_memory_map, desc_size,
|
||||
- filtered_memory_map_end, BYTES_TO_PAGES (required_bytes));
|
||||
+ err = add_memory_regions (filtered_memory_map, desc_size,
|
||||
+ filtered_memory_map_end,
|
||||
+ BYTES_TO_PAGES (required_bytes));
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ return err;
|
||||
|
||||
#if 0
|
||||
/* For debug. */
|
76
0321-kern-efi-mm-Implement-runtime-addition-of-pages.patch
Normal file
76
0321-kern-efi-mm-Implement-runtime-addition-of-pages.patch
Normal file
@ -0,0 +1,76 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Patrick Steinhardt <ps@pks.im>
|
||||
Date: Thu, 21 Apr 2022 15:24:22 +1000
|
||||
Subject: [PATCH] kern/efi/mm: Implement runtime addition of pages
|
||||
|
||||
Adjust the interface of grub_efi_mm_add_regions() to take a set of
|
||||
GRUB_MM_ADD_REGION_* flags, which most notably is currently only the
|
||||
GRUB_MM_ADD_REGION_CONSECUTIVE flag. This allows us to set the function
|
||||
up as callback for the memory subsystem and have it call out to us in
|
||||
case there's not enough pages available in the current heap.
|
||||
|
||||
Signed-off-by: Patrick Steinhardt <ps@pks.im>
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Tested-by: Patrick Steinhardt <ps@pks.im>
|
||||
(cherry picked from commit 1df2934822df4c1170dde069d97cfbf7a9572bba)
|
||||
(cherry picked from commit d2c744833aafcd84485e7b1faebaade5bfe7db7a)
|
||||
---
|
||||
grub-core/kern/efi/mm.c | 15 +++++++++++----
|
||||
1 file changed, 11 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
|
||||
index 29cf178aa9..fc7561bbf7 100644
|
||||
--- a/grub-core/kern/efi/mm.c
|
||||
+++ b/grub-core/kern/efi/mm.c
|
||||
@@ -518,7 +518,8 @@ static grub_err_t
|
||||
add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
|
||||
grub_efi_uintn_t desc_size,
|
||||
grub_efi_memory_descriptor_t *memory_map_end,
|
||||
- grub_efi_uint64_t required_pages)
|
||||
+ grub_efi_uint64_t required_pages,
|
||||
+ unsigned int flags)
|
||||
{
|
||||
grub_efi_memory_descriptor_t *desc;
|
||||
|
||||
@@ -532,6 +533,10 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
|
||||
|
||||
start = desc->physical_start;
|
||||
pages = desc->num_pages;
|
||||
+
|
||||
+ if (pages < required_pages && (flags & GRUB_MM_ADD_REGION_CONSECUTIVE))
|
||||
+ continue;
|
||||
+
|
||||
if (pages > required_pages)
|
||||
{
|
||||
start += PAGES_TO_BYTES (pages - required_pages);
|
||||
@@ -673,7 +678,7 @@ grub_nx_init (void)
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
-grub_efi_mm_add_regions (grub_size_t required_bytes)
|
||||
+grub_efi_mm_add_regions (grub_size_t required_bytes, unsigned int flags)
|
||||
{
|
||||
grub_efi_memory_descriptor_t *memory_map;
|
||||
grub_efi_memory_descriptor_t *memory_map_end;
|
||||
@@ -730,7 +735,8 @@ grub_efi_mm_add_regions (grub_size_t required_bytes)
|
||||
/* Allocate memory regions for GRUB's memory management. */
|
||||
err = add_memory_regions (filtered_memory_map, desc_size,
|
||||
filtered_memory_map_end,
|
||||
- BYTES_TO_PAGES (required_bytes));
|
||||
+ BYTES_TO_PAGES (required_bytes),
|
||||
+ flags);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
return err;
|
||||
|
||||
@@ -757,8 +763,9 @@ grub_efi_mm_add_regions (grub_size_t required_bytes)
|
||||
void
|
||||
grub_efi_mm_init (void)
|
||||
{
|
||||
- if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE) != GRUB_ERR_NONE)
|
||||
+ if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE, GRUB_MM_ADD_REGION_NONE) != GRUB_ERR_NONE)
|
||||
grub_fatal ("%s", grub_errmsg);
|
||||
+ grub_mm_add_region_fn = grub_efi_mm_add_regions;
|
||||
}
|
||||
|
||||
#if defined (__aarch64__) || defined (__arm__) || defined (__riscv)
|
32
0322-efi-Increase-default-memory-allocation-to-32-MiB.patch
Normal file
32
0322-efi-Increase-default-memory-allocation-to-32-MiB.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Tue, 20 Sep 2022 00:30:30 +1000
|
||||
Subject: [PATCH] efi: Increase default memory allocation to 32 MiB
|
||||
|
||||
We have multiple reports of things being slower with a 1 MiB initial static
|
||||
allocation, and a report (more difficult to nail down) of a boot failure
|
||||
as a result of the smaller initial allocation.
|
||||
|
||||
Make the initial memory allocation 32 MiB.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
(cherry picked from commit 75e38e86e7d9202f050b093f20500d9ad4c6dad9)
|
||||
(cherry picked from commit 7cae9dcf90a9db0cdfae144356fe97e5391862e9)
|
||||
---
|
||||
grub-core/kern/efi/mm.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
|
||||
index fc7561bbf7..fde92ac9a5 100644
|
||||
--- a/grub-core/kern/efi/mm.c
|
||||
+++ b/grub-core/kern/efi/mm.c
|
||||
@@ -39,7 +39,7 @@
|
||||
#define MEMORY_MAP_SIZE 0x3000
|
||||
|
||||
/* The default heap size for GRUB itself in bytes. */
|
||||
-#define DEFAULT_HEAP_SIZE 0x100000
|
||||
+#define DEFAULT_HEAP_SIZE 0x2000000
|
||||
|
||||
static void *finish_mmap_buf = 0;
|
||||
static grub_efi_uintn_t finish_mmap_size = 0;
|
@ -0,0 +1,58 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zhang Boyang <zhangboyang.id@gmail.com>
|
||||
Date: Sat, 15 Oct 2022 22:15:11 +0800
|
||||
Subject: [PATCH] mm: Try invalidate disk caches last when out of memory
|
||||
|
||||
Every heap grow will cause all disk caches invalidated which decreases
|
||||
performance severely. This patch moves disk cache invalidation code to
|
||||
the last of memory squeezing measures. So, disk caches are released only
|
||||
when there are no other ways to get free memory.
|
||||
|
||||
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
Reviewed-by: Patrick Steinhardt <ps@pks.im>
|
||||
(cherry picked from commit 17975d10a80e2457e5237f87fa58a7943031983e)
|
||||
(cherry picked from commit a048b2280ae6a2cf90fd5d2960823843e17e4d66)
|
||||
---
|
||||
grub-core/kern/mm.c | 14 +++++++-------
|
||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
|
||||
index f2e27f263b..da1ac9427c 100644
|
||||
--- a/grub-core/kern/mm.c
|
||||
+++ b/grub-core/kern/mm.c
|
||||
@@ -443,12 +443,6 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
||||
switch (count)
|
||||
{
|
||||
case 0:
|
||||
- /* Invalidate disk caches. */
|
||||
- grub_disk_cache_invalidate_all ();
|
||||
- count++;
|
||||
- goto again;
|
||||
-
|
||||
- case 1:
|
||||
/* Request additional pages, contiguous */
|
||||
count++;
|
||||
|
||||
@@ -458,7 +452,7 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
||||
|
||||
/* fallthrough */
|
||||
|
||||
- case 2:
|
||||
+ case 1:
|
||||
/* Request additional pages, anything at all */
|
||||
count++;
|
||||
|
||||
@@ -474,6 +468,12 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
||||
|
||||
/* fallthrough */
|
||||
|
||||
+ case 2:
|
||||
+ /* Invalidate disk caches. */
|
||||
+ grub_disk_cache_invalidate_all ();
|
||||
+ count++;
|
||||
+ goto again;
|
||||
+
|
||||
default:
|
||||
break;
|
||||
}
|
73
grub.patches
73
grub.patches
@ -277,32 +277,47 @@ Patch0276: 0276-nx-set-page-permissions-for-loaded-modules.patch
|
||||
Patch0277: 0277-nx-set-attrs-in-our-kernel-loaders.patch
|
||||
Patch0278: 0278-nx-set-the-nx-compatible-flag-in-EFI-grub-images.patch
|
||||
Patch0279: 0279-Make-debug-file-show-which-file-filters-get-run.patch
|
||||
Patch0280: 0280-efi-make-the-default-arena-most-of-ram.patch
|
||||
Patch0281: 0281-efi-use-enumerated-array-positions-for-our-allocatio.patch
|
||||
Patch0282: 0282-efi-split-allocation-policy-for-kernel-vs-initrd-mem.patch
|
||||
Patch0283: 0283-efi-allocate-the-initrd-within-the-bounds-expressed-.patch
|
||||
Patch0284: 0284-efi-use-EFI_LOADER_-CODE-DATA-for-kernel-and-initrd-.patch
|
||||
Patch0285: 0285-BLS-create-etc-kernel-cmdline-during-mkconfig.patch
|
||||
Patch0286: 0286-ieee1275-implement-vec5-for-cas-negotiation.patch
|
||||
Patch0287: 0287-squish-don-t-dup-rhgb-quiet-check-mtimes.patch
|
||||
Patch0288: 0288-squish-give-up-on-rhgb-quiet.patch
|
||||
Patch0289: 0289-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch
|
||||
Patch0290: 0290-x86-efi-Fix-an-incorrect-array-size-in-kernel-alloca.patch
|
||||
Patch0291: 0291-commands-efi-tpm-Refine-the-status-of-log-event.patch
|
||||
Patch0292: 0292-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch
|
||||
Patch0293: 0293-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch
|
||||
Patch0294: 0294-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch
|
||||
Patch0295: 0295-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch
|
||||
Patch0296: 0296-font-Fix-several-integer-overflows-in-grub_font_cons.patch
|
||||
Patch0297: 0297-font-Remove-grub_font_dup_glyph.patch
|
||||
Patch0298: 0298-font-Fix-integer-overflow-in-ensure_comb_space.patch
|
||||
Patch0299: 0299-font-Fix-integer-overflow-in-BMP-index.patch
|
||||
Patch0300: 0300-font-Fix-integer-underflow-in-binary-search-of-char-.patch
|
||||
Patch0301: 0301-kern-efi-sb-Enforce-verification-of-font-files.patch
|
||||
Patch0302: 0302-fbutil-Fix-integer-overflow.patch
|
||||
Patch0303: 0303-font-Fix-an-integer-underflow-in-blit_comb.patch
|
||||
Patch0304: 0304-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch
|
||||
Patch0305: 0305-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch
|
||||
Patch0306: 0306-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch
|
||||
Patch0307: 0307-Correction-in-vector-5-values.patch
|
||||
Patch0308: 0308-ppc64le-signed-boot-media-changes.patch
|
||||
Patch0280: 0280-efi-use-enumerated-array-positions-for-our-allocatio.patch
|
||||
Patch0281: 0281-efi-split-allocation-policy-for-kernel-vs-initrd-mem.patch
|
||||
Patch0282: 0282-efi-allocate-the-initrd-within-the-bounds-expressed-.patch
|
||||
Patch0283: 0283-efi-use-EFI_LOADER_-CODE-DATA-for-kernel-and-initrd-.patch
|
||||
Patch0284: 0284-BLS-create-etc-kernel-cmdline-during-mkconfig.patch
|
||||
Patch0285: 0285-ieee1275-implement-vec5-for-cas-negotiation.patch
|
||||
Patch0286: 0286-squish-don-t-dup-rhgb-quiet-check-mtimes.patch
|
||||
Patch0287: 0287-squish-give-up-on-rhgb-quiet.patch
|
||||
Patch0288: 0288-squish-BLS-only-write-etc-kernel-cmdline-if-writable.patch
|
||||
Patch0289: 0289-x86-efi-Fix-an-incorrect-array-size-in-kernel-alloca.patch
|
||||
Patch0290: 0290-commands-efi-tpm-Refine-the-status-of-log-event.patch
|
||||
Patch0291: 0291-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch
|
||||
Patch0292: 0292-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch
|
||||
Patch0293: 0293-font-Reject-glyphs-exceeds-font-max_glyph_width-or-f.patch
|
||||
Patch0294: 0294-font-Fix-size-overflow-in-grub_font_get_glyph_intern.patch
|
||||
Patch0295: 0295-font-Fix-several-integer-overflows-in-grub_font_cons.patch
|
||||
Patch0296: 0296-font-Remove-grub_font_dup_glyph.patch
|
||||
Patch0297: 0297-font-Fix-integer-overflow-in-ensure_comb_space.patch
|
||||
Patch0298: 0298-font-Fix-integer-overflow-in-BMP-index.patch
|
||||
Patch0299: 0299-font-Fix-integer-underflow-in-binary-search-of-char-.patch
|
||||
Patch0300: 0300-kern-efi-sb-Enforce-verification-of-font-files.patch
|
||||
Patch0301: 0301-fbutil-Fix-integer-overflow.patch
|
||||
Patch0302: 0302-font-Fix-an-integer-underflow-in-blit_comb.patch
|
||||
Patch0303: 0303-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch
|
||||
Patch0304: 0304-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch
|
||||
Patch0305: 0305-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch
|
||||
Patch0306: 0306-Correction-in-vector-5-values.patch
|
||||
Patch0307: 0307-ppc64le-signed-boot-media-changes.patch
|
||||
Patch0308: 0308-mm-Clarify-grub_real_malloc.patch
|
||||
Patch0309: 0309-mm-grub_real_malloc-Make-small-allocs-comment-match-.patch
|
||||
Patch0310: 0310-mm-Document-grub_free.patch
|
||||
Patch0311: 0311-mm-Document-grub_mm_init_region.patch
|
||||
Patch0312: 0312-mm-Document-GRUB-internal-memory-management-structur.patch
|
||||
Patch0313: 0313-mm-Assert-that-we-preserve-header-vs-region-alignmen.patch
|
||||
Patch0314: 0314-mm-When-adding-a-region-merge-with-region-after-as-w.patch
|
||||
Patch0315: 0315-mm-Debug-support-for-region-operations.patch
|
||||
Patch0316: 0316-mm-Drop-unused-unloading-of-modules-on-OOM.patch
|
||||
Patch0317: 0317-mm-Allow-dynamically-requesting-additional-memory-re.patch
|
||||
Patch0318: 0318-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch
|
||||
Patch0319: 0319-kern-efi-mm-Extract-function-to-add-memory-regions.patch
|
||||
Patch0320: 0320-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch
|
||||
Patch0321: 0321-kern-efi-mm-Implement-runtime-addition-of-pages.patch
|
||||
Patch0322: 0322-efi-Increase-default-memory-allocation-to-32-MiB.patch
|
||||
Patch0323: 0323-mm-Try-invalidate-disk-caches-last-when-out-of-memor.patch
|
||||
|
@ -14,7 +14,7 @@
|
||||
Name: grub2
|
||||
Epoch: 1
|
||||
Version: 2.06
|
||||
Release: 56%{?dist}
|
||||
Release: 57%{?dist}
|
||||
Summary: Bootloader with support for Linux, Multiboot and more
|
||||
License: GPLv3+
|
||||
URL: http://www.gnu.org/software/grub/
|
||||
@ -532,6 +532,10 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Wed Feb 01 2023 Robbie Harwood <rharwood@redhat.com> - 2.06-57
|
||||
- Pull in allocator fixes from upstream
|
||||
- Resolves: #2156419
|
||||
|
||||
* Tue Jan 31 2023 Robbie Harwood <rharwood@redhat.com> - 2.06-56
|
||||
- ppc64le: disable mdraid < 1.1
|
||||
- Resolves: #2143420
|
||||
|
Loading…
Reference in New Issue
Block a user