Unfortunately it looks as if my original fix for this was wrong, and in particular causes one of the SPARC64 QEMU advent calendar images which uses a preloaded kernel to panic on boot.
The SILO memory allocators search through the physical memory "available" property but then don't actually allocate the result: instead hardcoded virtual addresses are only mapped to the physical addresses that are determined to be free.
These patches remove the physical and virtual allocations introduced as part of the original fix and map these memory areas in exactly the same way that SILO does.
This also solves the issue the original patches were trying to fix, which was that clients could still claim the memory in-use by the kernel via the CIF - the virtual addresses used by SILO are higher up in memory, making a clash extremely unlikely (and indeed, if it did happen, would mean the kernel/initrd combination would also fail to boot under SILO).
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk
Mark Cave-Ayland (2): SPARC64: fix kernel and initrd mapping to match SILO SPARC32: fix kernel and initrd mapping to match SILO
arch/sparc32/boot.h | 3 +++ arch/sparc32/openbios.c | 31 ++++++++++++++++--------------- arch/sparc64/boot.c | 2 +- arch/sparc64/boot.h | 3 +++ arch/sparc64/openbios.c | 16 +++++++--------- 5 files changed, 30 insertions(+), 25 deletions(-)
The previous attempt to fix this was wrong in that I misinterpreted what SILO was doing: whilst it detects a free region of memory for the kernel/initrd, it simply maps the areas at fixed addresses rather than allocating them.
Fixes: 3464681 "SPARC64: mark initrd memory as mapped and in use before booting kernel" Fixes: c21c366 "SPARC64: mark kernel memory as mapped and in use before booting kernel" Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- arch/sparc64/boot.c | 2 +- arch/sparc64/boot.h | 3 +++ arch/sparc64/openbios.c | 16 +++++++--------- 3 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/arch/sparc64/boot.c b/arch/sparc64/boot.c index 43bd562..2534f13 100644 --- a/arch/sparc64/boot.c +++ b/arch/sparc64/boot.c @@ -37,7 +37,7 @@ void boot(void) unsigned long p4, unsigned long p5);
printk("[sparc64] Kernel already loaded\n"); - entry = (void *) (unsigned long)kernel_image; + entry = (void *) (unsigned long)(IMAGE_VIRT_ADDR + 0x4000); entry(0, 0, 0, 0, (unsigned long)&sparc64_of_client_interface); }
diff --git a/arch/sparc64/boot.h b/arch/sparc64/boot.h index a4f5c12..84a6db1 100644 --- a/arch/sparc64/boot.h +++ b/arch/sparc64/boot.h @@ -6,6 +6,9 @@ * the copyright and warranty status of this work. */
+#define INITRD_VIRT_ADDR 0x40c00000 +#define IMAGE_VIRT_ADDR 0x40000000 + // linux_load.c int linux_load(struct sys_info *info, const char *file, const char *cmdline);
diff --git a/arch/sparc64/openbios.c b/arch/sparc64/openbios.c index e9f4726..aa774c4 100644 --- a/arch/sparc64/openbios.c +++ b/arch/sparc64/openbios.c @@ -564,10 +564,8 @@ void arch_nvram_get(char *data) 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), PAGE_ALIGN(kernel_size), -1); + /* Map kernel memory the same as SILO */ + ofmem_map(PAGE_ALIGN(kernel_image) - 0x4000, IMAGE_VIRT_ADDR, PAGE_ALIGN(kernel_size), -1); }
size = fw_cfg_read_i32(FW_CFG_CMDLINE_SIZE); @@ -585,14 +583,14 @@ void arch_nvram_get(char *data) 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), PAGE_ALIGN(initrd_size), -1); + /* Map initrd memory the same as SILO */ + ofmem_map(PAGE_ALIGN(initrd_image), INITRD_VIRT_ADDR, PAGE_ALIGN(initrd_size), -1); }
if (kernel_size) - printk("kernel addr %llx size %llx\n", kernel_image, kernel_size); + printk("kernel phys %llx virt %x size 0x%llx\n", kernel_image, IMAGE_VIRT_ADDR + 0x4000, kernel_size); + if (initrd_size) + printk("initrd phys %llx virt %x size 0x%llx\n", initrd_image, INITRD_VIRT_ADDR, initrd_size); if (size) printk("kernel cmdline %s\n", obio_cmdline);
The previous attempt to fix this was wrong in that I misinterpreted what SILO was doing: whilst it detects a free region of memory for the kernel/initrd, it simply maps the areas at fixed addresses rather than allocating them.
Fixes: f633f31 "SPARC32: mark initrd memory as mapped and in use before booting kernel" Fixes: c87d0eb "SPARC32: mark kernel memory as mapped" Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- arch/sparc32/boot.h | 3 +++ arch/sparc32/openbios.c | 31 ++++++++++++++++--------------- 2 files changed, 19 insertions(+), 15 deletions(-)
diff --git a/arch/sparc32/boot.h b/arch/sparc32/boot.h index 366e0f6..d225a31 100644 --- a/arch/sparc32/boot.h +++ b/arch/sparc32/boot.h @@ -6,6 +6,9 @@ * the copyright and warranty status of this work. */
+#define INITRD_VIRT_ADDR 0x60000000 +#define IMAGE_VIRT_ADDR 0x4000 + // linux_load.c int linux_load(struct sys_info *info, const char *file, const char *cmdline);
diff --git a/arch/sparc32/openbios.c b/arch/sparc32/openbios.c index 9ec28bf..9af4e18 100644 --- a/arch/sparc32/openbios.c +++ b/arch/sparc32/openbios.c @@ -925,10 +925,8 @@ arch_init( void ) if (kernel_size) { kernel_image = fw_cfg_read_i32(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), PAGE_ALIGN(kernel_size), -1); + /* Map krnel memory a similar way to SILO */ + ofmem_map(PAGE_ALIGN(kernel_image), IMAGE_VIRT_ADDR, PAGE_ALIGN(kernel_size), -1); }
kernel_cmdline = (const char *) fw_cfg_read_i32(FW_CFG_KERNEL_CMDLINE); @@ -944,19 +942,22 @@ arch_init( void ) 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), PAGE_ALIGN(initrd_size), -1); + /* Map krnel memory a similar way to SILO */ + ofmem_map(PAGE_ALIGN(initrd_image), INITRD_VIRT_ADDR, PAGE_ALIGN(initrd_size), -1); }
- /* Setup nvram variables */ - push_str("/options"); - fword("find-device"); - push_str(cmdline); - fword("encode-string"); - push_str("boot-file"); - fword("property"); + if (kernel_size) + printk("kernel phys 0x%x virt 0x%x size 0x%x\n", kernel_image, 0x4000, kernel_size); + if (initrd_size) + printk("initrd phys 0x%x virt 0x%x size 0x%x\n", initrd_image, INITRD_VIRT_ADDR, initrd_size); + + /* Setup nvram variables */ + push_str("/options"); + fword("find-device"); + push_str(cmdline); + fword("encode-string"); + push_str("boot-file"); + fword("property");
boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE);