From ilepore@damnhippie.dyndns.org  Tue Oct 11 14:52:32 2011
Return-Path: <ilepore@damnhippie.dyndns.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id D5D511065670
	for <freebsd-gnats-submit@freebsd.org>; Tue, 11 Oct 2011 14:52:32 +0000 (UTC)
	(envelope-from ilepore@damnhippie.dyndns.org)
Received: from qmta02.emeryville.ca.mail.comcast.net (qmta02.emeryville.ca.mail.comcast.net [76.96.30.24])
	by mx1.freebsd.org (Postfix) with ESMTP id BADC08FC1E
	for <freebsd-gnats-submit@freebsd.org>; Tue, 11 Oct 2011 14:52:32 +0000 (UTC)
Received: from omta17.emeryville.ca.mail.comcast.net ([76.96.30.73])
	by qmta02.emeryville.ca.mail.comcast.net with comcast
	id jR5V1h0091afHeLA2SfFfD; Tue, 11 Oct 2011 14:39:15 +0000
Received: from damnhippie.dyndns.org ([24.8.232.202])
	by omta17.emeryville.ca.mail.comcast.net with comcast
	id jSTQ1h00a4NgCEG8dSTQdt; Tue, 11 Oct 2011 14:27:24 +0000
Received: from revolution.hippie.lan (revolution.hippie.lan [172.22.42.240])
	by damnhippie.dyndns.org (8.14.3/8.14.3) with ESMTP id p9BEdK8L013182
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 11 Oct 2011 08:39:20 -0600 (MDT)
	(envelope-from ilepore@damnhippie.dyndns.org)
Received: (from ilepore@localhost)
	by revolution.hippie.lan (8.14.4/8.14.4/Submit) id p9BEdKIb052251;
	Tue, 11 Oct 2011 08:39:20 -0600 (MDT)
	(envelope-from ilepore)
Message-Id: <201110111439.p9BEdKIb052251@revolution.hippie.lan>
Date: Tue, 11 Oct 2011 08:39:20 -0600 (MDT)
From: Ian Lepore <freebsd@damnhippie.dyndns.org>
Reply-To: Ian Lepore <freebsd@damnhippie.dyndns.org>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [patch] ARM thread-data/RAS page is not properly initialized		
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         161492
>Category:       arm
>Synopsis:       [patch] ARM thread-data/RAS page is not properly initialized
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-arm
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Oct 11 15:00:16 UTC 2011
>Closed-Date:    Wed Nov 09 14:14:20 UTC 2011
>Last-Modified:  Sat Mar 16 01:32:13 UTC 2013
>Originator:     Ian Lepore <freebsd@damnhippie.dyndns.org>
>Release:        FreeBSD 8.2-RC3 arm
>Organization:
none
>Environment:
FreeBSD tflex 8.2-STABLE FreeBSD 8.2-STABLE #29: Tue Oct 11 13:32:35 UTC 2011     root@revolution.hippie.lan:/usr/obj/arm/usr/src/sys/TFLEX  arm

>Description:
The global page that holds ARM_TP_ADDRESS and the RAS start/end addresses is
allocated using the VM_ALLOC_ZERO flag, but that flag only indicates a 
preference for a pre-zeroed page if one is available, it doesn't guarantee
the returned page has been zeroed.

It appears that often (perhaps always?) there are no pre-zeroed pages 
available early in startup, and the page will contain random values.  Some
combinations of these random values may be misinterpreted by the RAS code
in PUSHFRAMEINSVC, causing it to use the garbage value from RAS_START when
returning from the first trap/interrupt, typically causing a panic due to
supervisor-mode access fault.

>How-To-Repeat:
Naturally a failure scenario based on inopportune values of random data is 
pretty rare and hard to repeat.

>Fix:
This patch zeroes the page if necessary after allocating it, and also
initializes ARM_RAS_END to 0xffffffff, since that's one of the preconditions
of the RAS scheme when no atomic sequence is running.

