Subject: README: Please give this a try!
To: None <port-mac68k@NetBSD.ORG>
From: Scott Reynolds <scottr@og.org>
List: port-mac68k
Date: 05/20/1998 02:11:52
i would appreciate any testing that folks can reasonably do by the end of
the week on this change.  please submit any feedback that you may have by
saturday evening directly to me.  (this is important:  mail to the list
has a lower priority than mail sent directly to me!)


what it is:

this is a change to (hopefully) once and for all kill the problems that
people seem to have with rebooting.

the old way:

map the ROM into the space it likes to be, then jump to the ROM reset with
our fingers crossed.

the new way:

map a single page at the end of physical RAM such that the virtual address
equals the physical address.  copy code to disable the MMU and jump to the
ROM reset into this page, then jump to the code we just copied. 

my analysis:

the old way has a fatal flaw.  it might be reassigning a page that the
kernel really wants to have around, particularly a page table page or
other vm/pmap structure.  the new way maps a single page that's reserved
at boot time, minimizing the chance that we'll run into problems later on.

note that i'm also addressing a problem where the startup process fails to
determine the cpu/fpu/mmu types.  that generally doesn't happen, but it
led to... unpredictable results.


this has so far worked on a wide range of systems, from original II-series
to IIci-class to several performa and quadra systems.  however, i'd like
to see as much testing done as possible before this one goes into mthe
tree.  any feedback will be most appreciated, even if it's to say my
analysis is flawed in itself. :-}

--scott

!!  this patch is intended to be applied against NetBSD-current source.
    it _will_not_ work without modification on a 1.3 or 1.3.1 source
    tree.

Index: locore.s
===================================================================
RCS file: /cvsroot/src/sys/arch/mac68k/mac68k/locore.s,v
retrieving revision 1.97
diff -c -r1.97 locore.s
*** locore.s	1998/04/24 05:27:25	1.97
--- locore.s	1998/05/11 05:33:46
***************
*** 131,136 ****
--- 131,148 ----
  	movc	d0,sfc			|   as source
  	movc	d0,dfc			|   and destination of transfers
  
+ 	/*
+ 	 * Some parameters provided by MacOS
+ 	 *
+ 	 * LAK: This section is the new way to pass information from the booter
+ 	 * to the kernel.  At A1 there is an environment variable which has
+ 	 * a bunch of stuff in ascii format, "VAR=value\0VAR=value\0\0".
+ 	 */
+ 	movl	a1,sp@-			| Address of buffer
+ 	movl	d4,sp@-			| Some flags... (mostly not used)
+ 	jbsr	_C_LABEL(getenvvars)	| Parse the environment buffer
+ 	addql	#8,sp
+ 
  	/* Determine MMU/MPU from what we can test empirically */
  	movl	#0x200,d0		| data freeze bit
  	movc	d0,cacr			|   only exists on 68030
***************
*** 200,216 ****
  	jra	Ldoboot1
  
  Lstart2:
- 	/*
- 	 * Some parameters provided by MacOS
- 	 *
- 	 * LAK: This section is the new way to pass information from the booter
- 	 * to the kernel.  At A1 there is an environment variable which has
- 	 * a bunch of stuff in ascii format, "VAR=value\0VAR=value\0\0".
- 	 */
- 	movl	a1,sp@-			| Address of buffer
- 	movl	d4,sp@-			| Some flags... (mostly not used)
- 	jbsr	_C_LABEL(getenvvars)	| Parse the environment buffer
- 	addql	#8,sp
  	jbsr	_C_LABEL(setmachdep)	| Set some machine-dep stuff
  	jbsr	_C_LABEL(consinit)	| XXX Should only be if graybar on
  
--- 212,217 ----
***************
*** 1587,1619 ****
  
  /*
   * Handle the nitty-gritty of rebooting the machine.
!  * Basically we just jump to the appropriate ROM routine after mapping
!  * the ROM into its proper home (back in machdep).
   */
  ENTRY_NOPROFILE(doboot)
! 	movw	#PSL_HIGHIPL,sr		| no interrupts
! 
  	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
