diff options
-rw-r--r-- | sys/arch/hp300/hp300/pmap_bootstrap.c | 480 | ||||
-rw-r--r-- | sys/arch/m68k/m68k/pmap_bootstrap.c | 531 | ||||
-rw-r--r-- | sys/arch/mvme68k/mvme68k/pmap_bootstrap.c | 505 |
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() |