ppc64le sysfs and mm update

Resolves: #2026579
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
This commit is contained in:
Robbie Harwood 2023-02-20 17:22:34 +00:00
parent 611ca8bf3e
commit 36401863be
6 changed files with 349 additions and 1 deletions

View File

@ -0,0 +1,70 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mukesh Kumar Chaurasiya <mchauras@linux.vnet.ibm.com>
Date: Thu, 9 Feb 2023 13:09:16 +0530
Subject: [PATCH] osdep/linux/hostdisk: Modify sector by sysfs as disk sector
The disk sector size provided by sysfs file system considers the sector
size of 512 irrespective of disk sector size, thus causing the read by
the GRUB to an incorrect offset from what was originally intended.
Considering the 512 sector size of sysfs data the actual sector needs to
be modified corresponding to disk sector size.
Signed-off-by: Mukesh Kumar Chaurasiya <mchauras@linux.vnet.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
(cherry picked from commit f7564844f82b57078d601befadc438b5bc1fa01b)
---
grub-core/osdep/linux/hostdisk.c | 7 ++++---
include/grub/disk.h | 7 +++++++
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/grub-core/osdep/linux/hostdisk.c b/grub-core/osdep/linux/hostdisk.c
index 7bc99ac1c1..a9ea0bb465 100644
--- a/grub-core/osdep/linux/hostdisk.c
+++ b/grub-core/osdep/linux/hostdisk.c
@@ -240,7 +240,8 @@ have_devfs (void)
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
static int
-grub_hostdisk_linux_find_partition (char *dev, grub_disk_addr_t sector)
+grub_hostdisk_linux_find_partition (const grub_disk_t disk, char *dev,
+ grub_disk_addr_t sector)
{
size_t len = strlen (dev);
const char *format;
@@ -305,7 +306,7 @@ grub_hostdisk_linux_find_partition (char *dev, grub_disk_addr_t sector)
if (fstat (fd, &st) < 0
|| !grub_util_device_is_mapped_stat (&st)
|| !grub_util_get_dm_node_linear_info (st.st_rdev, 0, 0, &start))
- start = grub_util_find_partition_start_os (real_dev);
+ start = grub_disk_to_native_sector (disk, grub_util_find_partition_start_os (real_dev));
/* We don't care about errors here. */
grub_errno = GRUB_ERR_NONE;
@@ -386,7 +387,7 @@ grub_util_fd_open_device (const grub_disk_t disk, grub_disk_addr_t sector, int f
&& strncmp (dev, "/dev/", 5) == 0)
{
if (sector >= part_start)
- is_partition = grub_hostdisk_linux_find_partition (dev, part_start);
+ is_partition = grub_hostdisk_linux_find_partition (disk, dev, part_start);
else
*max = part_start - sector;
}
diff --git a/include/grub/disk.h b/include/grub/disk.h
index 06210a7049..881addcc77 100644
--- a/include/grub/disk.h
+++ b/include/grub/disk.h
@@ -208,6 +208,13 @@ grub_disk_from_native_sector (grub_disk_t disk, grub_disk_addr_t sector)
return sector << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
}
+/* Convert from GRUB native disk sized sector to disk sized sector. */
+static inline grub_disk_addr_t
+grub_disk_to_native_sector (grub_disk_t disk, grub_disk_addr_t sector)
+{
+ return sector >> (disk->log_sector_size - GRUB_DISK_SECTOR_BITS);
+}
+
/* This is called from the memory manager. */
void grub_disk_cache_invalidate_all (void);

View 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;
}

View 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;

View 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;

View File

@ -316,3 +316,7 @@ Patch0315: 0315-ieee1275-support-runtime-memory-claiming.patch
Patch0316: 0316-ieee1275-implement-vec5-for-cas-negotiation.patch
Patch0317: 0317-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch
Patch0318: 0318-powerpc-Drop-Open-Hack-Ware.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

View File

@ -16,7 +16,7 @@
Name: grub2
Epoch: 1
Version: 2.06
Release: 60%{?dist}
Release: 61%{?dist}
Summary: Bootloader with support for Linux, Multiboot and more
License: GPLv3+
URL: http://www.gnu.org/software/grub/
@ -533,6 +533,10 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg
%endif
%changelog
* Mon Feb 20 2023 Robbie Harwood <rharwood@redhat.com> - 2.06-61
- ppc64le sysfs and mm update
- Resolves: #2026579
* Wed Feb 15 2023 Robbie Harwood <rharwood@redhat.com> - 2.06-60
- Sync patches with Fedora
- Resolves: #2007427