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;