Index: cpukit/score/cpu/nios2/ChangeLog
===================================================================
--- cpukit/score/cpu/nios2/ChangeLog	(revision 3ce764a9ebd17dcd14d67eb017227421bde14aa4)
+++ cpukit/score/cpu/nios2/ChangeLog	(revision 9f1412b9dc37a3919f21794f29b0199dc9ec4ea4)
@@ -1,2 +1,10 @@
+2011-09-16	Sebastian Huber <sebastian.huber@embedded-brains.de>
+
+	* nios2-eic-il-low-level.S, nios2-eic-rsie-low-level.S: New files.
+	* Makefile.am: Reflect changes above.
+	* rtems/score/cpu.h, rtems/score/nios2-utility.h,
+	nios2-thread-dispatch-disabled.c, nios2-context-switch.S: Added
+	support for thread stack protection via the MPU.
+
 2011-09-14	Sebastian Huber <sebastian.huber@embedded-brains.de>
 
Index: cpukit/score/cpu/nios2/Makefile.am
===================================================================
--- cpukit/score/cpu/nios2/Makefile.am	(revision 3ce764a9ebd17dcd14d67eb017227421bde14aa4)
+++ cpukit/score/cpu/nios2/Makefile.am	(revision 9f1412b9dc37a3919f21794f29b0199dc9ec4ea4)
@@ -27,4 +27,6 @@
 libscorecpu_a_SOURCES += nios2-context-initialize.c
 libscorecpu_a_SOURCES += nios2-context-switch.S
+libscorecpu_a_SOURCES += nios2-eic-il-low-level.S
+libscorecpu_a_SOURCES += nios2-eic-rsie-low-level.S
 libscorecpu_a_SOURCES += nios2-fatal-halt.c
 libscorecpu_a_SOURCES += nios2-iic-low-level.S
Index: cpukit/score/cpu/nios2/nios2-context-switch.S
===================================================================
--- cpukit/score/cpu/nios2/nios2-context-switch.S	(revision 3ce764a9ebd17dcd14d67eb017227421bde14aa4)
+++ cpukit/score/cpu/nios2/nios2-context-switch.S	(revision 9f1412b9dc37a3919f21794f29b0199dc9ec4ea4)
@@ -44,9 +44,9 @@
 	stw	sp, NIOS2_CONTEXT_OFFSET_SP(r4)
 	stw	ra, NIOS2_CONTEXT_OFFSET_RA(r4)
-	stw	r9, NIOS2_CONTEXT_OFFSET_TDD(r4)
+	stw	r9, NIOS2_CONTEXT_OFFSET_THREAD_DISPATCH_DISABLED(r4)
 
 restore:
 
-	ldw	r10, NIOS2_CONTEXT_OFFSET_TDD(r5)
+	ldw	r10, NIOS2_CONTEXT_OFFSET_THREAD_DISPATCH_DISABLED(r5)
 	ldw	r16, NIOS2_CONTEXT_OFFSET_R16(r5)
 	ldw	r17, NIOS2_CONTEXT_OFFSET_R17(r5)
