source: rtems/cpukit/score/cpu/m68k/cpu_asm.S @ 511dc4b

5
Last change on this file since 511dc4b was 511dc4b, checked in by Sebastian Huber <sebastian.huber@…>, on 06/19/18 at 07:09:51

Rework initialization and interrupt stack support

Statically initialize the interrupt stack area
(_Configuration_Interrupt_stack_area_begin,
_Configuration_Interrupt_stack_area_end, and
_Configuration_Interrupt_stack_size) via <rtems/confdefs.h>. Place the
interrupt stack area in a special section ".rtemsstack.interrupt". Let
BSPs define the optimal placement of this section in their linker
command files (e.g. in a fast on-chip memory).

This change makes makes the CPU_HAS_SOFTWARE_INTERRUPT_STACK and
CPU_HAS_HARDWARE_INTERRUPT_STACK CPU port defines superfluous, since the
low level initialization code has all information available via global
symbols.

This change makes the CPU_ALLOCATE_INTERRUPT_STACK CPU port define
superfluous, since the interrupt stacks are allocated by confdefs.h for
all architectures. There is no need for BSP-specific linker command
file magic (except the section placement), see previous ARM linker
command file as a bad example.

Remove _CPU_Install_interrupt_stack(). Initialize the hardware
interrupt stack in _CPU_Initialize() if necessary (e.g.
m68k_install_interrupt_stack()).

The optional _CPU_Interrupt_stack_setup() is still useful to customize
the registration of the interrupt stack area in the per-CPU information.

The initialization stack can reuse the interrupt stack, since

  • interrupts are disabled during the sequential system initialization, and
  • the boot_card() function does not return.

This stack resuse saves memory.

Changes per architecture:

arm:

  • Mostly replace the linker symbol based configuration of stacks with the standard <rtems/confdefs.h> configuration via CONFIGURE_INTERRUPT_STACK_SIZE. The size of the FIQ, ABT and UND mode stack is still defined via linker symbols. These modes are rarely used in applications and the default values provided by the BSP should be sufficient in most cases.
  • Remove the bsp_processor_count linker symbol hack used for the SMP support. This is possible since the interrupt stack area is now allocated by the linker and not allocated from the heap. This makes some configure.ac stuff obsolete. Remove the now superfluous BSP variants altcycv_devkit_smp and realview_pbx_a9_qemu_smp.

bfin:

  • Remove unused magic linker command file allocation of initialization stack. Maybe a previous linker command file copy and paste problem? In the start.S the initialization stack is set to a hard coded value.

lm32, m32c, mips, nios2, riscv, sh, v850:

  • Remove magic linker command file allocation of initialization stack. Reuse interrupt stack for initialization stack.

m68k:

  • Remove magic linker command file allocation of initialization stack. Reuse interrupt stack for initialization stack.

powerpc:

  • Remove magic linker command file allocation of initialization stack. Reuse interrupt stack for initialization stack.
  • Used dedicated memory region (REGION_RTEMSSTACK) for the interrupt stack on BSPs using the shared linkcmds.base (replacement for REGION_RWEXTRA).

sparc:

  • Remove the hard coded initialization stack. Use the interrupt stack for the initialization stack on the boot processor. This saves 16KiB of RAM.

Update #3459.

  • Property mode set to 100644
