Port-x68k archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

options EXTENDED_MEMORY changes for PR/45915



I'll commit the attached patch to actually fix x68k specific part of
PR port-m68k/45915 (panic: pmap_enter_ptpage: can't get KPT page).

 * after recent (just before netbsd-6 branch cut) VM changes
   uvm(9) system requires more kernel memories per physical memory size
   as mentioned in PR/45915:
http://mail-index.netbsd.org/source-changes/2012/01/27/msg031054.html
http://mail-index.netbsd.org/netbsd-bugs/2012/02/04/msg026012.html

 * most hp300 pmap based m68k ports were fixed to prepare enough
   preallocated "nptpages" pages per physmem in pmap_bootstrap():
http://mail-index.netbsd.org/netbsd-bugs/2012/02/10/msg026131.html

 * but some ports doesn't initialize the physmem variable before
   pmap_bootstrap() is called:
http://mail-index.netbsd.org/port-mvme68k/2013/09/17/msg000083.html
http://mail-index.netbsd.org/port-next68k/2013/10/18/msg000013.html
   but they can be fixed easily by moving physmem calculations
   before the nptpages initialization
   (i.e. all necessary info about memory regions are already prepared)

 * on x68k bootloader passes a physical memory size (per SRAM value)
   to kernel but it doesn't include amounts of extended memories
   like TS-6BE16 and 060turbo
   (x68k ROM BIOS doesn't check possible extended memories at all
    because these extended memories were built and sold by third parties)

 * currently x68k/pmap_bootstrap.c preserve enough nptpages for
   expected maximum extended memory size:
http://nxr.netbsd.org/xref/src/sys/arch/x68k/x68k/pmap_bootstrap.c?r=1.59#128
   but this might waste pages on low memory machines

 * the right solution of this problem is to probe and calculate
   extended memory size before pmap_bootstrap()
   (currently it's done after MMU is enabled but before uvm_init(9))

 * setmemrange() and mem_exist() in machdep.c are current functions
   that detect extended memories:
http://nxr.netbsd.org/xref/src/sys/arch/x68k/x68k/machdep.c?r=1.186#1013

 * on x68k hardware higher 8bits (D31-24) in the address bus are
   not decoded and only extended memories recognize these bits,
   so all accesses to 0xXY000000 - 0xXYBFFFFF address range
   are transparent to 0x00000000 - 0x00BFFFFF memories regions

 * the mem_exist() function maps both base and extended regions
   and checks they are idential memory or not

 * to probe possible extended memories before pmap_bootstrap(),
   we have to do the similar check under disabled MMU,
   i.e. no pmap_enter(9) etc.

Fortunately we can assume PA == VA on NetBSD/x68k and we can also
handle the bus error trap at the point pmap_bootstrap() is called,
so we can reuse the existing mem_exist() functions with a few changes.

My patch includes the following changes:

 - call setmemrange() (that returns an amount of physical memory)
   before pmap_boostrap()

 - modify setmemrange() to set info of both base and extended
   memory regions into new struct phys_seg_t variables,
   phys_basemem_seg and phys_extmem_seg[]

 - setmemrange() fills phys_basemem_seg per info passed from
   bootloader (i.e. the default physmem value) and also calls
   mem_exist() to probe all possible extended memory regions
   and also update physmem and maxmem accodingly
   (cache flush is no longer necessary because all cache is
    disabled in locore.s and not enabled yet)

 - mem_exist() is modified to use passed addresses directly
   without pmap(9) functions because all passed addresses are
   physical address and we assume MMU is not enabled yet
   (DPRINTFs are also removed because it's called before consinit)

 - x68k_init() function calls uvm_page_physload(9) per info
   stored in both the above phys_basemem_seg and phys_extmem_seg[]
   (msgbuf is allocated at the end of basemem for compatibility)

 - expected extended memory regions are also expanded for XM6i emulator
   (that might have upto 1008MB across the both regions)

 - while here I also rename various variable names and types
   for readability (for future readers)

Tested on my X68030 (without any extended memory though)
and XM6i with various extended memory settings.
http://www.ceres.dti.ne.jp/tsutsui/netbsd/x68k/img/xm6i-settings-highmem.png

Eventually we can consider a new feature that copies and relocates
all kernel text/data/bss regions from basemem into extended memory
(which is working with no wait access) like amiga and atari,
but it will be a separate project.
(see code around #ifdef RELOC_KERNEL in sys/arch/atari/atari/atari_init.c)


I'll commit it in a few days if there is no particular objection.
(though I guess all possible affected x68k users already know my patch)

Thanks,

---
Index: x68k/locore.s
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/x68k/locore.s,v
retrieving revision 1.110
diff -u -p -r1.110 locore.s
--- x68k/locore.s       19 May 2012 08:29:32 -0000      1.110
+++ x68k/locore.s       18 Oct 2013 18:07:23 -0000
@@ -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: x68k/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/x68k/machdep.c,v
retrieving revision 1.186
diff -u -p -r1.186 machdep.c
--- x68k/machdep.c      22 Jan 2013 11:58:39 -0000      1.186
+++ x68k/machdep.c      18 Oct 2013 18:07:24 -0000
@@ -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: x68k/pmap_bootstrap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/x68k/pmap_bootstrap.c,v
retrieving revision 1.59
diff -u -p -r1.59 pmap_bootstrap.c
--- x68k/pmap_bootstrap.c       25 Feb 2012 02:43:08 -0000      1.59
+++ x68k/pmap_bootstrap.c       18 Oct 2013 18:07:24 -0000
@@ -39,7 +39,6 @@
 __KERNEL_RCSID(0, "$NetBSD: pmap_bootstrap.c,v 1.59 2012/02/25 02:43:08 
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;
 

---
Izumi Tsutsui 


Home | Main Index | Thread Index | Old Index