source: trunk/hal/tsar_mips32/hal_kentry.S @ 26

Last change on this file since 26 was 16, checked in by alain, 8 years ago

mprove the HAL for interrupt, exception, syscall handling.

File size: 11.0 KB
Line 
1/*
2 * hal_kentry.S - exception/interrupt/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# - If the core is in user mode:
33#   . we desactivate the MMU.
34#   . we save the context in the uzone of the calling thread descriptor.
35#   . we increment the cores_in_kernel variable.
36#   . we call the relevant exception/interrupt/syscall handler
37#
38# - If the core is already in kernel mode:
39#   . we save the context in the kernel stack
40#   . we call the relevant exception/interrupt/syscall handler
41#
42# - In both cases, when the handler returns:
43#   . we restore the context
44#   . we reactivate the MMU ???
45#---------------------------------------------------------------------------------
46
47        .section   .kentry,"ax",@progbits
48        .extern    cpu_do_interrupt
49        .extern    cpu_do_exception
50        .extern    cpu_do_syscall
51        .extern    cpu_kentry
52        .extern    cpu_kexit
53        .org       0x180
54        .ent       kentry
55        .global    kentry
56        .global    kentry_load
57        .set       noat
58        .set       noreorder
59
60#define SAVE_SIZE      CPU_REGS_NR*4
61#define LID_WIDTH      2
62#define CXY_WIDTH      8
63#define CXY_MASK       0xFF
64#define MMU_MODE_MASK  0xF
65#define GID_MASK       0x3FF   
66#define LID_MASK       0x3     
67
68#---------------------------------------------------------------------------------
69# Kernel Entry point
70#---------------------------------------------------------------------------------
71
72kentry:
73        mfc0    $26,    $12                 # read SR to test user/kernel mode
74        andi    $26,    $26,  0x10          # User Mode bitmask
75        beq     $26,    $0,       kernel_mode
76        ori     $26,    $0,       0x3               # $26 <= MMU OFF value
77       
78#---------------------------------------------------------------------------------------       
79# this code is executed when the core is in user mode:
80# - we use the uzone defined in user thread descriptor.
81# - we set the MMU off, and save the CP2_MODE register to uzone.
82# - we save the user thread stack pointer to uzone and load the kernel stack pointer
83# - we store the uzone pointer in $27
84
85user_mode:
86        mtc2    $26,    $1                              # set MMU OFF
87        nop
88
89        mfc0    $26,    $4,   2             # $26 <= thread pointer
90        lw      $26,    0($26)              # $26 <= uzone pointer
91
92        sw      $29,    (UZ_SP*4)($26)      # save user stack to uzone
93        lw      $29,    (UZ_KSP*4)($26)     # load kernel stack from uzone
94
95        ori     $27,    $0,       0xF           # MMU old value: assumed ON
96        sw      $27,    (UZ_MODE*4)($26)    # save MMU MODE to uzone
97
98        j           unified_mode
99        or      $27,    $0,       $26           # $27 <= uzone
100
101#---------------------------------------------------------------------------------------       
102# this code is executed when the core is in kernel mode:
103# - we use an uzone allocated in kernel stack.
104# - we set the MMU off, set the MMU data_paddr extension to local_cxy,
105#   and save the CP2_MODE and CP2_DEXT to uzone.
106# - we save the kernel stack pointer to uzone and load the new kernel stack pointer
107# - we store the uzone pointer in $27
108
109kernel_mode:
110        mfc2    $26,    $24
111        andi    $26,    $26,  CXY_MASK      # $26 <= CP2_DEXT
112
113        mfc0    $27,    $15,  1
114        andi    $27,    $27,  GID_MASK      # $27 <= core_gid (4/4/2 format)   
115
116        srl         $27,    $27,  LID_WIDTH         # $27 <= local_cxy
117        mtc2    $27,    $24                             # set local_cxy to CP2_DEXT
118
119    # use $26 to save both CP2_MODE (4 bits) and CP2_DEXT (8 bits) values
120
121        mfc2    $27,    $1
122        andi    $27,    $27,  MMU_MODE_MASK     # $27 <= CP2_MODE
123        sll         $27,    $27,  CXY_WIDTH         # $27 <= 0x00000M00
124        or          $26,    $26,  $27           # $26 <= 0x00000MXY
125
126        ori     $27,    $0,       0x3
127        mtc2    $27,    $1                              # set MMU OFF
128
129        # save old SP, CP2_MODE and CP2_DEXT in uzone allocated in kernel stack
130
131        addiu   $27,    $29,  -(SAVE_SIZE)      # allocate an uzone in stack (use $27 as KSP)
132        sw      $29,    (UZ_SP*4)($27)      # save old KSP in this uzone
133
134        srl     $29,    $26,  CXY_WIDTH
135        sw      $29,    (UZ_MODE*4)($27)    # save CP2_MODE in this uzone
136
137        andi    $26,    $26,  CXY_MASK 
138        sw      $26,    (UZ_DEXT*4)($27)    # save CP2_DEXT in this uzone
139
140        or      $29,    $27,    $0          # load new kernel stack pointer
141
142#--------------------------------------------------------------------------------------
143# this code is executed in both modes, with the two following assumptions:
144# - $27 contains the pointer on uzone to save the cpu 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        srl         $3,     $18,  5                 # put SR in kernel mode, IRQ disabled, clear exl
189        sll     $3,         $3,   5     
190        mtc0    $3,         $12                         # Set new SR
191
192        andi    $1,     $17,  0x3F          # $1 <= XCODE (from CR)
193
194        # signal that core enters kernel
195        jal         cluster_core_kernel_enter
196    nop
197
198#---------------------------------------------------------------------------------------
199# Depending on XCODE (in $1) , call the apropriate handler. The three called
200# functions take the same two arguments: thread pointer and uzone pointer.
201
202        mfc0    $4,     $4,   2             # $4 <= thread pointer (first arg)
203        or          $5,     $0,   $27               # $5 <= uzone pointer (second arg)
204        or          $19,    $0,   $27           # $19 <= &uzone (for kentry_exit)
205
206        ori         $8,     $0,   0x20          # $8 <= cause syscall
207    beq     $8,     $1,   cause_sys
208    nop
209        beq     $1,     $0,       cause_int
210    nop
211
212cause_excp:
213        la      $1,         hal_do_exception
214        jalr    $1                              # call exception handler
215        addiu   $29,    $29,  -8                # hal_do_exception has 2 args
216        addiu   $29,    $29,  8
217        j       kentry_exit                 # jump to kentry_exit
218    nop
219
220cause_sys:
221        la          $1,         hal_do_syscall
222        jalr    $1                          # call syscall handler                 
223        addiu   $29,    $29,  -8            # hal_do_syscall has 2 args
224        addiu   $29,    $29,  8
225        j           kentry_exit                 # jump to kentry_exit
226        or          $19,        $0,   $2
227       
228cause_int:
229        la          $1,     hal_do_interrupt
230        jalr    $1                          # call interrupt handler
231        addiu   $29,    $29,  -8            # hal_do_interrupt has 2 args
232        addiu   $29,    $29,  8
233
234# -----------------------------------------------------------------------------------
235# Kentry exit
236# -----------------------------------------------------------------------------------
237kentry_exit:
238
239        # signal that core exit kernel
240    jal     cluster_core_kernel_exit
241
242        # restore context from uzone
243        or          $27,    $0, $19             # $27 <= &uzone
244
245        lw          $29,        (UZ_SP*4)($27)          # restore SP from uzone
246        lw          $16,        (UZ_EPC*4)($27)       
247        mtc0    $16,    $14                             # restore EPC from uzone
248        lw          $16,    (UZ_HI*4)($27)
249        mthi    $16                                         # restore HI from uzone
250        lw          $16,    (UZ_LO*4)($27)
251        mtlo    $16                                         # restore LO from uzone
252
253        lw          $17,        (UZ_SR*4)($27)          # get saved SR value from uzone
254        andi    $17,    $17,    0x1F        # keep only the 5 LSB bits
255        mfc0    $26,    $12                             # get current SR value from CP0
256        or          $26,    $26,        $17         # merge the two values
257        mtc0    $26,    $12                             # setup new SR to CP0
258
259        lw          $1,     (UZ_AT*4)($27)             
260        lw          $2,     (UZ_V0*4)($27)
261        lw          $3,     (UZ_V1*4)($27)
262        lw          $4,     (UZ_A0*4)($27)
263        lw          $5,     (UZ_A1*4)($27)
264        lw          $6,     (UZ_A2*4)($27)
265        lw          $7,     (UZ_A3*4)($27)
266        lw          $8,     (UZ_T0*4)($27)
267        lw          $9,     (UZ_T1*4)($27)
268        lw          $10,    (UZ_T2*4)($27)
269        lw          $11,    (UZ_T3*4)($27)
270        lw          $12,    (UZ_T4*4)($27)
271        lw          $13,    (UZ_T5*4)($27)
272        lw          $14,    (UZ_T6*4)($27)
273        lw          $15,    (UZ_T7*4)($27)
274        lw          $16,    (UZ_S0*4)($27)
275        lw          $17,    (UZ_S1*4)($27)
276        lw          $18,        (UZ_S2*4)($27)
277        lw          $19,    (UZ_S3*4)($27)
278        lw          $20,        (UZ_S4*4)($27)
279        lw          $21,        (UZ_S5*4)($27)
280        lw          $22,        (UZ_S6*4)($27)
281        lw          $23,        (UZ_S7*4)($27)
282        lw          $24,    (UZ_T8*4)($27)
283        lw          $25,    (UZ_T9*4)($27)     
284        lw          $28,        (UZ_GP*4)($27)
285        lw          $30,        (UZ_S8*4)($27)
286        lw          $31,        (UZ_RA*4)($27)
287
288
289        lw          $26,    (UZ_DEXT*4)($27)
290        mtc2    $26,    $24                             # restore CP2_DEXT from uzone
291
292    #TODO: optimize
293        lw          $26,    (UZ_MODE*4)($27)    # get saved CP2_MODE from uzone
294        andi    $26,    $26,    0xc         # keep only the TLBs controling bits
295        beq     $26,    $0,         out_mmu_3   # both MSB are 0 (the first two LSB are always set)
296        andi    $26,    $26,    0x8
297        beq     $26,    $0,         out_mmu_7   # first MSB is 0 (bit 2 is set)
298
299# Possible value for MMU_MODE
300# In kernel mode : 0x7/0x3
301# In user mode   : 0xF
302
303# DP_EXT can either be local or remote
304# Once these register set we can no longuer
305# access global data
306
307out_mmu_F:
308        ori         $26,        $0,        0xF
309        mtc2    $26,    $1                              # CP2_MODE <= 0xF
310        j           out_kentry
311        nop
312
313out_mmu_7:
314        ori         $26,    $0,    0x7 
315        mtc2    $26,    $1                              # CP2_MODE <= 0x7
316        j       out_kentry
317        nop
318
319out_mmu_3:
320        ori     $26,    $0,        0x3
321        mtc2    $26,    $1                              # CP2_MODE <= 0x3
322
323out_kentry:
324        nop
325    eret
326
327    .end kentry
328    .set reorder
329    .set at
330
331        .ent kentry_load
332kentry_load:
333        # theses nops are required to load the eret instruction
334        # while we are in virtual mode (processor pipeline) ?
335        mtc2     $26,    $1            # set MMU MODE
336        nop                     
337        nop
338    eret
339    .end kentry_load
340
341#-------------------------------------------------------------------------------
342
Note: See TracBrowser for help on using the repository browser.