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(a)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);
--
2.11.0