Index: cpukit/score/cpu/nios2/nios2-eic-il-low-level.S
===================================================================
--- cpukit/score/cpu/nios2/nios2-eic-il-low-level.S	(revision 9f1412b9dc37a3919f21794f29b0199dc9ec4ea4)
+++ cpukit/score/cpu/nios2/nios2-eic-il-low-level.S	(revision 9f1412b9dc37a3919f21794f29b0199dc9ec4ea4)
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2011 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/score/percpu.h>
+#include <rtems/score/nios2-utility.h>
+
+#define FRAME_OFFSET_RA 0
+#define FRAME_OFFSET_AT 4
+#define FRAME_OFFSET_R2 8
+#define FRAME_OFFSET_R3 12
+#define FRAME_OFFSET_R4 16
+#define FRAME_OFFSET_R5 20
+#define FRAME_OFFSET_R6 24
+#define FRAME_OFFSET_R7 28
+#define FRAME_OFFSET_R8 32
+#define FRAME_OFFSET_R9 36
+#define FRAME_OFFSET_R10 40
+#define FRAME_OFFSET_R11 44
+#define FRAME_OFFSET_R12 48
+#define FRAME_OFFSET_R13 52
+#define FRAME_OFFSET_R14 56
+#define FRAME_OFFSET_R15 60
+#define FRAME_OFFSET_STATUS 64
+#define FRAME_OFFSET_EA  68
+
+#define FRAME_SIZE (FRAME_OFFSET_EA + 4)
+
+	.set	noat
+	.section	.text
+
+	.extern	_Per_CPU_Information
+	.extern	_Thread_Dispatch_disable_level
+	.extern	_Nios2_Thread_dispatch_disabled
+	.extern	_Nios2_ISR_Status_interrupts_disabled
+
+	.globl	_Nios2_ISR_Dispatch_with_shadow_non_preemptive
+
+_Nios2_ISR_Dispatch_with_shadow_non_preemptive:
+
+	/* Load thread dispatch disable level */
+	ldw	r16, %gprel(_Thread_Dispatch_disable_level)(gp)
+
+	/* Load high level handler address and argument */
+	ldw	r8, 4(et)
+	ldw	r4, 8(et)
+
+	/* Increment and store thread dispatch disable level */
+	addi	r9, r16, 1
+	stw	r9, %gprel(_Thread_Dispatch_disable_level)(gp)
+
+	/* Call high level handler with argument */
+	callr	r8
+
+	/* Load thread dispatch necessary */
+	ldb	r12, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
+
+	/* Load Nios II specific thread dispatch disabled */
+	ldw	r13, %gprel(_Nios2_Thread_dispatch_disabled)(gp)
+
+	/* Fix return address */
+	subi	ea, ea, 4
+
+	/*
+	 * Restore the thread dispatch disable level.  We must do this before
+	 * we return to the normal register set, because otherwise we have
+	 * problems if someone deletes or restarts the interrupted thread while
+	 * we are in the thread dispatch helper.
+	 */
+	stw	r16, %gprel(_Thread_Dispatch_disable_level)(gp)
+
+	/* Is thread dispatch allowed? */
+	bne	r16, zero, no_thread_dispatch
+
+	/* Is thread dispatch necessary? */
+	beq	r12, zero, no_thread_dispatch
+
+	/* Is outermost interrupt? */
+	andhi	r14, sstatus, 0x3f
+	bne	r14, zero, no_thread_dispatch
+
+	/* Is Nios II specific thread dispatch allowed? */
+	bne	r13, zero, no_thread_dispatch
+
+	/* Obtain stack frame in normal register set */
+	rdprs	r15, sp, -FRAME_SIZE
+
+	/* Disable Nios II specific thread dispatch */
+	stw	r12, %gprel(_Nios2_Thread_dispatch_disabled)(gp)
+
+	/* Save context */
+	stw	sstatus, FRAME_OFFSET_STATUS(r15)
+	stw	ea, FRAME_OFFSET_EA(r15)
+
+	/* Set thread dispatch helper address */
+	movhi	ea, %hiadj(thread_dispatch_helper)
+	addi	ea, ea, %lo(thread_dispatch_helper)
+
+	/* Update stack pointer in normal register set */
+	wrprs	sp, r15
+
+no_thread_dispatch:
+
+	/*
+	 * Return to thread dispatch helper, interrupted thread or interrupted
+	 * lower level interrupt service routine.
+	 */
+	eret
+
+thread_dispatch_helper:
+
+	/* This code executes in the context of the interrupted thread */
+
+	/* Save volatile registers */
+	stw	ra, FRAME_OFFSET_RA(sp)
+	stw	at, FRAME_OFFSET_AT(sp)
+	stw	r2, FRAME_OFFSET_R2(sp)
+	stw	r3, FRAME_OFFSET_R3(sp)
+	stw	r4, FRAME_OFFSET_R4(sp)
+	stw	r5, FRAME_OFFSET_R5(sp)
+	stw	r6, FRAME_OFFSET_R6(sp)
+	stw	r7, FRAME_OFFSET_R7(sp)
+	stw	r8, FRAME_OFFSET_R8(sp)
+	stw	r9, FRAME_OFFSET_R9(sp)
+	stw	r10, FRAME_OFFSET_R10(sp)
+	stw	r11, FRAME_OFFSET_R11(sp)
+	stw	r12, FRAME_OFFSET_R12(sp)
+	stw	r13, FRAME_OFFSET_R13(sp)
+	stw	r14, FRAME_OFFSET_R14(sp)
+	stw	r15, FRAME_OFFSET_R15(sp)
+
+do_thread_dispatch:
+
+	call	_Thread_Dispatch
+
+	/* Restore some volatile registers */
+	ldw	ra, FRAME_OFFSET_RA(sp)
+	ldw	at, FRAME_OFFSET_AT(sp)
+	ldw	r2, FRAME_OFFSET_R2(sp)
+	ldw	r3, FRAME_OFFSET_R3(sp)
+	ldw	r4, FRAME_OFFSET_R4(sp)
+	ldw	r5, FRAME_OFFSET_R5(sp)
+	ldw	r6, FRAME_OFFSET_R6(sp)
+	ldw	r7, FRAME_OFFSET_R7(sp)
+	ldw	r8, FRAME_OFFSET_R8(sp)
+	ldw	r9, FRAME_OFFSET_R9(sp)
+	ldw	r10, FRAME_OFFSET_R10(sp)
+	ldw	r11, FRAME_OFFSET_R11(sp)
+	ldw	r12, FRAME_OFFSET_R12(sp)
+	ldw	r13, FRAME_OFFSET_R13(sp)
+
+	/*
+	 * Disable interrupts.
+	 *
+	 * We have the following invariants:
+	 *   1. status.RSIE == 0: thread context initialization
+	 *   2. status.CRS == 0: thread context initialization
+	 *   3. status.PRS: arbitrary
+	 *   4. status.IL < interrupt disable IL: else we would not be here
+	 *   5. status.IH == 0: thread context initialization
+	 *   6. status.U == 0: thread context initialization
+	 *   7. status.PIE == 1: thread context initialization
+	 * Thus we can use a constant to disable interrupts.
+	 */
+	rdctl	r14, status
+	movi	r15, %lo(_Nios2_ISR_Status_interrupts_disabled)
+	wrctl	status, r15
+
+	/* Load thread dispatch necessary */
+	ldb	r12, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
+
+	/* Is thread dispatch necessary? */
+	bne	r12, zero, enable_interrupts_before_thread_dispatch
+
+	/* Enable Nios II specific thread dispatch */
+	stw	zero, %gprel(_Nios2_Thread_dispatch_disabled)(gp)
+
+	/* Restore remaining volatile register */
+	ldw	r14, FRAME_OFFSET_R14(sp)
+	ldw	r15, FRAME_OFFSET_R15(sp)
+
+	/* Restore context */
+	ldw	et, FRAME_OFFSET_STATUS(sp)
+	ldw	ea, FRAME_OFFSET_EA(sp)
+
+	/* Release stack frame */
+	addi	sp, sp, FRAME_SIZE
+
+	/* Restore context */
+	wrctl	estatus, et
+
+	/* Return to interrupted thread */
+	eret
+
+enable_interrupts_before_thread_dispatch:
+
+	/* Restore status */
+	wrctl	status, r14
+
+	br	do_thread_dispatch
Index: cpukit/score/cpu/nios2/nios2-eic-rsie-low-level.S
===================================================================
--- cpukit/score/cpu/nios2/nios2-eic-rsie-low-level.S	(revision 9f1412b9dc37a3919f21794f29b0199dc9ec4ea4)
+++ cpukit/score/cpu/nios2/nios2-eic-rsie-low-level.S	(revision 9f1412b9dc37a3919f21794f29b0199dc9ec4ea4)
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2011 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/score/percpu.h>
+
+#define FRAME_OFFSET_AT 0
+#define FRAME_OFFSET_R2 4
+#define FRAME_OFFSET_R3 8
+#define FRAME_OFFSET_R4 12
+#define FRAME_OFFSET_R5 16
+#define FRAME_OFFSET_R6 20
+#define FRAME_OFFSET_R7 24
+#define FRAME_OFFSET_R8 28
+#define FRAME_OFFSET_R9 32
+#define FRAME_OFFSET_R10 36
+#define FRAME_OFFSET_R11 40
+#define FRAME_OFFSET_R12 44
+#define FRAME_OFFSET_R13 48
+#define FRAME_OFFSET_R14 52
+#define FRAME_OFFSET_R15 56
+#define FRAME_OFFSET_RA  60
+#define FRAME_OFFSET_EA  64
+#define FRAME_OFFSET_ESTATUS 68
+#define FRAME_OFFSET_R16 72
+
+#define FRAME_SIZE (FRAME_OFFSET_R16 + 4)
+
+	.set	noat
+	.section	.text
+
+	.extern	_Per_CPU_Information
+	.extern	_Thread_Dispatch_disable_level
+
+	.globl	_Nios2_ISR_Dispatch_with_shadow_preemptive
+
+_Nios2_ISR_Dispatch_with_shadow_preemptive:
+
+	/* Obtain stack frame */
+	subi	sp, sp, FRAME_SIZE
+
+	/* Save volatile registers */
+	stw	at, FRAME_OFFSET_AT(sp)
+	stw	r2, FRAME_OFFSET_R2(sp)
+	stw	r3, FRAME_OFFSET_R3(sp)
+	stw	r4, FRAME_OFFSET_R4(sp)
+	stw	r5, FRAME_OFFSET_R5(sp)
+	stw	r6, FRAME_OFFSET_R6(sp)
+	stw	r7, FRAME_OFFSET_R7(sp)
+	stw	r8, FRAME_OFFSET_R8(sp)
+	stw	r9, FRAME_OFFSET_R9(sp)
+	stw	r10, FRAME_OFFSET_R10(sp)
+	stw	r11, FRAME_OFFSET_R11(sp)
+	stw	r12, FRAME_OFFSET_R12(sp)
+	stw	r13, FRAME_OFFSET_R13(sp)
+	stw	r14, FRAME_OFFSET_R14(sp)
+	stw	r15, FRAME_OFFSET_R15(sp)
+
+	/* Save context */
+	rdctl	r2, estatus
+	subi	ea, ea, 4
+	stw	ra, FRAME_OFFSET_RA(sp)
+	stw	ea, FRAME_OFFSET_EA(sp)
+	stw	r2, FRAME_OFFSET_ESTATUS(sp)
+
+	/* Save one non-volatile register for further usage */
+	stw	r16, FRAME_OFFSET_R16(sp)
+
+	/* Save stack pointer */
+	mov	r16, sp
+
+	/* Increment ISR nest level and thread dispatch disable level */
+	ldw	r9, %gprel(_Per_CPU_Information + PER_CPU_ISR_NEST_LEVEL)(gp)
+	ldw	r10, %gprel(_Thread_Dispatch_disable_level)(gp)
+	addi	r11, r9, 1
+	addi	r10, r10, 1
+	stw	r11, %gprel(_Per_CPU_Information + PER_CPU_ISR_NEST_LEVEL)(gp)
+	stw	r10, %gprel(_Thread_Dispatch_disable_level)(gp)
+
+	/* Switch to interrupt stack if necessary */
+	bne	r9, zero, switch_to_interrupt_stack_done
+	ldw	sp, %gprel(_Per_CPU_Information + PER_CPU_INTERRUPT_STACK_HIGH)(gp)
+
+switch_to_interrupt_stack_done:
+
+	/* Load high level handler address and argument */
+	ldw	r12, 4(et)
+	ldw	r4, 8(et)
+
+	/* Enable interrupts */
+	rdctl	r13, status
+	orhi	r13, r13, 0x0080
+	wrctl	status, r13
+
+	/* Call high level handler with argument */
+	callr	r12
+
+	/* Disable interrupts */
+	rdctl	r12, status
+	movhi	r13, 0xff80
+	subi	r13, r13, 1
+	and	r12, r12, r13
+	wrctl	status, r12
+
+	/* Decrement ISR nest level and thread dispatch disable level */
+	ldw	r9, %gprel(_Per_CPU_Information + PER_CPU_ISR_NEST_LEVEL)(gp)
+	ldw	r10, %gprel(_Thread_Dispatch_disable_level)(gp)
+	subi	r9, r9, 1
+	subi	r10, r10, 1
+	stw	r9, %gprel(_Per_CPU_Information + PER_CPU_ISR_NEST_LEVEL)(gp)
+	stw	r10, %gprel(_Thread_Dispatch_disable_level)(gp)
+
+	/*
+	 * Restore stack pointer.  If the ISR nest level is greater than one,
+	 * then this is a nop, else we switch back to the thread stack.
+	 */
+	mov	sp, r16
+
+	/* Thread dispatch */
+	bne	r10, zero, thread_dispatch_done
+	call	_Thread_Dispatch
+
+thread_dispatch_done:
+
+	/* Restore volatile registers */
+	ldw	at, FRAME_OFFSET_AT(sp)
+	ldw	r2, FRAME_OFFSET_R2(sp)
+	ldw	r3, FRAME_OFFSET_R3(sp)
+	ldw	r4, FRAME_OFFSET_R4(sp)
+	ldw	r5, FRAME_OFFSET_R5(sp)
+	ldw	r6, FRAME_OFFSET_R6(sp)
+	ldw	r7, FRAME_OFFSET_R7(sp)
+	ldw	r8, FRAME_OFFSET_R8(sp)
+	ldw	r9, FRAME_OFFSET_R9(sp)
+	ldw	r10, FRAME_OFFSET_R10(sp)
+	ldw	r11, FRAME_OFFSET_R11(sp)
+	ldw	r12, FRAME_OFFSET_R12(sp)
+	ldw	r13, FRAME_OFFSET_R13(sp)
+	ldw	r14, FRAME_OFFSET_R14(sp)
+	ldw	r15, FRAME_OFFSET_R15(sp)
+
+	/* Restore context */
+	ldw	ra, FRAME_OFFSET_RA(sp)
+	ldw	ea, FRAME_OFFSET_EA(sp)
+	ldw	et, FRAME_OFFSET_ESTATUS(sp)
+
+	/* Restore the non-volatile register */
+	ldw	r16, FRAME_OFFSET_R16(sp)
+
+	/* Release stack frame */
+	addi	sp, sp, FRAME_SIZE
+
+	/* Restore context */
+	wrctl	estatus, et
+
+	/* Return */
+	eret
Index: cpukit/score/cpu/nios2/nios2-thread-dispatch-disabled.c
===================================================================
--- cpukit/score/cpu/nios2/nios2-thread-dispatch-disabled.c	(revision 3ce764a9ebd17dcd14d67eb017227421bde14aa4)
+++ cpukit/score/cpu/nios2/nios2-thread-dispatch-disabled.c	(revision 9f1412b9dc37a3919f21794f29b0199dc9ec4ea4)
@@ -40,5 +40,7 @@
 NIOS2_ASSERT_OFFSET(sp, SP);
 NIOS2_ASSERT_OFFSET(ra, RA);