--- machdep.c.diff begins here ---
--- src/sys/arm/arm/machdep.c.orig	Tue Jun 21 12:50:26 2011 -0600
+++ src/sys/arm/arm/machdep.c	Tue Oct 11 08:10:43 2011 -0600
@@ -308,10 +308,14 @@ cpu_startup(void *dummy)
 #ifdef ARM_CACHE_LOCK_ENABLE
 	pmap_kenter_user(ARM_TP_ADDRESS, ARM_TP_ADDRESS);
 	arm_lock_cache_line(ARM_TP_ADDRESS);
+	bzero((void*)ARM_TP_ADDRESS, PAGE_SIZE);
 #else
 	m = vm_page_alloc(NULL, 0, VM_ALLOC_NOOBJ | VM_ALLOC_ZERO);
 	pmap_kenter_user(ARM_TP_ADDRESS, VM_PAGE_TO_PHYS(m));
+	if ((m->flags & PG_ZERO) == 0)
+		bzero((void*)ARM_TP_ADDRESS, PAGE_SIZE);
 #endif
+	*(uint32_t *)ARM_RAS_END = 0xffffffff;
 }
 
 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
--- machdep.c.diff ends here ---

>Release-Note:
>Audit-Trail:

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: arm/161492: commit references a PR
Date: Sun, 16 Oct 2011 17:38:08 +0000 (UTC)

 Author: cognet
 Date: Sun Oct 16 17:37:54 2011
 New Revision: 226441
 URL: http://svn.freebsd.org/changeset/base/226441
 
 Log:
   Explicitely set ARM_RAS_START and ARM_RAS_END once the cacheline or the
   page has been allocated, or we could end up using random values, and bad things
   could happen.
   
   PR:		arm/161492
   Submitted by:	Ian Lepore <freebsd AT damnhippie dot dyndns DOT org>
   MFC after:	1 week
 
 Modified:
   head/sys/arm/arm/machdep.c
 
 Modified: head/sys/arm/arm/machdep.c
 ==============================================================================
 --- head/sys/arm/arm/machdep.c	Sun Oct 16 16:58:28 2011	(r226440)
 +++ head/sys/arm/arm/machdep.c	Sun Oct 16 17:37:54 2011	(r226441)
 @@ -312,6 +312,8 @@ cpu_startup(void *dummy)
  	m = vm_page_alloc(NULL, 0, VM_ALLOC_NOOBJ | VM_ALLOC_ZERO);
  	pmap_kenter_user(ARM_TP_ADDRESS, VM_PAGE_TO_PHYS(m));
  #endif
 +	*(uint32_t *)ARM_RAS_START = 0;
 +	*(uint32_t *)ARM_RAS_END = 0xffffffff;
  }
  
  SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->closed 