File size: 13.2 KB
Line 
1/*  cpu_asm.s
2 *
3 *  This file contains all assembly code for the MC68020 implementation
4 *  of RTEMS.
5 *
6 *  COPYRIGHT (c) 1989-2008.
7 *  On-Line Applications Research Corporation (OAR).
8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
11 *  http://www.rtems.org/license/LICENSE.
12 */
13
14
15#ifdef HAVE_CONFIG_H
16#include "config.h"
17#endif
18
19#include <rtems/asm.h>
20#include <rtems/score/percpu.h>
21
22/*  void _CPU_Context_switch( run_context, heir_context )
23 *
24 *  This routine performs a normal non-FP context.
25 */
26
27        .align  4
28        .global SYM (_CPU_Context_switch)
29
30.set RUNCONTEXT_ARG,   4                 | save context argument
31.set HEIRCONTEXT_ARG,  8                 | restore context argument
32
33SYM (_CPU_Context_switch):
34          moval    a7@(RUNCONTEXT_ARG),a0| a0 = running thread context
35          movw     sr,d1                 | d1 = status register
36          movml    d1-d7/a2-a7,a0@       | save context
37
38          moval    a7@(HEIRCONTEXT_ARG),a0| a0 = heir thread context
39
40#if defined( __mcoldfire__ ) && ( M68K_HAS_FPU == 1 )
41          moveb    a0@(13*4),d0                 | get context specific DF bit info in d0
42          btstb    #4,d0                        | test context specific DF bit info
43          beq      fpu_on                       | branch if FPU needs to be switched on
44
45fpu_off:  movl     _CPU_cacr_shadow,d0          | get content of _CPU_cacr_shadow in d0
46          btstl    #4,d0                        | test DF bit info in d0
47          bne      restore                      | branch if FPU is already switched off
48          bsetl    #4,d0                        | set DF bit in d0
49          bra      cacr_set                     | branch to set the new FPU setting in cacr and _CPU_cacr_shadow
50
51fpu_on:   movl     _CPU_cacr_shadow,d0          | get content of _CPU_cacr_shadow in d1
52          btstl    #4,d0                        | test context specific DF bit info
53          beq      restore                      | branch if FPU is already switched on
54          bclrl    #4,d0                        | clear DF bit info in d0
55
56cacr_set: movew    sr,d1                        | get content of sr in d1
57          oril     #0x00000700,d1               | mask d1
58          movew    d1,sr                        | disable all interrupts
59          movl     d0,_CPU_cacr_shadow          | move _CPU_cacr_shadow to d1
60          movec    d0,cacr                      | enable FPU in cacr
61#endif
62
63
64restore:  movml    a0@,d1-d7/a2-a7       | restore context
65          movw     d1,sr                 | restore status register
66          rts
67
68        .global SYM (_CPU_Context_Restart_self)
69.set    CONTEXT_ARG, 4                   | context arg
70
71#if defined( __mcoldfire__ ) && ( M68K_HAS_FPU == 1 )
72/* XXX _CPU_Context_switch maintains FPU context -- do we have to restore
73 *     that, too??
74 */
75#warning "_CPU_Context_Restart_self restoring FPU context not implemented"
76#endif
77SYM(_CPU_Context_Restart_self):
78         moval    a7@(CONTEXT_ARG),a0
79         bra      restore
80/*
81 * Floating point context save and restore.
82 *
83 * The code for the MC68881 or MC68882 is based upon the code shown on pages
84 * 6-38 of the MC68881/68882 Users Manual (rev 1).  CPU_FP_CONTEXT_SIZE is
85 * higher than expected to account for the -1 pushed at end of this sequence.
86 */
87
88#if ( CPU_HARDWARE_FP == TRUE )
89
90.set FPCONTEXT_ARG,   4                   | save FP context argument
91
92        .align  4
93        .global SYM (_CPU_Context_save_fp)
94SYM (_CPU_Context_save_fp):
95
96        /* Get context save area pointer argument from the stack */
97        moval    a7@(FPCONTEXT_ARG), a1
98        moval    a1@, a0
99
100  #if defined( __mcoldfire__ )
101        /* Move MACSR to data register and disable rounding */
102        movel    macsr, d0
103        clrl     d1
104        movl     d1, macsr
105
106        /* Save MACSR and ACC0 */
107        movl     acc0, d1
108        moveml   d0-d1, a0@(0)
109
110        /* Save ACC1 and ACC2 */
111        movl     acc1, d0
112        movl     acc2, d1
113        moveml   d0-d1, a0@(8)
114
115        /* Save ACC3 and ACCEXT01 */
116        movl     acc3, d0
117        movl     accext01, d1
118        moveml   d0-d1, a0@(16)
119
120        /* Save ACCEXT23 and MASK */
121        movl     accext23, d0
122        movl     mask, d1
123        moveml   d0-d1, a0@(24)
124
125    #if ( M68K_HAS_FPU == 1 )
126        /* Save FP state */
127        fsave    a0@(32)
128
129        /* Save FP instruction address */
130        fmovel   fpi, a0@(48)
131
132        /* Save FP data */
133        fmovem   fp0-fp7, a0@(52)
134    #endif
135  #else
136    #if defined( __mc68060__ )
137        lea      a0@(-M68K_FP_STATE_SIZE), a0
138        fsave    a0@                      | save 68060 state frame
139    #else
140        fsave    a0@-                     | save 68881/68882 state frame
141    #endif
142        tstb     a0@                      | check for a null frame
143        beq.b    nosv                     | Yes, skip save of user model
144        fmovem   fp0-fp7, a0@-            | save data registers (fp0-fp7)
145        fmovem   fpc/fps/fpi, a0@-        | and save control registers
146        movl     #-1, a0@-                | place not-null flag on stack
147nosv:
148        movl     a0, a1@                  | save pointer to saved context
149  #endif
150
151        /* Return */
152        rts
153
154        .align  4
155        .global SYM (_CPU_Context_restore_fp)
156SYM (_CPU_Context_restore_fp):
157
158        /* Get context save area pointer argument from the stack */
159        moval    a7@(FPCONTEXT_ARG), a1
160        moval    a1@, a0
161
162  #if defined( __mcoldfire__ )
163    #if ( M68K_HAS_FPU == 1 )
164        /* Restore FP data */
165        fmovem   a0@(52), fp0-fp7
166
167        /* Restore FP instruction address */
168        fmovel   a0@(48), fpi
169
170        /* Restore FP state */
171        frestore a0@(32)
172    #endif
173
174        /* Disable rounding */
175        clrl     d0
176        movl     d0, macsr
177
178        /* Restore MASK and ACCEXT23 */
179        moveml   a0@(24), d0-d1
180        movl     d0, mask
181        movl     d1, accext23
182
183        /* Restore ACCEXT01 and ACC3 */
184        moveml   a0@(16), d0-d1
185        movl     d0, accext01
186        movl     d1, acc3
187
188        /* Restore ACC2 and ACC1 */
189        moveml   a0@(8), d0-d1
190        movl     d0, acc2
191        movl     d1, acc1
192
193        /* Restore ACC0 and MACSR */
194        moveml   a0@(0), d0-d1
195        movl     d0, acc0
196        movl     d1, macsr
197  #else
198        tstb     a0@                      | Null context frame?
199        beq.b    norst                    | Yes, skip fp restore
200        addql    #4, a0                   | throwaway non-null flag
201        fmovem   a0@+, fpc/fps/fpi        | restore control registers
202        fmovem   a0@+, fp0-fp7            | restore data regs (fp0-fp7)
203norst:
204    #if defined( __mc68060__ )
205        frestore a0@                      | restore 68060 state frame
206        lea      a0@(M68K_FP_STATE_SIZE), a0
207    #else
208        frestore a0@+                     | restore 68881/68882 state frame
209    #endif
210        movl     a0, a1@                  | save pointer to saved context
211  #endif
212
213        /* Return */
214        rts
215#endif
216
217/*void _ISR_Handler()
218 *
219 *  This routine provides the RTEMS interrupt management.
220 *
221 *  NOTE:
222 *    Upon entry, the master stack will contain an interrupt stack frame
223 *    back to the interrupted thread and the interrupt stack will contain
224 *    a throwaway interrupt stack frame.  If dispatching is enabled, and this
225 *    is the outer most interrupt, and a context switch is necessary or
226 *    the current thread has pending signals, then set up the master stack to
227 *    transfer control to the interrupt dispatcher.
228 */
229
230#if ( defined(__mcoldfire__) )
231.set SR_OFFSET,    2                     | Status register offset
232.set PC_OFFSET,    4                     | Program Counter offset
233.set FVO_OFFSET,   0                     | Format/vector offset
234#elif ( M68K_HAS_VBR == 1)
235.set SR_OFFSET,    0                     | Status register offset
236.set PC_OFFSET,    2                     | Program Counter offset
237.set FVO_OFFSET,   6                     | Format/vector offset
238#else
239.set SR_OFFSET,    2                     | Status register offset
240.set PC_OFFSET,    4                     | Program Counter offset
241.set FVO_OFFSET,   0                     | Format/vector offset placed in the stack
242#endif /* M68K_HAS_VBR */
243
244.set SAVED,        16                    | space for saved registers
245
246        .align  4
247        .global SYM (_ISR_Handler)
248
249SYM (_ISR_Handler):
250                                         | disable multitasking
251        addql   #1,THREAD_DISPATCH_DISABLE_LEVEL
252#if ( !defined(__mcoldfire__) )
253        moveml  d0-d1/a0-a1,a7@-         | save d0-d1,a0-a1
254#else
255        lea     a7@(-SAVED),a7
256        movm.l  d0-d1/a0-a1,a7@          | save d0-d1,a0-a1
257#endif
258        movew   a7@(SAVED+FVO_OFFSET),d0 | d0 = F/VO
259        andl    #0x03fc,d0               | d0 = vector offset in vbr
260
261
262#if ( M68K_HAS_SEPARATE_STACKS == 0 )
263        | Make a0 point just above interrupt stack
264        movel   INTERRUPT_STACK_HIGH,a0
265        cmpl    INTERRUPT_STACK_LOW,a7  | stack below interrupt stack?
266        bcs.b   1f                      | yes, switch to interrupt stack
267        cmpl    a0,a7                   | stack above interrupt stack?
268        bcs.b   2f                      | no, do not switch stacks
2691:
270        movel   a7,a1                   | copy task stack pointer
271        movel   a0,a7                   | switch to interrupt stack
272        movel   a1,a7@-                 | store task stack pointer
273                                        |     on interrupt stack
2742:
275#endif /* M68K_HAS_SEPARATE_STACKS == 0 */
276
277        addql   #1,ISR_NEST_LEVEL        | one nest level deeper
278
279        lea     SYM(_ISR_Vector_table),a0
280        movel   (a0,d0),a0               | a0 = address of user routine
281
282        lsrl    #2,d0                    | d0 = vector number
283        movel   d0,a7@-                  | push vector number
284        jbsr    a0@                      | invoke the user ISR
285        addql   #4,a7                    | remove vector number
286        subql   #1,ISR_NEST_LEVEL        | Reduce interrupt-nesting count
287
288#if ( M68K_HAS_SEPARATE_STACKS == 0 )
289        movel   INTERRUPT_STACK_HIGH,a0
290        subql   #4,a0
291        cmpl    a0,a7                   | At top of interrupt stack?
292        bne.b   1f                      | No, do not restore task stack pointer
293        movel   (a7),a7                 | Restore task stack pointer
2941:
295#endif /* M68K_HAS_SEPARATE_STACKS == 0 */
296        subql   #1,THREAD_DISPATCH_DISABLE_LEVEL
297                                         | unnest multitasking
298        bne.b    exit                    | If dispatch disabled, exit
299
300#if ( M68K_HAS_SEPARATE_STACKS == 1 )
301        movew   #0xf000,d0               | isolate format nibble
302        andw    a7@(SAVED+FVO_OFFSET),d0 | get F/VO
303        cmpiw   #0x1000,d0               | is it a throwaway isf?
304        bne.b   exit                     | NOT outer level, so branch
305#else
306/*
307 * If we have a CPU which allows a higher-priority interrupt to preempt a
308 * lower priority handler before the lower-priority handler can increment
309 * _Thread_Dispatch_disable_level then we must check the PC on the stack to
310 * see if it is _ISR_Handler.  If it is we have the case of nesting interrupts
311 * without the dispatch level being incremented.
312 */
313  #if ( !defined(__mcoldfire__) && !__mc68060__ )
314        cmpl    #_ISR_Handler,a7@(SAVED+PC_OFFSET)
315        beq.b   exit
316  #endif
317#endif
318        tstb    DISPATCH_NEEDED
319                                         | Is thread switch necessary?
320        beq.b   exit                     | No, then exit
321
322bframe:
323                                         | If sent, will be processed
324#if ( M68K_HAS_SEPARATE_STACKS == 1 )
325        movec   msp,a0                   | a0 = master stack pointer
326        movew   #0,a0@-                  | push format word
327        movel   #SYM(_ISR_Dispatch),a0@- | push return addr
328        movew   a0@(6),a0@-              | push saved sr
329        movec   a0,msp                   | set master stack pointer
330#else
331        jsr SYM (_Thread_Dispatch)       | Perform context switch
332#endif
333
334#if ( !defined(__mcoldfire__) )
335exit:   moveml  a7@+,d0-d1/a0-a1         | restore d0-d1,a0-a1
336#else
337exit:   moveml  a7@,d0-d1/a0-a1          | restore d0-d1,a0-a1
338        lea     a7@(SAVED),a7
339#endif
340
341#if ( M68K_HAS_VBR == 0 )
342        addql   #2,a7                    | pop format/id
343#endif /* M68K_HAS_VBR */
344        rte                              | return to thread
345                                         |   OR _Isr_dispatch
346
347/*void _ISR_Dispatch()
348 *
349 *  Entry point from the outermost interrupt service routine exit.
350 *  The current stack is the supervisor mode stack if this processor
351 *  has separate stacks.
352 *
353 *    1.  save all registers not preserved across C calls.
354 *    2.  invoke the _Thread_Dispatch routine to switch tasks
355 *        or a signal to the currently executing task.
356 *    3.  restore all registers not preserved across C calls.
357 *    4.  return from interrupt
358 */
359
360        .global SYM (_ISR_Dispatch)
361SYM (_ISR_Dispatch):
362#if ( !defined(__mcoldfire__) )
363        movml   d0-d1/a0-a1,a7@-
364        jsr     SYM (_Thread_Dispatch)
365        movml   a7@+,d0-d1/a0-a1
366#else
367        lea     a7@(-SAVED),a7
368        movml   d0-d1/a0-a1,a7@
369        jsr     SYM (_Thread_Dispatch)
370        movml   a7@,d0-d1/a0-a1
371        lea     a7@(SAVED),a7
372#endif
373
374#if ( M68K_HAS_VBR == 0 )
375        addql   #2,a7                    | pop format/id
376#endif /* M68K_HAS_VBR */
377        rte
Note: See TracBrowser for help on using the repository browser.