-NIOS2_ASSERT_OFFSET(thread_dispatch_disabled, TDD);
+NIOS2_ASSERT_OFFSET(thread_dispatch_disabled, THREAD_DISPATCH_DISABLED);
+NIOS2_ASSERT_OFFSET(stack_mpubase, STACK_MPUBASE);
+NIOS2_ASSERT_OFFSET(stack_mpuacc, STACK_MPUACC);
 
 uint32_t _Nios2_Thread_dispatch_disabled;
Index: cpukit/score/cpu/nios2/rtems/score/cpu.h
===================================================================
--- cpukit/score/cpu/nios2/rtems/score/cpu.h	(revision 3ce764a9ebd17dcd14d67eb017227421bde14aa4)
+++ cpukit/score/cpu/nios2/rtems/score/cpu.h	(revision 9f1412b9dc37a3919f21794f29b0199dc9ec4ea4)
@@ -135,4 +135,6 @@
   uint32_t ra;
   uint32_t thread_dispatch_disabled;
+  uint32_t stack_mpubase;
+  uint32_t stack_mpuacc;
 } Context_Control;
 
Index: cpukit/score/cpu/nios2/rtems/score/nios2-utility.h
===================================================================
--- cpukit/score/cpu/nios2/rtems/score/nios2-utility.h	(revision 3ce764a9ebd17dcd14d67eb017227421bde14aa4)
+++ cpukit/score/cpu/nios2/rtems/score/nios2-utility.h	(revision 9f1412b9dc37a3919f21794f29b0199dc9ec4ea4)
@@ -45,5 +45,7 @@
 #define NIOS2_CONTEXT_OFFSET_SP 40
 #define NIOS2_CONTEXT_OFFSET_RA 44
-#define NIOS2_CONTEXT_OFFSET_TDD 48
+#define NIOS2_CONTEXT_OFFSET_THREAD_DISPATCH_DISABLED 48
+#define NIOS2_CONTEXT_OFFSET_STACK_MPUBASE 52
+#define NIOS2_CONTEXT_OFFSET_STACK_MPUACC 56
 
 #define NIOS2_ISR_STATUS_MASK_IIC 0xfffffffe
