source: rtems/bsps/i386/shared/irq/irq_asm.S @ 3fe2155

5
Last change on this file since 3fe2155 was 3fe2155, checked in by Sebastian Huber <sebastian.huber@…>, on Feb 1, 2019 at 9:00:36 AM

Remove superfluous <rtems/system.h> includes

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/*
2 *  This file contains the implementation of the function described in irq.h
3 */
4
5/*
6 *  Copyright (C) 1998 valette@crf.canon.fr
7 *
8 *  COPYRIGHT (c) 1989-2011.
9 *  On-Line Applications Research Corporation (OAR).
10 *
11 *  The license and distribution terms for this file may be
12 *  found in found in the file LICENSE in this distribution or at
13 *  http://www.rtems.org/license/LICENSE.
14 */
15
16#include <rtems/asm.h>
17#include <bspopts.h>
18#include <rtems/score/cpu.h>
19#include <rtems/score/percpu.h>
20
21#include <bsp.h> /* to establish dependency on prototype */
22
23#ifndef CPU_STACK_ALIGNMENT
24#error "Missing header? CPU_STACK_ALIGNMENT is not defined here"
25#endif
26
27/* Stack frame we use for intermediate storage               */
28#define ARG_OFF 0
29#define MSK_OFF 4        /* not used any more                */
30#define EBX_OFF 8        /* ebx                              */
31#define EBP_OFF 12       /* code restoring ebp/esp relies on */
32#define ESP_OFF 16       /* esp being on top of ebp!         */
33#ifdef __SSE__
34/* need to be on 16 byte boundary for SSE, add 12 to do that */
35#define FRM_SIZ (20+12+512)
36#define SSE_OFF 32
37#else
38#define FRM_SIZ 20
39#endif
40
41        BEGIN_CODE
42
43SYM (_ISR_Handler):
44        /*
45         *  Before this was point is reached the vectors unique
46         *  entry point did the following:
47         *
48         *     1. saved scratch registers registers eax edx ecx"
49         *     2. put the vector number in ecx.
50         *
51         * BEGINNING OF ESTABLISH SEGMENTS
52         *
53         *  WARNING: If an interrupt can occur when the segments are
54         *           not correct, then this is where we should establish
55         *           the segments.  In addition to establishing the
56         *           segments, it may be necessary to establish a stack
57         *           in the current data area on the outermost interrupt.
58         *
59         *  NOTE:  If the previous values of the segment registers are
60         *         pushed, do not forget to adjust SAVED_REGS.
61         *
62         *  NOTE:  Make sure the exit code which restores these
63         *         when this type of code is needed.
64         */
65
66        /***** ESTABLISH SEGMENTS CODE GOES HERE  ******/
67
68        /*
69         * END OF ESTABLISH SEGMENTS
70         */
71
72        /*
73         * Establish an aligned stack frame
74         *   original sp
75         *   saved ebx
76         *   saved ebp
77         *   saved irq mask
78         *   vector arg to BSP_dispatch_isr   <- aligned SP
79         */
80        movl      esp, eax
81        subl      $FRM_SIZ, esp
82        andl      $ - CPU_STACK_ALIGNMENT, esp
83        movl      ebx, EBX_OFF(esp)
84        movl      eax, ESP_OFF(esp)
85        movl      ebp, EBP_OFF(esp)
86
87        /*
88         * GCC versions starting with 4.3 no longer place the cld
89         * instruction before string operations.  We  need to ensure
90         * it is set correctly for ISR handlers.
91         */
92        cld
93
94#ifdef __SSE__
95        /* NOTE: SSE only is supported if the BSP enables fxsave/fxrstor
96         * to save/restore SSE context! This is so far only implemented
97         * for pc386!.
98         */
99
100        /* We save SSE here (on the task stack) because we possibly
101         * call other C-code (besides the ISR, namely _Thread_Dispatch())
102         */
103    /*  don't wait here; a possible exception condition will eventually be
104     *  detected when the task resumes control and executes a FP instruction
105        fwait
106     */
107        fxsave SSE_OFF(esp)
108        fninit                          /* clean-slate FPU                */
109        movl   $0x1f80, ARG_OFF(esp)    /* use ARG_OFF as scratch space   */
110        ldmxcsr ARG_OFF(esp)            /* clean-slate MXCSR              */
111#endif
112
113        /*
114         *  Now switch stacks if necessary
115         */
116
117PUBLIC (ISR_STOP)
118ISR_STOP:
119.check_stack_switch:
120        movl      esp, ebp                  /* ebp = previous stack pointer */
121
122#ifdef RTEMS_SMP
123        call      SYM(_CPU_SMP_Get_current_processor)
124        sall      $PER_CPU_CONTROL_SIZE_LOG2, eax
125        addl      $SYM(_Per_CPU_Information), eax
126        movl      eax, ebx
127#else
128        movl      $SYM(_Per_CPU_Information), ebx
129#endif
130
131        /* is this the outermost interrupt? */
132        cmpl      $0, PER_CPU_ISR_NEST_LEVEL(ebx)
133        jne       nested                    /* No, then continue */
134        movl      PER_CPU_INTERRUPT_STACK_HIGH(ebx), esp
135
136        /*
137         *  We want to insure that the old stack pointer is in ebp
138         *  By saving it on every interrupt, all we have to do is
139         *  movl ebp->esp near the end of every interrupt.
140         */
141
142nested:
143        incl      PER_CPU_ISR_NEST_LEVEL(ebx)  /* one nest level deeper */
144        incl      PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(ebx) /* disable
145                                                                multitasking */
146        /*
147         *  ECX is preloaded with the vector number; store as arg
148         *  on top of stack. Note that _CPU_Interrupt_stack_high
149         *  was adjusted in _CPU_Interrupt_stack_setup() (score/rtems/cpu.h)
150         *  to make sure there is space.
151         */
152
153        movl      ecx, ARG_OFF(esp)  /* store vector arg in stack */
154        call      BSP_dispatch_isr
155
156        movl      ARG_OFF(esp), ecx     /* grab vector arg from stack */
157
158        /*
159         * Restore stack. This moves back to the task stack
160         * when all interrupts are unnested.
161         */
162        movl      ebp, esp
163
164        decl      PER_CPU_ISR_NEST_LEVEL(ebx)  /* one less ISR nest level */
165                                            /* If interrupts are nested, */
166                                            /*   then dispatching is disabled */
167
168        decl      PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(ebx)
169                                            /* unnest multitasking */
170                                            /* Is dispatch disabled */
171        jne       .exit                     /* Yes, then exit */
172
173        cmpb      $0, PER_CPU_DISPATCH_NEEDED(ebx)
174                                            /* Is task switch necessary? */
175        jne       .schedule                 /* Yes, then call the scheduler */
176        jmp       .exit                     /* No, exit */
177
178.schedule:
179        /*
180         * the scratch registers have already been saved and we are already
181         * back on the thread system stack. So we can call _Thread_Dispatch
182         * directly
183         */
184        call      _Thread_Dispatch
185        /*
186         * fall through exit to restore complete contex (scratch registers
187         * eip, CS, Flags).
188         */
189.exit:
190
191#ifdef __SSE__
192        fwait
193        fxrstor   SSE_OFF(esp)
194#endif
195
196        /* restore ebx, ebp and original esp */
197        addl      $EBX_OFF, esp
198        popl      ebx
199        popl      ebp
200        popl      esp
201
202        /*
203         * BEGINNING OF DE-ESTABLISH SEGMENTS
204         *
205         *  NOTE:  Make sure there is code here if code is added to
206         *         load the segment registers.
207         *
208         */
209
210        /******* DE-ESTABLISH SEGMENTS CODE GOES HERE ********/
211
212        /*
213         * END OF DE-ESTABLISH SEGMENTS
214         */
215        popl      edx
216        popl      ecx
217        popl      eax
218        iret
219
220#define DISTINCT_INTERRUPT_ENTRY(_vector) \
221        .p2align 4                         ; \
222        PUBLIC (rtems_irq_prologue_ ## _vector ) ; \
223SYM (rtems_irq_prologue_ ## _vector ):             \
224        pushl     eax                ; \
225        pushl     ecx                ; \
226        pushl     edx                ; \
227        movl      $ _vector, ecx     ; \
228        jmp       SYM (_ISR_Handler) ;
229
230DISTINCT_INTERRUPT_ENTRY(0)
231DISTINCT_INTERRUPT_ENTRY(1)
232DISTINCT_INTERRUPT_ENTRY(2)
233DISTINCT_INTERRUPT_ENTRY(3)
234DISTINCT_INTERRUPT_ENTRY(4)
235DISTINCT_INTERRUPT_ENTRY(5)
236DISTINCT_INTERRUPT_ENTRY(6)
237DISTINCT_INTERRUPT_ENTRY(7)
238DISTINCT_INTERRUPT_ENTRY(8)
239DISTINCT_INTERRUPT_ENTRY(9)
240DISTINCT_INTERRUPT_ENTRY(10)
241DISTINCT_INTERRUPT_ENTRY(11)
242DISTINCT_INTERRUPT_ENTRY(12)
243DISTINCT_INTERRUPT_ENTRY(13)
244DISTINCT_INTERRUPT_ENTRY(14)
245DISTINCT_INTERRUPT_ENTRY(15)
246DISTINCT_INTERRUPT_ENTRY(16)
247
248        /*
249         * routine used to initialize the IDT by default
250         */
251
252PUBLIC (default_raw_idt_handler)
253PUBLIC (raw_idt_notify)
254
255SYM (default_raw_idt_handler):
256        pusha
257        cld
258        mov       esp, ebp
259        andl     $ - CPU_STACK_ALIGNMENT, esp
260        call      raw_idt_notify
261        mov       ebp, esp
262        popa
263        iret
264
265END_CODE
266
267END
Note: See TracBrowser for help on using the repository browser.