Currently the /memory node reg property is set to a single range encompassing the entire physical RAM of the machine. This seems to cause issues with Solaris when booting on QEMU SS-10 and SS-20 machines whereby having just a single entry causes the top of physical memory to be calculated incorrectly and triggers a panic on boot.
Instead copy the behaviour of OBP which is to divide the reg property into a set of ranges representing the physical SIMM arrangement in the machine, which fixes the error and allows Solaris to boot under the QEMU SS-10 and SS-20 machines.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- arch/sparc32/boot.h | 2 +- arch/sparc32/lib.c | 14 +++++++++----- arch/sparc32/openbios.c | 6 +++++- 3 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/arch/sparc32/boot.h b/arch/sparc32/boot.h index e372acc..366e0f6 100644 --- a/arch/sparc32/boot.h +++ b/arch/sparc32/boot.h @@ -33,5 +33,5 @@ extern struct linux_mlist_v0 *ptphys; extern struct linux_mlist_v0 *ptmap; extern struct linux_mlist_v0 *ptavail;
-void ob_init_mmu(void); +void ob_init_mmu(uint32_t simm_size); void init_mmu_swift(void); diff --git a/arch/sparc32/lib.c b/arch/sparc32/lib.c index e88c0bf..727929c 100644 --- a/arch/sparc32/lib.c +++ b/arch/sparc32/lib.c @@ -294,12 +294,13 @@ static void ignore_dfault_addr(void) }
void -ob_init_mmu(void) +ob_init_mmu(uint32_t simm_size) { ucell *memreg; ucell *virtreg; phys_addr_t virtregsize; ofmem_t *ofmem = ofmem_arch_get_private(); + int i, c;
/* Find the phandles for the /memory and /virtual-memory nodes */ push_str("/memory"); @@ -315,14 +316,17 @@ ob_init_mmu(void) ofmem_register(s_phandle_memory, s_phandle_mmu);
/* Setup /memory:reg (totphys) property */ - memreg = malloc(3 * sizeof(ucell)); - ofmem_arch_encode_physaddr(memreg, 0); /* physical base */ - memreg[2] = (ucell)ofmem->ramsize; /* size */ + c = ofmem->ramsize / simm_size; + memreg = malloc(3 * c * sizeof(ucell)); + for (i = 0; i < c; i++) { + ofmem_arch_encode_physaddr(&memreg[i * 3], simm_size * i); /* physical base */ + memreg[i * 3 + 2] = simm_size; /* size */ + }
push_str("/memory"); fword("find-device"); PUSH(pointer2cell(memreg)); - PUSH(3 * sizeof(ucell)); + PUSH(3 * c * sizeof(ucell)); push_str("reg"); PUSH_ph(s_phandle_memory); fword("encode-property"); diff --git a/arch/sparc32/openbios.c b/arch/sparc32/openbios.c index 3ec8fd7..17a6550 100644 --- a/arch/sparc32/openbios.c +++ b/arch/sparc32/openbios.c @@ -42,6 +42,7 @@ struct hwdef { unsigned long aux1_offset, aux2_offset; uint64_t dma_base, esp_base, le_base; uint64_t tcx_base; + uint32_t simm_size; int intr_ncpu; int mid_offset; int machine_id_low, machine_id_high; @@ -65,6 +66,7 @@ static const struct hwdef hwdefs[] = { .dma_base = 0x78400000, .esp_base = 0x78800000, .le_base = 0x78c00000, + .simm_size = 0x2000000, .mid_offset = 0, .machine_id_low = 32, .machine_id_high = 63, @@ -86,6 +88,7 @@ static const struct hwdef hwdefs[] = { .dma_base = 0xef0400000ULL, .esp_base = 0xef0800000ULL, .le_base = 0xef0c00000ULL, + .simm_size = 0x4000000, .mid_offset = 8, .machine_id_low = 64, .machine_id_high = 65, @@ -107,6 +110,7 @@ static const struct hwdef hwdefs[] = { .dma_base = 0xef0081000ULL, .esp_base = 0xef0080000ULL, .le_base = 0xef0060000ULL, + .simm_size = 0x4000000, .mid_offset = 8, .machine_id_low = 66, .machine_id_high = 66, @@ -874,7 +878,7 @@ arch_init( void )
openbios_init(); modules_init(); - ob_init_mmu(); + ob_init_mmu(hwdef->simm_size); ob_init_iommu(hwdef->iommu_base);
bind_func("(sparc32-dma-alloc)", dma_alloc);