State-Changed-By: cognet 
State-Changed-When: Wed Nov 9 14:14:19 UTC 2011 
State-Changed-Why:  
Committed, with minor changes. Thanks! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=161492 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: arm/161492: commit references a PR
Date: Tue,  7 Feb 2012 15:50:49 +0000 (UTC)

 Author: cognet
 Date: Tue Feb  7 15:50:14 2012
 New Revision: 231131
 URL: http://svn.freebsd.org/changeset/base/231131
 
 Log:
   MFC r226441 and r226443
   r226441:
   Explicitely set ARM_RAS_START and ARM_RAS_END once the cacheline or the
   page has been allocated, or we could end up using random values, and bad things
    could happen.
   
    PR:		arm/161492
    Submitted by:	Ian Lepore <freebsd AT damnhippie dot dyndns DOT org>
   
   r226443:
   Fix 2 bugs :
   
   - A race condition could happen if two threads were using RAS at the same time
     as the code didn't reset RAS_END, the RAS code could believe we were not in
     a RAS, when we were in fact.
   - Using signed value logic to compare addresses wasn't such a good idea.
     Many thanks to Ian to investigate on these issues.
   
     Pointy hat to: 	cognet
     PR:		arm/161498
     Submitted by:	Ian Lepore <freebsd At damnhippie DOT dyndns dot org
 
 Modified:
   stable/8/sys/arm/arm/machdep.c
   stable/8/sys/arm/include/asmacros.h
   stable/8/sys/arm/include/sysarch.h
 
 Modified: stable/8/sys/arm/arm/machdep.c
 ==============================================================================
 --- stable/8/sys/arm/arm/machdep.c	Tue Feb  7 14:50:33 2012	(r231130)
 +++ stable/8/sys/arm/arm/machdep.c	Tue Feb  7 15:50:14 2012	(r231131)
 @@ -312,6 +312,8 @@ cpu_startup(void *dummy)
  	m = vm_page_alloc(NULL, 0, VM_ALLOC_NOOBJ | VM_ALLOC_ZERO);
  	pmap_kenter_user(ARM_TP_ADDRESS, VM_PAGE_TO_PHYS(m));
  #endif
 +	*(uint32_t *)ARM_RAS_START = 0;
 +	*(uint32_t *)ARM_RAS_END = 0xffffffff;
  }
  
  SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
 
 Modified: stable/8/sys/arm/include/asmacros.h
 ==============================================================================
 --- stable/8/sys/arm/include/asmacros.h	Tue Feb  7 14:50:33 2012	(r231130)
 +++ stable/8/sys/arm/include/asmacros.h	Tue Feb  7 15:50:14 2012	(r231131)
 @@ -71,9 +71,8 @@
  	ldr	r0, =ARM_RAS_START;					   \
  	mov	r1, #0;							   \
  	str	r1, [r0];						   \
 -	ldr	r0, =ARM_RAS_END;					   \
  	mov	r1, #0xffffffff;					   \
 -	str	r1, [r0];
 +	str	r1, [r0, #4];
  
  /*
   * PULLFRAME - macro to pull a trap frame from the stack in the current mode
 @@ -120,20 +119,19 @@
  	stmia	r0, {r13-r14}^;		/* Push the user mode registers */ \
          mov     r0, r0;                 /* NOP for previous instruction */ \
  	ldr	r5, =ARM_RAS_START;	/* Check if there's any RAS */	   \
 -	ldr	r3, [r5];						   \
 -	cmp	r3, #0;			/* Is the update needed ? */	   \
 -	ldrgt	lr, [r0, #16];						   \
 -	ldrgt	r1, =ARM_RAS_END;					   \
 -	ldrgt	r4, [r1];		/* Get the end of the RAS */	   \
 -	movgt	r2, #0;			/* Reset the magic addresses */	   \
 -	strgt	r2, [r5];						   \
 -	movgt	r2, #0xffffffff;					   \
 -	strgt	r2, [r1];						   \
 -	cmpgt	lr, r3;			/* Were we in the RAS ? */	   \
 -	cmpgt	r4, lr;							   \
 -	strgt	r3, [r0, #16];		/* Yes, update the pc */	   \
 -	mrs	r0, spsr_all;		/* Put the SPSR on the stack */	   \
 -	str	r0, [sp, #-4]!
 +	ldr     r4, [r5, #4];           /* reset it to point at the     */ \
 +	cmp     r4, #0xffffffff;        /* end of memory if necessary;  */ \
 +	movne   r1, #0xffffffff;        /* leave value in r4 for later  */ \
 +	strne   r1, [r5, #4];           /* comparision against PC.      */ \
 +	ldr     r3, [r5];               /* Retrieve global RAS_START    */ \
 +	cmp     r3, #0;                 /* and reset it if non-zero.    */ \
 +	movne   r1, #0;                 /* If non-zero RAS_START and    */ \
 +	strne   r1, [r5];               /* PC was lower than RAS_END,   */ \
 +	ldrne   r1, [r0, #16];          /* adjust the saved PC so that  */ \
 +	cmpne   r4, r1;                 /* execution later resumes at   */ \
 +	strhi   r3, [r0, #16];          /* the RAS_START location.      */ \
 +	mrs     r0, spsr_all;                                              \
 +	str     r0, [sp, #-4]!
  
  /*
   * PULLFRAMEFROMSVCANDEXIT - macro to pull a trap frame from the stack
 
 Modified: stable/8/sys/arm/include/sysarch.h
 ==============================================================================
 --- stable/8/sys/arm/include/sysarch.h	Tue Feb  7 14:50:33 2012	(r231130)
 +++ stable/8/sys/arm/include/sysarch.h	Tue Feb  7 15:50:14 2012	(r231131)
 @@ -42,9 +42,13 @@
   * The ARM_TP_ADDRESS points to a special purpose page, which is used as local
   * store for the ARM per-thread data and Restartable Atomic Sequences support.
   * Put it just above the "high" vectors' page.
 - * the cpu_switch() code assumes ARM_RAS_START is ARM_TP_ADDRESS + 4, and
 + * The cpu_switch() code assumes ARM_RAS_START is ARM_TP_ADDRESS + 4, and
   * ARM_RAS_END is ARM_TP_ADDRESS + 8, so if that ever changes, be sure to
   * update the cpu_switch() (and cpu_throw()) code as well.
 + * In addition, code in arm/include/atomic.h and arm/include/asmacros.h
 + * assumes that ARM_RAS_END is at ARM_RAS_START+4, so be sure to update those
 + * if ARM_RAS_END moves in relation to ARM_RAS_START (look for occurrances
 + * of ldr/str rm,[rn, #4]).
   */
  #define ARM_TP_ADDRESS		(ARM_VECTORS_HIGH + 0x1000)
  #define ARM_RAS_START		(ARM_TP_ADDRESS + 4)
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: arm/161492: commit references a PR
Date: Tue,  7 Feb 2012 16:07:38 +0000 (UTC)

 Author: cognet
 Date: Tue Feb  7 16:07:29 2012
 New Revision: 231132
 URL: http://svn.freebsd.org/changeset/base/231132
 
 Log:
   MFC r226441 and r226443
   r226441:
   Explicitely set ARM_RAS_START and ARM_RAS_END once the cacheline or the
   page has been allocated, or we could end up using random values, and bad things
   could happen.
   
    PR:		arm/161492
    Submitted by:	Ian Lepore <freebsd AT damnhippie dot dyndns DOT org>
   
   r226443:
   Fix 2 bugs :
   
   - A race condition could happen if two threads were using RAS at the same time
     as the code didn't reset RAS_END, the RAS code could believe we were not in
      a RAS, when we were in fact.
   - Using signed value logic to compare addresses wasn't such a good idea.
   
   Many thanks to Ian to investigate on these issues.
   
     Pointy hat to: 	cognet
     PR:		arm/161498
     Submitted by:	Ian Lepore <freebsd At damnhippie DOT dyndns dot org
 
 Modified:
   stable/9/sys/arm/arm/machdep.c
   stable/9/sys/arm/include/asmacros.h
   stable/9/sys/arm/include/sysarch.h
 
 Modified: stable/9/sys/arm/arm/machdep.c
 ==============================================================================
 --- stable/9/sys/arm/arm/machdep.c	Tue Feb  7 15:50:14 2012	(r231131)
 +++ stable/9/sys/arm/arm/machdep.c	Tue Feb  7 16:07:29 2012	(r231132)
 @@ -312,6 +312,8 @@ cpu_startup(void *dummy)
  	m = vm_page_alloc(NULL, 0, VM_ALLOC_NOOBJ | VM_ALLOC_ZERO);
  	pmap_kenter_user(ARM_TP_ADDRESS, VM_PAGE_TO_PHYS(m));
  #endif
 +	*(uint32_t *)ARM_RAS_START = 0;
 +	*(uint32_t *)ARM_RAS_END = 0xffffffff;
  }
  
  SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
 
 Modified: stable/9/sys/arm/include/asmacros.h
 ==============================================================================
 --- stable/9/sys/arm/include/asmacros.h	Tue Feb  7 15:50:14 2012	(r231131)
 +++ stable/9/sys/arm/include/asmacros.h	Tue Feb  7 16:07:29 2012	(r231132)
 @@ -71,9 +71,8 @@
  	ldr	r0, =ARM_RAS_START;					   \
  	mov	r1, #0;							   \
  	str	r1, [r0];						   \
 -	ldr	r0, =ARM_RAS_END;					   \
  	mov	r1, #0xffffffff;					   \
 -	str	r1, [r0];
 +	str	r1, [r0, #4];
  
  /*
   * PULLFRAME - macro to pull a trap frame from the stack in the current mode
 @@ -120,20 +119,19 @@
  	stmia	r0, {r13-r14}^;		/* Push the user mode registers */ \
          mov     r0, r0;                 /* NOP for previous instruction */ \
  	ldr	r5, =ARM_RAS_START;	/* Check if there's any RAS */	   \
 -	ldr	r3, [r5];						   \
 -	cmp	r3, #0;			/* Is the update needed ? */	   \
 -	ldrgt	lr, [r0, #16];						   \
 -	ldrgt	r1, =ARM_RAS_END;					   \
 -	ldrgt	r4, [r1];		/* Get the end of the RAS */	   \
 -	movgt	r2, #0;			/* Reset the magic addresses */	   \
 -	strgt	r2, [r5];						   \
 -	movgt	r2, #0xffffffff;					   \
 -	strgt	r2, [r1];						   \
 -	cmpgt	lr, r3;			/* Were we in the RAS ? */	   \
 -	cmpgt	r4, lr;							   \
 -	strgt	r3, [r0, #16];		/* Yes, update the pc */	   \
 -	mrs	r0, spsr_all;		/* Put the SPSR on the stack */	   \
 -	str	r0, [sp, #-4]!
 +	ldr     r4, [r5, #4];           /* reset it to point at the     */ \
 +	cmp     r4, #0xffffffff;        /* end of memory if necessary;  */ \
 +	movne   r1, #0xffffffff;        /* leave value in r4 for later  */ \
 +	strne   r1, [r5, #4];           /* comparision against PC.      */ \
 +	ldr     r3, [r5];               /* Retrieve global RAS_START    */ \
 +	cmp     r3, #0;                 /* and reset it if non-zero.    */ \
 +	movne   r1, #0;                 /* If non-zero RAS_START and    */ \
 +	strne   r1, [r5];               /* PC was lower than RAS_END,   */ \
 +	ldrne   r1, [r0, #16];          /* adjust the saved PC so that  */ \
 +	cmpne   r4, r1;                 /* execution later resumes at   */ \
 +	strhi   r3, [r0, #16];          /* the RAS_START location.      */ \
 +	mrs     r0, spsr_all;                                              \
 +	str     r0, [sp, #-4]!
  
  /*
   * PULLFRAMEFROMSVCANDEXIT - macro to pull a trap frame from the stack
 
 Modified: stable/9/sys/arm/include/sysarch.h
 ==============================================================================
 --- stable/9/sys/arm/include/sysarch.h	Tue Feb  7 15:50:14 2012	(r231131)
 +++ stable/9/sys/arm/include/sysarch.h	Tue Feb  7 16:07:29 2012	(r231132)
 @@ -42,9 +42,13 @@
   * The ARM_TP_ADDRESS points to a special purpose page, which is used as local
   * store for the ARM per-thread data and Restartable Atomic Sequences support.
   * Put it just above the "high" vectors' page.
 - * the cpu_switch() code assumes ARM_RAS_START is ARM_TP_ADDRESS + 4, and
 + * The cpu_switch() code assumes ARM_RAS_START is ARM_TP_ADDRESS + 4, and
   * ARM_RAS_END is ARM_TP_ADDRESS + 8, so if that ever changes, be sure to
   * update the cpu_switch() (and cpu_throw()) code as well.
 + * In addition, code in arm/include/atomic.h and arm/include/asmacros.h
 + * assumes that ARM_RAS_END is at ARM_RAS_START+4, so be sure to update those
 + * if ARM_RAS_END moves in relation to ARM_RAS_START (look for occurrances
 + * of ldr/str rm,[rn, #4]).
   */
  #define ARM_TP_ADDRESS		(ARM_VECTORS_HIGH + 0x1000)
  #define ARM_RAS_START		(ARM_TP_ADDRESS + 4)
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
