Hi,

Issue:
Linux kernel getting crash after loading kernel in VM system using RISCV
QEMU.

RootCause:
Memory corruption in uboot FDT memory while launching a VM system in RISCV
QEMU.

Fix:
In the board_f.c file the FDT memory region is reserved without FDT padding
bytes. uboot will add some params like bootargs while launching linux.
While relocate the FDT, if its decided as run in the Fixed memory location
i.e fdy_high is set as -1, then the padding bytes not added while
relocating the FDT,
but the size is blindly added with padding bytes without reserving the
physical memory in the FDT header in the image_fdt.c file.

Please find the attached patch file to fix the issue. Please review and
revert your comments.

Regards,
SelvakumarVelandi
Krutrim SI designs

-- 
***
This communication is confidential, may be privileged and is meant only 
for the intended recipient and purpose. No part of this email or any files 
transmitted with it can be shared, copied, forwarded or published online or 
offline, without prior written consent of the sender. If you are not the 
intended recipient, please preserve the confidentiality, delete the e-mail 
and attachments, if any from your system and inform the sender immediately. 
 

***





From f128c309a0481363952f7196180f83ce37663191 Mon Sep 17 00:00:00 2001
From: Selvakumar Velandi <selvakumar.velandi@olasilicon.com>
Date: Wed, 7 Feb 2024 12:16:59 +0530
Subject: [PATCH] [PATCH] RISCV QEMU: Add PAD size during the FDT memory
 reservation and update the FDT size also.

---
 boot/image-fdt.c | 10 ++++++++--
 common/board_f.c | 12 +++++++++++-
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/boot/image-fdt.c b/boot/image-fdt.c
index 75bdd55f32..cac5dc10b4 100644
--- a/boot/image-fdt.c
+++ b/boot/image-fdt.c
@@ -178,8 +178,7 @@ int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size)
 	}
 
 	/* position on a 4K boundary before the alloc_current */
-	/* Pad the FDT by a specified amount */
-	of_len = *of_size + CONFIG_SYS_FDT_PAD;
+	of_len = *of_size;
 
 	/* If fdt_high is set use it to select the relocation address */
 	fdt_high = env_get("fdt_high");
@@ -193,6 +192,8 @@ int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size)
 			lmb_reserve(lmb, map_to_sysmem(of_start), of_len);
 			disable_relocation = 1;
 		} else if (desired_addr) {
+			/* Pad the FDT by a specified amount */
+			of_len += CONFIG_SYS_FDT_PAD;
 			addr = lmb_alloc_base(lmb, of_len, 0x1000,
 					      desired_addr);
 			of_start = map_sysmem(addr, of_len);
@@ -201,6 +202,8 @@ int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size)
 				goto error;
 			}
 		} else {
+			/* Pad the FDT by a specified amount */
+			of_len += CONFIG_SYS_FDT_PAD;
 			addr = lmb_alloc(lmb, of_len, 0x1000);
 			of_start = map_sysmem(addr, of_len);
 		}
@@ -209,6 +212,9 @@ int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size)
 		low = env_get_bootm_low();
 		of_start = NULL;
 
+		/* Pad the FDT by a specified amount */
+		of_len += CONFIG_SYS_FDT_PAD;
+
 		for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
 			start = gd->bd->bi_dram[bank].start;
 			size = gd->bd->bi_dram[bank].size;
diff --git a/common/board_f.c b/common/board_f.c
index 442b8349d0..aab74fb44d 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -572,7 +572,12 @@ static int reserve_fdt(void)
 		 * section, then it will be relocated with other data.
 		 */
 		if (gd->fdt_blob) {
-			gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob), 32);
+			/*
+			 * Reserve the FDT with padded bytes to of breathing room in case
+			 * the device tree needs to be expanded later.
+			 * Update the size in fdt header during relocate.
+			 */
+			gd->fdt_size = ALIGN((fdt_totalsize(gd->fdt_blob) + CONFIG_SYS_FDT_PAD), 32);
 
 			gd->start_addr_sp = reserve_stack_aligned(gd->fdt_size);
 			gd->new_fdt = map_sysmem(gd->start_addr_sp, gd->fdt_size);
@@ -669,6 +674,11 @@ static int reloc_fdt(void)
 			memcpy(gd->new_fdt, gd->fdt_blob,
 			       fdt_totalsize(gd->fdt_blob));
 			gd->fdt_blob = gd->new_fdt;
+			/*
+			 * Size maybe updated with padded bytes in new fdt reservation
+			 * So update the FDT size also.
+			 */
+			fdt_set_totalsize(gd->fdt_blob, gd->fdt_size);
 		}
 	}
 
-- 
2.34.1

Reply via email to