summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/hp300/hp300/pmap_bootstrap.c480
-rw-r--r--sys/arch/m68k/m68k/pmap_bootstrap.c531
-rw-r--r--sys/arch/mvme68k/mvme68k/pmap_bootstrap.c505
3 files changed, 625 insertions, 891 deletions
diff --git a/sys/arch/hp300/hp300/pmap_bootstrap.c b/sys/arch/hp300/hp300/pmap_bootstrap.c
index 99d08782c16..5278c9dc12c 100644
--- a/sys/arch/hp300/hp300/pmap_bootstrap.c
+++ b/sys/arch/hp300/hp300/pmap_bootstrap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap_bootstrap.c,v 1.15 2002/01/10 21:10:45 miod Exp $ */
+/* $OpenBSD: pmap_bootstrap.c,v 1.16 2002/02/23 04:58:25 miod Exp $ */
/* $NetBSD: pmap_bootstrap.c,v 1.13 1997/06/10 18:56:50 veego Exp $ */
/*
@@ -42,464 +42,76 @@
#include <sys/param.h>
#include <sys/msgbuf.h>
-#include <sys/proc.h>
-#include <machine/frame.h>
#include <machine/cpu.h>
-#include <machine/hp300spu.h>
-#include <machine/vmparam.h>
+#include <machine/frame.h>
#include <machine/pte.h>
+#include <machine/vmparam.h>
+#include <machine/hp300spu.h>
#include <hp300/hp300/clockreg.h>
#include <uvm/uvm_extern.h>
-#include <uvm/uvm_pmap.h>
-#define RELOC(v, t) *((t*)((u_int)&(v) + firstpa))
+caddr_t ledbase; /* SPU LEDs mapping */
-extern char *etext;
-extern int Sysptsize;
-extern char *extiobase, *proc0paddr;
-extern st_entry_t *Sysseg;
-extern pt_entry_t *Sysptmap, *Sysmap;
extern vaddr_t CLKbase, MMUbase;
+extern char *extiobase;
+extern int maxmem;
-extern int maxmem, physmem;
-extern paddr_t avail_start, avail_end;
-extern vaddr_t virtual_avail, virtual_end;
-extern vsize_t mem_size;
-#ifdef M68K_MMU_HP
-extern int pmap_aliasmask;
-#endif
-
-void pmap_bootstrap __P((paddr_t, paddr_t));
-
-/*
- * Special purpose kernel virtual addresses, used for mapping
- * physical pages for a variety of temporary or permanent purposes:
- *
- * CADDR1, CADDR2: pmap zero/copy operations
- * vmmap: /dev/mem, crash dumps, parity error checking
- * ledbase: SPU LEDs
- * msgbufp: kernel message buffer
- */
-caddr_t CADDR1, CADDR2, vmmap, ledbase;
-
-/*
- * Bootstrap the VM system.
- *
- * Called with MMU off so we must relocate all global references by `firstpa'
- * (don't call any functions here!) `nextpa' is the first available physical
- * memory address. Returns an updated first PA reflecting the memory we
- * have allocated. MMU is still off when we return.
- *
- * XXX assumes sizeof(u_int) == sizeof(pt_entry_t)
- * XXX a PIC compiler would make this much easier.
- */
-void
-pmap_bootstrap(nextpa, firstpa)
- paddr_t nextpa;
- paddr_t firstpa;
-{
- paddr_t kstpa, kptpa, iiopa, eiopa, kptmpa, lkptpa, p0upa;
- u_int nptpages, kstsize;
- st_entry_t protoste, *ste;
- pt_entry_t protopte, *pte, *epte;
+#define RELOC(v, t) *((t*)((u_int)&(v) + firstpa))
+#define PA2VA(v, t) *((t*)((u_int)&(v)))
- /*
- * Calculate important physical addresses:
- *
- * kstpa kernel segment table 1 page (!040)
- * N pages (040)
- *
- * kptpa statically allocated
- * kernel PT pages Sysptsize+ pages
- *
- * iiopa internal IO space
- * PT pages IIOMAPSIZE pages
- *
- * eiopa external IO space
- * PT pages EIOMAPSIZE pages
- *
- * [ Sysptsize is the number of pages of PT, IIOMAPSIZE and
- * EIOMAPSIZE are the number of PTEs, hence we need to round
- * the total to a page boundary with IO maps at the end. ]
- *
- * kptmpa kernel PT map 1 page
- *
- * lkptpa last kernel PT page 1 page
- *
- * p0upa proc 0 u-area UPAGES pages
- *
- * The KVA corresponding to any of these PAs is:
- * (PA - firstpa + KERNBASE).
- */
- if (RELOC(mmutype, int) == MMU_68040)
- kstsize = MAXKL2SIZE / (NPTEPG/SG4_LEV2SIZE);
- else
- kstsize = 1;
- kstpa = nextpa;
- nextpa += kstsize * NBPG;
- kptpa = nextpa;
- nptpages = RELOC(Sysptsize, int) +
- (IIOMAPSIZE + EIOMAPSIZE + NPTEPG - 1) / NPTEPG;
- nextpa += nptpages * NBPG;
- eiopa = nextpa - EIOMAPSIZE * sizeof(pt_entry_t);
- iiopa = eiopa - IIOMAPSIZE * sizeof(pt_entry_t);
- kptmpa = nextpa;
- nextpa += NBPG;
- lkptpa = nextpa;
- nextpa += NBPG;
- p0upa = nextpa;
- nextpa += USPACE;
+#define MACHINE_IIOMAPSIZE IIOMAPSIZE
+#define MACHINE_INTIOBASE INTIOBASE
+#define MACHINE_EIOMAPSIZE EIOMAPSIZE
- /*
- * Initialize segment table and kernel page table map.
- *
- * On 68030s and earlier MMUs the two are identical except for
- * the valid bits so both are initialized with essentially the
- * same values. On the 68040, which has a mandatory 3-level
- * structure, the segment table holds the level 1 table and part
- * (or all) of the level 2 table and hence is considerably
- * different. Here the first level consists of 128 descriptors
- * (512 bytes) each mapping 32mb of address space. Each of these
- * points to blocks of 128 second level descriptors (512 bytes)
- * each mapping 256kb. Note that there may be additional "segment
- * table" pages depending on how large MAXKL2SIZE is.
- *
- * Portions of the last segment of KVA space (0xFFF00000 -
- * 0xFFFFFFFF) are mapped for a couple of purposes. 0xFFF00000
- * for UPAGES is used for mapping the current process u-area
- * (u + kernel stack). The very last page (0xFFFFF000) is mapped
- * to the last physical page of RAM to give us a region in which
- * PA == VA. We use the first part of this page for enabling
- * and disabling mapping. The last part of this page also contains
- * info left by the boot ROM.
- *
- * XXX cramming two levels of mapping into the single "segment"
- * table on the 68040 is intended as a temporary hack to get things
- * working. The 224mb of address space that this allows will most
- * likely be insufficient in the future (at least for the kernel).
- */
- if (RELOC(mmutype, int) == MMU_68040) {
- int num;
+#define PMAP_MD_LOCALS /* nothing */
- /*
- * First invalidate the entire "segment table" pages
- * (levels 1 and 2 have the same "invalid" value).
- */
- pte = (u_int *)kstpa;
- epte = &pte[kstsize * NPTEPG];
- while (pte < epte)
- *pte++ = SG_NV;
- /*
- * Initialize level 2 descriptors (which immediately
- * follow the level 1 table). We need:
- * NPTEPG / SG4_LEV3SIZE
- * level 2 descriptors to map each of the nptpages+1
- * pages of PTEs. Note that we set the "used" bit
- * now to save the HW the expense of doing it.
- */
- num = (nptpages + 1) * (NPTEPG / SG4_LEV3SIZE);
- pte = &((u_int *)kstpa)[SG4_LEV1SIZE];
- epte = &pte[num];
- protoste = kptpa | SG_U | SG_RW | SG_V;
- while (pte < epte) {
- *pte++ = protoste;
- protoste += (SG4_LEV3SIZE * sizeof(st_entry_t));
- }
- /*
- * Initialize level 1 descriptors. We need:
- * roundup(num, SG4_LEV2SIZE) / SG4_LEV2SIZE
- * level 1 descriptors to map the `num' level 2's.
- */
- pte = (u_int *)kstpa;
- epte = &pte[roundup(num, SG4_LEV2SIZE) / SG4_LEV2SIZE];
- protoste = (u_int)&pte[SG4_LEV1SIZE] | SG_U | SG_RW | SG_V;
- while (pte < epte) {
- *pte++ = protoste;
- protoste += (SG4_LEV2SIZE * sizeof(st_entry_t));
- }
- /*
- * Initialize the final level 1 descriptor to map the last
- * block of level 2 descriptors.
- */
- ste = &((u_int *)kstpa)[SG4_LEV1SIZE-1];
- pte = &((u_int *)kstpa)[kstsize*NPTEPG - SG4_LEV2SIZE];
- *ste = (u_int)pte | SG_U | SG_RW | SG_V;
- /*
- * Now initialize the final portion of that block of
- * descriptors to map the "last PT page".
- */
- pte = &((u_int *)kstpa)[kstsize*NPTEPG - NPTEPG/SG4_LEV3SIZE];
- epte = &pte[NPTEPG/SG4_LEV3SIZE];
- protoste = lkptpa | SG_U | SG_RW | SG_V;
- while (pte < epte) {
- *pte++ = protoste;
- protoste += (SG4_LEV3SIZE * sizeof(st_entry_t));
- }
- /*
- * Initialize Sysptmap
- */
- pte = (u_int *)kptmpa;
- epte = &pte[nptpages+1];
- protopte = kptpa | PG_RW | PG_CI | PG_V;
- while (pte < epte) {
- *pte++ = protopte;
- protopte += NBPG;
- }
- /*
- * Invalidate all but the last remaining entry.
- */
- epte = &((u_int *)kptmpa)[NPTEPG-1];
- while (pte < epte) {
- *pte++ = PG_NV;
- }
- /*
- * Initialize the last to point to the page
- * table page allocated earlier.
- */
- *pte = lkptpa | PG_RW | PG_CI | PG_V;
- } else {
- /*
- * Map the page table pages in both the HW segment table
- * and the software Sysptmap. Note that Sysptmap is also
- * considered a PT page hence the +1.
- */
- ste = (u_int *)kstpa;
- pte = (u_int *)kptmpa;
- epte = &pte[nptpages+1];
- protoste = kptpa | SG_RW | SG_V;
- protopte = kptpa | PG_RW | PG_CI | PG_V;
- while (pte < epte) {
- *ste++ = protoste;
- *pte++ = protopte;
- protoste += NBPG;
- protopte += NBPG;
- }
- /*
- * Invalidate all but the last remaining entries in both.
- */
- epte = &((u_int *)kptmpa)[NPTEPG-1];
- while (pte < epte) {
- *ste++ = SG_NV;
- *pte++ = PG_NV;
- }
- /*
- * Initialize the last to point to point to the page
- * table page allocated earlier.
- */
- *ste = lkptpa | SG_RW | SG_V;
- *pte = lkptpa | PG_RW | PG_CI | PG_V;
- }
- /*
- * Invalidate all but the final entry in the last kernel PT page
- * (u-area PTEs will be validated later). The final entry maps
- * the last page of physical memory.
- */
- pte = (u_int *)lkptpa;
- epte = &pte[NPTEPG-1];
- while (pte < epte)
- *pte++ = PG_NV;
- *pte = MAXADDR | PG_RW | PG_CI | PG_V;
- /*
- * Initialize kernel page table.
- * Start by invalidating the `nptpages' that we have allocated.
- */
- pte = (u_int *)kptpa;
- epte = &pte[nptpages * NPTEPG];
- while (pte < epte)
- *pte++ = PG_NV;
+#define PMAP_MD_RELOC1() /* nothing */
- /*
- * Validate PTEs for kernel text (RO). The first page
- * of kernel text remains invalid; see locore.s
- */
- pte = &((u_int *)kptpa)[m68k_btop(KERNBASE + NBPG)];
- epte = &pte[m68k_btop(trunc_page((vaddr_t)&etext))];
- protopte = (firstpa + NBPG) | PG_RO | PG_V;
- while (pte < epte) {
- *pte++ = protopte;
- protopte += NBPG;
- }
- /*
- * Validate PTEs for kernel data/bss, dynamic data allocated
- * by us so far (nextpa - firstpa bytes), and pages for proc0
- * u-area and page table allocated below (RW).
- */
- epte = &((u_int *)kptpa)[m68k_btop(nextpa - firstpa)];
- protopte = (protopte & ~PG_PROT) | PG_RW;
- /*
- * Enable copy-back caching of data pages
- */
- if (RELOC(mmutype, int) == MMU_68040)
- protopte |= PG_CCB;
- while (pte < epte) {
- *pte++ = protopte;
- protopte += NBPG;
- }
- /*
- * Finally, validate the internal IO space PTEs (RW+CI).
- * We do this here since the 320/350 MMU registers (also
- * used, but to a lesser extent, on other models) are mapped
- * in this range and it would be nice to be able to access
- * them after the MMU is turned on.
- */
- pte = (u_int *)iiopa;
- epte = (u_int *)eiopa;
- protopte = INTIOBASE | PG_RW | PG_CI | PG_V;
- while (pte < epte) {
- *pte++ = protopte;
- protopte += NBPG;
- }
+#define PMAP_MD_MAPIOSPACE() /* nothing */
/*
- * Calculate important exported kernel virtual addresses
- */
- /*
- * Sysseg: base of kernel segment table
- */
- RELOC(Sysseg, st_entry_t *) =
- (st_entry_t *)(kstpa - firstpa);
- /*
- * Sysptmap: base of kernel page table map
- */
- RELOC(Sysptmap, pt_entry_t *) =
- (pt_entry_t *)(kptmpa - firstpa);
- /*
- * Sysmap: kernel page table (as mapped through Sysptmap)
- * Immediately follows `nptpages' of static kernel page table.
- */
- RELOC(Sysmap, pt_entry_t *) =
- (pt_entry_t *)m68k_ptob(nptpages * NPTEPG);
- /*
* intiobase, intiolimit: base and end of internal (DIO) IO space.
- * IIOMAPSIZE pages prior to external IO space at end of static
- * kernel page table.
- */
- RELOC(intiobase, char *) =
- (char *)m68k_ptob(nptpages*NPTEPG - (IIOMAPSIZE+EIOMAPSIZE));
- RELOC(intiolimit, char *) =
- (char *)m68k_ptob(nptpages*NPTEPG - EIOMAPSIZE);
- /*
+ * MACHINE_IIOMAPSIZE pages prior to external IO space at end of
+ * static kernel page table.
* extiobase: base of external (DIO-II) IO space.
- * EIOMAPSIZE pages at the end of the static kernel page table.
- */
- RELOC(extiobase, char *) =
- (char *)m68k_ptob(nptpages*NPTEPG - EIOMAPSIZE);
- /*
+ * MACHINE_EIOMAPSIZE pages at the end of the static kernel page table.
* CLKbase, MMUbase: important registers in internal IO space
- * accessed from assembly language.
- */
- RELOC(CLKbase, vaddr_t) =
- (vaddr_t)RELOC(intiobase, char *) + CLKBASE;
- RELOC(MMUbase, vaddr_t) =
- (vaddr_t)RELOC(intiobase, char *) + MMUBASE;
-
- /*
- * Setup u-area for process 0.
- */
- /*
- * Zero the u-area.
- * NOTE: `pte' and `epte' aren't PTEs here.
- */
- pte = (u_int *)p0upa;
- epte = (u_int *)(p0upa + USPACE);
- while (pte < epte)
- *pte++ = 0;
- /*
- * Remember the u-area address so it can be loaded in the
- * proc struct p_addr field later.
- */
- RELOC(proc0paddr, char *) = (char *)(p0upa - firstpa);
-
- /*
- * 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. Since the last page is used
- * for rebooting the system (code is copied there and
- * excution continues from copied code before the MMU
- * is disabled), the msgbuf will get trounced between
- * reboots if it's placed in the last physical page.
- * To work around this, we move avail_end back one more
- * page so the msgbuf can be preserved.
- */
- RELOC(avail_start, paddr_t) = nextpa;
- RELOC(avail_end, paddr_t) = m68k_ptob(RELOC(maxmem, int)) -
- (round_page(MSGBUFSIZE) + m68k_ptob(1));
- RELOC(mem_size, vsize_t) = m68k_ptob(RELOC(physmem, int));
- RELOC(virtual_avail, vaddr_t) =
- VM_MIN_KERNEL_ADDRESS + (nextpa - firstpa);
- RELOC(virtual_end, vaddr_t) = VM_MAX_KERNEL_ADDRESS;
-
-#ifdef M68K_MMU_HP
- /*
- * Determine VA aliasing distance if any
- */
- if (RELOC(ectype, int) == EC_VIRT) {
- if (RELOC(machineid, int) == HP_320)
- RELOC(pmap_aliasmask, int) = 0x3fff; /* 16k */
- else if (RELOC(machineid, int) == HP_350)
- RELOC(pmap_aliasmask, int) = 0x7fff; /* 32k */
- }
-#endif
-
- /*
- * Kernel page/segment table allocated in locore,
- * just initialize pointers.
- */
- {
- struct pmap *kpm = &RELOC(kernel_pmap_store, struct pmap);
-
- kpm->pm_stab = RELOC(Sysseg, st_entry_t *);
- kpm->pm_ptab = RELOC(Sysmap, pt_entry_t *);
- simple_lock_init(&kpm->pm_lock);
- kpm->pm_count = 1;
- kpm->pm_stpa = (st_entry_t *)kstpa;
- /*
- * For the 040 we also initialize the free level 2
- * descriptor mask noting that we have used:
- * 0: level 1 table
- * 1 to `num': map page tables
- * MAXKL2SIZE-1: maps last-page page table
- */
- if (RELOC(mmutype, int) == MMU_68040) {
- int num;
-
- kpm->pm_stfree = ~l2tobm(0);
- num = roundup((nptpages + 1) * (NPTEPG / SG4_LEV3SIZE),
- SG4_LEV2SIZE) / SG4_LEV2SIZE;
- while (num)
- kpm->pm_stfree &= ~l2tobm(num--);
- kpm->pm_stfree &= ~l2tobm(MAXKL2SIZE-1);
- for (num = MAXKL2SIZE;
- num < sizeof(kpm->pm_stfree)*NBBY;
- num++)
- kpm->pm_stfree &= ~l2tobm(num);
- }
- }
+ * accessed from locore.
+ */
+#define PMAP_MD_RELOC2() \
+do { \
+ RELOC(intiobase, char *) = \
+ (char *)m68k_ptob(nptpages * NPTEPG - \
+ (MACHINE_IIOMAPSIZE + MACHINE_EIOMAPSIZE)); \
+ RELOC(intiolimit, char *) = \
+ (char *)m68k_ptob(nptpages * NPTEPG - MACHINE_EIOMAPSIZE); \
+ RELOC(extiobase, char *) = \
+ (char *)m68k_ptob(nptpages * NPTEPG - MACHINE_EIOMAPSIZE); \
+ RELOC(CLKbase, vaddr_t) = \
+ (vaddr_t)RELOC(intiobase, char *) + CLKBASE; \
+ RELOC(MMUbase, vaddr_t) = \
+ (vaddr_t)RELOC(intiobase, char *) + MMUBASE; \
+} while (0)
+
+#define PMAP_MD_MEMSIZE() \
+do { \
+ RELOC(avail_end, paddr_t) = m68k_ptob(RELOC(maxmem, int)) - \
+ (round_page(MSGBUFSIZE) + m68k_ptob(1)); \
+} while (0)
/*
* Allocate some fixed, special purpose kernel virtual addresses
*/
- {
- vaddr_t va = RELOC(virtual_avail, vaddr_t);
+#define PMAP_MD_RELOC3() \
+do { \
+ RELOC(ledbase, caddr_t) = (caddr_t)va; \
+ va += NBPG; \
+} while (0)
- RELOC(CADDR1, caddr_t) = (caddr_t)va;
- va += NBPG;
- RELOC(CADDR2, caddr_t) = (caddr_t)va;
- va += NBPG;
- RELOC(vmmap, caddr_t) = (caddr_t)va;
- va += NBPG;
- RELOC(ledbase, caddr_t) = (caddr_t)va;
- va += NBPG;
- RELOC(msgbufp, struct msgbuf *) = (struct msgbuf *)va;
- va += MSGBUFSIZE;
- RELOC(virtual_avail, vaddr_t) = va;
- }
-}
+#include <m68k/m68k/pmap_bootstrap.c>
void
pmap_init_md()
diff --git a/sys/arch/m68k/m68k/pmap_bootstrap.c b/sys/arch/m68k/m68k/pmap_bootstrap.c
new file mode 100644
index 00000000000..709a6eb7a8d
--- /dev/null
+++ b/sys/arch/m68k/m68k/pmap_bootstrap.c
@@ -0,0 +1,531 @@
+/* $OpenBSD: pmap_bootstrap.c,v 1.1 2002/02/23 04:58:28 miod Exp $ */
+
+/*
+ * Copyright (c) 1995 Theo de Raadt
+ * Copyright (c) 1999 Steve Murphree, Jr. (68060 support)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed under OpenBSD by
+ * Theo de Raadt for Willowglen Singapore.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pmap_bootstrap.c 8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * NOTICE: This is not a standalone file. To use it, #include it in
+ * your port's pmap_bootstrap.c, like so:
+ *
+ * #include <m68k/m68k/pmap_bootstrap.c>
+ *
+ * after having defined the following macros:
+ * RELOC relocate a variable
+ * PA2VA simple crude mapping for bootstraping
+ * PMAP_MD_LOCALS local variable declaration
+ * PMAP_MD_RELOC1() early variable relocation
+ * PMAP_MD_RELOC2() internal IO space variable relocation
+ * PMAP_MD_RELOC3() general purpose kernel virtual addresses relocation
+ * PMAP_MD_MAPIOSPACE() setup machine-specific internal iospace components
+ * PMAP_MD_MEMSIZE() compute avail_end
+ */
+
+extern char *etext;
+extern int Sysptsize;
+extern char *proc0paddr;
+extern st_entry_t *Sysseg;
+extern pt_entry_t *Sysptmap, *Sysmap;
+
+extern int physmem;
+extern paddr_t avail_start, avail_end;
+extern vaddr_t virtual_avail, virtual_end;
+extern vsize_t mem_size;
+#ifdef M68K_MMU_HP
+extern int pmap_aliasmask;
+#endif
+
+void pmap_bootstrap __P((paddr_t, paddr_t));
+
+
+/*
+ * Special purpose kernel virtual addresses, used for mapping
+ * physical pages for a variety of temporary or permanent purposes:
+ *
+ * CADDR1, CADDR2: pmap zero/copy operations
+ * vmmap: /dev/mem, crash dumps, parity error checking
+ */
+caddr_t CADDR1, CADDR2, vmmap;
+
+/*
+ * Bootstrap the VM system.
+ *
+ * Called with MMU off so we must relocate all global references by `firstpa'
+ * (don't call any functions here!) `nextpa' is the first available physical
+ * memory address. Returns an updated first PA reflecting the memory we
+ * have allocated. MMU is still off when we return.
+ *
+ * XXX assumes sizeof(u_int) == sizeof(pt_entry_t)
+ * XXX a PIC compiler would make this much easier.
+ */
+void
+pmap_bootstrap(nextpa, firstpa)
+ paddr_t nextpa;
+ paddr_t firstpa;
+{
+ paddr_t kstpa, kptpa, iiopa, eiopa, kptmpa, lkptpa, p0upa;
+ u_int nptpages, kstsize;
+ st_entry_t protoste, *ste;
+ pt_entry_t protopte, *pte, *epte;
+ PMAP_MD_LOCALS
+
+ /*
+ * Calculate important physical addresses:
+ *
+ * kstpa kernel segment table 1 page (020/030)
+ * N pages (040/060)
+ *
+ * kptpa statically allocated
+ * kernel PT pages Sysptsize+ pages
+ *
+ * iiopa internal IO space
+ * PT pages MACHINE_IIOMAPSIZE pages
+ *
+ * eiopa external IO space
+ * PT pages MACHINE_EIOMAPSIZE pages
+ *
+ * [ Sysptsize is the number of pages of PT, MACHINE_IIOMAPSIZE and
+ * MACHINE_EIOMAPSIZE are the number of PTEs, hence we need to round
+ * the total to a page boundary with IO maps at the end. ]
+ *
+ * kptmpa kernel PT map 1 page
+ *
+ * lkptpa last kernel PT page 1 page
+ *
+ * p0upa proc 0 u-area UPAGES pages
+ *
+ * The KVA corresponding to any of these PAs is:
+ * (PA - firstpa + KERNBASE).
+ */
+ if (RELOC(mmutype, int) <= MMU_68040)
+ kstsize = MAXKL2SIZE / (NPTEPG/SG4_LEV2SIZE);
+ else
+ kstsize = 1;
+ kstpa = nextpa;
+ nextpa += kstsize * NBPG;
+ kptpa = nextpa;
+ nptpages = RELOC(Sysptsize, int) +
+ (MACHINE_IIOMAPSIZE + MACHINE_EIOMAPSIZE + NPTEPG - 1) / NPTEPG;
+ nextpa += nptpages * NBPG;
+ eiopa = nextpa - MACHINE_EIOMAPSIZE * sizeof(pt_entry_t);
+ iiopa = eiopa - MACHINE_IIOMAPSIZE * sizeof(pt_entry_t);
+ kptmpa = nextpa;
+ nextpa += NBPG;
+ lkptpa = nextpa;
+ nextpa += NBPG;
+ p0upa = nextpa;
+ nextpa += USPACE;
+
+ PMAP_MD_RELOC1();
+
+ /*
+ * Initialize segment table and kernel page table map.
+ *
+ * On 68030s and earlier MMUs the two are identical except for
+ * the valid bits so both are initialized with essentially the
+ * same values. On the 680[46]0, which have a mandatory 3-level
+ * structure, the segment table holds the level 1 table and part
+ * (or all) of the level 2 table and hence is considerably
+ * different. Here the first level consists of 128 descriptors
+ * (512 bytes) each mapping 32mb of address space. Each of these
+ * points to blocks of 128 second level descriptors (512 bytes)
+ * each mapping 256kb. Note that there may be additional "segment
+ * table" pages depending on how large MAXKL2SIZE is.
+ *
+ * Portions of the last segment of KVA space (0xFFF00000 -
+ * 0xFFFFFFFF) are mapped for a couple of purposes. 0xFFF00000
+ * for UPAGES is used for mapping the current process u-area
+ * (u + kernel stack). The very last page (0xFFFFF000) is mapped
+ * to the last physical page of RAM to give us a region in which
+ * PA == VA. We use the first part of this page for enabling
+ * and disabling mapping. The last part of this page also contains
+ * info left by the boot ROM.
+ *
+ * XXX cramming two levels of mapping into the single "segment"
+ * table on the 68040 is intended as a temporary hack to get things
+ * working. The 224mb of address space that this allows will most
+ * likely be insufficient in the future (at least for the kernel).
+ */
+ if (RELOC(mmutype, int) <= MMU_68040) {
+ int num;
+
+ /*
+ * First invalidate the entire "segment table" pages
+ * (levels 1 and 2 have the same "invalid" value).
+ */
+ pte = PA2VA(kstpa, u_int *);
+ epte = &pte[kstsize * NPTEPG];
+ while (pte < epte)
+ *pte++ = SG_NV;
+ /*
+ * Initialize level 2 descriptors (which immediately
+ * follow the level 1 table). We need:
+ * NPTEPG / SG4_LEV3SIZE
+ * level 2 descriptors to map each of the nptpages+1
+ * pages of PTEs. Note that we set the "used" bit
+ * now to save the HW the expense of doing it.
+ */
+ num = (nptpages + 1) * (NPTEPG / SG4_LEV3SIZE);
+ pte = &(PA2VA(kstpa, u_int *))[SG4_LEV1SIZE];
+ epte = &pte[num];
+ protoste = kptpa | SG_U | SG_RW | SG_V;
+ while (pte < epte) {
+ *pte++ = protoste;
+ protoste += (SG4_LEV3SIZE * sizeof(st_entry_t));
+ }
+ /*
+ * Initialize level 1 descriptors. We need:
+ * roundup(num, SG4_LEV2SIZE) / SG4_LEV2SIZE
+ * level 1 descriptors to map the `num' level 2's.
+ */
+ pte = PA2VA(kstpa, u_int *);
+ epte = &pte[roundup(num, SG4_LEV2SIZE) / SG4_LEV2SIZE];
+ protoste = (u_int)&pte[SG4_LEV1SIZE] | SG_U | SG_RW | SG_V;
+ while (pte < epte) {
+ *pte++ = protoste;
+ protoste += (SG4_LEV2SIZE * sizeof(st_entry_t));
+ }
+ /*
+ * Initialize the final level 1 descriptor to map the last
+ * block of level 2 descriptors.
+ */
+ ste = &(PA2VA(kstpa, u_int *))[SG4_LEV1SIZE-1];
+ pte = &(PA2VA(kstpa, u_int *))[kstsize*NPTEPG - SG4_LEV2SIZE];
+ *ste = (u_int)pte | SG_U | SG_RW | SG_V;
+ /*
+ * Now initialize the final portion of that block of
+ * descriptors to map the "last PT page".
+ */
+ pte = &(PA2VA(kstpa, u_int *))
+ [kstsize*NPTEPG - NPTEPG/SG4_LEV3SIZE];
+ epte = &pte[NPTEPG/SG4_LEV3SIZE];
+ protoste = lkptpa | SG_U | SG_RW | SG_V;
+ while (pte < epte) {
+ *pte++ = protoste;
+ protoste += (SG4_LEV3SIZE * sizeof(st_entry_t));
+ }
+ /*
+ * Initialize Sysptmap
+ */
+ pte = PA2VA(kptmpa, u_int *);
+ epte = &pte[nptpages+1];
+ protopte = kptpa | PG_RW | PG_CI | PG_V | PG_U;
+ while (pte < epte) {
+ *pte++ = protopte;
+ protopte += NBPG;
+ }
+ /*
+ * Invalidate all but the last remaining entry.
+ */
+ epte = &(PA2VA(kptmpa, u_int *))[NPTEPG-1];
+ while (pte < epte) {
+ *pte++ = PG_NV | PG_U;
+ }
+ /*
+ * Initialize the last to point to the page
+ * table page allocated earlier.
+ */
+ *pte = lkptpa | PG_RW | PG_CI | PG_V | PG_U;
+ } else {
+ /*
+ * Map the page table pages in both the HW segment table
+ * and the software Sysptmap. Note that Sysptmap is also
+ * considered a PT page hence the +1.
+ */
+ ste = PA2VA(kstpa, u_int *);
+ pte = PA2VA(kptmpa, u_int *);
+ epte = &pte[nptpages+1];
+ protoste = kptpa | SG_RW | SG_V;
+ protopte = kptpa | PG_RW | PG_CI | PG_V;
+ while (pte < epte) {
+ *ste++ = protoste;
+ *pte++ = protopte;
+ protoste += NBPG;
+ protopte += NBPG;
+ }
+ /*
+ * Invalidate all but the last remaining entries in both.
+ */
+ epte = &(PA2VA(kptmpa, u_int *))[NPTEPG-1];
+ while (pte < epte) {
+ *ste++ = SG_NV;
+ *pte++ = PG_NV;
+ }
+ /*
+ * Initialize the last to point to point to the page
+ * table page allocated earlier.
+ */
+ *ste = lkptpa | SG_RW | SG_V;
+ *pte = lkptpa | PG_RW | PG_CI | PG_V;
+ }
+ /*
+ * Invalidate all but the final entry in the last kernel PT page
+ * (u-area PTEs will be validated later). The final entry maps
+ * the last page of physical memory.
+ */
+ pte = PA2VA(lkptpa, u_int *);
+ epte = &pte[NPTEPG-1];
+ while (pte < epte)
+ *pte++ = PG_NV;
+#ifdef MAXADDR
+ /*
+ * Temporary double-map for machines with physmem at the end of
+ * memory
+ */
+ *pte = MAXADDR | PG_RW | PG_CI | PG_V | PG_U;
+#endif
+ /*
+ * Initialize kernel page table.
+ * Start by invalidating the `nptpages' that we have allocated.
+ */
+ pte = PA2VA(kptpa, u_int *);
+ epte = &pte[nptpages * NPTEPG];
+ while (pte < epte)
+ *pte++ = PG_NV | PG_U;
+
+ /*
+ * Validate PTEs for kernel text (RO). The first page
+ * of kernel text will remain invalid to force *NULL in the
+ * kernel to fault.
+ */
+ pte = &(PA2VA(kptpa, u_int *))[m68k_btop(KERNBASE)];
+ epte = &pte[m68k_btop(trunc_page((vaddr_t)&etext))];
+ *pte++ = firstpa | PG_NV; /* make *NULL fail in the kernel */
+#if defined(KGDB) || defined(DDB)
+ protopte = (firstpa + NBPG) | PG_RW | PG_V | PG_U; /* XXX RW for now */
+#else
+ protopte = (firstpa + NBPG) | PG_RO | PG_V | PG_U;
+#endif
+ while (pte < epte) {
+ *pte++ = protopte;
+ protopte += NBPG;
+ }
+ /*
+ * Validate PTEs for kernel data/bss, dynamic data allocated
+ * by us so far (nextpa - firstpa bytes), and pages for proc0
+ * u-area and page table allocated below (RW).
+ */
+ epte = &(PA2VA(kptpa, u_int *))[m68k_btop(nextpa - firstpa)];
+ protopte = (protopte & ~PG_PROT) | PG_RW | PG_U;
+ /*
+ * Enable copy-back caching of data pages on 040, and write-through
+ * caching on 060
+ */
+ if (RELOC(mmutype, int) == MMU_68040)
+ protopte |= PG_CCB;
+#ifdef CPU_68060
+ else if (RELOC(mmutype, int) == MMU_68060)
+ protopte |= PG_CWT;
+#endif
+ while (pte < epte) {
+ *pte++ = protopte;
+ protopte += NBPG;
+ }
+
+ /*
+ * Finally, validate the internal IO space PTEs (RW+CI).
+ * We do this here since on hp300 machines with the HP MMU, the
+ * the MMU registers (also used, but to a lesser extent, on other
+ * models) are mapped in this range and it would be nice to be able
+ * to access them after the MMU is turned on.
+ */
+ pte = PA2VA(iiopa, u_int *);
+ epte = PA2VA(eiopa, u_int *);
+ protopte = MACHINE_INTIOBASE | PG_RW | PG_CI | PG_V | PG_U;
+ while (pte < epte) {
+ *pte++ = protopte;
+ protopte += NBPG;
+ }
+ PMAP_MD_MAPIOSPACE();
+
+ /*
+ * Calculate important exported kernel virtual addresses
+ */
+ /*
+ * Sysseg: base of kernel segment table
+ */
+ RELOC(Sysseg, st_entry_t *) =
+ (st_entry_t *)(kstpa - firstpa);
+ /*
+ * Sysptmap: base of kernel page table map
+ */
+ RELOC(Sysptmap, pt_entry_t *) =
+ (pt_entry_t *)(kptmpa - firstpa);
+ /*
+ * Sysmap: kernel page table (as mapped through Sysptmap)
+ * Immediately follows `nptpages' of static kernel page table.
+ */
+ RELOC(Sysmap, pt_entry_t *) =
+ (pt_entry_t *)m68k_ptob(nptpages * NPTEPG);
+
+ PMAP_MD_RELOC2();
+
+ /*
+ * Setup u-area for process 0.
+ */
+ /*
+ * Zero the u-area.
+ * NOTE: `pte' and `epte' aren't PTEs here.
+ */
+ pte = PA2VA(p0upa, u_int *);
+ epte = (u_int *)(PA2VA(p0upa, u_int) + USPACE);
+ while (pte < epte)
+ *pte++ = 0;
+ /*
+ * Remember the u-area address so it can be loaded in the
+ * proc struct p_addr field later.
+ */
+ RELOC(proc0paddr, char *) = (char *)(p0upa - firstpa);
+
+ /*
+ * 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. Since the last page is used
+ * for rebooting the system (code is copied there and
+ * excution continues from copied code before the MMU
+ * is disabled), the msgbuf will get trounced between
+ * reboots if it's placed in the last physical page.
+ * To work around this, we move avail_end back one more
+ * page so the msgbuf can be preserved.
+ */
+ RELOC(avail_start, paddr_t) = nextpa;
+ PMAP_MD_MEMSIZE();
+ RELOC(mem_size, vsize_t) = m68k_ptob(RELOC(physmem, int));
+ RELOC(virtual_avail, vaddr_t) =
+ VM_MIN_KERNEL_ADDRESS + (nextpa - firstpa);
+ RELOC(virtual_end, vaddr_t) = VM_MAX_KERNEL_ADDRESS;
+
+#ifdef M68K_MMU_HP
+ /*
+ * Determine VA aliasing distance if any
+ */
+ if (RELOC(ectype, int) == EC_VIRT) {
+ if (RELOC(machineid, int) == HP_320)
+ RELOC(pmap_aliasmask, int) = 0x3fff; /* 16k */
+ else if (RELOC(machineid, int) == HP_350)
+ RELOC(pmap_aliasmask, int) = 0x7fff; /* 32k */
+ }
+#endif
+
+ /*
+ * Kernel page/segment table allocated in locore,
+ * just initialize pointers.
+ */
+ {
+ struct pmap *kpm = &RELOC(kernel_pmap_store, struct pmap);
+
+ kpm->pm_stab = RELOC(Sysseg, st_entry_t *);
+ kpm->pm_ptab = RELOC(Sysmap, pt_entry_t *);
+ simple_lock_init(&kpm->pm_lock);
+ kpm->pm_count = 1;
+ kpm->pm_stpa = (st_entry_t *)kstpa;
+ /*
+ * For the 040 and 060 we also initialize the free level 2
+ * descriptor mask noting that we have used:
+ * 0: level 1 table
+ * 1 to `num': map page tables
+ * MAXKL2SIZE-1: maps last-page page table
+ */
+ if (RELOC(mmutype, int) <= MMU_68040) {
+ int num;
+
+ kpm->pm_stfree = ~l2tobm(0);
+ num = roundup((nptpages + 1) * (NPTEPG / SG4_LEV3SIZE),
+ SG4_LEV2SIZE) / SG4_LEV2SIZE;
+ while (num)
+ kpm->pm_stfree &= ~l2tobm(num--);
+ kpm->pm_stfree &= ~l2tobm(MAXKL2SIZE-1);
+ for (num = MAXKL2SIZE;
+ num < sizeof(kpm->pm_stfree)*NBBY;
+ num++)
+ kpm->pm_stfree &= ~l2tobm(num);
+ }
+ }
+
+ /*
+ * Allocate some fixed, special purpose kernel virtual addresses
+ */
+ {
+ vaddr_t va = RELOC(virtual_avail, vaddr_t);
+
+ RELOC(CADDR1, caddr_t) = (caddr_t)va;
+ va += NBPG;
+ RELOC(CADDR2, caddr_t) = (caddr_t)va;
+ va += NBPG;
+ RELOC(vmmap, caddr_t) = (caddr_t)va;
+ va += NBPG;
+
+ PMAP_MD_RELOC3();
+
+ RELOC(msgbufp, struct msgbuf *) = (struct msgbuf *)va;
+ va += MSGBUFSIZE;
+ RELOC(virtual_avail, vaddr_t) = va;
+ }
+}
diff --git a/sys/arch/mvme68k/mvme68k/pmap_bootstrap.c b/sys/arch/mvme68k/mvme68k/pmap_bootstrap.c
index aabf3ea5cef..f8ae7787af2 100644
--- a/sys/arch/mvme68k/mvme68k/pmap_bootstrap.c
+++ b/sys/arch/mvme68k/mvme68k/pmap_bootstrap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap_bootstrap.c,v 1.14 2002/02/22 22:45:34 miod Exp $ */
+/* $OpenBSD: pmap_bootstrap.c,v 1.15 2002/02/23 04:58:28 miod Exp $ */
/*
* Copyright (c) 1995 Theo de Raadt
@@ -79,477 +79,68 @@
#include <uvm/uvm_extern.h>
-#define RELOC(v, t) *((t*)((u_int)&(v) + firstpa))
-
-extern char *etext;
-extern int Sysptsize;
-extern char *extiobase, *proc0paddr;
-extern st_entry_t *Sysseg;
-extern pt_entry_t *Sysptmap, *Sysmap;
-
-extern int maxmem, physmem;
-extern paddr_t avail_start, avail_end;
-extern vaddr_t virtual_avail, virtual_end;
-extern vsize_t mem_size;
-#ifdef M68K_MMU_HP
-extern int pmap_aliasmask;
-#endif
-
char *iiomapbase;
int iiomapsize;
#define ETHERPAGES 16
void *etherbuf;
int etherlen;
-#define MACHINE_IIOMAPSIZE RELOC(iiomapsize, int)
-#define MACHINE_INTIOBASE RELOC(iiomapbase, int)
-
-void pmap_bootstrap __P((paddr_t, paddr_t));
-
-
-/*
- * Special purpose kernel virtual addresses, used for mapping
- * physical pages for a variety of temporary or permanent purposes:
- *
- * CADDR1, CADDR2: pmap zero/copy operations
- * vmmap: /dev/mem, crash dumps, parity error checking
- * ledbase: SPU LEDs
- * msgbufp: kernel message buffer
- */
-caddr_t CADDR1, CADDR2, vmmap;
-
-/*
- * Bootstrap the VM system.
- *
- * Called with MMU off so we must relocate all global references by `firstpa'
- * (don't call any functions here!) `nextpa' is the first available physical
- * memory address. Returns an updated first PA reflecting the memory we
- * have allocated. MMU is still off when we return.
- *
- * XXX assumes sizeof(u_int) == sizeof(pt_entry_t)
- * XXX a PIC compiler would make this much easier.
- */
-void
-pmap_bootstrap(nextpa, firstpa)
- paddr_t nextpa;
- paddr_t firstpa;
-{
- paddr_t kstpa, kptpa, iiopa, eiopa, kptmpa, lkptpa, p0upa;
- u_int nptpages, kstsize;
- st_entry_t protoste, *ste;
- pt_entry_t protopte, *pte, *epte;
-
- /*
- * Calculate important physical addresses:
- *
- * kstpa kernel segment table 1 page (020/030)
- * N pages (040/060)
- *
- * kptpa statically allocated
- * kernel PT pages Sysptsize+ pages
- *
- * iiopa internal IO space
- * PT pages MACHINE_IIOMAPSIZE pages
- *
- * eiopa external IO space
- * PT pages EIOMAPSIZE pages
- *
- * [ Sysptsize is the number of pages of PT, MACHINE_IIOMAPSIZE and
- * EIOMAPSIZE are the number of PTEs, hence we need to round
- * the total to a page boundary with IO maps at the end. ]
- *
- * kptmpa kernel PT map 1 page
- *
- * lkptpa last kernel PT page 1 page
- *
- * p0upa proc 0 u-area UPAGES pages
- *
- * The KVA corresponding to any of these PAs is:
- * (PA - firstpa + KERNBASE).
- */
- if (RELOC(mmutype, int) <= MMU_68040)
- kstsize = MAXKL2SIZE / (NPTEPG/SG4_LEV2SIZE);
- else
- kstsize = 1;
- kstpa = nextpa;
- nextpa += kstsize * NBPG;
- kptpa = nextpa;
- nptpages = RELOC(Sysptsize, int) +
- (MACHINE_IIOMAPSIZE + EIOMAPSIZE + NPTEPG - 1) / NPTEPG;
- nextpa += nptpages * NBPG;
- eiopa = nextpa - EIOMAPSIZE * sizeof(pt_entry_t);
- iiopa = eiopa - MACHINE_IIOMAPSIZE * sizeof(pt_entry_t);
- kptmpa = nextpa;
- nextpa += NBPG;
- lkptpa = nextpa;
- nextpa += NBPG;
- p0upa = nextpa;
- nextpa += USPACE;
+extern char *extiobase;
+extern int maxmem;
- RELOC(etherbuf, void *) = (void *)nextpa;
- nextpa += ETHERPAGES * NBPG;
+#define RELOC(v, t) *((t*)((u_int)&(v) + firstpa))
+#define PA2VA(v, t) *((t*)((u_int)&(v)))
- /*
- * Initialize segment table and kernel page table map.
- *
- * On 68030s and earlier MMUs the two are identical except for
- * the valid bits so both are initialized with essentially the
- * same values. On the 680[46]0, which have a mandatory 3-level
- * structure, the segment table holds the level 1 table and part
- * (or all) of the level 2 table and hence is considerably
- * different. Here the first level consists of 128 descriptors
- * (512 bytes) each mapping 32mb of address space. Each of these
- * points to blocks of 128 second level descriptors (512 bytes)
- * each mapping 256kb. Note that there may be additional "segment
- * table" pages depending on how large MAXKL2SIZE is.
- *
- * Portions of the last segment of KVA space (0xFFF00000 -
- * 0xFFFFFFFF) are mapped for a couple of purposes. 0xFFF00000
- * for UPAGES is used for mapping the current process u-area
- * (u + kernel stack). The very last page (0xFFFFF000) is mapped
- * to the last physical page of RAM to give us a region in which
- * PA == VA. We use the first part of this page for enabling
- * and disabling mapping. The last part of this page also contains
- * info left by the boot ROM.
- *
- * XXX cramming two levels of mapping into the single "segment"
- * table on the 68040 is intended as a temporary hack to get things
- * working. The 224mb of address space that this allows will most
- * likely be insufficient in the future (at least for the kernel).
- */
- if (RELOC(mmutype, int) <= MMU_68040) {
- int num;
+#define MACHINE_IIOMAPSIZE RELOC(iiomapsize, int)
+#define MACHINE_INTIOBASE RELOC(iiomapbase, int)
+#define MACHINE_EIOMAPSIZE EIOMAPSIZE
- /*
- * First invalidate the entire "segment table" pages
- * (levels 1 and 2 have the same "invalid" value).
- */
- pte = (u_int *)kstpa;
- epte = &pte[kstsize * NPTEPG];
- while (pte < epte)
- *pte++ = SG_NV;
- /*
- * Initialize level 2 descriptors (which immediately
- * follow the level 1 table). We need:
- * NPTEPG / SG4_LEV3SIZE
- * level 2 descriptors to map each of the nptpages+1
- * pages of PTEs. Note that we set the "used" bit
- * now to save the HW the expense of doing it.
- */
- num = (nptpages + 1) * (NPTEPG / SG4_LEV3SIZE);
- pte = &((u_int *)kstpa)[SG4_LEV1SIZE];
- epte = &pte[num];
- protoste = kptpa | SG_U | SG_RW | SG_V;
- while (pte < epte) {
- *pte++ = protoste;
- protoste += (SG4_LEV3SIZE * sizeof(st_entry_t));
- }
- /*
- * Initialize level 1 descriptors. We need:
- * roundup(num, SG4_LEV2SIZE) / SG4_LEV2SIZE
- * level 1 descriptors to map the `num' level 2's.
- */
- pte = (u_int *)kstpa;
- epte = &pte[roundup(num, SG4_LEV2SIZE) / SG4_LEV2SIZE];
- protoste = (u_int)&pte[SG4_LEV1SIZE] | SG_U | SG_RW | SG_V;
- while (pte < epte) {
- *pte++ = protoste;
- protoste += (SG4_LEV2SIZE * sizeof(st_entry_t));
- }
- /*
- * Initialize the final level 1 descriptor to map the last
- * block of level 2 descriptors.
- */
- ste = &((u_int *)kstpa)[SG4_LEV1SIZE-1];
- pte = &((u_int *)kstpa)[kstsize*NPTEPG - SG4_LEV2SIZE];
- *ste = (u_int)pte | SG_U | SG_RW | SG_V;
- /*
- * Now initialize the final portion of that block of
- * descriptors to map the "last PT page".
- */
- pte = &((u_int *)kstpa)[kstsize*NPTEPG - NPTEPG/SG4_LEV3SIZE];
- epte = &pte[NPTEPG/SG4_LEV3SIZE];
- protoste = lkptpa | SG_U | SG_RW | SG_V;
- while (pte < epte) {
- *pte++ = protoste;
- protoste += (SG4_LEV3SIZE * sizeof(st_entry_t));
- }
- /*
- * Initialize Sysptmap
- */
- pte = (u_int *)kptmpa;
- epte = &pte[nptpages+1];
- protopte = kptpa | PG_RW | PG_CI | PG_V | PG_U;
- while (pte < epte) {
- *pte++ = protopte;
- protopte += NBPG;
- }
- /*
- * Invalidate all but the last remaining entry.
- */
- epte = &((u_int *)kptmpa)[NPTEPG-1];
- while (pte < epte) {
- *pte++ = PG_NV | PG_U;
- }
- /*
- * Initialize the last to point to the page
- * table page allocated earlier.
- */
- *pte = lkptpa | PG_RW | PG_CI | PG_V | PG_U;
- } else {
- /*
- * Map the page table pages in both the HW segment table
- * and the software Sysptmap. Note that Sysptmap is also
- * considered a PT page hence the +1.
- */
- ste = (u_int *)kstpa;
- pte = (u_int *)kptmpa;
- epte = &pte[nptpages+1];
- protoste = kptpa | SG_RW | SG_V;
- protopte = kptpa | PG_RW | PG_CI | PG_V;
- while (pte < epte) {
- *ste++ = protoste;
- *pte++ = protopte;
- protoste += NBPG;
- protopte += NBPG;
- }
- /*
- * Invalidate all but the last remaining entries in both.
- */
- epte = &((u_int *)kptmpa)[NPTEPG-1];
- while (pte < epte) {
- *ste++ = SG_NV;
- *pte++ = PG_NV;
- }
- /*
- * Initialize the last to point to point to the page
- * table page allocated earlier.
- */
- *ste = lkptpa | SG_RW | SG_V;
- *pte = lkptpa | PG_RW | PG_CI | PG_V;
- }
- /*
- * Invalidate all but the final entry in the last kernel PT page
- * (u-area PTEs will be validated later). The final entry maps
- * the last page of physical memory.
- */
- pte = (u_int *)lkptpa;
- epte = &pte[NPTEPG-1];
- while (pte < epte)
- *pte++ = PG_NV;
-#ifdef MAXADDR
- /*
- * Temporary double-map for machines with physmem at the end of
- * memory
- */
- *pte = MAXADDR | PG_RW | PG_CI | PG_V | PG_U;
-#endif
- /*
- * Initialize kernel page table.
- * Start by invalidating the `nptpages' that we have allocated.
- */
- pte = (u_int *)kptpa;
- epte = &pte[nptpages * NPTEPG];
- while (pte < epte)
- *pte++ = PG_NV | PG_U;
+#define PMAP_MD_LOCALS /* nothing */
- /*
- * Validate PTEs for kernel text (RO). The first page
- * of kernel text remains invalid; see locore.s
- */
- pte = &((u_int *)kptpa)[m68k_btop(KERNBASE)];
- epte = &pte[m68k_btop(trunc_page((vaddr_t)&etext))];
-#if defined(KGDB) || defined(DDB)
- protopte = firstpa | PG_RW | PG_V | PG_U; /* XXX RW for now */
-#else
- protopte = firstpa | PG_RO | PG_V | PG_U;
-#endif
- *pte++ = firstpa | PG_NV; /* make *NULL fail in the kernel */
- protopte += NBPG;
- while (pte < epte) {
- *pte++ = protopte;
- protopte += NBPG;
- }
- /*
- * Validate PTEs for kernel data/bss, dynamic data allocated
- * by us so far (nextpa - firstpa bytes), and pages for proc0
- * u-area and page table allocated below (RW).
- */
- epte = &((u_int *)kptpa)[m68k_btop(nextpa - firstpa)];
- protopte = (protopte & ~PG_PROT) | PG_RW | PG_U;
- /*
- * Enable copy-back caching of data pages on 040, and write-through
- * caching on 060
- */
- if (RELOC(mmutype, int) == MMU_68040)
- protopte |= PG_CCB;
- else if (RELOC(mmutype, int) == MMU_68060)
- protopte |= PG_CWT;
- while (pte < epte) {
- *pte++ = protopte;
- protopte += NBPG;
- }
+#define PMAP_MD_RELOC1() \
+do { \
+ RELOC(etherbuf, void *) = (void *)nextpa; \
+ nextpa += ETHERPAGES * NBPG; \
+} while (0)
- pte = &((u_int *)kptpa)[m68k_btop(etherbuf)];
- epte = pte + ETHERPAGES;
- while (pte < epte) {
- *pte = (*pte & ~PG_CMASK) | PG_CIS | PG_U;
- pte++;
- }
- RELOC(etherlen, int) = ETHERPAGES * NBPG;
+#define PMAP_MD_MAPIOSPACE() \
+do { \
+ pte = &((u_int *)kptpa)[m68k_btop(etherbuf)]; \
+ epte = pte + ETHERPAGES; \
+ while (pte < epte) { \
+ *pte = (*pte & ~PG_CMASK) | PG_CIS | PG_U; \
+ pte++; \
+ } \
+ RELOC(etherlen, int) = ETHERPAGES * NBPG; \
+} while (0)
/*
- * Finally, validate the internal IO space PTEs (RW+CI).
- * We do this here since on hp300 machines with the HP MMU, the
- * the MMU registers (also used, but to a lesser extent, on other
- * models) are mapped in this range and it would be nice to be able
- * to access them after the MMU is turned on.
- */
- pte = (u_int *)iiopa;
- epte = (u_int *)eiopa;
- protopte = MACHINE_INTIOBASE | PG_RW | PG_CI | PG_V | PG_U;
- while (pte < epte) {
- *pte++ = protopte;
- protopte += NBPG;
- }
-
- /*
- * Calculate important exported kernel virtual addresses
- */
- /*
- * Sysseg: base of kernel segment table
- */
- RELOC(Sysseg, st_entry_t *) =
- (st_entry_t *)(kstpa - firstpa);
- /*
- * Sysptmap: base of kernel page table map
- */
- RELOC(Sysptmap, pt_entry_t *) =
- (pt_entry_t *)(kptmpa - firstpa);
- /*
- * Sysmap: kernel page table (as mapped through Sysptmap)
- * Immediately follows `nptpages' of static kernel page table.
- */
- RELOC(Sysmap, pt_entry_t *) =
- (pt_entry_t *)m68k_ptob(nptpages * NPTEPG);
- /*
- * intiobase, intiolimit: base and end of internal (DIO) IO space.
+ * intiobase, intiolimit: base and end of internal IO space.
* MACHINE_IIOMAPSIZE pages prior to external IO space at end of
* static kernel page table.
- */
- RELOC(intiobase, char *) =
- (char *)m68k_ptob(nptpages*NPTEPG - (MACHINE_IIOMAPSIZE+EIOMAPSIZE));
- RELOC(intiolimit, char *) =
- (char *)m68k_ptob(nptpages*NPTEPG - EIOMAPSIZE);
- /*
- * extiobase: base of external (DIO-II) IO space.
- * EIOMAPSIZE pages at the end of the static kernel page table.
- */
- RELOC(extiobase, char *) =
- (char *)m68k_ptob(nptpages*NPTEPG - EIOMAPSIZE);
-
- /*
- * Setup u-area for process 0.
- */
- /*
- * Zero the u-area.
- * NOTE: `pte' and `epte' aren't PTEs here.
- */
- pte = (u_int *)p0upa;
- epte = (u_int *)(p0upa + USPACE);
- while (pte < epte)
- *pte++ = 0;
- /*
- * Remember the u-area address so it can be loaded in the
- * proc struct p_addr field later.
- */
- RELOC(proc0paddr, char *) = (char *)(p0upa - firstpa);
-
- /*
- * 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. Since the last page is used
- * for rebooting the system (code is copied there and
- * excution continues from copied code before the MMU
- * is disabled), the msgbuf will get trounced between
- * reboots if it's placed in the last physical page.
- * To work around this, we move avail_end back one more
- * page so the msgbuf can be preserved.
- */
- RELOC(avail_start, paddr_t) = nextpa;
- RELOC(avail_end, paddr_t) = m68k_ptob(RELOC(maxmem, int)) -
- (round_page(MSGBUFSIZE) + m68k_ptob(1));
- RELOC(mem_size, vsize_t) = m68k_ptob(RELOC(physmem, int));
- RELOC(virtual_avail, vaddr_t) =
- VM_MIN_KERNEL_ADDRESS + (nextpa - firstpa);
- RELOC(virtual_end, vaddr_t) = VM_MAX_KERNEL_ADDRESS;
-
-#ifdef M68K_MMU_HP
- /*
- * Determine VA aliasing distance if any
- */
- if (RELOC(ectype, int) == EC_VIRT) {
- if (RELOC(machineid, int) == HP_320)
- RELOC(pmap_aliasmask, int) = 0x3fff; /* 16k */
- else if (RELOC(machineid, int) == HP_350)
- RELOC(pmap_aliasmask, int) = 0x7fff; /* 32k */
- }
-#endif
-
- /*
- * Kernel page/segment table allocated in locore,
- * just initialize pointers.
- */
- {
- struct pmap *kpm = &RELOC(kernel_pmap_store, struct pmap);
-
- kpm->pm_stab = RELOC(Sysseg, st_entry_t *);
- kpm->pm_ptab = RELOC(Sysmap, pt_entry_t *);
- simple_lock_init(&kpm->pm_lock);
- kpm->pm_count = 1;
- kpm->pm_stpa = (st_entry_t *)kstpa;
- /*
- * For the 040 and 060 we also initialize the free level 2
- * descriptor mask noting that we have used:
- * 0: level 1 table
- * 1 to `num': map page tables
- * MAXKL2SIZE-1: maps last-page page table
- */
- if (RELOC(mmutype, int) <= MMU_68040) {
- int num;
-
- kpm->pm_stfree = ~l2tobm(0);
- num = roundup((nptpages + 1) * (NPTEPG / SG4_LEV3SIZE),
- SG4_LEV2SIZE) / SG4_LEV2SIZE;
- while (num)
- kpm->pm_stfree &= ~l2tobm(num--);
- kpm->pm_stfree &= ~l2tobm(MAXKL2SIZE-1);
- for (num = MAXKL2SIZE;
- num < sizeof(kpm->pm_stfree)*NBBY;
- num++)
- kpm->pm_stfree &= ~l2tobm(num);
- }
- }
-
- /*
- * Allocate some fixed, special purpose kernel virtual addresses
- */
- {
- vaddr_t va = RELOC(virtual_avail, vaddr_t);
-
- RELOC(CADDR1, caddr_t) = (caddr_t)va;
- va += NBPG;
- RELOC(CADDR2, caddr_t) = (caddr_t)va;
- va += NBPG;
- RELOC(vmmap, caddr_t) = (caddr_t)va;
- va += NBPG;
- RELOC(msgbufp, struct msgbuf *) = (struct msgbuf *)va;
- va += MSGBUFSIZE;
- RELOC(virtual_avail, vaddr_t) = va;
- }
-}
+ * extiobase: base of external IO space.
+ * MACHINE_EIOMAPSIZE pages at the end of the static kernel page table.
+ */
+#define PMAP_MD_RELOC2() \
+do { \
+ RELOC(intiobase, char *) = \
+ (char *)m68k_ptob(nptpages * NPTEPG - \
+ (MACHINE_IIOMAPSIZE + MACHINE_EIOMAPSIZE)); \
+ RELOC(intiolimit, char *) = \
+ (char *)m68k_ptob(nptpages * NPTEPG - MACHINE_EIOMAPSIZE); \
+ RELOC(extiobase, char *) = \
+ (char *)m68k_ptob(nptpages * NPTEPG - MACHINE_EIOMAPSIZE); \
+} while (0)
+
+#define PMAP_MD_MEMSIZE() \
+do { \
+ RELOC(avail_end, paddr_t) = m68k_ptob(RELOC(maxmem, int)) - \
+ (round_page(MSGBUFSIZE) + m68k_ptob(1)); \
+} while (0)
+
+#define PMAP_MD_RELOC3() /* nothing */
+
+#include <m68k/m68k/pmap_bootstrap.c>
void
pmap_init_md()