Change the bootstrap procedure to avoid temporarily mapping physical memory.

Now, on the Amiga, we copy a small piece of code to chip memory and enable the
MMU from here.
On the DraCo, we setup %itt0 so that we shadow physical memory without
touching the page tables and very temporarily. The DraCo's memory layout
guarantees that there is no overlap in this case between physical and
virtual addresses.

This fixes a bug where Amiga's with physical memory at 0x200000 wouldn't boot
kernels >2M in size, and possibly other corner cases.

Joint work with Ilpo Ruotsalainen and Ignatios Souvatzis.
This commit is contained in:
aymeric 2003-01-11 10:47:08 +00:00
parent e648b82855
commit 04afe0c722
2 changed files with 85 additions and 146 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: amiga_init.c,v 1.82 2003/01/06 13:04:56 wiz Exp $ */
/* $NetBSD: amiga_init.c,v 1.83 2003/01/11 10:47:08 aymeric Exp $ */
/*
* Copyright (c) 1994 Michael L. Hitch
@ -35,7 +35,7 @@
#include "opt_p5ppc68kboard.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: amiga_init.c,v 1.82 2003/01/06 13:04:56 wiz Exp $");
__KERNEL_RCSID(0, "$NetBSD: amiga_init.c,v 1.83 2003/01/11 10:47:08 aymeric Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -105,9 +105,6 @@ volatile unsigned short *amiga_intena_read, *amiga_intena_write;
vaddr_t amigahwaddr;
u_int namigahwpg;
vaddr_t amigashdwaddr;
u_int namigashdwpg;
vaddr_t CHIPMEMADDR;
vaddr_t chipmem_start;
vaddr_t chipmem_end;
@ -117,6 +114,8 @@ static vaddr_t z2mem_end; /* XXX */
int use_z2_mem = 1; /* XXX */
u_long boot_fphystart, boot_fphysize, boot_cphysize;
static u_int start_c_fphystart;
static u_int start_c_pstart;
static u_long boot_flags;
@ -136,7 +135,7 @@ int kernel_reload_write(struct uio *);
extern void kernel_reload(char *, u_long, u_long, u_long, u_long,
u_long, u_long, u_long, u_long, u_long, u_long);
extern void etext(void);
void start_c_cleanup(void);
void start_c_finish(void);
void *
chipmem_steal(long amount)
@ -213,13 +212,9 @@ start_c(id, fphystart, fphysize, cphysize, esym_addr, flags, inh_sync,
u_int Sysptmap_pa;
register st_entry_t sg_proto, *sg, *esg;
register pt_entry_t pg_proto, *pg;
u_int tc, end_loaded, ncd, i;
u_int end_loaded, ncd, i;
struct boot_memlist *ml;
u_int loadbase = 0; /* XXXXXXXXXXXXXXXXXXXXXXXXXXXX */
u_int *shadow_pt = 0; /* XXXXXXXXXXXXXXXXXXXXXXXXXXXX */
#ifdef P5PPC68KBOARD
struct cfdev *cdp, *ecdp;
#endif
#ifdef DEBUG_KERNEL_START
/* XXX this only is valid if Altais is in slot 0 */
@ -384,14 +379,6 @@ start_c(id, fphystart, fphysize, cphysize, esym_addr, flags, inh_sync,
#endif
ptextra = NCHIPMEMPG + NCIAPG + NZTWOROMPG + RELOC(NZTWOMEMPG, u_int) +
btoc(RELOC(ZBUSAVAIL, u_int)) + NPCMCIAPG;
/*
* if kernel shadow mapping will overlap any initial mapping
* of Zorro I/O space or the page table map, we need to
* adjust things to remove the overlap.
*/
if (loadbase != 0) {
/* What to do, what to do? */
}
ptsize = (RELOC(Sysptsize, u_int) +
howmany(ptextra, NPTEPG)) << PGSHIFT;
@ -448,9 +435,6 @@ start_c(id, fphystart, fphysize, cphysize, esym_addr, flags, inh_sync,
*/
i = ((ptsize >> PGSHIFT) + 1) * (NPTEPG / SG4_LEV3SIZE);
sg = &((u_int *)(RELOC(Sysseg_pa, u_int)))[SG4_LEV1SIZE];
if (loadbase != 0)
/* start of next L2 table */
shadow_pt = &sg[roundup(i, SG4_LEV2SIZE)];
esg = &sg[i];
sg_proto = ptpa | SG_U | SG_RW | SG_V;
while (sg < esg) {
@ -472,46 +456,6 @@ start_c(id, fphystart, fphysize, cphysize, esym_addr, flags, inh_sync,
*sg++ = sg_proto;
sg_proto += (SG4_LEV2SIZE * sizeof(st_entry_t));
}
if (loadbase != 0) {
sg = (u_int *)RELOC(Sysseg_pa, u_int);
if (sg[loadbase >> SG4_SHIFT1] == 0) {
/* allocate another level 2 table */
sg[loadbase >> SG4_SHIFT1] =
(u_int)shadow_pt | SG_U | SG_RW | SG_V;
shadow_pt = NULL;
RELOC(protostfree, u_int) =
RELOC(protostfree, u_int) << 1;
}
sg = (u_int *)(sg[loadbase >> SG4_SHIFT1] & SG4_ADDR1);
if (sg[(loadbase & SG4_MASK2) >> SG4_SHIFT2] == 0) {
/* no page table exists, need to allocate it */
sg_proto = pstart | SG_U | SG_RW | SG_V;
sg = &sg[(loadbase & SG4_MASK2) >> SG4_SHIFT2];
sg = (u_int *)((int)sg &
~(NBPG / SG4_LEV3SIZE - 1));
esg = &sg[NPTEPG / SG4_LEV3SIZE];
while (sg < esg) {
*sg++ = sg_proto;
sg_proto += SG4_LEV3SIZE *
sizeof (st_entry_t);
}
pg = (u_int *) pstart;
esg = (u_int *)&pg[NPTEPG];
while (pg < esg)
*pg++ = PG_NV;
pstart += NBPG;
vstart += NBPG;
avail -= NBPG;
/* ptmap??? */
}
sg = (u_int *)RELOC(Sysseg_pa, u_int);
sg = (u_int *)(sg[loadbase >> SG4_SHIFT1] & SG4_ADDR1);
shadow_pt =
((u_int *)(sg[(loadbase & SG4_MASK2) >> SG4_SHIFT2]
& SG4_ADDR1)) +
((loadbase & SG4_MASK3) >> SG4_SHIFT3); /* XXX is */
}
/*
* Initialize Sysptmap
*/
@ -555,28 +499,6 @@ start_c(id, fphystart, fphysize, cphysize, esym_addr, flags, inh_sync,
*sg++ = SG_NV;
*pg++ = PG_NV;
}
if (loadbase != 0) {
sg = (u_int *)RELOC(Sysseg_pa, u_int);
if (sg[loadbase >> SG_ISHIFT] == 0) {
/* no page table exists, need to allocate it */
sg[loadbase >> SG_ISHIFT] =
pstart | SG_RW | SG_V;
pg = (u_int *)Sysptmap_pa;
pg[loadbase >> SG_ISHIFT] =
pstart | PG_RW | PG_CI | PG_V;
pg = (u_int *) pstart;
esg = (u_int *)&pg[NPTEPG];
while (pg < esg)
*pg++ = PG_NV;
pstart += NBPG;
vstart += NBPG;
avail -= NBPG;
}
shadow_pt =
((u_int *)(sg[loadbase >> SG_ISHIFT] & 0xffffff00))
+ ((loadbase & SG_PMASK) >> SG_PSHIFT);
}
}
/*
@ -691,23 +613,6 @@ start_c(id, fphystart, fphysize, cphysize, esym_addr, flags, inh_sync,
}
}
/*
* Initial any "shadow" mapping of the kernel
*/
if (loadbase != 0 && shadow_pt != 0) {
RELOC(amigashdwaddr, vaddr_t) = (u_int)shadow_pt - loadbase;
RELOC(namigashdwpg, u_int) = (vstart + USPACE) >> PGSHIFT;
pg_proto = fphystart | PG_RO | PG_V;
pg = shadow_pt;
*pg++ = PG_NV; /* Make page 0 invalid */
pg_proto += NBPG;
for (i = NBPG; i < (u_int)etext; i += NBPG, pg_proto += NBPG)
*pg++ = pg_proto;
pg_proto = (pg_proto & PG_FRAME) | PG_RW | PG_V;
for (; i < vstart + USPACE; i += NBPG, pg_proto += NBPG)
*pg++ = pg_proto;
}
/*
*[ following page tables MAY be allocated to ZORRO3 space,
* but they're then later mapped in autoconf.c ]
@ -840,14 +745,6 @@ start_c(id, fphystart, fphysize, cphysize, esym_addr, flags, inh_sync,
*/
#if defined(M68040) || defined(M68060)
if (RELOC(mmutype, int) == MMU_68040) {
/*
* movel Sysseg_pa,a0;
* movec a0,SRP;
* pflusha;
* movel #$0xc000,d0;
* movec d0,TC
*/
if (id & AMIGA_68060) {
/* do i need to clear the branch cache? */
asm volatile ( ".word 0x4e7a,0x0002;"
@ -855,9 +752,13 @@ start_c(id, fphystart, fphysize, cphysize, esym_addr, flags, inh_sync,
".word 0x4e7b,0x0002" : : : "d0");
}
/*
* movel Sysseg_pa,%a0;
* movec %a0,%srp;
*/
asm volatile ("movel %0,%%a0; .word 0x4e7b,0x8807"
: : "a" (RELOC(Sysseg_pa, u_int)) : "a0");
asm volatile (".word 0xf518" : : );
#ifdef DEBUG_KERNEL_START
if ((id>>24)==0x7D) {
@ -868,27 +769,29 @@ start_c(id, fphystart, fphysize, cphysize, esym_addr, flags, inh_sync,
} else
((volatile struct Custom *)0xdff000)->color[0] = 0xA70; /* ORANGE */
#endif
asm volatile ("movel #0xc000,%%d0; .word 0x4e7b,0x0003"
: : :"d0" );
} else
#endif
{
/*
* setup and load SRP
* nolimit, share global, 4 byte PTE's
*/
(RELOC(protorp[0], u_int)) = 0x80000202;
asm volatile ("pmove %0@,%%srp":: "a" (&RELOC(protorp, u_int)));
/*
* setup and load TC register.
* enable_cpr, enable_srp, pagesize=8k,
* A = 8 bits, B = 11 bits
*/
tc = 0x82d08b00;
asm volatile ("pmove %0@,%%tc" : : "a" (&tc));
}
RELOC(start_c_fphystart, u_int) = fphystart;
RELOC(start_c_pstart, u_int) = pstart;
}
void
start_c_finish()
{
extern u_int32_t delaydivisor;
#ifdef P5PPC68KBOARD
struct cfdev *cdp, *ecdp;
#endif
#ifdef DEBUG_KERNEL_START
#ifdef DRACO
if ((id >> 24) == 0x7D) { /* mapping on, is_draco() is valid */
@ -907,8 +810,8 @@ start_c(id, fphystart, fphysize, cphysize, esym_addr, flags, inh_sync,
((volatile struct Custom *)CUSTOMADDR)->color[0] = 0x0a0; /* GREEN */
#endif
bzero ((u_char *)proc0paddr, USPACE); /* XXXXXXXXXXXXXXXXXXXXX */
pmap_bootstrap(pstart, fphystart); /* XXXXXXXXXXXXXXXXXXXXXXx*/
bzero ((u_char *)proc0paddr, USPACE);
pmap_bootstrap(start_c_pstart, start_c_fphystart);
/*
* to make life easier in locore.s, set these addresses explicitly
@ -941,8 +844,10 @@ start_c(id, fphystart, fphysize, cphysize, esym_addr, flags, inh_sync,
z2mem_start = ZTWOMEMADDR;
}
#if 0
i = *(int *)proc0paddr;
*(volatile int *)proc0paddr = i;
#endif
/*
* disable all interrupts but enable allow them to be enabled
@ -1018,24 +923,6 @@ start_c(id, fphystart, fphysize, cphysize, esym_addr, flags, inh_sync,
}
}
#endif
}
void
start_c_cleanup()
{
u_int *sg, *esg;
extern u_int32_t delaydivisor;
/*
* remove shadow mapping of kernel?
*/
if (amigashdwaddr == 0)
return;
sg = (u_int *) amigashdwaddr;
esg = (u_int *)&sg[namigashdwpg];
while (sg < esg)
*sg++ = PG_NV;
/*
* preliminary delay divisor value
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: locore.s,v 1.132 2002/11/02 20:03:04 chs Exp $ */
/* $NetBSD: locore.s,v 1.133 2003/01/11 10:47:08 aymeric Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@ -918,16 +918,68 @@ Lstartnot040:
movc %d0,%sfc | as source
movc %d0,%dfc | and destination of transfers
/* let the C function initialize everything and enable the MMU */
/* let the C function initialize everything */
RELOC(start_c, %a0)
jbsr %a0@
addl #28,%sp
jmp Lunshadow:l
Lunshadow:
#ifdef DRACO
RELOC(machineid,%a0)
cmpb #0x7d,%a0@
jne LAmiga_enable_MMU
lea %pc@(0),%a0
movl %a0,%d0
andl #0xff000000,%d0
orl #0x0000c044,%d0 | 16 MB, ro, cache inhibited
.word 0x4e7b,0x0004 | movc %d0,%itt0
.word 0xf518 | pflusha
movl #0xc000,%d0 | enable MMU
.word 0x4e7b,0x0003 | movc %d0,%tc
jmp Lcleanitt0:l
Lcleanitt0:
movq #0,%d0
.word 0x4e7b,0x0004 | movc %d0,%itt0
bra LMMUenable_end
LAmiga_enable_MMU:
#endif /* DRACO */
/* Copy just the code to enable the MMU into chip memory */
lea LMMUenable_start,%a0
movl #LMMUenable_start:l,%a1
lea LMMUenable_end,%a2
Lcopy_MMU_enabler:
movl %a0@+,%a1@+
cmpl %a0,%a2
jgt Lcopy_MMU_enabler
jmp LMMUenable_start:l
LMMUenable_start:
/* enable the MMU */
#if defined(M68040) || defined(M68060)
RELOC(mmutype, %a0)
cmpl #MMU_68040,%a0@
jne Lenable030
.word 0xf518 | pflusha
movl #0xc000,%d0 | enable MMU
.word 0x4e7b,0x0003 | movc %d0,%tc
jmp LMMUenable_end:l
#endif /* M68040 || M68060 */
Lenable030:
lea Ltc,%a0
pmove %a0@,%tc
jmp LMMUenable_end:l
/* ENABLE, SRP_ENABLE, 8K pages, 8bit A-level, 11bit B-level */
Ltc: .long 0x82d08b00
LMMUenable_end:
lea _ASM_LABEL(tmpstk),%sp | give ourselves a temporary stack
jbsr _C_LABEL(start_c_cleanup)
jbsr _C_LABEL(start_c_finish)
/* set kernel stack, user SP, and initial pcb */
movl _C_LABEL(proc0paddr),%a1 | proc0 kernel stack