forked from Imagelibrary/rtems
bsps/powerpc: Move exceptions support to bsps
This patch is a part of the BSP source reorganization. Update #3285.
This commit is contained in:
471
bsps/powerpc/shared/exceptions/ppc_exc_async_normal.S
Normal file
471
bsps/powerpc/shared/exceptions/ppc_exc_async_normal.S
Normal file
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2017 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Dornierstr. 4
|
||||
* 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.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <bspopts.h>
|
||||
#include <rtems/score/percpu.h>
|
||||
#include <bsp/vectors.h>
|
||||
|
||||
#ifdef PPC_EXC_CONFIG_USE_FIXED_HANDLER
|
||||
|
||||
#define SCRATCH_0_REGISTER r0
|
||||
#define SCRATCH_1_REGISTER r3
|
||||
#define SCRATCH_2_REGISTER r4
|
||||
#define SCRATCH_3_REGISTER r5
|
||||
#define SCRATCH_4_REGISTER r6
|
||||
#define SCRATCH_5_REGISTER r7
|
||||
#define SCRATCH_6_REGISTER r8
|
||||
#define SCRATCH_7_REGISTER r9
|
||||
#define SCRATCH_8_REGISTER r10
|
||||
#define SCRATCH_9_REGISTER r11
|
||||
#define SCRATCH_10_REGISTER r12
|
||||
#define FRAME_REGISTER r14
|
||||
|
||||
#define SCRATCH_0_OFFSET GPR0_OFFSET
|
||||
#define SCRATCH_1_OFFSET GPR3_OFFSET
|
||||
#define SCRATCH_2_OFFSET GPR4_OFFSET
|
||||
#define SCRATCH_3_OFFSET GPR5_OFFSET
|
||||
#define SCRATCH_4_OFFSET GPR6_OFFSET
|
||||
#define SCRATCH_5_OFFSET GPR7_OFFSET
|
||||
#define SCRATCH_6_OFFSET GPR8_OFFSET
|
||||
#define SCRATCH_7_OFFSET GPR9_OFFSET
|
||||
#define SCRATCH_8_OFFSET GPR10_OFFSET
|
||||
#define SCRATCH_9_OFFSET GPR11_OFFSET
|
||||
#define SCRATCH_10_OFFSET GPR12_OFFSET
|
||||
#define FRAME_OFFSET PPC_EXC_INTERRUPT_FRAME_OFFSET
|
||||
|
||||
#ifdef RTEMS_PROFILING
|
||||
.macro GET_TIME_BASE REG
|
||||
#if defined(__PPC_CPU_E6500__)
|
||||
mfspr \REG, FSL_EIS_ATBL
|
||||
#elif defined(ppc8540)
|
||||
mfspr \REG, TBRL
|
||||
#else /* ppc8540 */
|
||||
mftb \REG
|
||||
#endif /* ppc8540 */
|
||||
.endm
|
||||
#endif /* RTEMS_PROFILING */
|
||||
|
||||
.global ppc_exc_min_prolog_async_tmpl_normal
|
||||
.global ppc_exc_interrupt
|
||||
|
||||
ppc_exc_min_prolog_async_tmpl_normal:
|
||||
|
||||
stwu r1, -PPC_EXC_INTERRUPT_FRAME_SIZE(r1)
|
||||
PPC_REG_STORE SCRATCH_1_REGISTER, SCRATCH_1_OFFSET(r1)
|
||||
li SCRATCH_1_REGISTER, 0xffff8000
|
||||
|
||||
/*
|
||||
* We store the absolute branch target address here. It will be used
|
||||
* to generate the branch operation in ppc_exc_make_prologue().
|
||||
*/
|
||||
.int ppc_exc_interrupt
|
||||
|
||||
ppc_exc_interrupt:
|
||||
|
||||
/* Save non-volatile FRAME_REGISTER */
|
||||
PPC_REG_STORE FRAME_REGISTER, FRAME_OFFSET(r1)
|
||||
|
||||
#ifdef RTEMS_PROFILING
|
||||
/* Get entry instant */
|
||||
GET_TIME_BASE FRAME_REGISTER
|
||||
stw FRAME_REGISTER, PPC_EXC_INTERRUPT_ENTRY_INSTANT_OFFSET(r1)
|
||||
#endif /* RTEMS_PROFILING */
|
||||
|
||||
#ifdef __SPE__
|
||||
/* Enable SPE */
|
||||
mfmsr FRAME_REGISTER
|
||||
oris FRAME_REGISTER, FRAME_REGISTER, MSR_SPE >> 16
|
||||
mtmsr FRAME_REGISTER
|
||||
isync
|
||||
|
||||
/*
|
||||
* Save high order part of SCRATCH_1_REGISTER here. The low order part
|
||||
* was saved in the minimal prologue.
|
||||
*/
|
||||
evmergehi SCRATCH_1_REGISTER, SCRATCH_1_REGISTER, FRAME_REGISTER
|
||||
PPC_REG_STORE FRAME_REGISTER, GPR3_OFFSET(r1)
|
||||
#endif
|
||||
|
||||
#if defined(PPC_MULTILIB_FPU) || defined(PPC_MULTILIB_ALTIVEC)
|
||||
/* Enable FPU and/or AltiVec */
|
||||
mfmsr FRAME_REGISTER
|
||||
#ifdef PPC_MULTILIB_FPU
|
||||
ori FRAME_REGISTER, FRAME_REGISTER, MSR_FP
|
||||
#endif
|
||||
#ifdef PPC_MULTILIB_ALTIVEC
|
||||
oris FRAME_REGISTER, FRAME_REGISTER, MSR_VE >> 16
|
||||
#endif
|
||||
mtmsr FRAME_REGISTER
|
||||
isync
|
||||
#endif
|
||||
|
||||
/* Move frame pointer to non-volatile FRAME_REGISTER */
|
||||
mr FRAME_REGISTER, r1
|
||||
|
||||
/*
|
||||
* Save volatile registers. The SCRATCH_1_REGISTER has been saved in
|
||||
* minimum prologue.
|
||||
*/
|
||||
PPC_GPR_STORE SCRATCH_0_REGISTER, SCRATCH_0_OFFSET(r1)
|
||||
#ifdef __powerpc64__
|
||||
PPC_GPR_STORE r2, GPR2_OFFSET(r1)
|
||||
LA32 r2, .TOC.
|
||||
#endif
|
||||
PPC_GPR_STORE SCRATCH_2_REGISTER, SCRATCH_2_OFFSET(r1)
|
||||
GET_SELF_CPU_CONTROL SCRATCH_2_REGISTER
|
||||
PPC_GPR_STORE SCRATCH_3_REGISTER, SCRATCH_3_OFFSET(r1)
|
||||
PPC_GPR_STORE SCRATCH_4_REGISTER, SCRATCH_4_OFFSET(r1)
|
||||
PPC_GPR_STORE SCRATCH_5_REGISTER, SCRATCH_5_OFFSET(r1)
|
||||
PPC_GPR_STORE SCRATCH_6_REGISTER, SCRATCH_6_OFFSET(r1)
|
||||
PPC_GPR_STORE SCRATCH_7_REGISTER, SCRATCH_7_OFFSET(r1)
|
||||
PPC_GPR_STORE SCRATCH_8_REGISTER, SCRATCH_8_OFFSET(r1)
|
||||
PPC_GPR_STORE SCRATCH_9_REGISTER, SCRATCH_9_OFFSET(r1)
|
||||
PPC_GPR_STORE SCRATCH_10_REGISTER, SCRATCH_10_OFFSET(r1)
|
||||
|
||||
/* Load ISR nest level and thread dispatch disable level */
|
||||
lwz SCRATCH_3_REGISTER, PER_CPU_ISR_NEST_LEVEL(SCRATCH_2_REGISTER)
|
||||
lwz SCRATCH_4_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SCRATCH_2_REGISTER)
|
||||
|
||||
/* Save SRR0, SRR1, CR, XER, CTR, and LR */
|
||||
mfsrr0 SCRATCH_0_REGISTER
|
||||
mfsrr1 SCRATCH_5_REGISTER
|
||||
mfcr SCRATCH_6_REGISTER
|
||||
mfxer SCRATCH_7_REGISTER
|
||||
mfctr SCRATCH_8_REGISTER
|
||||
mflr SCRATCH_9_REGISTER
|
||||
PPC_REG_STORE SCRATCH_0_REGISTER, SRR0_FRAME_OFFSET(r1)
|
||||
PPC_REG_STORE SCRATCH_5_REGISTER, SRR1_FRAME_OFFSET(r1)
|
||||
stw SCRATCH_6_REGISTER, EXC_CR_OFFSET(r1)
|
||||
stw SCRATCH_7_REGISTER, EXC_XER_OFFSET(r1)
|
||||
PPC_REG_STORE SCRATCH_8_REGISTER, EXC_CTR_OFFSET(r1)
|
||||
PPC_REG_STORE SCRATCH_9_REGISTER, EXC_LR_OFFSET(r1)
|
||||
|
||||
#ifdef __SPE__
|
||||
/* Save SPEFSCR and ACC */
|
||||
mfspr SCRATCH_0_REGISTER, FSL_EIS_SPEFSCR
|
||||
evxor SCRATCH_5_REGISTER, SCRATCH_5_REGISTER, SCRATCH_5_REGISTER
|
||||
evmwumiaa SCRATCH_5_REGISTER, SCRATCH_5_REGISTER, SCRATCH_5_REGISTER
|
||||
stw SCRATCH_0_REGISTER, PPC_EXC_SPEFSCR_OFFSET(r1)
|
||||
evstdd SCRATCH_5_REGISTER, PPC_EXC_ACC_OFFSET(r1)
|
||||
#endif
|
||||
|
||||
#ifdef PPC_MULTILIB_ALTIVEC
|
||||
/* Save volatile AltiVec context */
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(0)
|
||||
stvx v0, r1, SCRATCH_0_REGISTER
|
||||
mfvscr v0
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(1)
|
||||
stvx v1, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(2)
|
||||
stvx v2, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(3)
|
||||
stvx v3, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(4)
|
||||
stvx v4, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(5)
|
||||
stvx v5, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(6)
|
||||
stvx v6, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(7)
|
||||
stvx v7, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(8)
|
||||
stvx v8, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(9)
|
||||
stvx v9, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(10)
|
||||
stvx v10, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(11)
|
||||
stvx v11, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(12)
|
||||
stvx v12, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(13)
|
||||
stvx v13, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(14)
|
||||
stvx v14, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(15)
|
||||
stvx v15, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(16)
|
||||
stvx v16, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(17)
|
||||
stvx v17, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(18)
|
||||
stvx v18, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(19)
|
||||
stvx v19, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VSCR_OFFSET
|
||||
stvewx v0, r1, SCRATCH_0_REGISTER
|
||||
#endif
|
||||
|
||||
#ifdef PPC_MULTILIB_FPU
|
||||
/* Save volatile FPU context */
|
||||
stfd f0, PPC_EXC_MIN_FR_OFFSET(0)(r1)
|
||||
mffs f0
|
||||
stfd f1, PPC_EXC_MIN_FR_OFFSET(1)(r1)
|
||||
stfd f2, PPC_EXC_MIN_FR_OFFSET(2)(r1)
|
||||
stfd f3, PPC_EXC_MIN_FR_OFFSET(3)(r1)
|
||||
stfd f4, PPC_EXC_MIN_FR_OFFSET(4)(r1)
|
||||
stfd f5, PPC_EXC_MIN_FR_OFFSET(5)(r1)
|
||||
stfd f6, PPC_EXC_MIN_FR_OFFSET(6)(r1)
|
||||
stfd f7, PPC_EXC_MIN_FR_OFFSET(7)(r1)
|
||||
stfd f8, PPC_EXC_MIN_FR_OFFSET(8)(r1)
|
||||
stfd f9, PPC_EXC_MIN_FR_OFFSET(9)(r1)
|
||||
stfd f10, PPC_EXC_MIN_FR_OFFSET(10)(r1)
|
||||
stfd f11, PPC_EXC_MIN_FR_OFFSET(11)(r1)
|
||||
stfd f12, PPC_EXC_MIN_FR_OFFSET(12)(r1)
|
||||
stfd f13, PPC_EXC_MIN_FR_OFFSET(13)(r1)
|
||||
stfd f0, PPC_EXC_MIN_FPSCR_OFFSET(r1)
|
||||
#endif
|
||||
|
||||
/* Increment ISR nest level and thread dispatch disable level */
|
||||
cmpwi SCRATCH_3_REGISTER, 0
|
||||
#ifdef RTEMS_PROFILING
|
||||
cmpwi cr2, SCRATCH_3_REGISTER, 0
|
||||
#endif
|
||||
addi SCRATCH_3_REGISTER, SCRATCH_3_REGISTER, 1
|
||||
addi SCRATCH_4_REGISTER, SCRATCH_4_REGISTER, 1
|
||||
stw SCRATCH_3_REGISTER, PER_CPU_ISR_NEST_LEVEL(SCRATCH_2_REGISTER)
|
||||
stw SCRATCH_4_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SCRATCH_2_REGISTER)
|
||||
|
||||
/* Switch stack if necessary */
|
||||
mfspr SCRATCH_0_REGISTER, SPRG1
|
||||
iselgt r1, r1, SCRATCH_0_REGISTER
|
||||
|
||||
/* Call fixed high level handler */
|
||||
bl bsp_interrupt_dispatch
|
||||
PPC64_NOP_FOR_LINKER_TOC_POINTER_RESTORE
|
||||
|
||||
#ifdef RTEMS_PROFILING
|
||||
/* Update profiling data if necessary */
|
||||
bne cr2, .Lprofiling_done
|
||||
GET_SELF_CPU_CONTROL r3
|
||||
lwz r4, PPC_EXC_INTERRUPT_ENTRY_INSTANT_OFFSET(FRAME_REGISTER)
|
||||
GET_TIME_BASE r5
|
||||
bl _Profiling_Outer_most_interrupt_entry_and_exit
|
||||
PPC64_NOP_FOR_LINKER_TOC_POINTER_RESTORE
|
||||
.Lprofiling_done:
|
||||
#endif /* RTEMS_PROFILING */
|
||||
|
||||
/* Load some per-CPU variables */
|
||||
GET_SELF_CPU_CONTROL SCRATCH_1_REGISTER
|
||||
lbz SCRATCH_0_REGISTER, PER_CPU_DISPATCH_NEEDED(SCRATCH_1_REGISTER)
|
||||
lwz SCRATCH_5_REGISTER, PER_CPU_ISR_DISPATCH_DISABLE(SCRATCH_1_REGISTER)
|
||||
lwz SCRATCH_6_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SCRATCH_1_REGISTER)
|
||||
lwz SCRATCH_3_REGISTER, PER_CPU_ISR_NEST_LEVEL(SCRATCH_1_REGISTER)
|
||||
|
||||
/*
|
||||
* Switch back to original stack (FRAME_REGISTER == r1 if we are still
|
||||
* on the IRQ stack) and restore FRAME_REGISTER.
|
||||
*/
|
||||
mr r1, FRAME_REGISTER
|
||||
PPC_REG_LOAD FRAME_REGISTER, FRAME_OFFSET(r1)
|
||||
|
||||
/* Decrement levels and determine thread dispatch state */
|
||||
xori SCRATCH_0_REGISTER, SCRATCH_0_REGISTER, 1
|
||||
or SCRATCH_0_REGISTER, SCRATCH_0_REGISTER, SCRATCH_5_REGISTER
|
||||
subi SCRATCH_4_REGISTER, SCRATCH_6_REGISTER, 1
|
||||
or. SCRATCH_0_REGISTER, SCRATCH_0_REGISTER, SCRATCH_4_REGISTER
|
||||
subi SCRATCH_3_REGISTER, SCRATCH_3_REGISTER, 1
|
||||
|
||||
/* Store thread dispatch disable and ISR nest levels */
|
||||
stw SCRATCH_4_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SCRATCH_1_REGISTER)
|
||||
stw SCRATCH_3_REGISTER, PER_CPU_ISR_NEST_LEVEL(SCRATCH_1_REGISTER)
|
||||
|
||||
/*
|
||||
* Check thread dispatch necessary, ISR dispatch disable and thread
|
||||
* dispatch disable level.
|
||||
*/
|
||||
bne .Lthread_dispatch_done
|
||||
|
||||
/* Thread dispatch */
|
||||
.Ldo_thread_dispatch:
|
||||
|
||||
/* Set ISR dispatch disable and thread dispatch disable level to one */
|
||||
li SCRATCH_0_REGISTER, 1
|
||||
stw SCRATCH_0_REGISTER, PER_CPU_ISR_DISPATCH_DISABLE(SCRATCH_1_REGISTER)
|
||||
stw SCRATCH_0_REGISTER, PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(SCRATCH_1_REGISTER)
|
||||
|
||||
/*
|
||||
* Call _Thread_Do_dispatch(), this function will enable interrupts.
|
||||
* The r3 is SCRATCH_1_REGISTER.
|
||||
*/
|
||||
mfmsr r4
|
||||
ori r4, r4, MSR_EE
|
||||
bl _Thread_Do_dispatch
|
||||
PPC64_NOP_FOR_LINKER_TOC_POINTER_RESTORE
|
||||
|
||||
/* Disable interrupts */
|
||||
wrteei 0
|
||||
|
||||
/* SCRATCH_1_REGISTER is volatile, we must set it again */
|
||||
GET_SELF_CPU_CONTROL SCRATCH_1_REGISTER
|
||||
|
||||
/* Check if we have to do the thread dispatch again */
|
||||
lbz SCRATCH_0_REGISTER, PER_CPU_DISPATCH_NEEDED(SCRATCH_1_REGISTER)
|
||||
cmpwi SCRATCH_0_REGISTER, 0
|
||||
bne .Ldo_thread_dispatch
|
||||
|
||||
/* We are done with thread dispatching */
|
||||
li SCRATCH_0_REGISTER, 0
|
||||
stw SCRATCH_0_REGISTER, PER_CPU_ISR_DISPATCH_DISABLE(SCRATCH_1_REGISTER)
|
||||
|
||||
.Lthread_dispatch_done:
|
||||
|
||||
#ifdef PPC_MULTILIB_ALTIVEC
|
||||
/* Restore volatile AltiVec context */
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VSCR_OFFSET
|
||||
lvewx v0, r1, SCRATCH_0_REGISTER
|
||||
mtvscr v0
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(0)
|
||||
lvx v0, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(1)
|
||||
lvx v1, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(2)
|
||||
lvx v2, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(3)
|
||||
lvx v3, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(4)
|
||||
lvx v4, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(5)
|
||||
lvx v5, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(6)
|
||||
lvx v6, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(7)
|
||||
lvx v7, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(8)
|
||||
lvx v8, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(9)
|
||||
lvx v9, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(10)
|
||||
lvx v10, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(11)
|
||||
lvx v11, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(12)
|
||||
lvx v12, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(13)
|
||||
lvx v13, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(14)
|
||||
lvx v14, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(15)
|
||||
lvx v15, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(16)
|
||||
lvx v16, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(17)
|
||||
lvx v17, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(18)
|
||||
lvx v18, r1, SCRATCH_0_REGISTER
|
||||
li SCRATCH_0_REGISTER, PPC_EXC_MIN_VR_OFFSET(19)
|
||||
lvx v19, r1, SCRATCH_0_REGISTER
|
||||
#endif
|
||||
|
||||
#ifdef PPC_MULTILIB_FPU
|
||||
/* Restore volatile FPU context */
|
||||
lfd f0, PPC_EXC_MIN_FPSCR_OFFSET(r1)
|
||||
mtfsf 0xff, f0
|
||||
lfd f0, PPC_EXC_MIN_FR_OFFSET(0)(r1)
|
||||
lfd f1, PPC_EXC_MIN_FR_OFFSET(1)(r1)
|
||||
lfd f2, PPC_EXC_MIN_FR_OFFSET(2)(r1)
|
||||
lfd f3, PPC_EXC_MIN_FR_OFFSET(3)(r1)
|
||||
lfd f4, PPC_EXC_MIN_FR_OFFSET(4)(r1)
|
||||
lfd f5, PPC_EXC_MIN_FR_OFFSET(5)(r1)
|
||||
lfd f6, PPC_EXC_MIN_FR_OFFSET(6)(r1)
|
||||
lfd f7, PPC_EXC_MIN_FR_OFFSET(7)(r1)
|
||||
lfd f8, PPC_EXC_MIN_FR_OFFSET(8)(r1)
|
||||
lfd f9, PPC_EXC_MIN_FR_OFFSET(9)(r1)
|
||||
lfd f10, PPC_EXC_MIN_FR_OFFSET(10)(r1)
|
||||
lfd f11, PPC_EXC_MIN_FR_OFFSET(11)(r1)
|
||||
lfd f12, PPC_EXC_MIN_FR_OFFSET(12)(r1)
|
||||
lfd f13, PPC_EXC_MIN_FR_OFFSET(13)(r1)
|
||||
#endif
|
||||
|
||||
#ifdef __SPE__
|
||||
/* Load SPEFSCR and ACC */
|
||||
lwz SCRATCH_3_REGISTER, PPC_EXC_SPEFSCR_OFFSET(r1)
|
||||
evldd SCRATCH_4_REGISTER, PPC_EXC_ACC_OFFSET(r1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We must clear reservations here, since otherwise compare-and-swap
|
||||
* atomic operations with interrupts enabled may yield wrong results.
|
||||
* A compare-and-swap atomic operation is generated by the compiler
|
||||
* like this:
|
||||
*
|
||||
* .L1:
|
||||
* lwarx r9, r0, r3
|
||||
* cmpw r9, r4
|
||||
* bne- .L2
|
||||
* stwcx. r5, r0, r3
|
||||
* bne- .L1
|
||||
* .L2:
|
||||
*
|
||||
* Consider the following scenario. A thread is interrupted right
|
||||
* before the stwcx. The interrupt updates the value using a
|
||||
* compare-and-swap sequence. Everything is fine up to this point.
|
||||
* The interrupt performs now a compare-and-swap sequence which fails
|
||||
* with a branch to .L2. The current processor has now a reservation.
|
||||
* The interrupt returns without further stwcx. The thread updates the
|
||||
* value using the unrelated reservation of the interrupt.
|
||||
*/
|
||||
li SCRATCH_0_REGISTER, FRAME_OFFSET
|
||||
stwcx. SCRATCH_0_REGISTER, r1, SCRATCH_0_REGISTER
|
||||
|
||||
/* Load SRR0, SRR1, CR, XER, CTR, and LR */
|
||||
PPC_REG_LOAD SCRATCH_5_REGISTER, SRR0_FRAME_OFFSET(r1)
|
||||
PPC_REG_LOAD SCRATCH_6_REGISTER, SRR1_FRAME_OFFSET(r1)
|
||||
lwz SCRATCH_7_REGISTER, EXC_CR_OFFSET(r1)
|
||||
lwz SCRATCH_8_REGISTER, EXC_XER_OFFSET(r1)
|
||||
PPC_REG_LOAD SCRATCH_9_REGISTER, EXC_CTR_OFFSET(r1)
|
||||
PPC_REG_LOAD SCRATCH_10_REGISTER, EXC_LR_OFFSET(r1)
|
||||
|
||||
/* Restore volatile registers */
|
||||
PPC_GPR_LOAD SCRATCH_0_REGISTER, SCRATCH_0_OFFSET(r1)
|
||||
#ifdef __powerpc64__
|
||||
PPC_GPR_LOAD r2, GPR2_OFFSET(r1)
|
||||
#endif
|
||||
PPC_GPR_LOAD SCRATCH_1_REGISTER, SCRATCH_1_OFFSET(r1)
|
||||
PPC_GPR_LOAD SCRATCH_2_REGISTER, SCRATCH_2_OFFSET(r1)
|
||||
|
||||
#ifdef __SPE__
|
||||
/* Restore SPEFSCR and ACC */
|
||||
mtspr FSL_EIS_SPEFSCR, SCRATCH_3_REGISTER
|
||||
evmra SCRATCH_4_REGISTER, SCRATCH_4_REGISTER
|
||||
#endif
|
||||
|
||||
/* Restore volatile registers */
|
||||
PPC_GPR_LOAD SCRATCH_3_REGISTER, SCRATCH_3_OFFSET(r1)
|
||||
PPC_GPR_LOAD SCRATCH_4_REGISTER, SCRATCH_4_OFFSET(r1)
|
||||
|
||||
/* Restore SRR0, SRR1, CR, CTR, XER, and LR plus volatile registers */
|
||||
mtsrr0 SCRATCH_5_REGISTER
|
||||
PPC_GPR_LOAD SCRATCH_5_REGISTER, SCRATCH_5_OFFSET(r1)
|
||||
mtsrr1 SCRATCH_6_REGISTER
|
||||
PPC_GPR_LOAD SCRATCH_6_REGISTER, SCRATCH_6_OFFSET(r1)
|
||||
mtcr SCRATCH_7_REGISTER
|
||||
PPC_GPR_LOAD SCRATCH_7_REGISTER, SCRATCH_7_OFFSET(r1)
|
||||
mtxer SCRATCH_8_REGISTER
|
||||
PPC_GPR_LOAD SCRATCH_8_REGISTER, SCRATCH_8_OFFSET(r1)
|
||||
mtctr SCRATCH_9_REGISTER
|
||||
PPC_GPR_LOAD SCRATCH_9_REGISTER, SCRATCH_9_OFFSET(r1)
|
||||
mtlr SCRATCH_10_REGISTER
|
||||
PPC_GPR_LOAD SCRATCH_10_REGISTER, SCRATCH_10_OFFSET(r1)
|
||||
|
||||
/* Pop stack */
|
||||
addi r1, r1, PPC_EXC_INTERRUPT_FRAME_SIZE
|
||||
|
||||
/* Return */
|
||||
rfi
|
||||
|
||||
/* Symbol provided for debugging and tracing */
|
||||
ppc_exc_interrupt_end:
|
||||
|
||||
#endif /* PPC_EXC_CONFIG_USE_FIXED_HANDLER */
|
||||
Reference in New Issue
Block a user