Bootloaders such as SILO will have already allocated and mapped the memory for the kernel and initrd before jumping into the kernel, so this patchset does the same for a kernel/initrd loaded directly by QEMU.
Otherwise if the kernel/initrd grow beyond the default 1:1 memory region mapped by the PROM then the kernel will panic when clearing the memory on startup.
In order for this to work on SPARC32 then the corresponding QEMU patch at https://lists.gnu.org/archive/html/qemu-devel/2019-01/msg06635.html must also be applied.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk
Mark Cave-Ayland (5): SPARC32: fix obp_arg.argv when no kernel command line specified SPARC32: mark kernel memory as mapped SPARC32: mark initrd memory as mapped and in use before booting kernel SPARC64: mark kernel memory as mapped and in use before booting kernel SPARC64: mark initrd memory as mapped and in use before booting kernel
arch/sparc32/boot.c | 2 ++ arch/sparc32/openbios.c | 29 ++++++++++++++++++++--------- arch/sparc64/boot.c | 2 ++ arch/sparc64/boot.h | 2 ++ arch/sparc64/openbios.c | 18 +++++++++++++++++- include/drivers/drivers.h | 2 ++ 6 files changed, 45 insertions(+), 10 deletions(-)
Make sure that obp_arg.argv is set to an empty string if no command line is passed from QEMU. Otherwise the kernel will panic on startup when trying to access it.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- arch/sparc32/openbios.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/arch/sparc32/openbios.c b/arch/sparc32/openbios.c index 17a6550..c03847c 100644 --- a/arch/sparc32/openbios.c +++ b/arch/sparc32/openbios.c @@ -922,14 +922,14 @@ arch_init( void ) ofmem_claim_virt(PAGE_ALIGN(kernel_image), PAGE_ALIGN(kernel_size), 0); }
- kernel_cmdline = (const char *) fw_cfg_read_i32(FW_CFG_KERNEL_CMDLINE); - if (kernel_cmdline) { - cmdline = strdup(kernel_cmdline); - obp_arg.argv[1] = cmdline; - } else { - cmdline = strdup(""); - } - qemu_cmdline = (uint32_t)cmdline; + kernel_cmdline = (const char *) fw_cfg_read_i32(FW_CFG_KERNEL_CMDLINE); + if (kernel_cmdline) { + cmdline = strdup(kernel_cmdline); + } else { + cmdline = strdup(""); + } + obp_arg.argv[1] = cmdline; + qemu_cmdline = (uint32_t)cmdline;
/* Setup nvram variables */ push_str("/options");
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- arch/sparc32/openbios.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/sparc32/openbios.c b/arch/sparc32/openbios.c index c03847c..65bda23 100644 --- a/arch/sparc32/openbios.c +++ b/arch/sparc32/openbios.c @@ -917,9 +917,10 @@ arch_init( void ) if (kernel_size) { kernel_image = fw_cfg_read_i32(FW_CFG_KERNEL_ADDR);
- /* Mark the kernel memory as in use */ + /* Mark the kernel memory as mapped 1:1 and in use */ ofmem_claim_phys(PAGE_ALIGN(kernel_image), PAGE_ALIGN(kernel_size), 0); ofmem_claim_virt(PAGE_ALIGN(kernel_image), PAGE_ALIGN(kernel_size), 0); + ofmem_map(PAGE_ALIGN(kernel_image), PAGE_ALIGN(kernel_image), kernel_size, -1); }
kernel_cmdline = (const char *) fw_cfg_read_i32(FW_CFG_KERNEL_CMDLINE);
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- arch/sparc32/boot.c | 2 ++ arch/sparc32/openbios.c | 10 ++++++++++ include/drivers/drivers.h | 2 ++ 3 files changed, 14 insertions(+)
diff --git a/arch/sparc32/boot.c b/arch/sparc32/boot.c index e9605f5..bb5a579 100644 --- a/arch/sparc32/boot.c +++ b/arch/sparc32/boot.c @@ -17,6 +17,8 @@
uint32_t kernel_image; uint32_t kernel_size; +uint32_t initrd_image; +uint32_t initrd_size; uint32_t qemu_cmdline; uint32_t cmdline_size; char boot_device; diff --git a/arch/sparc32/openbios.c b/arch/sparc32/openbios.c index 65bda23..e424219 100644 --- a/arch/sparc32/openbios.c +++ b/arch/sparc32/openbios.c @@ -932,6 +932,16 @@ arch_init( void ) obp_arg.argv[1] = cmdline; qemu_cmdline = (uint32_t)cmdline;
+ initrd_size = fw_cfg_read_i32(FW_CFG_INITRD_SIZE); + if (initrd_size) { + initrd_image = fw_cfg_read_i32(FW_CFG_INITRD_ADDR); + + /* Mark initrd memory as mapped 1:1 and in use */ + ofmem_claim_phys(PAGE_ALIGN(initrd_image), PAGE_ALIGN(initrd_size), 0); + ofmem_claim_virt(PAGE_ALIGN(initrd_image), PAGE_ALIGN(initrd_size), 0); + ofmem_map(PAGE_ALIGN(initrd_image), PAGE_ALIGN(initrd_image), initrd_size, -1); + } + /* Setup nvram variables */ push_str("/options"); fword("find-device"); diff --git a/include/drivers/drivers.h b/include/drivers/drivers.h index d162901..e568f28 100644 --- a/include/drivers/drivers.h +++ b/include/drivers/drivers.h @@ -106,6 +106,8 @@ void ob_intr(int intr); /* arch/sparc32/boot.c */ extern uint32_t kernel_image; extern uint32_t kernel_size; +extern uint32_t initrd_image; +extern uint32_t initrd_size; extern uint32_t qemu_cmdline; extern uint32_t cmdline_size; extern char boot_device;
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- arch/sparc64/openbios.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/sparc64/openbios.c b/arch/sparc64/openbios.c index b2e79d0..61610d1 100644 --- a/arch/sparc64/openbios.c +++ b/arch/sparc64/openbios.c @@ -560,9 +560,15 @@ void arch_nvram_get(char *data) }
kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE); - if (kernel_size) + if (kernel_size) { kernel_image = fw_cfg_read_i64(FW_CFG_KERNEL_ADDR);
+ /* Mark the kernel memory as mapped 1:1 and in use */ + ofmem_claim_phys(PAGE_ALIGN(kernel_image), PAGE_ALIGN(kernel_size), 0); + ofmem_claim_virt(PAGE_ALIGN(kernel_image), PAGE_ALIGN(kernel_size), 0); + ofmem_map(PAGE_ALIGN(kernel_image), PAGE_ALIGN(kernel_image), kernel_size, -1); + } + size = fw_cfg_read_i32(FW_CFG_CMDLINE_SIZE); if (size) { obio_cmdline = (char *)malloc(size + 1);
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- arch/sparc64/boot.c | 2 ++ arch/sparc64/boot.h | 2 ++ arch/sparc64/openbios.c | 10 ++++++++++ 3 files changed, 14 insertions(+)
diff --git a/arch/sparc64/boot.c b/arch/sparc64/boot.c index 54f6f7a..43bd562 100644 --- a/arch/sparc64/boot.c +++ b/arch/sparc64/boot.c @@ -13,6 +13,8 @@
uint64_t kernel_image; uint64_t kernel_size; +uint64_t initrd_image; +uint64_t initrd_size; uint64_t qemu_cmdline; uint64_t cmdline_size; char *boot_device; diff --git a/arch/sparc64/boot.h b/arch/sparc64/boot.h index 88beb1c..a4f5c12 100644 --- a/arch/sparc64/boot.h +++ b/arch/sparc64/boot.h @@ -12,6 +12,8 @@ int linux_load(struct sys_info *info, const char *file, const char *cmdline); // boot.c extern uint64_t kernel_image; extern uint64_t kernel_size; +extern uint64_t initrd_image; +extern uint64_t initrd_size; extern uint64_t qemu_cmdline; extern uint64_t cmdline_size; extern char *boot_device; diff --git a/arch/sparc64/openbios.c b/arch/sparc64/openbios.c index 61610d1..c4feae2 100644 --- a/arch/sparc64/openbios.c +++ b/arch/sparc64/openbios.c @@ -580,6 +580,16 @@ void arch_nvram_get(char *data) qemu_cmdline = (uint64_t)obio_cmdline; cmdline_size = size;
+ initrd_size = fw_cfg_read_i32(FW_CFG_INITRD_SIZE); + if (initrd_size) { + initrd_image = fw_cfg_read_i32(FW_CFG_INITRD_ADDR); + + /* Mark initrd memory as mapped 1:1 and in use */ + ofmem_claim_phys(PAGE_ALIGN(initrd_image), PAGE_ALIGN(initrd_size), 0); + ofmem_claim_virt(PAGE_ALIGN(initrd_image), PAGE_ALIGN(initrd_size), 0); + ofmem_map(PAGE_ALIGN(initrd_image), PAGE_ALIGN(initrd_image), initrd_size, -1); + } + if (kernel_size) printk("kernel addr %llx size %llx\n", kernel_image, kernel_size); if (size)