! 	jne	Ldobootnot040		| yes, skip
! 	movl	#CACHE40_OFF,d0		| 68040 cache disable
! 	movc	d0, cacr
! 	.word	0xf4f8			| cpusha bc - push and invalidate caches
! 	jra	Ldoboot1
! 
! Ldobootnot040:
  	movl	#CACHE_OFF,d0
  	movc	d0,cacr			| disable on-chip cache(s)
! #ifdef __notyet__
! 	tstl	_C_LABEL(ectype)	| external cache?
! 	jeq	Ldoboot1		| no, skip
! 					| Disable external cache here.
  #endif
  
  Ldoboot1:
! 	movl	_C_LABEL(MacOSROMBase),_C_LABEL(ROMBase) | Load MacOS ROMBase
! 	movl	#0x90,a1		| offset of ROM reset routine
! 	addl	_C_LABEL(ROMBase),a1	| add to ROM base
! 	jra	a1@			| and jump to ROM to reset machine
  
  /*
   * u_long ptest040(caddr_t addr, u_int fc);
--- 1588,1642 ----
  
  /*
   * Handle the nitty-gritty of rebooting the machine.
!  * Basically we just turn off the MMU and jump to the appropriate ROM routine.
!  * Note that we must be running in an address range that is mapped one-to-one
!  * logical to physical so that the PC is still valid immediately after the MMU
!  * is turned off.  We have conveniently mapped the last page of physical
!  * memory this way.
   */
  ENTRY_NOPROFILE(doboot)
! #if defined(M68040)
  	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
! 	jeq	Lnocache5		| yes, skip
! #endif
  	movl	#CACHE_OFF,d0
  	movc	d0,cacr			| disable on-chip cache(s)
! Lnocache5:
! 	movl	_C_LABEL(maxaddr),a0	| last page of physical memory
! 	lea	Lbootcode,a1		| start of boot code
! 	lea	Lebootcode,a3		| end of boot code
! Lbootcopy:
! 	movw	a1@+,a0@+		| copy a word
! 	cmpl	a3,a1			| done yet?
! 	jcs	Lbootcopy		| no, keep going
! #if defined(M68040)
! 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
! 	jne	LmotommuE		| no, skip
! 	.word	0xf4f8			| cpusha bc
! LmotommuE:
! #endif
! 	movl	_C_LABEL(maxaddr),a0
! 	jmp	a0@			| jump to last page
! 
! Lbootcode:
! 	lea	a0@(0x800),sp		| physical SP in case of NMI
! #if defined(M68040)
! 	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
! 	jne	LmotommuF		| no, skip
! 	movl	#0,d0
! 	movc	d0,cacr			| caches off
! 	.long	0x4e7b0003		| movc d0,tc (disable MMU)
! 	jra	Ldoboot1
! LmotommuF:
  #endif
+ 	movl	#0,a3@			| value for pmove to TC (turn off MMU)
+ 	pmove	a3@,tc			| disable MMU
  
  Ldoboot1:
! 	movl	_C_LABEL(MacOSROMBase),a1 | Load MacOS ROMBase
! 	lea	a1@(0x90),a1		| offset of ROM reset routine
! 	jmp	a1@			| and jump to ROM to reset machine
! Lebootcode:
  
  /*
   * u_long ptest040(caddr_t addr, u_int fc);
Index: machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mac68k/mac68k/machdep.c,v
retrieving revision 1.195
diff -c -r1.195 machdep.c
*** machdep.c	1998/05/05 06:48:52	1.195
--- machdep.c	1998/05/08 09:19:31
***************
*** 706,712 ****
  	int howto;
  	char *bootstr;
  {
! 	extern u_long MacOSROMBase;
  	extern int cold;
  
  #if __GNUC__	/* XXX work around lame compiler problem (gcc 2.7.2) */
--- 706,712 ----
  	int howto;
  	char *bootstr;
  {
! 	extern u_long maxaddr;
  	extern int cold;
  
  #if __GNUC__	/* XXX work around lame compiler problem (gcc 2.7.2) */
***************
*** 767,778 ****
  		(void)cngetc();
  	}
  
! 	/*
! 	 * Map ROM where the MacOS likes it, so we can reboot,
! 	 * hopefully.
! 	 */
! 	pmap_map(MacOSROMBase, MacOSROMBase, MacOSROMBase + 4 * 1024 * 1024,
! 	    VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
  
  	printf("rebooting...\n");
  	DELAY(1000000);
--- 767,775 ----
  		(void)cngetc();
  	}
  
