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

Last change on this file since 408 was 408, checked in by alain, 4 years ago

Fix several bugs in the fork() syscall.

File size: 12.9 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#define      UZ_MODE         0                 
27#define      UZ_AT           1
28#define      UZ_V0           2
29#define      UZ_V1           3
30#define      UZ_A0           4
31#define      UZ_A1           5
32#define      UZ_A2           6
33#define      UZ_A3           7
34#define      UZ_T0           8
35#define      UZ_T1           9
36#define      UZ_T2           10
37#define      UZ_T3           11
38#define      UZ_T4           12
39#define      UZ_T5           13
40#define      UZ_T6           14
41#define      UZ_T7           15
42#define      UZ_S0           16
43#define      UZ_S1           17
44#define      UZ_S2           18
45#define      UZ_S3           19
46#define      UZ_S4           20
47#define      UZ_S5           21
48#define      UZ_S6           22
49#define      UZ_S7           23
50#define      UZ_T8           24
51#define      UZ_T9           25
52
53#define      UZ_LO           26
54#define      UZ_HI           27
55
56#define      UZ_GP           28
57#define      UZ_SP           29
58#define      UZ_S8           30
59#define      UZ_RA           31
60#define      UZ_PTPR         32
61#define      UZ_EPC          33
62#define      UZ_SR           34
63#define      UZ_TH           35
64#define      UZ_CR           36
65
66#define      UZ_REGS         37
67
68#include <kernel_config.h>
69
70        .section   .kentry, "ax", @progbits
71
72        .extern    hal_do_interrupt
73        .extern    hal_do_exception
74        .extern    hal_do_syscall
75    .extern    puts
76    .extern    putx
77    .extern    putl
78
79        .org       0x180
80
81        .global    hal_kentry_enter
82    .global    hal_kentry_eret
83
84        .set       noat
85        .set       noreorder
86
87#------------------------------------------------------------------------------------
88# Kernel Entry point for Interrupt / Exception / Syscall
89# The c2_dext and c2_iext CP2 registers must have been previously set
90# to "local_cxy", because the kernel run with MMU desactivated.
91#------------------------------------------------------------------------------------
92
93hal_kentry_enter:
94
95        mfc0    $26,    $12                 # get c0_sr
96        andi    $26,    $26,  0x10          # test User Mode bit
97        beq     $26,    $0,       kernel_mode   # jump if core already in kernel
98        ori     $27,    $0,       0x3           # $27 <= code for MMU OFF
99       
100#------------------------------------------------------------------------------------
101# This code is executed when the core is in user mode:
102# - save current c2_mode in $26.
103# - set MMU OFF.
104# - save user stack pointer in $27.
105# - set kernel stack pointer in $29.
106
107user_mode:
108
109    mfc2    $26,    $1                  # $26 <= c2_mode
110        mtc2    $27,    $1                              # set MMU OFF
111    move    $27,    $29                 # $27 <= user stack pointer
112        mfc0    $29,    $4,   2             # get pointer on thread descriptor from c0_th
113    addi    $29,    $29,  CONFIG_THREAD_DESC_SIZE
114    addi    $29,    $29,  -8            # $29 <= kernel stack pointer
115    j       unified_mode
116    nop
117
118#------------------------------------------------------------------------------------
119# This code is executed when the core is already in kernel mode:
120# - save current c2_mode in $26.
121# - set MMU OFF.
122# - save current kernel stack pointer in $27.
123
124kernel_mode:
125
126    mfc2    $26,    $1                  # $26 <= c2_mode
127        mtc2    $27,    $1                              # set MMU OFF
128    move    $27,    $29                 # $27 <= current kernel stack pointer
129
130#------------------------------------------------------------------------------------   
131# This code is executed in both modes (user or kernel):
132# The assumptions are:
133# - c2_mode contains the MMU OFF value.
134# - $26 contains the previous c2_mode value.
135# - $27 contains the previous sp value (can be usp or ksp).
136# - $29 contains the kernel stack pointer.
137# We execute the following actions:
138# - allocate an uzone in kernel stack, decrementing $29.
139# - save relevant GPR, CP0 and CP2 registers to uzone.
140# - set the SR in kernel mode: IRQ disabled, clear exl.
141
142unified_mode:
143
144        addiu   $29,    $29,  -(UZ_REGS*4)      # allocate uzone in kernel stack
145
146        sw      $1,         (UZ_AT*4)($29)
147        sw      $2,     (UZ_V0*4)($29)
148        sw      $3,     (UZ_V1*4)($29)
149        sw      $4,     (UZ_A0*4)($29)
150        sw      $5,     (UZ_A1*4)($29)
151        sw      $6,     (UZ_A2*4)($29)
152        sw      $7,     (UZ_A3*4)($29)
153        sw      $8,     (UZ_T0*4)($29)
154        sw      $9,     (UZ_T1*4)($29)
155        sw      $10,    (UZ_T2*4)($29)
156        sw      $11,    (UZ_T3*4)($29)
157        sw      $12,    (UZ_T4*4)($29)
158        sw      $13,    (UZ_T5*4)($29)
159        sw      $14,    (UZ_T6*4)($29)
160        sw      $15,    (UZ_T7*4)($29)
161        sw      $16,    (UZ_S0*4)($29)
162        sw      $17,    (UZ_S1*4)($29)
163        sw          $18,        (UZ_S2*4)($29)
164        sw          $19,        (UZ_S3*4)($29)
165        sw          $20,        (UZ_S4*4)($29)
166        sw          $21,        (UZ_S5*4)($29)
167        sw          $22,        (UZ_S6*4)($29)
168        sw          $23,        (UZ_S7*4)($29)
169        sw      $24,    (UZ_T8*4)($29)
170        sw      $25,    (UZ_T9*4)($29)
171
172        mflo    $1
173        sw      $1,     (UZ_LO*4)($29)      # save lo
174        mflo    $1
175        sw      $1,     (UZ_HI*4)($29)      # save hi
176
177        sw          $28,        (UZ_GP*4)($29)      # save gp
178        sw          $27,        (UZ_SP*4)($29)      # save previous sp (can be usp or ksp)
179        sw          $30,        (UZ_S8*4)($29)      # save s8
180        sw          $31,        (UZ_RA*4)($29)      # save ra
181
182        mfc0    $1,     $14
183        sw      $1,     (UZ_EPC*4)($29)     # save c0_epc
184        mfc0    $1,         $12
185        sw          $1,     (UZ_SR*4)($29)              # save c0_sr
186        mfc0    $1,     $4,  2
187        sw      $1,         (UZ_TH*4)($29)              # save c0_th
188        mfc0    $1,     $13   
189        sw      $1,         (UZ_CR*4)($29)              # save c0_cr
190        mfc2    $1,     $0
191        sw      $1,     (UZ_PTPR*4)($29)        # save c2_ptpr
192
193    sw      $26,    (UZ_MODE*4)($29)    # save previous c2_mode (can be user or kernel)
194
195    mfc0    $3,     $12
196        srl         $3,     $3,   5
197        sll     $3,         $3,   5                 # reset 5 LSB bits
198        mtc0    $3,         $12                         # set new c0_sr
199
200#if CONFIG_KENTRY_DEBUG
201
202    # display "enter" message
203    la      $4,     msg_enter
204    jal     puts
205    nop
206    move    $4,     $29
207    jal     putx
208    nop
209    la      $4,     msg_crlf
210    jal     puts
211    nop   
212    # display saved SP value
213    la      $4,     msg_sp
214    jal     puts
215    nop
216    lw      $4,         (UZ_SP*4)($29)
217    jal     putx
218    nop
219    la      $4,     msg_crlf
220    jal     puts
221    nop   
222    # display saved RA value
223    la      $4,     msg_ra
224    jal     puts
225    nop
226    lw      $4,         (UZ_RA*4)($29)
227    jal     putx
228    nop
229    la      $4,     msg_crlf
230    jal     puts
231    nop   
232    # display saved TH value
233    la      $4,     msg_th
234    jal     puts
235    nop
236    lw      $4,         (UZ_TH*4)($29)
237    jal     putx
238    nop
239    la      $4,     msg_crlf
240    jal     puts
241    nop   
242    # display saved EPC value
243    la      $4,     msg_epc
244    jal     puts
245    nop
246    lw      $4,         (UZ_EPC*4)($29)
247    jal     putx
248    nop
249    la      $4,     msg_crlf
250    jal     puts
251    nop   
252    # display saved MODE value
253    la      $4,     msg_mode
254    jal     puts
255    nop
256    lw      $4,         (UZ_MODE*4)($29)
257    jal     putx
258    nop
259    la      $4,     msg_crlf
260    jal     puts
261    nop   
262    # display saved V0 value
263    la      $4,     msg_v0
264    jal     puts
265    nop
266    lw      $4,         (UZ_V0*4)($29)
267    jal     putx
268    nop
269    la      $4,     msg_crlf
270    jal     puts
271    nop   
272       
273#endif
274   
275#------------------------------------------------------------------------------------
276# This code update the uzone field in thread descriptor,
277# and call the relevant Interrupt / Exception / Syscall handler,
278# depending on XCODE in CP0_CR.
279# assumption: $29 contains the kernel stack pointer, that is the uzone base.
280
281        mfc0    $17,    $13                 # $17 <= CR
282        andi    $17,    $17,   0x3F         # $17 <= XCODE
283
284        mfc0    $4,     $4,   2             # $4 <= pointer on thread desc
285    sw      $29,    8($4)               # update uzone pointer in thread desc
286
287        ori         $8,     $0,   0x20
288    beq     $8,     $17,  cause_sys     # go to syscall handler
289    nop
290        beq     $17,    $0,       cause_int     # go to interrupt handler
291    nop
292
293cause_excp:
294        jal     hal_do_exception            # call exception handler
295        nop
296        j       kentry_exit                 # jump to kentry_exit
297    nop
298
299cause_sys:
300        jal     hal_do_syscall              # call syscall handler                 
301    nop
302        j           kentry_exit                 # jump to kentry_exit
303        nop
304       
305cause_int:
306        jal     hal_do_interrupt            # call interrupt handler
307    nop
308
309# -----------------------------------------------------------------------------------
310# Kernel exit
311# The pointer on uzone is supposed to be contained in $29
312# -----------------------------------------------------------------------------------
313kentry_exit:
314
315#if CONFIG_KENTRY_DEBUG
316
317    # display "exit" message
318    la      $4,     msg_exit
319    jal     puts
320    nop
321    move    $4,     $29
322    jal     putx
323    nop
324    la      $4,     msg_crlf
325    jal     puts
326    nop   
327    # display saved SP value
328    la      $4,     msg_sp
329    jal     puts
330    nop
331    lw      $4,         (UZ_SP*4)($29)
332    jal     putx
333    nop
334    la      $4,     msg_crlf
335    jal     puts
336    nop   
337    # display saved RA value
338    la      $4,     msg_ra
339    jal     puts
340    nop
341    lw      $4,         (UZ_RA*4)($29)
342    jal     putx
343    nop
344    la      $4,     msg_crlf
345    jal     puts
346    nop   
347    # display saved TH value
348    la      $4,     msg_th
349    jal     puts
350    nop
351    lw      $4,         (UZ_TH*4)($29)
352    jal     putx
353    nop
354    la      $4,     msg_crlf
355    jal     puts
356    nop   
357    # display saved EPC value
358    la      $4,     msg_epc
359    jal     puts
360    nop
361    lw      $4,         (UZ_EPC*4)($29)
362    jal     putx
363    nop
364    la      $4,     msg_crlf
365    jal     puts
366    nop   
367    # display saved MODE value
368    la      $4,     msg_mode
369    jal     puts
370    nop
371    lw      $4,         (UZ_MODE*4)($29)
372    jal     putx
373    nop
374    la      $4,     msg_crlf
375    jal     puts
376    nop   
377    # display saved V0 value
378    la      $4,     msg_v0
379    jal     puts
380    nop
381    lw      $4,         (UZ_V0*4)($29)
382    jal     putx
383    nop
384    la      $4,     msg_crlf
385    jal     puts
386    nop   
387       
388#endif
389   
390        # restore registers from uzone
391        or          $27,    $0, $29             # $27 <= ksp (contains &uzone)
392
393        lw          $1,     (UZ_EPC*4)($27)           
394        mtc0    $1,         $14                         # restore c0_epc from uzone
395        lw          $1,     (UZ_SR*4)($27)
396        mtc0    $1,     $12                             # restore c0_sr from uzone
397
398        lw          $26,    (UZ_HI*4)($27)
399        mthi    $26                                         # restore hi from uzone
400        lw          $26,    (UZ_LO*4)($27)
401        mtlo    $26                                         # restore lo from uzone
402
403        lw          $1,     (UZ_AT*4)($27)             
404    lw      $2,     (UZ_V0*4)($27)
405    lw      $3,     (UZ_V1*4)($27)
406        lw          $4,     (UZ_A0*4)($27)
407        lw          $5,     (UZ_A1*4)($27)
408        lw          $6,     (UZ_A2*4)($27)
409        lw          $7,     (UZ_A3*4)($27)
410        lw          $8,     (UZ_T0*4)($27)
411        lw          $9,     (UZ_T1*4)($27)
412        lw          $10,    (UZ_T2*4)($27)
413        lw          $11,    (UZ_T3*4)($27)
414        lw          $12,    (UZ_T4*4)($27)
415        lw          $13,    (UZ_T5*4)($27)
416        lw          $14,    (UZ_T6*4)($27)
417        lw          $15,    (UZ_T7*4)($27)
418        lw          $16,    (UZ_S0*4)($27)
419        lw          $17,    (UZ_S1*4)($27)
420        lw          $18,        (UZ_S2*4)($27)
421        lw          $19,    (UZ_S3*4)($27)
422        lw          $20,        (UZ_S4*4)($27)
423        lw          $21,        (UZ_S5*4)($27)
424        lw          $22,        (UZ_S6*4)($27)
425        lw          $23,        (UZ_S7*4)($27)
426        lw          $24,    (UZ_T8*4)($27)
427        lw          $25,    (UZ_T9*4)($27)     
428
429        lw          $28,        (UZ_GP*4)($27)      # restore gp_28 from uzone
430        lw          $29,        (UZ_SP*4)($27)          # restore sp_29 from uzone
431        lw          $30,        (UZ_S8*4)($27)      # restore s8_30 from uzone
432        lw          $31,        (UZ_RA*4)($27)      # restore ra_31 from uzone
433
434        lw          $26,    (UZ_MODE*4)($27)   
435    mtc2    $26,    $1                  # restore CP2_MODE from uzone
436
437# -----------------------------------------------------------------------------------
438# eret function
439# -----------------------------------------------------------------------------------
440
441hal_kentry_eret:
442    eret                                # jump to EPC, reset EXL bit
443
444    .set reorder
445    .set at
446
447#------------------------------------------------------------------------------------
448    .section .kdata
449
450msg_sp:
451    .align 2
452    .asciiz "- UZ_SP   = "
453msg_ra:
454    .align 2
455    .asciiz "- UZ_RA   = "
456msg_epc:
457    .align 2
458    .asciiz "- UZ_EPC  = "
459msg_th:
460    .align 2
461    .asciiz "- UZ_TH   = "
462msg_mode:
463    .align 2
464    .asciiz "- UZ_MODE = "
465msg_v0:
466    .align 2
467    .asciiz "- UZ_V0   = "
468msg_crlf:
469    .align 2
470    .asciiz "\n"
471msg_enter:
472    .align 2
473    .asciiz "\nenter kernel : &uzone = "
474msg_exit:
475    .align 2
476    .asciiz "\nexit kernel : &uzone = "
477
Note: See TracBrowser for help on using the repository browser.