Module Name: src
Committed By: tsutsui
Date: Sun Oct 27 02:06:06 UTC 2013
Modified Files:
src/sys/arch/x68k/x68k: locore.s machdep.c pmap_bootstrap.c
Log Message:
Probe extended memories before pmap_boostrap() for actual fix of PR/45915.
Also expand expected maximum extended memory regions to recognize
upto 1008 MB RAM that is supported by the XM6i emulator.
See my post on port-x68k@ for more details:
http://mail-index.NetBSD.org/port-x68k/2013/10/19/msg000039.html
Probably worth to pullup to netbsd-6.
To generate a diff of this commit:
cvs rdiff -u -r1.110 -r1.111 src/sys/arch/x68k/x68k/locore.s
cvs rdiff -u -r1.186 -r1.187 src/sys/arch/x68k/x68k/machdep.c
cvs rdiff -u -r1.59 -r1.60 src/sys/arch/x68k/x68k/pmap_bootstrap.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/x68k/x68k/locore.s
diff -u src/sys/arch/x68k/x68k/locore.s:1.110 src/sys/arch/x68k/x68k/locore.s:1.111
--- src/sys/arch/x68k/x68k/locore.s:1.110 Sat May 19 08:29:32 2012
+++ src/sys/arch/x68k/x68k/locore.s Sun Oct 27 02:06:06 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: locore.s,v 1.110 2012/05/19 08:29:32 tsutsui Exp $ */
+/* $NetBSD: locore.s,v 1.111 2013/10/27 02:06:06 tsutsui Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@@ -777,6 +777,8 @@ Lstart1:
#endif
movl #_C_LABEL(end),%d5 | end of static kernel text/data
Lstart2:
+ RELOC(setmemrange,%a0) | call setmemrange()
+ jbsr %a0@ | to probe all memory regions
addl #PAGE_SIZE-1,%d5
andl #PG_FRAME,%d5 | round to a page
movl %d5,%a4
Index: src/sys/arch/x68k/x68k/machdep.c
diff -u src/sys/arch/x68k/x68k/machdep.c:1.186 src/sys/arch/x68k/x68k/machdep.c:1.187
--- src/sys/arch/x68k/x68k/machdep.c:1.186 Tue Jan 22 11:58:39 2013
+++ src/sys/arch/x68k/x68k/machdep.c Sun Oct 27 02:06:06 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.186 2013/01/22 11:58:39 isaki Exp $ */
+/* $NetBSD: machdep.c,v 1.187 2013/10/27 02:06:06 tsutsui Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.186 2013/01/22 11:58:39 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.187 2013/10/27 02:06:06 tsutsui Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
@@ -130,10 +130,6 @@ void initcpu(void);
int cpu_dumpsize(void);
int cpu_dump(int (*)(dev_t, daddr_t, void *, size_t), daddr_t *);
void cpu_init_kcore_hdr(void);
-#ifdef EXTENDED_MEMORY
-static int mem_exists(void *, u_long);
-static void setmemrange(void);
-#endif
/* functions called from locore.s */
void x68k_init(void);
@@ -142,6 +138,24 @@ void straytrap(int, u_short);
void nmihand(struct frame);
void intrhand(int);
+/* memory probe function called from locore.s */
+void setmemrange(void);
+#ifdef EXTENDED_MEMORY
+static bool mem_exists(paddr_t, paddr_t);
+#endif
+
+typedef struct {
+ paddr_t start;
+ paddr_t end;
+} phys_seg_t;
+
+static int basemem;
+static phys_seg_t phys_basemem_seg;
+#ifdef EXTENDED_MEMORY
+#define EXTMEM_SEGS (VM_PHYSSEG_MAX - 1)
+static phys_seg_t phys_extmem_seg[EXTMEM_SEGS];
+#endif
+
/*
* On the 68020/68030, the value of delay_divisor is roughly
* 2048 / cpuspeed (where cpuspeed is in MHz).
@@ -167,24 +181,35 @@ x68k_init(void)
{
u_int i;
paddr_t msgbuf_pa;
+ paddr_t s, e;
/*
- * Tell the VM system about available physical memory.
+ * Most m68k ports allocate msgbuf at the end of available memory
+ * (i.e. just after avail_end), but on x68k we allocate msgbuf
+ * at the end of main memory for compatibility.
*/
- uvm_page_physload(atop(avail_start), atop(avail_end),
- atop(avail_start), atop(avail_end),
- VM_FREELIST_MAINMEM);
+ msgbuf_pa = phys_basemem_seg.end - m68k_round_page(MSGBUFSIZE);
/*
- * avail_end was pre-decremented in pmap_bootstrap to compensate
- * for msgbuf pages, but avail_end is also used to check DMA'able
- * memory range for intio devices and it would be updated per
- * probed extended memories, so explicitly save msgbuf address here.
+ * Tell the VM system about available physical memory.
*/
- msgbuf_pa = avail_end;
+ /* load the main memory region */
+ s = avail_start;
+ e = msgbuf_pa;
+ uvm_page_physload(atop(s), atop(e), atop(s), atop(e),
+ VM_FREELIST_MAINMEM);
#ifdef EXTENDED_MEMORY
- setmemrange();
+ /* load extended memory regions */
+ for (i = 0; i < EXTMEM_SEGS; i++) {
+ if (phys_extmem_seg[i].start == phys_extmem_seg[i].end)
+ continue;
+ uvm_page_physload(atop(phys_extmem_seg[i].start),
+ atop(phys_extmem_seg[i].end),
+ atop(phys_extmem_seg[i].start),
+ atop(phys_extmem_seg[i].end),
+ VM_FREELIST_HIGHMEM);
+ }
#endif
/*
@@ -1011,57 +1036,63 @@ module_init_md(void)
#endif
#ifdef EXTENDED_MEMORY
-#ifdef EM_DEBUG
-static int em_debug = 0;
-#define DPRINTF(str) do{ if (em_debug) printf str; } while (0);
-#else
-#define DPRINTF(str)
-#endif
-static struct memlist {
- void *base;
- psize_t min;
- psize_t max;
+static const struct memlist {
+ paddr_t exstart;
+ psize_t minsize;
+ psize_t maxsize;
} memlist[] = {
- /* TS-6BE16 16MB memory */
- {(void *)0x01000000, 0x01000000, 0x01000000},
- /* 060turbo SIMM slot (4--128MB) */
- {(void *)0x10000000, 0x00400000, 0x08000000},
+ /* We define two extended memory regions for all possible settings. */
+
+ /*
+ * The first region is at 0x01000000:
+ *
+ * TS-6BE16: 16MB at 0x01000000 (to 0x01FFFFFF)
+ * XM6i: 4MB - 240MB at 0x01000000 (upto 0x0FFFFFFF)
+ */
+ { 0x01000000, 0x00400000, 0x0f000000 },
+
+ /*
+ * The second region is at 0x10000000:
+ *
+ * 060turbo: 4MB - 128MB at 0x10000000 (upto 0x17FFFFFF)
+ * XM6i: 4MB - 768MB at 0x10000000 (upto 0x3FFFFFFF)
+ */
+ { 0x10000000, 0x00400000, 0x30000000 },
};
-static vaddr_t mem_v, base_v;
+
+/* check each 4MB region */
+#define EXTMEM_RANGE (4 * 1024 * 1024)
/*
* check memory existency
*/
-static int
-mem_exists(void *mem, u_long basemax)
+static bool
+mem_exists(paddr_t mem, paddr_t basemax)
{
/* most variables must be register! */
volatile unsigned char *m, *b;
unsigned char save_m, save_b=0; /* XXX: shutup gcc */
- int baseismem;
- int exists = 0;
+ bool baseismem;
+ bool exists = false;
void *base;
void *begin_check, *end_check;
label_t faultbuf;
- DPRINTF(("Enter mem_exists(%p, %lx)\n", mem, basemax));
- DPRINTF((" pmap_enter(%" PRIxVADDR ", %p) for target... ", mem_v, mem));
- pmap_enter(pmap_kernel(), mem_v, (paddr_t)mem,
- VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|PMAP_WIRED);
- pmap_update(pmap_kernel());
- DPRINTF((" done.\n"));
+ /*
+ * In this function we assume:
+ * - MMU is not enabled yet but PA == VA
+ * (i.e. no RELOC() macro to convert PA to VA)
+ * - bus error can be caught by setjmp()
+ * (i.e. %vbr register is initialized properly)
+ * - all memory cache is not enabled
+ */
/* only 24bits are significant on normal X680x0 systems */
- base = (void *)((u_long)mem & 0x00FFFFFF);
- DPRINTF((" pmap_enter(%" PRIxVADDR ", %p) for shadow... ", base_v, base));
- pmap_enter(pmap_kernel(), base_v, (paddr_t)base,
- VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|PMAP_WIRED);
- pmap_update(pmap_kernel());
- DPRINTF((" done.\n"));
+ base = (void *)(mem & 0x00FFFFFF);
- m = (void *)mem_v;
- b = (void *)base_v;
+ m = (void *)mem;
+ b = (void *)base;
/* This is somewhat paranoid -- avoid overwriting myself */
__asm("lea %%pc@(begin_check_mem),%0" : "=a"(begin_check));
@@ -1069,7 +1100,6 @@ mem_exists(void *mem, u_long basemax)
if (base >= begin_check && base < end_check) {
size_t off = (char *)end_check - (char *)begin_check;
- DPRINTF((" Adjusting the testing area.\n"));
m -= off;
b -= off;
}
@@ -1077,16 +1107,9 @@ mem_exists(void *mem, u_long basemax)
nofault = (int *)&faultbuf;
if (setjmp((label_t *)nofault)) {
nofault = (int *)0;
- pmap_remove(pmap_kernel(), mem_v, mem_v+PAGE_SIZE);
- pmap_remove(pmap_kernel(), base_v, base_v+PAGE_SIZE);
- pmap_update(pmap_kernel());
- DPRINTF(("Fault!!! Returning 0.\n"));
- return 0;
+ return false;
}
- DPRINTF((" Let's begin. mem=%p, base=%p, m=%p, b=%p\n",
- mem, base, m, b));
-
(void)*m;
/*
* Can't check by writing if the corresponding
@@ -1122,7 +1145,7 @@ __asm("begin_check_mem:");
if (*m != 0x55 || (baseismem && *b != 0xAA))
goto out;
- exists = 1;
+ exists = true;
out:
*m = save_m;
if (baseismem)
@@ -1131,100 +1154,69 @@ out:
__asm("end_check_mem:");
nofault = (int *)0;
- pmap_remove(pmap_kernel(), mem_v, mem_v+PAGE_SIZE);
- pmap_remove(pmap_kernel(), base_v, base_v+PAGE_SIZE);
- pmap_update(pmap_kernel());
-
- DPRINTF((" End.\n"));
-
- DPRINTF(("Returning from mem_exists. result = %d\n", exists));
return exists;
}
+#endif
-static void
+void
setmemrange(void)
{
+#ifdef EXTENDED_MEMORY
int i;
- psize_t s, minimum, maximum;
- struct memlist *mlist = memlist;
- u_long h;
- int basemax = ctob(physmem);
-
- /*
- * VM system is not started yet. Use the first and second avalable
- * pages to map the (possible) target memory and its shadow.
- */
- mem_v = virtual_avail; /* target */
- base_v = mem_v + PAGE_SIZE; /* shadow */
-
- { /* Turn off the processor cache. */
- int cacr;
- PCIA(); /* cpusha dc */
- switch (cputype) {
- default:
- case CPU_68030:
- cacr = CACHE_OFF;
- break;
- case CPU_68040:
- cacr = CACHE40_OFF;
- break;
- case CPU_68060:
- cacr = CACHE60_OFF;
- break;
- }
- __asm volatile ("movc %0,%%cacr"::"d"(cacr));
- }
+ paddr_t exstart, exend;
+ psize_t size, minsize, maxsize;
+ const struct memlist *mlist = memlist;
+ paddr_t basemax = m68k_ptob(physmem);
+#endif
+
+ /*
+ * VM system is not started yet, and even MMU is not enabled here.
+ * We assume VA == PA and don't bother to use RELOC() macro
+ * as pmap_bootstrap() does.
+ */
+
+ /* save the original base memory range */
+ basemem = physmem;
+
+ /*
+ * XXX
+ * Probably we should also probe the main memory region
+ * for machines which might have a wrong value in a dead SRAM.
+ */
+ phys_basemem_seg.start = lowram;
+ phys_basemem_seg.end = m68k_ptob(basemem) + lowram;
+#ifdef EXTENDED_MEMORY
/* discover extended memory */
- for (i = 0; i < sizeof(memlist) / sizeof(memlist[0]); i++) {
- minimum = mlist[i].min;
- maximum = mlist[i].max;
+ for (i = 0; i < __arraycount(memlist); i++) {
+ exstart = mlist[i].exstart;
+ minsize = mlist[i].minsize;
+ maxsize = mlist[i].maxsize;
/*
* Normally, x68k hardware is NOT 32bit-clean.
* But some type of extended memory is in 32bit address space.
* Check whether.
*/
- if (!mem_exists(mlist[i].base, basemax))
+ if (!mem_exists(exstart, basemax))
continue;
- h = 0;
+ exend = 0;
/* range check */
- for (s = minimum; s <= maximum; s += 0x00100000) {
- if (!mem_exists((char*)mlist[i].base + s - 4, basemax))
+ for (size = minsize; size <= maxsize; size += EXTMEM_RANGE) {
+ if (!mem_exists(exstart + size - 4, basemax))
break;
- h = (u_long)((char*)mlist[i].base + s);
+ exend = exstart + size;
}
- if ((u_long)mlist[i].base < h) {
- uvm_page_physload(atop(mlist[i].base), atop(h),
- atop(mlist[i].base), atop(h),
- VM_FREELIST_HIGHMEM);
- mem_size += h - (u_long) mlist[i].base;
- if (avail_end < h)
- avail_end = h;
- }
- }
-
- { /* Re-enable the processor cache. */
- int cacr;
- ICIA();
- switch (cputype) {
- default:
- case CPU_68030:
- cacr = CACHE_ON;
- break;
- case CPU_68040:
- cacr = CACHE40_ON;
- break;
- case CPU_68060:
- cacr = CACHE60_ON;
- break;
+ if (exstart < exend) {
+ phys_extmem_seg[i].start = exstart;
+ phys_extmem_seg[i].end = exend;
+ physmem += m68k_btop(exend - exstart);
+ if (maxmem < m68k_btop(exend))
+ maxmem = m68k_btop(exend);
}
- __asm volatile ("movc %0,%%cacr"::"d"(cacr));
}
-
- physmem = m68k_btop(mem_size);
-}
#endif
+}
volatile int ssir;
int idepth;
Index: src/sys/arch/x68k/x68k/pmap_bootstrap.c
diff -u src/sys/arch/x68k/x68k/pmap_bootstrap.c:1.59 src/sys/arch/x68k/x68k/pmap_bootstrap.c:1.60
--- src/sys/arch/x68k/x68k/pmap_bootstrap.c:1.59 Sat Feb 25 02:43:08 2012
+++ src/sys/arch/x68k/x68k/pmap_bootstrap.c Sun Oct 27 02:06:06 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap_bootstrap.c,v 1.59 2012/02/25 02:43:08 tsutsui Exp $ */
+/* $NetBSD: pmap_bootstrap.c,v 1.60 2013/10/27 02:06:06 tsutsui Exp $ */
/*
* Copyright (c) 1991, 1993
@@ -36,10 +36,9 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap_bootstrap.c,v 1.59 2012/02/25 02:43:08 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap_bootstrap.c,v 1.60 2013/10/27 02:06:06 tsutsui Exp $");
#include "opt_m68k_arch.h"
-#include "opt_extmem.h"
#include <sys/param.h>
#include <uvm/uvm_extern.h>
@@ -125,19 +124,6 @@ pmap_bootstrap(paddr_t nextpa, paddr_t f
kptpa = nextpa;
nptpages = RELOC(Sysptsize, int) + howmany(RELOC(physmem, int), NPTEPG) +
(IIOMAPSIZE + NPTEPG - 1) / NPTEPG;
-#ifdef EXTENDED_MEMORY
- /*
- * Current supported maximum EXTENDED_MEMORY is 128MB on 060turbo.
- */
-#define MAX_EXTENDED_MEMORY (128 * 1024 * 1024)
- nptpages += howmany(btoc(MAX_EXTENDED_MEMORY), NPTEPG);
-
- /*
- * mem_exist() in machdep.c needs two extra VA pages before pmap_init()
- * to probe >16MB memory.
- */
- nptpages += 1;
-#endif
nextpa += nptpages * PAGE_SIZE;
/*
@@ -413,12 +399,11 @@ pmap_bootstrap(paddr_t nextpa, paddr_t f
* VM data structures are now initialized, set up data for
* the pmap module.
*
- * Note about avail_end: msgbuf is initialized just after
- * avail_end in machdep.c.
+ * Note about avail_end: msgbuf is initialized at the end of
+ * main memory region (not after avail_end) in machdep.c.
*/
RELOC(avail_start, paddr_t) = nextpa;
- RELOC(avail_end, paddr_t) = m68k_ptob(RELOC(maxmem, int)) -
- m68k_round_page(MSGBUFSIZE);
+ RELOC(avail_end, paddr_t) = m68k_ptob(RELOC(maxmem, int));
RELOC(mem_size, psize_t) = m68k_ptob(RELOC(physmem, int));
RELOC(virtual_end, vaddr_t) = VM_MAX_KERNEL_ADDRESS;