Subject: [PATCH] Fixup for Amigas with memory at 0x200000
To: Hubert Feyrer <hubert.feyrer@informatik.fh-regensburg.de>
From: Aymeric Vincent <Aymeric.Vincent@labri.fr>
List: port-amiga
Date: 01/07/2003 01:28:11
[ Testers needed. Please read ahead ]

Okay, so I finally gave it a try. I think the following patch is good
because it simplifies amiga_init() and it makes my Amiga capable of
booting a GENERIC -current kernel.

I'm pretty confident that it'll work for you Hubert, but I'd like
people with Draco's and 68040/60's to test it before committing it.
Could anyone who tests it please report successes and failures?


Tech part:

Booting is now done this way:

- start_c() is called. It sets the page tables up.
- locore.s takes over to:
 - copy the small code that switches the MMU on into chip memory
   (so that for this small chunk, PA == VA)
 - switch on the MMU
 - jump to the final virtual location of the kernel
- start_c_finish() (formerly start_c_cleanup) does all the rest that
  start_c() could do thanks to the dual mappings which do not exist
  anymore.

No more shadow pointers or anything else.

The only thing is that it requires to have some physical memory near
address 0 (because we know locore.o is linked at the beginning of the
kernel) and I guess this is the case even on the Draco. (?)

Enjoy,
 Aymeric

Index: amiga_init.c
===================================================================
RCS file: /usr/local/cvsroot/src/sys/arch/amiga/amiga/amiga_init.c,v
retrieving revision 1.81
diff -u -r1.81 amiga_init.c
--- amiga_init.c	10 Dec 2002 17:14:04 -0000	1.81
+++ amiga_init.c	6 Jan 2003 20:56:13 -0000
@@ -117,6 +117,8 @@
 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 +138,7 @@
 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 +215,9 @@
 	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 +382,6 @@
 #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 +438,6 @@
 		 */
 		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 +459,6 @@
 			*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 +502,6 @@
 			*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);
-		}
 	}
 
 	/*
@@ -692,23 +617,6 @@
 	}
 
 	/*
-	 * 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 ]
 	 */
@@ -843,9 +751,6 @@
 		/*
 		 * movel Sysseg_pa,a0;
 		 * movec a0,SRP;
-		 * pflusha;
-		 * movel #$0xc000,d0;
-		 * movec d0,TC
 		 */
 
 		if (id & AMIGA_68060) {
@@ -868,9 +773,6 @@
 		} else
 ((volatile struct Custom *)0xdff000)->color[0] = 0xA70;		/* ORANGE */
 #endif
-
-		asm volatile ("movel #0xc000,%%d0; .word 0x4e7b,0x0003"
-		    : : :"d0" );
 	} else
 #endif
 	{
@@ -881,14 +783,20 @@
 		 */
 		(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 +815,8 @@
 ((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 +849,10 @@
 		z2mem_start = ZTWOMEMADDR;
 	}
 
+#if 0
 	i = *(int *)proc0paddr;
 	*(volatile int *)proc0paddr = i;
+#endif
 
 	/*
 	 * disable all interupts but enable allow them to be enabled
@@ -1018,24 +928,6 @@
 			}
         }
 #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
 	 */
Index: locore.s
===================================================================
RCS file: /usr/local/cvsroot/src/sys/arch/amiga/amiga/locore.s,v
retrieving revision 1.132
diff -u -r1.132 locore.s
--- locore.s	2 Nov 2002 20:03:04 -0000	1.132
+++ locore.s	6 Jan 2003 21:13:23 -0000
@@ -918,16 +918,47 @@
 	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
+
+/* 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
+	pflusha
+	movl	#0xc000,%d0
+	.word	0x4e7b, 0x0003		| movec	%d0,%tc
+	jmp	Lunshadow:l
+#endif /* M68040 || M68060 */
+/* ENABLE, SRP_ENABLE, 8K pages, 8bit A-level, 11bit B-level */
+Ltc:	.long	0x82d08b00
+Lenable030:
+	lea	Ltc,%a0
+	pmove	%a0@,%tc
 	jmp	Lunshadow:l
 
 Lunshadow:
 
+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