summaryrefslogtreecommitdiff
path: root/sys/arch/sgi
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2008-05-04 12:27:47 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2008-05-04 12:27:47 +0000
commit8cb2e385f14cca2abafb8a4901f0619248d4f0f2 (patch)
treef5fbc56c60ea20509b4c1e6e1e0228518f39bbce /sys/arch/sgi
parentac601af741ec6b7286d79ec95cef84354dcf0cfe (diff)
Unpopulated CRIME memory banks (or logically empty due to CRIME merging
contiguous 64MB DIMMs in a single 128MB one) are not reported as memory at offset zero, but actually as duplicates of the first entry (which always matches real memory). If the DIMMs are set up in decreasing sizes, as recommanded by SGI, the first entry will be configured at offset zero, so the existing code would run fine. If, however, you order your DIMMs in a different order, the first entry might not be at offset zero, so the kernel will mess up its memory information, which will cause random effects from simply misreported memory sizes, to the inability to boot. Fix this by strengthening the check for an empty bank. Problem reported by Jason Bergstrom (bergie, bergie dot net), analysis and fix by me.
Diffstat (limited to 'sys/arch/sgi')
-rw-r--r--sys/arch/sgi/sgi/ip32_machdep.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/sys/arch/sgi/sgi/ip32_machdep.c b/sys/arch/sgi/sgi/ip32_machdep.c
index 93a273b5645..e46587347d8 100644
--- a/sys/arch/sgi/sgi/ip32_machdep.c
+++ b/sys/arch/sgi/sgi/ip32_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip32_machdep.c,v 1.2 2008/04/24 12:29:34 jsing Exp $ */
+/* $OpenBSD: ip32_machdep.c,v 1.3 2008/05/04 12:27:46 miod Exp $ */
/*
* Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -59,26 +59,37 @@ crime_configure_memory(void)
volatile u_int64_t *bank_ctrl;
paddr_t addr;
psize_t size;
+ u_int64_t ctrl0, ctrl;
u_int32_t first_page, last_page;
int bank, i;
bank_ctrl = (void *)PHYS_TO_KSEG1(CRIMEBUS_BASE + CRIME_MEM_BANK0_CONTROL);
for (bank = 0; bank < CRIME_MAX_BANKS; bank++) {
- addr = (bank_ctrl[bank] & CRIME_MEM_BANK_ADDR) << 25;
- size = (bank_ctrl[bank] & CRIME_MEM_BANK_128MB) ? 128 : 32;
+ ctrl = bank_ctrl[bank];
+ addr = (ctrl & CRIME_MEM_BANK_ADDR) << 25;
+ size = (ctrl & CRIME_MEM_BANK_128MB) ? 128 : 32;
+
+ /*
+ * Empty banks are reported as duplicates of bank #0.
+ */
+ if (bank == 0)
+ ctrl0 = ctrl;
+ else if (ctrl == ctrl0)
+ continue;
+
#ifdef DEBUG
- bios_printf("crime: bank %d contains %ld MB at 0x%lx\n",
+ bios_printf("crime: bank %d contains %ld MB at %p\n",
bank, size, addr);
#endif
/*
- * Do not report memory regions below 256MB, since ARCBIOS will do.
- * Moreover, empty banks are reported at address zero.
+ * Do not report memory regions below 256MB, since ARCBIOS
+ * will do.
*/
if (addr < 256 * 1024 * 1024)
continue;
- addr += 1024 * 1024 * 1024;
+ addr += CRIME_MEMORY_OFFSET;
size *= 1024 * 1024;
first_page = atop(addr);
last_page = atop(addr + size);
@@ -100,12 +111,13 @@ crime_configure_memory(void)
m->mem_last_page = last_page;
}
}
- if (m != NULL && m->mem_last_page == 0) {
- m->mem_first_page = first_page;
- m->mem_last_page = last_page;
- }
- if (m != NULL)
+ if (m != NULL) {
+ if (m->mem_last_page == 0) {
+ m->mem_first_page = first_page;
+ m->mem_last_page = last_page;
+ }
physmem += atop(size);
+ }
}
#ifdef DEBUG