Subject: Problems flushing cache with KUSEG addresses
To: None <port-mips@netbsd.org>
From: Wayne Knowles <w.knowles@niwa.cri.nz>
List: port-mips
Date: 07/27/2000 16:41:45
It looks like there is a mips only stability problem in -current with the
way the caches are being flushed in the setregs() function.   This causes
random machine lockups when my machine starts running thru the /etc/rc
startup scripts.

The problem is that a kuseg virtual address is being passed to
MachFlushICache in the setregs() function.   Under stressful conditions
the cache flushing routines can produce a TLB miss exception which has to
be handled by the high level TLB Exception functions.  Since the processor
is isolated from main memory at that stage weird things start to happen.

All memory addresses passed to MachFlush{I,D}Cache should be kseg0 or
kseg1 addresses to ensure no TLB miss exceptions are generated during the
cache invalidation.

The normal method of using MIPS_PHYS_TO_KSEG0(kvtophys(addr)) doesn't seem
to apply here either, since the address comes from the user address space.
In my tests the virtual address works out at 0x7fffefe0

What I have done is force a dummy read of the address which will cause the
TLB entry to be loaded if it isn't available:

Index: mips_machdep.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/mips/mips/mips_machdep.c,v
retrieving revision 1.95
diff -u -C7 -r1.95 mips_machdep.c
*** mips_machdep.c	2000/07/20 18:33:42	1.95
--- mips_machdep.c	2000/07/27 04:33:44
***************
*** 664,677 ****
--- 664,678 ----
  {
  	int szsigcode = pack->ep_emul->e_esigcode - pack->ep_emul->e_sigcode;
  	struct frame *f = (struct frame *)p->p_md.md_regs;
  
  	/*
  	 * Make sure sigreturn trampoline is coherent.
  	 */
+ 	*(volatile int *)p->p_sigacts->ps_sigcode; /* preload TLB entry */
  #ifdef MIPS3
  	if (CPUISMIPS3)
  		MachFlushDCache((vaddr_t)p->p_sigacts->ps_sigcode, szsigcode);
  #endif
  	MachFlushICache((vaddr_t)p->p_sigacts->ps_sigcode, szsigcode);
  
  	memset(f, 0, sizeof(struct frame));

With this patch the mipsco port I'm in the process of merging with
NetBSD-current no longer freezes at random, and can complete a kernel
build successfully.

More than likely there is a better fix than the one I have suggested.  My
only concern might be an interrupt that causes all TLB entries to be
replaced between the preload operation and the calls to
MachFlush{D,I}Cache - in which case a splhigh() wrapper needs to be placed
around the code.

Wayne
--
  _____	   	Wayne Knowles,  Systems Manager
 / o   \/   	National Institute of Water & Atmospheric Research Ltd
 \/  v /\   	P.O. Box 14-901 Kilbirnie, Wellington, NEW ZEALAND
  `---'     	Email:   w.knowles@niwa.cri.nz