Update mm fixes from upstream
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
This commit is contained in:
parent
b86fd390b8
commit
5c83f50804
145
0320-mm-Adjust-new-region-size-to-take-management-overhea.patch
Normal file
145
0320-mm-Adjust-new-region-size-to-take-management-overhea.patch
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Zhang Boyang <zhangboyang.id@gmail.com>
|
||||||
|
Date: Sun, 29 Jan 2023 19:49:31 +0800
|
||||||
|
Subject: [PATCH] mm: Adjust new region size to take management overhead into
|
||||||
|
account
|
||||||
|
|
||||||
|
When grub_memalign() encounters out-of-memory, it will try
|
||||||
|
grub_mm_add_region_fn() to request more memory from system firmware.
|
||||||
|
However, the size passed to it doesn't take region management overhead
|
||||||
|
into account. Adding a memory area of "size" bytes may result in a heap
|
||||||
|
region of less than "size" bytes really available. Thus, the new region
|
||||||
|
may not be adequate for current allocation request, confusing
|
||||||
|
out-of-memory handling code.
|
||||||
|
|
||||||
|
This patch introduces GRUB_MM_MGMT_OVERHEAD to address the region
|
||||||
|
management overhead (e.g. metadata, padding). The value of this new
|
||||||
|
constant must be large enough to make sure grub_memalign(align, size)
|
||||||
|
always succeeds after a successful call to
|
||||||
|
grub_mm_init_region(addr, size + align + GRUB_MM_MGMT_OVERHEAD),
|
||||||
|
for any given addr and size (assuming no integer overflow).
|
||||||
|
|
||||||
|
The size passed to grub_mm_add_region_fn() is now correctly adjusted,
|
||||||
|
thus if grub_mm_add_region_fn() succeeded, current allocation request
|
||||||
|
can always succeed.
|
||||||
|
|
||||||
|
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
(cherry picked from commit 2282cbfe5aa1ff6c1bbcbdcd2003089ad7c03ba3)
|
||||||
|
---
|
||||||
|
grub-core/kern/mm.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++---
|
||||||
|
1 file changed, 61 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
|
||||||
|
index da1ac9427c..f29a3e5cbd 100644
|
||||||
|
--- a/grub-core/kern/mm.c
|
||||||
|
+++ b/grub-core/kern/mm.c
|
||||||
|
@@ -83,6 +83,46 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * GRUB_MM_MGMT_OVERHEAD is an upper bound of management overhead of
|
||||||
|
+ * each region, with any possible padding taken into account.
|
||||||
|
+ *
|
||||||
|
+ * The value must be large enough to make sure grub_memalign(align, size)
|
||||||
|
+ * always succeeds after a successful call to
|
||||||
|
+ * grub_mm_init_region(addr, size + align + GRUB_MM_MGMT_OVERHEAD),
|
||||||
|
+ * for any given addr, align and size (assuming no interger overflow).
|
||||||
|
+ *
|
||||||
|
+ * The worst case which has maximum overhead is shown in the figure below:
|
||||||
|
+ *
|
||||||
|
+ * +-- addr
|
||||||
|
+ * v |<- size + align ->|
|
||||||
|
+ * +---------+----------------+----------------+------------------+---------+
|
||||||
|
+ * | padding | grub_mm_region | grub_mm_header | usable bytes | padding |
|
||||||
|
+ * +---------+----------------+----------------+------------------+---------+
|
||||||
|
+ * |<- a ->|<- b ->|<- c ->|<- d ->|<- e ->|
|
||||||
|
+ * ^
|
||||||
|
+ * b == sizeof (struct grub_mm_region) | / Assuming no other suitable
|
||||||
|
+ * c == sizeof (struct grub_mm_header) | | block is available, then:
|
||||||
|
+ * d == size + align +-| If align == 0, this will be
|
||||||
|
+ * | the pointer returned by next
|
||||||
|
+ * Assuming addr % GRUB_MM_ALIGN == 1, then: | grub_memalign(align, size).
|
||||||
|
+ * a == GRUB_MM_ALIGN - 1 | If align > 0, this chunk may
|
||||||
|
+ * | need to be split to fulfill
|
||||||
|
+ * Assuming d % GRUB_MM_ALIGN == 1, then: | alignment requirements, and
|
||||||
|
+ * e == GRUB_MM_ALIGN - 1 | the returned pointer may be
|
||||||
|
+ * \ inside these usable bytes.
|
||||||
|
+ * Therefore, the maximum overhead is:
|
||||||
|
+ * a + b + c + e == (GRUB_MM_ALIGN - 1) + sizeof (struct grub_mm_region)
|
||||||
|
+ * + sizeof (struct grub_mm_header) + (GRUB_MM_ALIGN - 1)
|
||||||
|
+ */
|
||||||
|
+#define GRUB_MM_MGMT_OVERHEAD ((GRUB_MM_ALIGN - 1) \
|
||||||
|
+ + sizeof (struct grub_mm_region) \
|
||||||
|
+ + sizeof (struct grub_mm_header) \
|
||||||
|
+ + (GRUB_MM_ALIGN - 1))
|
||||||
|
+
|
||||||
|
+/* The size passed to grub_mm_add_region_fn() is aligned up by this value. */
|
||||||
|
+#define GRUB_MM_HEAP_GROW_ALIGN 4096
|
||||||
|
+
|
||||||
|
grub_mm_region_t grub_mm_base;
|
||||||
|
grub_mm_add_region_func_t grub_mm_add_region_fn;
|
||||||
|
|
||||||
|
@@ -230,6 +270,11 @@ 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);
|
||||||
|
+ /*
|
||||||
|
+ * If you want to modify the code below, please also take a look at
|
||||||
|
+ * GRUB_MM_MGMT_OVERHEAD and make sure it is synchronized with the code.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
/* Allocate a region from the head. */
|
||||||
|
r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN);
|
||||||
|
|
||||||
|
@@ -410,6 +455,7 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
||||||
|
{
|
||||||
|
grub_mm_region_t r;
|
||||||
|
grub_size_t n = ((size + GRUB_MM_ALIGN - 1) >> GRUB_MM_ALIGN_LOG2) + 1;
|
||||||
|
+ grub_size_t grow;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
if (!grub_mm_base)
|
||||||
|
@@ -418,10 +464,22 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
||||||
|
if (size > ~(grub_size_t) align)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Pre-calculate the necessary size of heap growth (if applicable),
|
||||||
|
+ * with region management overhead taken into account.
|
||||||
|
+ */
|
||||||
|
+ if (grub_add (size + align, GRUB_MM_MGMT_OVERHEAD, &grow))
|
||||||
|
+ goto fail;
|
||||||
|
+
|
||||||
|
+ /* Align up heap growth to make it friendly to CPU/MMU. */
|
||||||
|
+ if (grow > ~(grub_size_t) (GRUB_MM_HEAP_GROW_ALIGN - 1))
|
||||||
|
+ goto fail;
|
||||||
|
+ grow = ALIGN_UP (grow, GRUB_MM_HEAP_GROW_ALIGN);
|
||||||
|
+
|
||||||
|
/* We currently assume at least a 32-bit grub_size_t,
|
||||||
|
so limiting allocations to <adress space size> - 1MiB
|
||||||
|
in name of sanity is beneficial. */
|
||||||
|
- if ((size + align) > ~(grub_size_t) 0x100000)
|
||||||
|
+ if (grow > ~(grub_size_t) 0x100000)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
align = (align >> GRUB_MM_ALIGN_LOG2);
|
||||||
|
@@ -447,7 +505,7 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
||||||
|
count++;
|
||||||
|
|
||||||
|
if (grub_mm_add_region_fn != NULL &&
|
||||||
|
- grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_CONSECUTIVE) == GRUB_ERR_NONE)
|
||||||
|
+ grub_mm_add_region_fn (grow, GRUB_MM_ADD_REGION_CONSECUTIVE) == GRUB_ERR_NONE)
|
||||||
|
goto again;
|
||||||
|
|
||||||
|
/* fallthrough */
|
||||||
|
@@ -462,7 +520,7 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
||||||
|
* 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);
|
||||||
|
+ grub_mm_add_region_fn (grow, GRUB_MM_ADD_REGION_NONE);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
53
0321-mm-Preallocate-some-space-when-adding-new-regions.patch
Normal file
53
0321-mm-Preallocate-some-space-when-adding-new-regions.patch
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Zhang Boyang <zhangboyang.id@gmail.com>
|
||||||
|
Date: Sun, 29 Jan 2023 19:49:32 +0800
|
||||||
|
Subject: [PATCH] mm: Preallocate some space when adding new regions
|
||||||
|
|
||||||
|
When grub_memalign() encounters out-of-memory, it will try
|
||||||
|
grub_mm_add_region_fn() to request more memory from system firmware.
|
||||||
|
However, it doesn't preallocate memory space for future allocation
|
||||||
|
requests. In extreme cases, it requires one call to
|
||||||
|
grub_mm_add_region_fn() for each memory allocation request. This can
|
||||||
|
be very slow.
|
||||||
|
|
||||||
|
This patch introduces GRUB_MM_HEAP_GROW_EXTRA, the minimal heap growth
|
||||||
|
granularity. The new region size is now set to the bigger one of its
|
||||||
|
original value and GRUB_MM_HEAP_GROW_EXTRA. Thus, it will result in some
|
||||||
|
memory space preallocated if current allocations request is small.
|
||||||
|
|
||||||
|
The value of GRUB_MM_HEAP_GROW_EXTRA is set to 1MB. If this value is
|
||||||
|
smaller, the cost of small memory allocations will be higher. If this
|
||||||
|
value is larger, more memory will be wasted and it might cause
|
||||||
|
out-of-memory on machines with small amount of RAM.
|
||||||
|
|
||||||
|
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
(cherry picked from commit 21869baec15239b6d99122b32b14a778af4c754f)
|
||||||
|
---
|
||||||
|
grub-core/kern/mm.c | 6 ++++++
|
||||||
|
1 file changed, 6 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
|
||||||
|
index f29a3e5cbd..cc8a4703bc 100644
|
||||||
|
--- a/grub-core/kern/mm.c
|
||||||
|
+++ b/grub-core/kern/mm.c
|
||||||
|
@@ -123,6 +123,9 @@
|
||||||
|
/* The size passed to grub_mm_add_region_fn() is aligned up by this value. */
|
||||||
|
#define GRUB_MM_HEAP_GROW_ALIGN 4096
|
||||||
|
|
||||||
|
+/* Minimal heap growth granularity when existing heap space is exhausted. */
|
||||||
|
+#define GRUB_MM_HEAP_GROW_EXTRA 0x100000
|
||||||
|
+
|
||||||
|
grub_mm_region_t grub_mm_base;
|
||||||
|
grub_mm_add_region_func_t grub_mm_add_region_fn;
|
||||||
|
|
||||||
|
@@ -471,6 +474,9 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
||||||
|
if (grub_add (size + align, GRUB_MM_MGMT_OVERHEAD, &grow))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
+ /* Preallocate some extra space if heap growth is small. */
|
||||||
|
+ grow = grub_max (grow, GRUB_MM_HEAP_GROW_EXTRA);
|
||||||
|
+
|
||||||
|
/* Align up heap growth to make it friendly to CPU/MMU. */
|
||||||
|
if (grow > ~(grub_size_t) (GRUB_MM_HEAP_GROW_ALIGN - 1))
|
||||||
|
goto fail;
|
72
0322-mm-Avoid-complex-heap-growth-math-in-hot-path.patch
Normal file
72
0322-mm-Avoid-complex-heap-growth-math-in-hot-path.patch
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Zhang Boyang <zhangboyang.id@gmail.com>
|
||||||
|
Date: Sun, 29 Jan 2023 19:49:33 +0800
|
||||||
|
Subject: [PATCH] mm: Avoid complex heap growth math in hot path
|
||||||
|
|
||||||
|
We do a lot of math about heap growth in hot path of grub_memalign().
|
||||||
|
However, the result is only used if out of memory is encountered, which
|
||||||
|
is seldom.
|
||||||
|
|
||||||
|
This patch moves these calculations away from hot path. These
|
||||||
|
calculations are now only done if out of memory is encountered. This
|
||||||
|
change can also help compiler to optimize integer overflow checks away.
|
||||||
|
|
||||||
|
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
|
||||||
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||||
|
(cherry picked from commit 65bc45963014773e2062ccc63ff34a089d2e352e)
|
||||||
|
---
|
||||||
|
grub-core/kern/mm.c | 34 ++++++++++++++++++++--------------
|
||||||
|
1 file changed, 20 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
|
||||||
|
index cc8a4703bc..630d7be0e2 100644
|
||||||
|
--- a/grub-core/kern/mm.c
|
||||||
|
+++ b/grub-core/kern/mm.c
|
||||||
|
@@ -467,20 +467,7 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
||||||
|
if (size > ~(grub_size_t) align)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * Pre-calculate the necessary size of heap growth (if applicable),
|
||||||
|
- * with region management overhead taken into account.
|
||||||
|
- */
|
||||||
|
- if (grub_add (size + align, GRUB_MM_MGMT_OVERHEAD, &grow))
|
||||||
|
- goto fail;
|
||||||
|
-
|
||||||
|
- /* Preallocate some extra space if heap growth is small. */
|
||||||
|
- grow = grub_max (grow, GRUB_MM_HEAP_GROW_EXTRA);
|
||||||
|
-
|
||||||
|
- /* Align up heap growth to make it friendly to CPU/MMU. */
|
||||||
|
- if (grow > ~(grub_size_t) (GRUB_MM_HEAP_GROW_ALIGN - 1))
|
||||||
|
- goto fail;
|
||||||
|
- grow = ALIGN_UP (grow, GRUB_MM_HEAP_GROW_ALIGN);
|
||||||
|
+ grow = size + align;
|
||||||
|
|
||||||
|
/* We currently assume at least a 32-bit grub_size_t,
|
||||||
|
so limiting allocations to <adress space size> - 1MiB
|
||||||
|
@@ -510,6 +497,25 @@ grub_memalign (grub_size_t align, grub_size_t size)
|
||||||
|
/* Request additional pages, contiguous */
|
||||||
|
count++;
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Calculate the necessary size of heap growth (if applicable),
|
||||||
|
+ * with region management overhead taken into account.
|
||||||
|
+ */
|
||||||
|
+ if (grub_add (grow, GRUB_MM_MGMT_OVERHEAD, &grow))
|
||||||
|
+ goto fail;
|
||||||
|
+
|
||||||
|
+ /* Preallocate some extra space if heap growth is small. */
|
||||||
|
+ grow = grub_max (grow, GRUB_MM_HEAP_GROW_EXTRA);
|
||||||
|
+
|
||||||
|
+ /* Align up heap growth to make it friendly to CPU/MMU. */
|
||||||
|
+ if (grow > ~(grub_size_t) (GRUB_MM_HEAP_GROW_ALIGN - 1))
|
||||||
|
+ goto fail;
|
||||||
|
+ grow = ALIGN_UP (grow, GRUB_MM_HEAP_GROW_ALIGN);
|
||||||
|
+
|
||||||
|
+ /* Do the same sanity check again. */
|
||||||
|
+ if (grow > ~(grub_size_t) 0x100000)
|
||||||
|
+ goto fail;
|
||||||
|
+
|
||||||
|
if (grub_mm_add_region_fn != NULL &&
|
||||||
|
grub_mm_add_region_fn (grow, GRUB_MM_ADD_REGION_CONSECUTIVE) == GRUB_ERR_NONE)
|
||||||
|
goto again;
|
@ -317,3 +317,6 @@ Patch0316: 0316-ieee1275-implement-vec5-for-cas-negotiation.patch
|
|||||||
Patch0317: 0317-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch
|
Patch0317: 0317-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch
|
||||||
Patch0318: 0318-powerpc-Drop-Open-Hack-Ware.patch
|
Patch0318: 0318-powerpc-Drop-Open-Hack-Ware.patch
|
||||||
Patch0319: 0319-osdep-linux-hostdisk-Modify-sector-by-sysfs-as-disk-.patch
|
Patch0319: 0319-osdep-linux-hostdisk-Modify-sector-by-sysfs-as-disk-.patch
|
||||||
|
Patch0320: 0320-mm-Adjust-new-region-size-to-take-management-overhea.patch
|
||||||
|
Patch0321: 0321-mm-Preallocate-some-space-when-adding-new-regions.patch
|
||||||
|
Patch0322: 0322-mm-Avoid-complex-heap-growth-math-in-hot-path.patch
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
Name: grub2
|
Name: grub2
|
||||||
Epoch: 1
|
Epoch: 1
|
||||||
Version: 2.06
|
Version: 2.06
|
||||||
Release: 87%{?dist}
|
Release: 88%{?dist}
|
||||||
Summary: Bootloader with support for Linux, Multiboot and more
|
Summary: Bootloader with support for Linux, Multiboot and more
|
||||||
License: GPLv3+
|
License: GPLv3+
|
||||||
URL: http://www.gnu.org/software/grub/
|
URL: http://www.gnu.org/software/grub/
|
||||||
@ -544,6 +544,9 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Mon Feb 20 2023 Robbie Harwood <rharwood@redhat.com> - 2.06-88
|
||||||
|
- Update mm fixes from upstream
|
||||||
|
|
||||||
* Thu Feb 16 2023 Robbie Harwood <rharwood@redhat.com> - 2.06-87
|
* Thu Feb 16 2023 Robbie Harwood <rharwood@redhat.com> - 2.06-87
|
||||||
- Fix disk sector size computation
|
- Fix disk sector size computation
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user