summaryrefslogtreecommitdiffstats
path: root/pk/ppe42/ppe42_context.h
diff options
context:
space:
mode:
Diffstat (limited to 'pk/ppe42/ppe42_context.h')
-rw-r--r--pk/ppe42/ppe42_context.h382
1 files changed, 64 insertions, 318 deletions
diff --git a/pk/ppe42/ppe42_context.h b/pk/ppe42/ppe42_context.h
index f13ec8a7..2412565b 100644
--- a/pk/ppe42/ppe42_context.h
+++ b/pk/ppe42/ppe42_context.h
@@ -54,59 +54,24 @@
// system-reserved in ABI applications, and is the base for read-only small data
// in EABI applications.
-// A fair amount of complexity is involved in handling the non-critical and
-// critical interrupt levels, and the emphasis on performance of fast-mode
-// interrupt handlers. Several different approaches and philosophies could
-// have been implemented - this is only one. In this implementation
-// critical/non-critical interrupt levels are treated more or less the same,
-// and the interrupt priority is just that - a kind of preemption priority.
-// Critical interrupt handling does have a little less overhead because it
-// does not have a thread scheduling step at the end.
-
-// A full context save takes place in 3 or 4 steps. Thread switches always do
-// steps 1, 2 and 3.
-// 1. The fast context that is always saved in response to every interrupt;
-// 1a. The optional save/update of the kernel context for interrupts.
-// 2. The (volatile - fast) context that is saved if an interrupt handler
-// switches from fast-mode to full-mode.
-// 3. The non-volatile context that is saved when a thread is switched out.
-
// USPRG0 holds the __PkKernelContext structure (defined in ppe42.h) that
// represents the current kernel context. The layout is as follows:
//
// Bits Meaning
// ==============
-// 0:7 The critical interrupt count
-// 8:15 The non-critical interrupt count
-// 16:23 The IRQ currently being processed
-// 24 The 'thread_mode' flag
-// 25:31 The thread priority of the running thread
+// 0 The 'thread_mode' flag
+// 1 The 'processing_interrupt" flag
+// 2:7 The thread priority of the running thread
+// 8 The 'discard_ctx' flag
+// 9:15 The IRQ currently being processed
+// 16:31 The application specific data
//
// When PK is initialized USPRG0 is initialized to 0. When thread-mode is
-// entered (by pk_start_threads()) bit 24 is set to 1. In order to support
-// PgP/OCC firmware, once initialized (with pk_initialize()) PK can simply
+// entered (by pk_start_threads()) bit 0 is set to 1. If desired,
+// once initialized (with pk_initialize()) PK can simply
// handle interrupts, reverting back to the non-thread-mode idle loop when
// there's nothing to do.
//
-// Note that it would require a serious error for the interrupt counts to ever
-// equal or exceed 2**8 as this would imply runaway reentrancy and stack
-// overflow. In fact it is most likely an error if an interrupt handler is
-// ever re-entered while active.
-
-// Registers SRR2 and SRR3 are always saved in IRQ context because
-// __pk_irq_fast2full must save the (volatile - fast) context to provide
-// working registers before it can look at USPRG0 to determine critical
-// vs. non-critical context. However, when restoring a non-critical interrupt
-// or thread these registers need not be restored. SRR2 and SRR3 are never
-// saved or restored for thread context switches, because threads always
-// operate at noncritical level.
-
-// When MMU protection is enabled, relocation/protection is re-established
-// immediately upon entry to the interrupt handler, before any memory
-// operations (load/store) take place. This requires using SPRG0 and SPGR4
-// for temporary storage for noncritical/critical handlers respectively in
-// accordance with the PK conventions for SPRGn usage by fast-mode
-// interrupts.
## ------------------------------------------------------------
## Unused registers for embedded PPE42`
@@ -119,240 +84,77 @@
.set UNUSED_GPR13, 0xd # Dedicated; (E)ABI read-write small data area
## ------------------------------------------------------------
- ## Flags for context push/pop
- ## ------------------------------------------------------------
-
- .set PK_THREAD_CONTEXT, 0
- .set PK_IRQ_CONTEXT, 1
-
- ## ------------------------------------------------------------
- ## The PK fast context layout for Embedded PPE42
+ ## The PK context layout for Embedded PPE42
## ------------------------------------------------------------
- .set PK_FAST_CTX_GPR1, 0x00 # Dedicated; Stack pointer
- .set PK_FAST_CTX_HANDLER_LR, 0x04 # Slot for handler to store LR
- .set PK_FAST_CTX_GPR3, 0x08 # Volatile; Parameter; Return Value
- .set PK_FAST_CTX_GPR4, 0x0c # Volatile; Parameter
- .set PK_FAST_CTX_GPR5, 0x10 # Volatile; Parameter
- .set PK_FAST_CTX_GPR6, 0x14 # Volatile; Parameter
- .set PK_FAST_CTX_CR, 0x18 # Condition register
- .set PK_FAST_CTX_LR, 0x1c # Link register SPRN 0x008
- .set PK_FAST_CTX_KERNEL_CTX, 0x20 # Saved __PkKernelContext for IRQ
-
- .set PK_FAST_CTX_SIZE, 0x28 # Must be 8-byte aligned
+ .set PK_CTX_GPR1, 0x00 # Dedicated; Stack pointer
+ .set PK_CTX_LINKAGE, 0x04 # Slot for handler to store LR
+ .set PK_CTX_GPR3, 0x08 # Volatile; Parameter; Return Value
+ .set PK_CTX_GPR4, 0x0c # Volatile; Parameter
+ .set PK_CTX_GPR5, 0x10 # Volatile; Parameter
+ .set PK_CTX_GPR6, 0x14 # Volatile; Parameter
+ .set PK_CTX_CR, 0x18 # Condition register
+ .set PK_CTX_LR, 0x1c # Link register
- ## ------------------------------------------------------------
- ## The PK (volatile - fast) context layout for Embedded PPE42
- ## ------------------------------------------------------------
+ .set PK_CTX_GPR7, 0x20 # Volatile; Parameter
+ .set PK_CTX_GPR8, 0x24 # Volatile; Parameter
+ .set PK_CTX_GPR9, 0x28 # Volatile; Parameter
+ .set PK_CTX_GPR10, 0x2c # Volatile; Parameter
+ .set PK_CTX_GPR28, 0x30 # Non-volatile
+ .set PK_CTX_GPR29, 0x34 # Non-volatile
+ .set PK_CTX_GPR30, 0x38 # Non-volatile
+ .set PK_CTX_GPR31, 0x3c # Non-volatile
- .set PK_VOL_FAST_CTX_GPR1, 0x00 # Dedicated; Stack pointer
- .set PK_VOL_FAST_CTX_HANDLER_LR, 0x04 # Slot for handler to store LR
- .set PK_VOL_FAST_CTX_GPR7, 0x08 # Volatile; Parameter
- .set PK_VOL_FAST_CTX_GPR8, 0x0c # Volatile; Parameter
- .set PK_VOL_FAST_CTX_GPR9, 0x10 # Volatile; Parameter
- .set PK_VOL_FAST_CTX_GPR10, 0x14 # Volatile; Parameter
- .set PK_VOL_FAST_CTX_XER, 0x18 # Fixed-point exception register SPRN 0x001
- .set PK_VOL_FAST_CTX_CTR, 0x1c # Count register SPRN 0x009
- .set PK_VOL_FAST_CTX_SRR0, 0x20 # Save/restore register 0 SPRN 0x01a
- .set PK_VOL_FAST_CTX_SRR1, 0x24 # Save/restore register 1 SPRN 0x01b
- .set PK_VOL_FAST_CTX_GPR0, 0x28 # Volatile; Language specific
+ .set PK_CTX_XER, 0x40 # Fixed-point exception register
+ .set PK_CTX_CTR, 0x44 # Count register
+ .set PK_CTX_SRR0, 0x48 # Save/restore register 0
+ .set PK_CTX_SRR1, 0x4c # Save/restore register 1
+ .set PK_CTX_GPR0, 0x50 # Volatile; Language specific
+ .set PK_CTX_KERNEL_CTX, 0x54 # Saved __PkKernelContext for IRQ
- .set PK_VOL_FAST_CTX_SIZE, 0x30 # Must be 8-byte aligned
+ .set PK_CTX_SIZE, 0x58 # Must be 8-byte aligned
## ------------------------------------------------------------
- ## The PK non-volatile context layout for Embedded PowerPC
- ## ------------------------------------------------------------
-
- ## The 'preferred form' for stmw is for the LSB of R31 to fall into the
- ## end of a 16-byte aligned block.
-
- .set PK_NON_VOL_CTX_GPR1, 0x00 # Dedicated; Stack Pointer
- .set PK_NON_VOL_CTX_HANDLER_LR, 0x04 # Slot for handler to store LR
- .set PK_NON_VOL_CTX_GPR28, 0x08 # Non-volatile
- .set PK_NON_VOL_CTX_GPR29, 0x0c # Non-volatile
- .set PK_NON_VOL_CTX_GPR30, 0x10 # Non-volatile
- .set PK_NON_VOL_CTX_GPR31, 0x14 # Non-volatile
-
- .set PK_NON_VOL_CTX_SIZE, 0x18 # Must be 8-byte aligned
-
- ## ------------------------------------------------------------
- ## Save/restore the fast context
+ ## Push the interrupted context if necessary
+ ##
+ ## This macro saves off some context in preparation for calling
+ ## the pk_ctx_check_discard routine. This is an attempt to use
+ ## the 32 byte cache more efficiently.
##
- ## 11 Instructions, 8 Loads/Stores : If MMU is disabled
- ## 17 Instructions, 8 Loads/Stores : If MMU is enabled
+ ## 8 Instructions
## ------------------------------------------------------------
##
- ## Without MMU support, an EIEIO is always executed at the entry point
- ## to gauarantee that all memory operations (especially MMIO
- ## operations) have completed prior to execution of the interrupt
- ## handler.
- ##
- ## If MMU support is enabled, address translation is re-established
- ## immediately at the entry of each interrupt, prior to performing any
- ## loads or stores. PK currently only supports using the MMU for
- ## protection, not for address translation. Therfore it is 'legal'
- ## to change translation modes a with an MTMSR followed by an
- ## ISYNC. This is much simpler then the complex instruction sequence
- ## that would be required if we had to set up RFI/RFCI sequences to
- ## change the execution context at this point.
- ##
- ## Note that since we are not really doing address translation, it
- ## would also be in keeping with the 'fast interrupt' idea to defer
- ## reenabling translation (protection) until the fast-to-full sequence
- ## was executed for full-mode interrupts, and run fast-mode interrupts
- ## unprotected. However here we chose to run all interrupts with MMU
- ## protection.
- ##
- ## Unfortunately the simple MTMSR;ISYNC sequence exposes a serious bug
- ## in the PPE42 core that causes the stack-pointer store instruction
- ## to generate a seemingly random, *real-mode* address in certain cases
- ## when this instruction in a noncritical interrupt prologue is
- ## interrupted by a critical interrupt. This bug is described in
- ## HW239446. The workaround is to follow the ISYNC sith a SYNC - which
- ## eliminates the problem for reasons still unknown. On the bright side
- ## this SYNC might also serve the same purpose as the EIEIO in the
- ## non-MMU case, guaranteeing that all MMIO has completed prior to the
- ## interrupt handler. However without the initial EIEIO we still
- ## experience failures, so this seemingly redundant instruction also
- ## remains in place. This requirement is assumed to be related to the
- ## HW239446 issue.
-
- .macro _pk_fast_ctx_push
-
- stwu %r1, -PK_FAST_CTX_SIZE(%r1)
-
- stvd %d3, PK_FAST_CTX_GPR3(%r1)
- stvd %d5, PK_FAST_CTX_GPR5(%r1)
+
+ .macro _pk_ctx_push_as_needed branch_addr:req
+ stwu %r1, -PK_CTX_SIZE(%r1)
+ stvd %d3, PK_CTX_GPR3(%r1)
mfcr %r3
mflr %r4
-
- stvd %d3, PK_FAST_CTX_CR(%r1)
-
+ stvd %d3, PK_CTX_CR(%r1)
+ _liw %r3, \branch_addr
+ b ctx_check_discard
.endm
- .macro _pk_fast_ctx_pop
-
- lvd %d3, PK_FAST_CTX_CR(%r1)
-
- mtcr0 %r3
- mtlr %r4
-
- lvd %d3, PK_FAST_CTX_GPR3(%r1)
- lvd %d5, PK_FAST_CTX_GPR5(%r1)
-
- lwz %r1, 0(%r1)
-
- .endm
-
## ------------------------------------------------------------
- ## Save/update the kernel context in response to an interrupt. This is
- ## not part of the fast context save because for external interupts the
- ## IRQ is not determined until later.
+ ## update the kernel context in response to an interrupt.
## ------------------------------------------------------------
- ## The kernel context is saved, then updated with the currently active
- ## IRQ in bits 16:23. The correct interrupt count is incremented and
- ## the context is returned to SPRG0.
-
- .macro _save_update_kernel_context irqreg, ctxreg
-
- #PK_TRACE_NONCRITICAL_IRQ_ENTRY \irqreg, \ctxreg
+ ## The kernel context is updated with the currently active
+ ## IRQ in bits 9:15.
- mfsprg0 \ctxreg
- stw \ctxreg, PK_FAST_CTX_KERNEL_CTX(%r1)
- #rlwimi \ctxreg, \irqreg, 24, 9, 15 //set the irq #
- rlwimi \ctxreg, \irqreg, 8, 16, 23 //set the irq #
- #oris \ctxreg, \ctxreg, 0x4000 //set the 'processing interrupt' PI bit
- addis \ctxreg, \ctxreg, 0x0001 //increment the irq count
+ .macro _update_kernel_context irqreg, ctxreg
+ rlwimi \ctxreg, \irqreg, 16, 9, 15 //set the irq #
+ oris \ctxreg, \ctxreg, 0x4000 //set the 'processing_interrupt' flag
mtsprg0 \ctxreg
- .endm
-
- ## ------------------------------------------------------------
- ## Fast-mode context pop and RF(C)I. This is only used by
- ## interrupt handlers - the thread context switch has its own
- ## code to handle updating USPRG0 for thread mode.
- ## ------------------------------------------------------------
-
- .macro _pk_fast_ctx_pop_exit
-
- .if PK_KERNEL_TRACE_ENABLE
- bl __pk_trace_noncritical_irq_exit
- .endif
-
- lwz %r3, PK_FAST_CTX_KERNEL_CTX(%r1)
- mtsprg0 %r3
- _pk_fast_ctx_pop
- rfi
-
- .endm
-
- ## ------------------------------------------------------------
- ## Save/restore the (volatile - fast) context
- ##
- ## Thread - 15 Instructions, 11 Loads/Stores
- ## IRQ - 19(15) Instructions, 13(11) Loads/Stores
- ## ------------------------------------------------------------
-
- .macro _pk_vol_fast_ctx_push
-
- stwu %r1, -PK_VOL_FAST_CTX_SIZE(%r1)
-
- stw %r0, PK_VOL_FAST_CTX_GPR0(%r1)
- stvd %d7, PK_VOL_FAST_CTX_GPR7(%r1)
- stvd %d9, PK_VOL_FAST_CTX_GPR9(%r1)
-
- mfxer %r7
- mfctr %r8
- mfsrr0 %r9
- mfsrr1 %r10
-
- stvd %d7, PK_VOL_FAST_CTX_XER(%r1)
- stvd %d9, PK_VOL_FAST_CTX_SRR0(%r1)
-
- .endm
-
-
- .macro _pk_vol_fast_ctx_pop
-
- lvd %d7, PK_VOL_FAST_CTX_XER(%r1)
- lvd %d9, PK_VOL_FAST_CTX_SRR0(%r1)
-
- mtxer %r7
- mtctr %r8
- mtsrr0 %r9
- mtsrr1 %r10
-
- lwz %r0, PK_VOL_FAST_CTX_GPR0(%r1)
- lvd %d7, PK_VOL_FAST_CTX_GPR7(%r1)
- lvd %d9, PK_VOL_FAST_CTX_GPR9(%r1)
-
- lwz %r1, 0(%r1)
-
- .endm
-
- ## ------------------------------------------------------------
- ## Save/restore the non-volatile context on the stack
- ##
- ## 2 Instructions, 19 Loads/Stores
- ## ------------------------------------------------------------
-
- .macro _pk_non_vol_ctx_push
-
- stwu %r1, -PK_NON_VOL_CTX_SIZE(%r1)
- stvd %d28, PK_NON_VOL_CTX_GPR28(%r1)
- stvd %d30, PK_NON_VOL_CTX_GPR30(%r1)
-
- .endm
-
-
- .macro _pk_non_vol_ctx_pop
-
- lvd %d28, PK_NON_VOL_CTX_GPR28(%r1)
- lvd %d30, PK_NON_VOL_CTX_GPR30(%r1)
- lwz %r1, 0(%r1)
+#if PK_KERNEL_TRACE_ENABLE
+ mr %r31, \irqreg
+ srwi \ctxreg, \ctxreg, 16
+ PK_KERN_TRACE_ASM16("INTERRUPT_CONTEXT(0x%04x)", \ctxreg)
+ mr \irqreg, %r31
+#endif
.endm
@@ -364,89 +166,33 @@
/// thread->saved_stack_pointer when a thread is fully context-switched out.
typedef struct {
-
- uint32_t r1_nv;
- uint32_t link_nv;
- uint32_t r28;
- uint32_t r29;
- uint32_t r30;
- uint32_t r31;
- uint32_t r1_vf;
- uint32_t link_vf;
- uint32_t r7;
- uint32_t r8;
- uint32_t r9;
- uint32_t r10;
- uint32_t xer;
- uint32_t ctr;
- uint32_t srr0;
- uint32_t srr1;
- uint32_t r0;
- uint32_t pad;
uint32_t r1;
- uint32_t link_fast;
+ uint32_t linkage;
uint32_t r3;
uint32_t r4;
uint32_t r5;
uint32_t r6;
uint32_t cr;
uint32_t lr;
- uint32_t sprg0;
-
-} PkThreadContext;
-
-/// PK thread context of an interrupted thread (full-mode handler)
-///
-/// When a thread is interrupted by a full-mode interrupt handler, this is the
-/// layout of the stack area pointed to by either __pk_saved_sp_noncritical
-/// or __pk_saved_sp_critical.
-typedef struct {
-
- uint32_t r1_vf;
- uint32_t link_vf;
uint32_t r7;
uint32_t r8;
uint32_t r9;
uint32_t r10;
+ uint32_t r28;
+ uint32_t r29;
+ uint32_t r30;
+ uint32_t r31;
+
uint32_t xer;
uint32_t ctr;
uint32_t srr0;
uint32_t srr1;
uint32_t r0;
- uint32_t pad;
- uint32_t r1;
- uint32_t link_fast;
- uint32_t r3;
- uint32_t r4;
- uint32_t r5;
- uint32_t r6;
- uint32_t cr;
- uint32_t lr;
uint32_t sprg0;
-} PkThreadContextFullIrq;
-
-
-/// PK thread context of an interrupted thread (fast-mode handler)
-///
-/// When a thread is interrupted by a fast-mode interrupt handler, this is the
-/// layout of the stack area pointed to by R1 - unless the fast-mode interrupt
-/// handler extends the stack.
-
-typedef struct {
-
- uint32_t r1;
- uint32_t link_fast;
- uint32_t r3;
- uint32_t r4;
- uint32_t r5;
- uint32_t r6;
- uint32_t cr;
- uint32_t lr;
- uint32_t sprg0;
+} PkThreadContext;
-} PkThreadContextFastIrq;
#endif /* __ASSEMBLER__ */
OpenPOWER on IntegriCloud