kern/ieee1275/init: ppc64: Restrict high memory in presence
of fadump Resolves: #RHEL-14283 Signed-off-by: Nicolas Frayer <nfrayer@redhat.com>
This commit is contained in:
parent
7a35ff39a8
commit
2c4092ba33
210
0580-kern-ieee1275-init-ppc64-Restrict-high-memory-in-pre.patch
Normal file
210
0580-kern-ieee1275-init-ppc64-Restrict-high-memory-in-pre.patch
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Berger <stefanb@linux.ibm.com>
|
||||||
|
Date: Tue, 8 Aug 2023 12:21:55 -0400
|
||||||
|
Subject: [PATCH] kern/ieee1275/init: ppc64: Restrict high memory in presence
|
||||||
|
of fadump
|
||||||
|
|
||||||
|
This is a backport of the patch with the same name to grub 2.02.
|
||||||
|
|
||||||
|
When a kernel dump is present then restrict the high memory regions to
|
||||||
|
avoid allocating memory where the kernel dump resides. Use the
|
||||||
|
ibm,kernel-dump node under /rtas to determine whether a kernel dump exists
|
||||||
|
and up to which limit grub can use available memory. Set the
|
||||||
|
upper_mem_limit to the size of the kernel dump section of type
|
||||||
|
'REAL_MODE_REGION' and therefore only allow grub's memory usage for high
|
||||||
|
addresses from 768MB to 'upper_mem_limit'. This means that grub can
|
||||||
|
use high memory in the range of 768MB to upper_mem_limit and
|
||||||
|
the kernel-dump memory regions above 'upper_mem_limit' remain untouched.
|
||||||
|
This change has no effect on memory allocations below 640MB.
|
||||||
|
|
||||||
|
Also, fall back to allocating below 640MB in case the chunk of
|
||||||
|
memory there would be larger than the chunk of memory above 768MB.
|
||||||
|
This can for example occur if a free memory area is found starting at 300MB
|
||||||
|
extending up to 1GB but a kernel dump is located at 768MB and therefore
|
||||||
|
does not allow the allocation of the high memory area but requiring to use
|
||||||
|
the chunk starting at 300MB to avoid an unnecessary out-of-memory
|
||||||
|
condition.
|
||||||
|
|
||||||
|
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
|
||||||
|
Cc: Hari Bathini <hbathini@linux.ibm.com>
|
||||||
|
Cc: Pavithra Prakash <pavrampu@in.ibm.com>
|
||||||
|
Cc: Michael Ellerman <mpe@ellerman.id.au>
|
||||||
|
Cc: Carolyn Scherrer <cpscherr@us.ibm.com>
|
||||||
|
Cc: Mahesh Salgaonkar <mahesh@linux.ibm.com>
|
||||||
|
Cc: Sourabh Jain <sourabhjain@linux.ibm.com>
|
||||||
|
---
|
||||||
|
grub-core/kern/ieee1275/init.c | 139 +++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 139 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
|
||||||
|
index 1fae84440403..31843ab70a62 100644
|
||||||
|
--- a/grub-core/kern/ieee1275/init.c
|
||||||
|
+++ b/grub-core/kern/ieee1275/init.c
|
||||||
|
@@ -17,6 +17,8 @@
|
||||||
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
+#include <stddef.h> /* offsetof() */
|
||||||
|
+
|
||||||
|
#include <grub/kernel.h>
|
||||||
|
#include <grub/dl.h>
|
||||||
|
#include <grub/disk.h>
|
||||||
|
@@ -180,6 +182,97 @@ grub_claim_heap (void)
|
||||||
|
+ GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
+
|
||||||
|
+/* ibm,kernel-dump data structures */
|
||||||
|
+struct kd_section
|
||||||
|
+{
|
||||||
|
+ grub_uint32_t flags;
|
||||||
|
+ grub_uint16_t src_datatype;
|
||||||
|
+#define KD_SRC_DATATYPE_REAL_MODE_REGION 0x0011
|
||||||
|
+ grub_uint16_t error_flags;
|
||||||
|
+ grub_uint64_t src_address;
|
||||||
|
+ grub_uint64_t num_bytes;
|
||||||
|
+ grub_uint64_t act_bytes;
|
||||||
|
+ grub_uint64_t dst_address;
|
||||||
|
+} GRUB_PACKED;
|
||||||
|
+
|
||||||
|
+#define MAX_KD_SECTIONS 10
|
||||||
|
+
|
||||||
|
+struct kernel_dump
|
||||||
|
+{
|
||||||
|
+ grub_uint32_t format;
|
||||||
|
+ grub_uint16_t num_sections;
|
||||||
|
+ grub_uint16_t status_flags;
|
||||||
|
+ grub_uint32_t offset_1st_section;
|
||||||
|
+ grub_uint32_t num_blocks;
|
||||||
|
+ grub_uint64_t start_block;
|
||||||
|
+ grub_uint64_t num_blocks_avail;
|
||||||
|
+ grub_uint32_t offet_path_string;
|
||||||
|
+ grub_uint32_t max_time_allowed;
|
||||||
|
+ struct kd_section kds[MAX_KD_SECTIONS]; /* offset_1st_section should point to kds[0] */
|
||||||
|
+} GRUB_PACKED;
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Determine if a kernel dump exists and if it does, then determine the highest
|
||||||
|
+ * address that grub can use for memory allocations.
|
||||||
|
+ * The caller must have initialized *highest to ~0. *highest will not
|
||||||
|
+ * be modified if no kernel dump is found.
|
||||||
|
+ */
|
||||||
|
+static int
|
||||||
|
+check_kernel_dump (grub_uint64_t *highest)
|
||||||
|
+{
|
||||||
|
+ struct kernel_dump kernel_dump;
|
||||||
|
+ grub_ssize_t kernel_dump_size;
|
||||||
|
+ grub_ieee1275_phandle_t rtas;
|
||||||
|
+ struct kd_section *kds;
|
||||||
|
+ grub_size_t i;
|
||||||
|
+
|
||||||
|
+ /* If there's a kernel-dump it must have at least one section */
|
||||||
|
+ if (grub_ieee1275_finddevice ("/rtas", &rtas) ||
|
||||||
|
+ grub_ieee1275_get_property (rtas, "ibm,kernel-dump", &kernel_dump,
|
||||||
|
+ sizeof (kernel_dump), &kernel_dump_size) ||
|
||||||
|
+ kernel_dump_size <= (grub_ssize_t) offsetof (struct kernel_dump, kds[1]))
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ kernel_dump_size = grub_min (kernel_dump_size, (grub_ssize_t) sizeof (kernel_dump));
|
||||||
|
+
|
||||||
|
+ if (grub_be_to_cpu32 (kernel_dump.format) != 1)
|
||||||
|
+ {
|
||||||
|
+ grub_printf (_("Error: ibm,kernel-dump has an unexpected format version '%u'\n"),
|
||||||
|
+ grub_be_to_cpu32 (kernel_dump.format));
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (grub_be_to_cpu16 (kernel_dump.num_sections) > MAX_KD_SECTIONS)
|
||||||
|
+ {
|
||||||
|
+ grub_printf (_("Error: Too many kernel dump sections: %d\n"),
|
||||||
|
+ grub_be_to_cpu32 (kernel_dump.num_sections));
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < grub_be_to_cpu16 (kernel_dump.num_sections); i++)
|
||||||
|
+ {
|
||||||
|
+ kds = (struct kd_section *) ((grub_addr_t) &kernel_dump +
|
||||||
|
+ grub_be_to_cpu32 (kernel_dump.offset_1st_section) +
|
||||||
|
+ i * sizeof (struct kd_section));
|
||||||
|
+ /* sanity check the address is within the 'kernel_dump' struct */
|
||||||
|
+ if ((grub_addr_t) kds > (grub_addr_t) &kernel_dump + kernel_dump_size + sizeof (*kds))
|
||||||
|
+ {
|
||||||
|
+ grub_printf (_("Error: 'kds' address beyond last available section\n"));
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ((grub_be_to_cpu16 (kds->src_datatype) == KD_SRC_DATATYPE_REAL_MODE_REGION) &&
|
||||||
|
+ (grub_be_to_cpu64 (kds->src_address) == 0))
|
||||||
|
+ {
|
||||||
|
+ *highest = grub_min (*highest, grub_be_to_cpu64 (kds->num_bytes));
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Helper for grub_claim_heap on powerpc. */
|
||||||
|
static int
|
||||||
|
heap_size (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type,
|
||||||
|
@@ -207,7 +300,9 @@ static int
|
||||||
|
heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
+ grub_uint64_t upper_mem_limit = ~0;
|
||||||
|
grub_uint32_t total = *(grub_uint32_t *)data;
|
||||||
|
+ int has_kernel_dump;
|
||||||
|
|
||||||
|
if (type != GRUB_MEMORY_AVAILABLE)
|
||||||
|
return 0;
|
||||||
|
@@ -243,6 +338,50 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type,
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ has_kernel_dump = check_kernel_dump (&upper_mem_limit);
|
||||||
|
+ if (has_kernel_dump)
|
||||||
|
+ {
|
||||||
|
+ grub_uint64_t lo_len = 0, hi_len = 0;
|
||||||
|
+
|
||||||
|
+ if (addr > upper_mem_limit || upper_mem_limit == (grub_uint64_t)~0)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ /* limit len to stay below upper_mem_limit */
|
||||||
|
+ if (addr < upper_mem_limit && (addr + len) > upper_mem_limit)
|
||||||
|
+ {
|
||||||
|
+ len = grub_min (len, upper_mem_limit - addr);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* We can allocate below 640MB or above 768MB.
|
||||||
|
+ * Choose the bigger chunk below 640MB or above 768MB.
|
||||||
|
+ */
|
||||||
|
+ if (addr < 0x28000000)
|
||||||
|
+ {
|
||||||
|
+ lo_len = grub_min (len, 0x28000000 - addr);
|
||||||
|
+ }
|
||||||
|
+ if (addr + len > 0x30000000)
|
||||||
|
+ {
|
||||||
|
+ if (addr < 0x30000000)
|
||||||
|
+ hi_len = len - (0x30000000 - addr);
|
||||||
|
+ else
|
||||||
|
+ hi_len = len;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (hi_len > lo_len)
|
||||||
|
+ {
|
||||||
|
+ len = hi_len;
|
||||||
|
+ if (addr < 0x30000000)
|
||||||
|
+ addr = 0x30000000;
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+ {
|
||||||
|
+ len = lo_len;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (len == 0)
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* If this block contains 0x30000000 (768MB), do not claim below that.
|
||||||
|
Linux likes to claim memory at min(RMO top, 768MB) and works down
|
||||||
|
without reference to /memory/available. */
|
@ -577,3 +577,4 @@ Patch0576: 0576-efi-http-change-uint32_t-to-uintn_t-for-grub_efi_htt.patch
|
|||||||
Patch0577: 0577-ieee1275-Converting-plain-numbers-to-constants-in-Ve.patch
|
Patch0577: 0577-ieee1275-Converting-plain-numbers-to-constants-in-Ve.patch
|
||||||
Patch0578: 0578-ieee1275-extended-support-in-options-vector5.patch
|
Patch0578: 0578-ieee1275-extended-support-in-options-vector5.patch
|
||||||
Patch0579: 0579-Regenerate-kernelopts-if-missing-on-ppc.patch
|
Patch0579: 0579-Regenerate-kernelopts-if-missing-on-ppc.patch
|
||||||
|
Patch0580: 0580-kern-ieee1275-init-ppc64-Restrict-high-memory-in-pre.patch
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
Name: grub2
|
Name: grub2
|
||||||
Epoch: 1
|
Epoch: 1
|
||||||
Version: 2.02
|
Version: 2.02
|
||||||
Release: 151%{?dist}
|
Release: 152%{?dist}
|
||||||
Summary: Bootloader with support for Linux, Multiboot and more
|
Summary: Bootloader with support for Linux, Multiboot and more
|
||||||
Group: System Environment/Base
|
Group: System Environment/Base
|
||||||
License: GPLv3+
|
License: GPLv3+
|
||||||
@ -510,6 +510,11 @@ fi
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Fri Oct 20 2023 Nicolas Frayer <nfrayer@redhat.com> - 2.02-152
|
||||||
|
- kern/ieee1275/init: ppc64: Restrict high memory in presence
|
||||||
|
of fadump
|
||||||
|
- Resolves: #RHEL-14283
|
||||||
|
|
||||||
* Mon Aug 28 2023 Nicolas Frayer <nfrayer@redhat.com> - 2.02-151
|
* Mon Aug 28 2023 Nicolas Frayer <nfrayer@redhat.com> - 2.02-151
|
||||||
- util: Regenerate kernelopts if missing on ppc
|
- util: Regenerate kernelopts if missing on ppc
|
||||||
- Resolves: #2051889
|
- Resolves: #2051889
|
||||||
|
Loading…
Reference in New Issue
Block a user