Subject: SunOS emul fix for 040s
To: None <port-m68k@NetBSD.ORG>
From: Niklas Hallqvist <niklas@cvs.openbsd.org>
List: port-m68k
Date: 11/28/1995 14:19:52
As Sun didn't know about the 040's split I/D cache when writing their ld.so
some cache purging is missing there for correct functionality of SunOS
emulation in NetBSD.  In order to fix this, we can either make our ld.so handle
SunOS dynamic binaries, or make writeable executable pages uncached for
SunOS processes.  This patch does the latter for the amiga.  Other ports
can do similarily...

Niklas

Index: arch/amiga/amiga/pmap.c
===================================================================
RCS file: /cvs/src/sys/arch/amiga/amiga/pmap.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -c -b -r1.2 -r1.3
*** pmap.c	1995/11/13 03:53:32	1.2
--- pmap.c	1995/11/28 20:47:34	1.3
***************
*** 1390,1398 ****
  	 * AMIGA pages in a MACH page.
  	 */
  #ifdef M68040
! 	if (mmutype == MMU_68040 && pmap == pmap_kernel() && va >= AMIGA_UPTBASE && 
! 	    va < (AMIGA_UPTBASE + AMIGA_UPTMAXSIZE))
  		cacheable = FALSE;	/* don't cache user page tables */
  #endif
  	npte = (pa & PG_FRAME) | pte_prot(pmap, prot) | PG_V;
  	npte |= (*(int *)pte & (PG_M|PG_U));
--- 1390,1404 ----
  	 * AMIGA pages in a MACH page.
  	 */
  #ifdef M68040
! 	if (mmutype == MMU_68040 && pmap == pmap_kernel() &&
! 	    va >= AMIGA_UPTBASE && va < (AMIGA_UPTBASE + AMIGA_UPTMAXSIZE))
  		cacheable = FALSE;	/* don't cache user page tables */
+ 
+ 	/* Don't cache if process can't take it, like SunOS ones.  */
+ 	if (mmutype == MMU_68040 && pmap != pmap_kernel() &&
+ 	    (curproc->p_md.md_flags & MDP_UNCACHE_WX) &&
+ 	    (prot & VM_PROT_EXECUTE) && (prot & VM_PROT_WRITE))
+ 		checkpv = cacheable = FALSE;
  #endif
  	npte = (pa & PG_FRAME) | pte_prot(pmap, prot) | PG_V;
  	npte |= (*(int *)pte & (PG_M|PG_U));
Index: arch/amiga/include/proc.h
===================================================================
RCS file: /cvs/src/sys/arch/amiga/include/proc.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -b -r1.1.1.1 -r1.2
*** proc.h	1995/10/18 08:50:04	1.1.1.1
--- proc.h	1995/11/28 20:48:49	1.2
***************
*** 50,53 ****
--- 50,55 ----
  #define MDP_STACKADJ	0x0002	/* frame SP adjusted, might have to
  				   undo when system call returns
  				   ERESTART. */
+ #define MDP_UNCACHE_WX	0x0004	/* The process might modify code, so
+ 				   don't cache writeable executable pages.  */
  #endif /* !_MACHINE_PROC_H_ */
Index: arch/m68k/m68k/sunos_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/m68k/m68k/sunos_machdep.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -b -r1.1.1.1 -r1.2
*** sunos_machdep.c	1995/10/18 08:51:01	1.1.1.1
--- sunos_machdep.c	1995/11/28 20:44:54	1.2
***************
*** 86,91 ****
--- 86,107 ----
  	struct sunos_sigcontext sf_sc;	/* I don't know if that's what 
  					   comes here */
  };
+ 
+ /*
+  * SunOS' ld.so does self-modifying code without knowing about the 040's
+  * cache purging needs.  So we need to uncache writeable executable pages.
+  */
+ void
+ sunos_setregs(p, pack, stack, retval)
+ 	register struct proc *p;
+ 	struct exec_package *pack;
+ 	u_long stack;
+ 	register_t *retval;
+ {
+ 	setregs(p, pack, stack, retval);
+ 	p->p_md.md_flags |= MDP_UNCACHE_WX;
+ }
+ 
  /*
   * much simpler sendsig() for SunOS processes, as SunOS does the whole
   * context-saving in usermode. For now, no hardware information (ie.
Index: compat/sunos/sunos_exec.c
===================================================================
RCS file: /cvs/src/sys/compat/sunos/sunos_exec.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -c -b -r1.1.1.1 -r1.2
*** sunos_exec.c	1995/10/18 08:52:21	1.1.1.1
--- sunos_exec.c	1995/11/28 20:43:08	1.2
***************
*** 68,73 ****
--- 68,77 ----
  extern char *sunos_syscallnames[];
  #endif
  extern void sunos_sendsig __P((sig_t, int, int, u_long));
+ #ifdef m68k
+ extern void sunos_setregs __P((struct proc *, struct exec_package *, u_long,
+ 			       register_t *));
+ #endif
  extern char sigcode[], esigcode[];
  const char sunos_emul_path[] = "/emul/sunos";
  
***************
*** 89,95 ****
--- 93,103 ----
  #endif
  	0,
  	copyargs,
+ #ifdef m68k
+ 	sunos_setregs,
+ #else
  	setregs,
+ #endif
  	sigcode,
  	esigcode,
  };