source: trunk/hal/tsar_mips32/core/hal_kentry.S @ 349

Last change on this file since 349 was 296, checked in by alain, 7 years ago

Several modifs in the generic scheduler and in the hal_context to
fix the context switch mechanism.

File size: 10.6 KB
Line 
1/*
2 * hal_kentry.S - Interrupt / Exception / Syscall kernel entry point for MIPS32
3 *
4 * AUthors   Ghassan Almaless (2007,2008,2009,2010,2011,2012)
5 *           Mohamed Lamine Karaoui (2015)
6 *           Alain Greiner (2017)
7 *
8 * Copyright (c) UPMC Sorbonne Universites
9 *
10 * This file is part of ALMOS-MKH.
11 *
12 * ALMOS-MKH is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; version 2.0 of the License.
15 *
16 * ALMOS-MKH is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26#include <mips32_uzone.h>
27
28#---------------------------------------------------------------------------------
29# This code is the unique kernel entry point in case of exception, interrupt,
30# or syscall for the TSAR_MIPS32 architecture. 
31#
32# When we enter the kernel, we test the status register:
33# - If the core is in user mode, we desactivate the MMU, and we save
34#   the core context in the uzone of the calling thread descriptor.
35# - If the core is already in kernel mode (in case of interrupt),
36#   we save the context in the kernel stack.
37# - In both cases, we increment the cores_in_kernel variable,
38#   and we call the relevant exception/interrupt/syscall handler
39#
40# When we exit the kernel after handler execution:
41# - we restore the core context from the uzone
42#---------------------------------------------------------------------------------
43
44        .section   .kentry, "ax", @progbits
45
46        .extern    hal_do_interrupt
47        .extern    hal_do_exception
48        .extern    hal_do_syscall
49        .extern    cluster_core_kernel_enter
50        .extern    cluster_core_kernel_exit
51
52        .org       0x180
53        .ent       kernel_enter
54        .global    kernel_enter
55
56        .set       noat
57        .set       noreorder
58
59#define SAVE_SIZE      CPU_REGS_NR*4
60#define LID_WIDTH      2
61#define CXY_WIDTH      8
62#define CXY_MASK       0xFF
63#define MMU_MODE_MASK  0xF
64#define GID_MASK       0x3FF   
65#define LID_MASK       0x3     
66
67#---------------------------------------------------------------------------------
68# Kernel Entry point for Interrupt / Exception / Syscall
69#---------------------------------------------------------------------------------
70
71kernel_enter:
72        mfc0    $26,    $12                 # read SR to test user/kernel mode
73        andi    $26,    $26,  0x10          # User Mode bitmask
74        beq     $26,    $0,       kernel_mode
75        ori     $26,    $0,       0x3               # $26 <= MMU OFF value
76       
77#---------------------------------------------------------------------------------------       
78# this code is executed when the core is in user mode:
79# - we use the uzone defined in user thread descriptor.
80# - we set the MMU off, and save the CP2_MODE register to uzone.
81# - we save the user thread stack pointer to uzone and load the kernel stack pointer
82# - we store the uzone pointer in $27
83
84user_mode:
85        mtc2    $26,    $1                              # set MMU OFF
86        nop
87
88        mfc0    $26,    $4,   2             # $26 <= thread pointer
89        lw      $26,    0($26)              # $26 <= uzone pointer
90
91        sw      $29,    (UZ_SP*4)($26)      # save user stack to uzone
92        lw      $29,    (UZ_KSP*4)($26)     # load kernel stack from uzone
93
94        ori     $27,    $0,       0xF           # MMU old value: assumed ON
95        sw      $27,    (UZ_MODE*4)($26)    # save MMU MODE to uzone
96
97        j           unified_mode
98        or      $27,    $0,       $26           # $27 <= uzone
99
100#---------------------------------------------------------------------------------------       
101# this code is executed when the core is in kernel mode:
102# - we use an uzone dynamically allocated in kernel stack.
103# - we set the MMU off, set the MMU data_paddr extension to local_cxy,
104#   and save the CP2_MODE and CP2_DEXT to uzone.
105# - we save the kernel stack pointer to uzone and load the new kernel stack pointer
106# - we store the uzone pointer in $27
107
108kernel_mode:
109        mfc2    $26,    $24
110        andi    $26,    $26,  CXY_MASK      # $26 <= CP2_DEXT
111
112        mfc0    $27,    $15,  1
113        andi    $27,    $27,  GID_MASK      # $27 <= core_gid (4/4/2 format)   
114
115        srl         $27,    $27,  LID_WIDTH         # $27 <= local_cxy
116        mtc2    $27,    $24                             # set local_cxy to CP2_DEXT
117
118    # use $26 to save both CP2_MODE (4 bits) and CP2_DEXT (8 bits) values
119
120        mfc2    $27,    $1
121        andi    $27,    $27,  MMU_MODE_MASK     # $27 <= CP2_MODE
122        sll         $27,    $27,  CXY_WIDTH         # $27 <= 0x00000M00
123        or          $26,    $26,  $27           # $26 <= 0x00000MXY
124
125        ori     $27,    $0,       0x3
126        mtc2    $27,    $1                              # set MMU OFF
127
128        # save old SP, CP2_MODE and CP2_DEXT in uzone allocated in kernel stack
129
130        addiu   $27,    $29,  -(SAVE_SIZE)      # allocate an uzone in stack (use $27 as KSP)
131        sw      $29,    (UZ_SP*4)($27)      # save old KSP in this uzone
132
133        srl     $29,    $26,  CXY_WIDTH
134        sw      $29,    (UZ_MODE*4)($27)    # save CP2_MODE in this uzone
135
136        andi    $26,    $26,  CXY_MASK 
137        sw      $26,    (UZ_DEXT*4)($27)    # save CP2_DEXT in this uzone
138
139        or      $29,    $27,    $0          # load new kernel stack pointer
140
141#--------------------------------------------------------------------------------------
142# This code is executed in both modes, and saves the core context,
143# with the two following assumptions:
144# - $27 contains the pointer on uzone to save the core registers
145# - $29 contains the kernel stack pointer
146
147unified_mode:   
148        sw      $1,         (UZ_AT*4)($27)
149        sw      $2,     (UZ_V0*4)($27)
150        sw      $3,     (UZ_V1*4)($27)
151        sw      $4,     (UZ_A0*4)($27)
152        sw      $5,     (UZ_A1*4)($27)
153        sw      $6,     (UZ_A2*4)($27)
154        sw      $7,     (UZ_A3*4)($27)
155        sw      $8,     (UZ_T0*4)($27)
156        sw      $9,     (UZ_T1*4)($27)
157        sw      $10,    (UZ_T2*4)($27)
158        sw      $11,    (UZ_T3*4)($27)
159        sw      $12,    (UZ_T4*4)($27)
160        sw      $13,    (UZ_T5*4)($27)
161        sw      $14,    (UZ_T6*4)($27)
162        sw      $15,    (UZ_T7*4)($27)
163        sw      $16,    (UZ_S0*4)($27)
164        sw      $17,    (UZ_S1*4)($27)
165        sw          $18,        (UZ_S2*4)($27)
166        sw          $19,        (UZ_S3*4)($27)
167        sw          $20,        (UZ_S4*4)($27)
168        sw          $21,        (UZ_S5*4)($27)
169        sw          $22,        (UZ_S6*4)($27)
170        sw          $23,        (UZ_S7*4)($27)
171        sw      $24,    (UZ_T8*4)($27)
172        sw      $25,    (UZ_T9*4)($27)
173        sw          $28,        (UZ_GP*4)($27)
174        sw          $30,        (UZ_S8*4)($27)
175        sw          $31,        (UZ_RA*4)($27)
176
177        mfc0    $16,    $14
178        sw      $16,    (UZ_EPC*4)($27)     # Save EPC
179        mflo    $14
180        sw      $14,    (UZ_LO*4)($27)      # save LO
181        mfhi    $15
182        sw      $15,    (UZ_HI*4)($27)          # save HI
183        mfc0    $18,    $12
184        sw          $18,        (UZ_SR*4)($27)          # Save SR
185        mfc0    $17,    $13
186        sw      $17,    (UZ_CR*4)($27)          # Save CR
187
188    # put SR in kernel mode, IRQ disabled, clear exl
189        srl         $3,     $18,  5
190        sll     $3,         $3,   5     
191        mtc0    $3,         $12                         # Set new SR
192
193        # signal that core enters kernel
194        la      $1,     cluster_core_kernel_enter
195        jal         $1
196    nop
197
198#---------------------------------------------------------------------------------------
199# This code call the relevant Interrupt / Exception / Syscall handler,
200# depending on XCODE in CP0_CR, with the two following assumptions:
201# - $27 contains the pointer on uzone containing to save the core registers
202# - $29 contains the kernel stack pointer
203# The three handlers take the same two arguments: thread pointer and uzone pointer.
204# The uzone pointer is saved in $19 to be used by kernel_exit.
205
206        mfc0    $17,    $13                 # $17 <= CR
207        andi    $17,    $17,   0x3F         # $17 <= XCODE
208
209        mfc0    $4,     $4,   2             # $4 <= thread pointer (first arg)
210        or          $5,     $0,   $27               # $5 <= uzone pointer (second arg)
211        or          $19,    $0,   $27           # $19 <= &uzone (for kernel_exit)
212
213        ori         $8,     $0,   0x20          # $8 <= cause syscall
214    beq     $8,     $17,  cause_sys     # go to syscall handler
215    nop
216        beq     $17,    $0,       cause_int     # go to interrupt handler
217    nop
218
219cause_excp:
220        la      $1,         hal_do_exception
221        jalr    $1                              # call exception handler
222        addiu   $29,    $29,  -8                # hal_do_exception has 2 args
223        addiu   $29,    $29,  8
224        j       kernel_exit                 # jump to kernel_exit
225    nop
226
227cause_sys:
228        la          $1,         hal_do_syscall
229        jalr    $1                          # call syscall handler                 
230        addiu   $29,    $29,  -8            # hal_do_syscall has 2 args
231        addiu   $29,    $29,  8
232        j           kernel_exit                 # jump to kernel_exit
233        nop
234       
235cause_int:
236        la          $1,     hal_do_interrupt
237        jalr    $1                          # call interrupt handler
238        addiu   $29,    $29,  -8            # hal_do_interrupt has 2 args
239        addiu   $29,    $29,  8
240
241# -----------------------------------------------------------------------------------
242# Kernel exit
243# The pointer on uzone is supposed to be stored in $19
244# -----------------------------------------------------------------------------------
245kernel_exit:
246
247        # signal that core exit kernel
248    la      $1,     cluster_core_kernel_exit
249    jalr    $1
250    nop
251
252        # restore context from uzone
253        or          $27,    $0, $19             # $27 <= &uzone
254
255        lw          $29,        (UZ_SP*4)($27)          # restore SP from uzone
256        lw          $16,        (UZ_EPC*4)($27)       
257        mtc0    $16,    $14                             # restore EPC from uzone
258        lw          $16,    (UZ_HI*4)($27)
259        mthi    $16                                         # restore HI from uzone
260        lw          $16,    (UZ_LO*4)($27)
261        mtlo    $16                                         # restore LO from uzone
262
263        lw          $17,        (UZ_SR*4)($27)          # get saved SR value from uzone
264        andi    $17,    $17,    0x1F        # keep only the 5 LSB bits
265        mfc0    $26,    $12                             # get current SR value from CP0
266        or          $26,    $26,        $17         # merge the two values
267        mtc0    $26,    $12                             # setup new SR to CP0
268
269        lw          $1,     (UZ_AT*4)($27)             
270        lw          $2,     (UZ_V0*4)($27)
271        lw          $3,     (UZ_V1*4)($27)
272        lw          $4,     (UZ_A0*4)($27)
273        lw          $5,     (UZ_A1*4)($27)
274        lw          $6,     (UZ_A2*4)($27)
275        lw          $7,     (UZ_A3*4)($27)
276        lw          $8,     (UZ_T0*4)($27)
277        lw          $9,     (UZ_T1*4)($27)
278        lw          $10,    (UZ_T2*4)($27)
279        lw          $11,    (UZ_T3*4)($27)
280        lw          $12,    (UZ_T4*4)($27)
281        lw          $13,    (UZ_T5*4)($27)
282        lw          $14,    (UZ_T6*4)($27)
283        lw          $15,    (UZ_T7*4)($27)
284        lw          $16,    (UZ_S0*4)($27)
285        lw          $17,    (UZ_S1*4)($27)
286        lw          $18,        (UZ_S2*4)($27)
287        lw          $19,    (UZ_S3*4)($27)
288        lw          $20,        (UZ_S4*4)($27)
289        lw          $21,        (UZ_S5*4)($27)
290        lw          $22,        (UZ_S6*4)($27)
291        lw          $23,        (UZ_S7*4)($27)
292        lw          $24,    (UZ_T8*4)($27)
293        lw          $25,    (UZ_T9*4)($27)     
294        lw          $28,        (UZ_GP*4)($27)
295        lw          $30,        (UZ_S8*4)($27)
296        lw          $31,        (UZ_RA*4)($27)
297
298        lw          $26,    (UZ_DEXT*4)($27)
299        mtc2    $26,    $24                             # restore CP2_DEXT from uzone
300
301        lw          $26,    (UZ_MODE*4)($27)   
302    mtc2    $26,    $1                  # restore CP2_MODE from uzone
303
304        nop
305    eret
306
307    .end kernel_enter
308    .set reorder
309    .set at
310
311#-------------------------------------------------------------------------------
312
Note: See TracBrowser for help on using the repository browser.