source: rtems/cpukit/score/cpu/nios2/nios2-eic-il-low-level.S @ 9165349d

Last change on this file since 9165349d was 9165349d, checked in by Sebastian Huber <sebastian.huber@…>, on 01/12/21 at 06:13:08

nios2: Use Per_CPU_Control::isr_dispatch_disable

  • Property mode set to 100644
File size: 5.5 KB
RevLine 
[9f1412b9]1/*
[99a1f122]2 * Copyright (c) 2011-2015 embedded brains GmbH.  All rights reserved.
[9f1412b9]3 *
4 *  embedded brains GmbH
[99a1f122]5 *  Dornierstr. 4
[9f1412b9]6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
[c499856]12 * http://www.rtems.org/license/LICENSE.
[9f1412b9]13 */
14
15#include <rtems/score/percpu.h>
16#include <rtems/score/nios2-utility.h>
17
18#define FRAME_OFFSET_RA 0
19#define FRAME_OFFSET_AT 4
20#define FRAME_OFFSET_R2 8
21#define FRAME_OFFSET_R3 12
22#define FRAME_OFFSET_R4 16
23#define FRAME_OFFSET_R5 20
24#define FRAME_OFFSET_R6 24
25#define FRAME_OFFSET_R7 28
26#define FRAME_OFFSET_R8 32
27#define FRAME_OFFSET_R9 36
28#define FRAME_OFFSET_R10 40
29#define FRAME_OFFSET_R11 44
30#define FRAME_OFFSET_R12 48
31#define FRAME_OFFSET_R13 52
32#define FRAME_OFFSET_R14 56
33#define FRAME_OFFSET_R15 60
34#define FRAME_OFFSET_STATUS 64
35#define FRAME_OFFSET_EA  68
36
37#define FRAME_SIZE (FRAME_OFFSET_EA + 4)
38
39        .set    noat
[99a1f122]40        .set    nobreak
[9f1412b9]41        .section        .text
42
43        .extern _Per_CPU_Information
44        .extern _Nios2_ISR_Status_interrupts_disabled
45
46        .globl  _Nios2_ISR_Dispatch_with_shadow_non_preemptive
47
48_Nios2_ISR_Dispatch_with_shadow_non_preemptive:
49
50        /* Load thread dispatch disable level */
[98c95d1]51        ldw     r16, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
[9f1412b9]52
53        /* Load high level handler address and argument */
54        ldw     r8, 4(et)
55        ldw     r4, 8(et)
56
57        /* Increment and store thread dispatch disable level */
58        addi    r9, r16, 1
[98c95d1]59        stw     r9, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
[9f1412b9]60
61        /* Call high level handler with argument */
62        callr   r8
63
64        /* Load thread dispatch necessary */
65        ldb     r12, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
66
[9165349d]67        /* Load thread dispatch after ISR disable indicator */
68        ldw     r13, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
[9f1412b9]69
[64d2c8ad]70        /* Read status */
71        rdctl   r14, status
72
[9f1412b9]73        /* Fix return address */
74        subi    ea, ea, 4
75
76        /*
77         * Restore the thread dispatch disable level.  We must do this before
78         * we return to the normal register set, because otherwise we have
79         * problems if someone deletes or restarts the interrupted thread while
80         * we are in the thread dispatch helper.
81         */
[98c95d1]82        stw     r16, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
[9f1412b9]83
84        /* Is thread dispatch allowed? */
85        bne     r16, zero, no_thread_dispatch
86
87        /* Is thread dispatch necessary? */
88        beq     r12, zero, no_thread_dispatch
89
90        /* Is outermost interrupt? */
[64d2c8ad]91        andhi   r14, r14, 0x3f
[9f1412b9]92        bne     r14, zero, no_thread_dispatch
93
[9165349d]94        /* Is thread dispatch after ISR allowed? */
[9f1412b9]95        bne     r13, zero, no_thread_dispatch
96
97        /* Obtain stack frame in normal register set */
98        rdprs   r15, sp, -FRAME_SIZE
99
[9165349d]100        /* Disable thread dispatch after ISR */
101        stw     r12, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
[9f1412b9]102
103        /* Save context */
104        stw     sstatus, FRAME_OFFSET_STATUS(r15)
105        stw     ea, FRAME_OFFSET_EA(r15)
106
107        /* Set thread dispatch helper address */
108        movhi   ea, %hiadj(thread_dispatch_helper)
109        addi    ea, ea, %lo(thread_dispatch_helper)
110
111        /* Update stack pointer in normal register set */
112        wrprs   sp, r15
113
114no_thread_dispatch:
115
116        /*
117         * Return to thread dispatch helper, interrupted thread or interrupted
118         * lower level interrupt service routine.
119         */
120        eret
121
122thread_dispatch_helper:
123
124        /* This code executes in the context of the interrupted thread */
125
126        /* Save volatile registers */
127        stw     ra, FRAME_OFFSET_RA(sp)
128        stw     at, FRAME_OFFSET_AT(sp)
129        stw     r2, FRAME_OFFSET_R2(sp)
130        stw     r3, FRAME_OFFSET_R3(sp)
131        stw     r4, FRAME_OFFSET_R4(sp)
132        stw     r5, FRAME_OFFSET_R5(sp)
133        stw     r6, FRAME_OFFSET_R6(sp)
134        stw     r7, FRAME_OFFSET_R7(sp)
135        stw     r8, FRAME_OFFSET_R8(sp)
136        stw     r9, FRAME_OFFSET_R9(sp)
137        stw     r10, FRAME_OFFSET_R10(sp)
138        stw     r11, FRAME_OFFSET_R11(sp)
139        stw     r12, FRAME_OFFSET_R12(sp)
140        stw     r13, FRAME_OFFSET_R13(sp)
141        stw     r14, FRAME_OFFSET_R14(sp)
142        stw     r15, FRAME_OFFSET_R15(sp)
143
144do_thread_dispatch:
145
146        call    _Thread_Dispatch
147
148        /* Restore some volatile registers */
149        ldw     ra, FRAME_OFFSET_RA(sp)
150        ldw     at, FRAME_OFFSET_AT(sp)
151        ldw     r2, FRAME_OFFSET_R2(sp)
152        ldw     r3, FRAME_OFFSET_R3(sp)
153        ldw     r4, FRAME_OFFSET_R4(sp)
154        ldw     r5, FRAME_OFFSET_R5(sp)
155        ldw     r6, FRAME_OFFSET_R6(sp)
156        ldw     r7, FRAME_OFFSET_R7(sp)
157        ldw     r8, FRAME_OFFSET_R8(sp)
158        ldw     r9, FRAME_OFFSET_R9(sp)
159        ldw     r10, FRAME_OFFSET_R10(sp)
160        ldw     r11, FRAME_OFFSET_R11(sp)
161        ldw     r12, FRAME_OFFSET_R12(sp)
162
163        /*
164         * Disable interrupts.
165         *
166         * We have the following invariants:
167         *   1. status.RSIE == 0: thread context initialization
168         *   2. status.CRS == 0: thread context initialization
169         *   3. status.PRS: arbitrary
170         *   4. status.IL < interrupt disable IL: else we would not be here
171         *   5. status.IH == 0: thread context initialization
172         *   6. status.U == 0: thread context initialization
173         *   7. status.PIE == 1: thread context initialization
174         * Thus we can use a constant to disable interrupts.
175         */
176        rdctl   r14, status
177        movi    r15, %lo(_Nios2_ISR_Status_interrupts_disabled)
178        wrctl   status, r15
179
180        /* Load thread dispatch necessary */
[0cce75e]181        ldb     r13, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
[9f1412b9]182
183        /* Is thread dispatch necessary? */
[0cce75e]184        bne     r13, zero, enable_interrupts_before_thread_dispatch
[9f1412b9]185
[9165349d]186        /* Enable thread dispatch after ISR */
187        stw     zero, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
[9f1412b9]188
189        /* Restore remaining volatile register */
[0cce75e]190        ldw     r13, FRAME_OFFSET_R13(sp)
[9f1412b9]191        ldw     r14, FRAME_OFFSET_R14(sp)
192        ldw     r15, FRAME_OFFSET_R15(sp)
193
194        /* Restore context */
195        ldw     et, FRAME_OFFSET_STATUS(sp)
196        ldw     ea, FRAME_OFFSET_EA(sp)
197
198        /* Release stack frame */
199        addi    sp, sp, FRAME_SIZE
200
201        /* Restore context */
202        wrctl   estatus, et
203
204        /* Return to interrupted thread */
205        eret
206
207enable_interrupts_before_thread_dispatch:
208
209        /* Restore status */
210        wrctl   status, r14
211
212        br      do_thread_dispatch
Note: See TracBrowser for help on using the repository browser.