! 	/* Map the last physical page VA = PA for doboot() */
! 	pmap_enter(pmap_kernel(), (vm_offset_t)maxaddr, (vm_offset_t)maxaddr,
! 	    VM_PROT_ALL, TRUE);
  
  	printf("rebooting...\n");
  	DELAY(1000000);
***************
*** 1295,1300 ****
--- 1292,1302 ----
  	    (flag & 0x40000)) && bootdev == 0)
  		bootdev = MAKEBOOTDEV(4, 0, 0, root_scsi_id, 0);
  
+ 	/*
+ 	 * Booter 1.11.3 and later pass a BOOTHOWTO variable with the
+ 	 * appropriate bits set.
+ 	 */
+ 	boothowto = getenv("BOOTHOWTO");
  	if (boothowto == 0)
  		boothowto = getenv("SINGLE_USER");
  
Index: pmap_bootstrap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mac68k/mac68k/pmap_bootstrap.c,v
retrieving revision 1.42
diff -c -r1.42 pmap_bootstrap.c
*** pmap_bootstrap.c	1998/04/26 03:59:18	1.42
--- pmap_bootstrap.c	1998/05/08 09:19:33
***************
*** 64,70 ****
  extern st_entry_t *Sysseg;
  extern pt_entry_t *Sysptmap, *Sysmap;
  
! extern int maxmem, physmem;
  extern int avail_remaining, avail_range, avail_end;
  extern vm_offset_t avail_start, avail_next;
  extern vm_offset_t virtual_avail, virtual_end;
--- 64,70 ----
  extern st_entry_t *Sysseg;
  extern pt_entry_t *Sysptmap, *Sysmap;
  
! extern int physmem;
  extern int avail_remaining, avail_range, avail_end;
  extern vm_offset_t avail_start, avail_next;
  extern vm_offset_t virtual_avail, virtual_end;
***************
*** 76,84 ****
  /*
   * These are used to map the RAM:
   */
! int		numranges; /* = 0 == don't use the ranges */
  u_long	low[8];
  u_long	high[8];
  int	vidlen;
  #define VIDMAPSIZE	btoc(vidlen)
  extern u_int32_t	mac68k_vidlog;
--- 76,85 ----
  /*
   * These are used to map the RAM:
   */
! int	numranges;	/* = 0 == don't use the ranges */
  u_long	low[8];
  u_long	high[8];
+ u_long	maxaddr;	/* PA of the last physical page */
  int	vidlen;
  #define VIDMAPSIZE	btoc(vidlen)
  extern u_int32_t	mac68k_vidlog;
***************
*** 317,323 ****
  		*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).
  	 */
  	pte = PA2VA(lkptpa, u_int *);
--- 318,324 ----
  		*pte = lkptpa | PG_RW | PG_CI | PG_V;
  	}
  	/*
! 	 * Invalidate all entries in the last kernel PT page
  	 * (u-area PTEs will be validated later).
  	 */
  	pte = PA2VA(lkptpa, u_int *);
***************
*** 445,450 ****
--- 446,460 ----
  	/*
  	 * 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.
  	 */
  	avail_next = avail_start = m68k_round_page(nextpa);
  	avail_remaining = 0;
***************
*** 459,466 ****
  	}
  	physmem = m68k_btop(avail_remaining + nextpa - firstpa);
  
! 	avail_remaining -= m68k_round_page(MSGBUFSIZE);
! 	high[numranges - 1] -= m68k_round_page(MSGBUFSIZE);
  	avail_end = high[numranges - 1];
  	avail_remaining = m68k_btop(m68k_trunc_page(avail_remaining));
  
--- 469,477 ----
  	}
  	physmem = m68k_btop(avail_remaining + nextpa - firstpa);
  
! 	maxaddr = high[numranges - 1] - m68k_ptob(1);
! 	high[numranges - 1] -= (m68k_round_page(MSGBUFSIZE) + m68k_ptob(1));
! 	avail_remaining -= (m68k_round_page(MSGBUFSIZE) + m68k_ptob(1));
  	avail_end = high[numranges - 1];
  	avail_remaining = m68k_btop(m68k_trunc_page(avail_remaining));