Subject: Re: Current ARM kernels hang during bootstrap
To: None <Richard.Earnshaw@arm.com>
From: Ben Harris <bjh21@NetBSD.org>
List: port-arm
Date: 01/17/2004 17:45:49
On Sat, 17 Jan 2004, Ben Harris wrote:

> On Sat, 17 Jan 2004, Richard Earnshaw wrote:
>
> > Since you committed your exit-path patch on 2004/01/04 all my ARM systems
> > have started to hang during bootstrap.
> >
> > Investigation using a Multi-ICE box shows that the vectors page is getting
> > unmapped (on all my machines the vectors are at VA 0x0, which puts it
> > notionally in user memory, although it's really a kernel page).  Loosing
> > the interrupt and fault vectors is obviously somewhat fatal to the health
> > of the machine.
> >
> > Have you any idea what might be the cause of this change in behaviour?
>
> It looks like it's this part:
>
> # From within the exiting process context:
> # * deactivate pmap and free vmspace while we can still block
>
> exit1() -> uvm_proc_exit() -> uvmspace_free() -> pmap_destroy()
>
> pmap_destroy() unmaps the vector page, so any interupts that happen before
> a new pmap is activated will cause pain and death.  I think this is
> arguably a bug in the arm32 pmap, which should arrange to map the vector
> page by other means if the current pmap is destroyed.

Here's a crude patch that works in minimal testing (my Risc PC comes up
multi-user now).  It could probably be done better, but likely not by me.
Any comments/improvements before I commit it?

Index: pmap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/arm32/pmap.c,v
retrieving revision 1.146
diff -u -u -r1.146 pmap.c
--- pmap.c      1 Nov 2003 17:35:42 -0000       1.146
+++ pmap.c      17 Jan 2004 17:43:59 -0000
@@ -3047,7 +3047,7 @@

 	pmap_set_pcb_pagedir(pm, pcb);

-	if (l == curlwp) {
+	if (l == curlwp || l == &lwp0) {
 		u_int cur_dacr, cur_ttb;

 		__asm __volatile("mrc p15, 0, %0, c2, c0, 0" :
"=r"(cur_ttb));
@@ -3195,6 +3195,8 @@
 	*/

 	if (vector_page < KERNEL_BASE) {
+		if (pmap_is_current(pm))
+			pmap_activate(&lwp0);
 		/* Remove the vector page mapping */
 		pmap_remove(pm, vector_page, vector_page + PAGE_SIZE);
 		pmap_update(pm);

-- 
Ben Harris                                                   <bjh21@NetBSD.org>
Portmaster, NetBSD/acorn26           <URL:http://www.NetBSD.org/Ports/acorn26/>