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

Last change on this file since 564 was 438, checked in by alain, 7 years ago

Fix a bug in scheduler related to RPC blocking.

File size: 14.8 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# to handle a syscall, an interrupt, or an user exception.
103# - save current c2_mode in $26.
104# - set MMU OFF.
105# - copy user stack pointer in $27 to be saved in uzone.
106# - set kernel stack pointer in $29 == top_kernel_stack(this).
107
108user_mode:
109
110    mfc2    $26,    $1                  # $26 <= c2_mode
111        mtc2    $27,    $1                              # set MMU OFF
112    move    $27,    $29                 # $27 <= user stack pointer
113        mfc0    $29,    $4,   2             # get pointer on thread descriptor from c0_th
114    addi    $29,    $29,  CONFIG_THREAD_DESC_SIZE
115    addi    $29,    $29,  -8            # $29 <= kernel stack pointer
116    j       unified_mode
117    nop
118
119#------------------------------------------------------------------------------------
120# This code is executed when the core is already in kernel mode,
121# after a syscall, to handle an interrupt, or to handle a non-fatal exception.
122# - save current c2_mode in $26.
123# - set MMU OFF.
124# - copy current kernel stack pointer in $27.
125
126kernel_mode:
127
128    mfc2    $26,    $1                  # $26 <= c2_mode
129        mtc2    $27,    $1                              # set MMU OFF
130    move    $27,    $29                 # $27 <= current kernel stack pointer
131
132#------------------------------------------------------------------------------------   
133# This code is executed in both modes (user or kernel):
134# The assumptions are:
135# - c2_mode contains the MMU OFF value.
136# - $26 contains the previous c2_mode value.
137# - $27 contains the previous sp value (can be usp or ksp).
138# - $29 contains the curren kernel stack pointer.
139# We execute the following actions:
140# - decrement $29 to allocate an uzone in kernel stack
141# - save relevant GPR, CP0 and CP2 registers to uzone.
142# - set the SR in kernel mode: IRQ disabled, clear exl.
143
144unified_mode:
145
146        addiu   $29,    $29,  -(UZ_REGS*4)      # allocate uzone in kernel stack
147
148        sw      $1,         (UZ_AT*4)($29)
149        sw      $2,     (UZ_V0*4)($29)
150        sw      $3,     (UZ_V1*4)($29)
151        sw      $4,     (UZ_A0*4)($29)
152        sw      $5,     (UZ_A1*4)($29)
153        sw      $6,     (UZ_A2*4)($29)
154        sw      $7,     (UZ_A3*4)($29)
155        sw      $8,     (UZ_T0*4)($29)
156        sw      $9,     (UZ_T1*4)($29)
157        sw      $10,    (UZ_T2*4)($29)
158        sw      $11,    (UZ_T3*4)($29)
159        sw      $12,    (UZ_T4*4)($29)
160        sw      $13,    (UZ_T5*4)($29)
161        sw      $14,    (UZ_T6*4)($29)
162        sw      $15,    (UZ_T7*4)($29)
163        sw      $16,    (UZ_S0*4)($29)
164        sw      $17,    (UZ_S1*4)($29)
165        sw          $18,        (UZ_S2*4)($29)
166        sw          $19,        (UZ_S3*4)($29)
167        sw          $20,        (UZ_S4*4)($29)
168        sw          $21,        (UZ_S5*4)($29)
169        sw          $22,        (UZ_S6*4)($29)
170        sw          $23,        (UZ_S7*4)($29)
171        sw      $24,    (UZ_T8*4)($29)
172        sw      $25,    (UZ_T9*4)($29)
173
174        mflo    $1
175        sw      $1,     (UZ_LO*4)($29)      # save lo
176        mflo    $1
177        sw      $1,     (UZ_HI*4)($29)      # save hi
178
179        sw          $28,        (UZ_GP*4)($29)      # save gp
180        sw          $27,        (UZ_SP*4)($29)      # save previous sp (can be usp or ksp)
181        sw          $30,        (UZ_S8*4)($29)      # save s8
182        sw          $31,        (UZ_RA*4)($29)      # save ra
183
184        mfc0    $1,     $14
185        sw      $1,     (UZ_EPC*4)($29)     # save c0_epc
186        mfc0    $1,         $12
187        sw          $1,     (UZ_SR*4)($29)              # save c0_sr
188        mfc0    $1,     $4,  2
189        sw      $1,         (UZ_TH*4)($29)              # save c0_th
190        mfc0    $1,     $13   
191        sw      $1,         (UZ_CR*4)($29)              # save c0_cr
192        mfc2    $1,     $0
193        sw      $1,     (UZ_PTPR*4)($29)        # save c2_ptpr
194
195    sw      $26,    (UZ_MODE*4)($29)    # save previous c2_mode (can be user or kernel)
196
197    mfc0    $3,     $12
198        srl         $3,     $3,   5
199        sll     $3,         $3,   5                 # reset 5 LSB bits
200        mtc0    $3,         $12                         # set new c0_sr
201
202#--------------------
203#if DEBUG_HAL_KENTRY
204
205    # display "enter" message
206    la      $4,     msg_enter
207    jal     puts
208    nop
209    move    $4,     $29
210    jal     putx
211    nop
212    la      $4,     msg_cycle
213    jal     puts
214    nop
215    jal     hal_time_stamp
216    nop
217    move    $4,     $2
218    jal     putx
219    nop
220    la      $4,     msg_crlf
221    jal     puts
222    nop   
223    # display saved SP value
224    la      $4,     msg_sp
225    jal     puts
226    nop
227    lw      $4,         (UZ_SP*4)($29)
228    jal     putx
229    nop
230    la      $4,     msg_crlf
231    jal     puts
232    nop   
233    # display saved RA value
234    la      $4,     msg_ra
235    jal     puts
236    nop
237    lw      $4,         (UZ_RA*4)($29)
238    jal     putx
239    nop
240    la      $4,     msg_crlf
241    jal     puts
242    nop   
243    # display saved TH value
244    la      $4,     msg_th
245    jal     puts
246    nop
247    lw      $4,         (UZ_TH*4)($29)
248    jal     putx
249    nop
250    la      $4,     msg_crlf
251    jal     puts
252    nop   
253    # display saved EPC value
254    la      $4,     msg_epc
255    jal     puts
256    nop
257    lw      $4,         (UZ_EPC*4)($29)
258    jal     putx
259    nop
260    la      $4,     msg_crlf
261    jal     puts
262    nop   
263    # display saved MODE value
264    la      $4,     msg_mode
265    jal     puts
266    nop
267    lw      $4,         (UZ_MODE*4)($29)
268    jal     putx
269    nop
270    la      $4,     msg_crlf
271    jal     puts
272    nop   
273    # display saved V0 value
274    la      $4,     msg_v0
275    jal     puts
276    nop
277    lw      $4,         (UZ_V0*4)($29)
278    jal     putx
279    nop
280    la      $4,     msg_crlf
281    jal     puts
282    nop   
283
284#endif
285#-----
286   
287#------------------------------------------------------------------------------------
288# This code handle the uzone pointers stack, and calls the relevant
289# Interrupt / Exception / Syscall handler, depending on XCODE in CP0_CR.
290# Both the hal_do_syscall() and the hal_do_exception() functions use
291# the values saved in the "uzone", but a syscall can be interrupted
292# by an interrupt, or by a non-fatal exception. Therefore, we need
293# to handle a two-slots "stack of uzones", implemented in the kernel stack,
294# using the two "current_uzone" and "previous_uzone" pointers in thread descriptor.
295# - at kernel_entry, we copy the "current_uzone" pointer to the "previous_uzone"
296#   slot, and copy the "$29" stack pointer to the "current_uzone" slot.
297# - at kernel_exit, we simply restore the "previous_uzone" value to the
298#   "current_uzone" slot.
299# For a syscall, the hal_do_syscall() function increment the uzone[EPC]
300# slot and set the return value in the uzone[V0] slot before returning.
301
302    # update "current_uzone" and "previous_uzone" pointers
303        mfc0    $4,     $4,   2             # $4 <= pointer on thread desc
304    lw      $5,     8($4)               # $5 <= current uzone pointer trom thread
305    sw      $29,    8($4)               # current uzone pointer <= $29
306    sw      $5,    12($4)               # previous uzone pointer <= current
307
308    # analyse XCODE to call relevant handler
309        mfc0    $17,    $13                 # $17 <= CR
310        andi    $17,    $17,  0x3F          # $17 <= XCODE
311        ori         $8,     $0,   0x20
312    beq     $8,     $17,  cause_sys     # go to syscall handler
313    nop
314        beq     $17,    $0,       cause_int     # go to interrupt handler
315    nop
316
317cause_excp:
318
319        jal     hal_do_exception            # call exception handler
320        nop
321        j       kentry_exit                 # jump to kentry_exit
322    nop
323
324cause_sys:
325
326        jal     hal_do_syscall              # call syscall handler                 
327    nop
328        j           kentry_exit                 # jump to kentry_exit
329        nop
330       
331cause_int:
332
333        jal     hal_do_interrupt            # call interrupt handler
334    nop
335
336# -----------------------------------------------------------------------------------
337# Kernel exit
338# - All registers saved in the uzone are restored, using the pointer on uzone,
339#   that is contained in $29.
340# - The "uzone" field in thread descriptor, that has beeen modified at kernel entry
341#   is restored from value contained in the uzone[UZ_SP] slot.
342# -----------------------------------------------------------------------------------
343
344kentry_exit:
345
346    # restore "current_uzone" pointer
347        mfc0    $4,      $4,   2            # $4 <= pointer on thread desc
348    lw      $5,   12($4)                # $5 <= previous uzone pointer from thread
349    sw      $5,    8($4)                # current uzone pointer <= previous
350
351#-------------------
352#if DEBUG_HAL_KENTRY
353
354    # display "exit" message
355    la      $4,     msg_exit
356    jal     puts
357    nop
358    move    $4,     $29
359    jal     putx
360    nop
361    la      $4,     msg_cycle
362    jal     puts
363    nop
364    jal     hal_time_stamp
365    nop
366    move    $4,     $2
367    jal     putx
368    nop
369    la      $4,     msg_crlf
370    jal     puts
371    nop   
372    # display saved SP value
373    la      $4,     msg_sp
374    jal     puts
375    nop
376    lw      $4,         (UZ_SP*4)($29)
377    jal     putx
378    nop
379    la      $4,     msg_crlf
380    jal     puts
381    nop   
382    # display saved RA value
383    la      $4,     msg_ra
384    jal     puts
385    nop
386    lw      $4,         (UZ_RA*4)($29)
387    jal     putx
388    nop
389    la      $4,     msg_crlf
390    jal     puts
391    nop   
392    # display saved TH value
393    la      $4,     msg_th
394    jal     puts
395    nop
396    lw      $4,         (UZ_TH*4)($29)
397    jal     putx
398    nop
399    la      $4,     msg_crlf
400    jal     puts
401    nop   
402    # display saved EPC value
403    la      $4,     msg_epc
404    jal     puts
405    nop
406    lw      $4,         (UZ_EPC*4)($29)
407    jal     putx
408    nop
409    la      $4,     msg_crlf
410    jal     puts
411    nop   
412    # display saved MODE value
413    la      $4,     msg_mode
414    jal     puts
415    nop
416    lw      $4,         (UZ_MODE*4)($29)
417    jal     putx
418    nop
419    la      $4,     msg_crlf
420    jal     puts
421    nop   
422    # display saved V0 value
423    la      $4,     msg_v0
424    jal     puts
425    nop
426    lw      $4,         (UZ_V0*4)($29)
427    jal     putx
428    nop
429    la      $4,     msg_crlf
430    jal     puts
431    nop   
432       
433#endif
434#-----
435   
436        # restore registers from uzone
437        or          $27,    $0, $29             # $27 <= ksp (contains &uzone)
438
439        lw          $1,     (UZ_EPC*4)($27)           
440        mtc0    $1,         $14                         # restore c0_epc from uzone
441        lw          $1,     (UZ_SR*4)($27)
442        mtc0    $1,     $12                             # restore c0_sr from uzone
443
444        lw          $26,    (UZ_HI*4)($27)
445        mthi    $26                                         # restore hi from uzone
446        lw          $26,    (UZ_LO*4)($27)
447        mtlo    $26                                         # restore lo from uzone
448
449        lw          $1,     (UZ_AT*4)($27)             
450    lw      $2,     (UZ_V0*4)($27)
451    lw      $3,     (UZ_V1*4)($27)
452        lw          $4,     (UZ_A0*4)($27)
453        lw          $5,     (UZ_A1*4)($27)
454        lw          $6,     (UZ_A2*4)($27)
455        lw          $7,     (UZ_A3*4)($27)
456        lw          $8,     (UZ_T0*4)($27)
457        lw          $9,     (UZ_T1*4)($27)
458        lw          $10,    (UZ_T2*4)($27)
459        lw          $11,    (UZ_T3*4)($27)
460        lw          $12,    (UZ_T4*4)($27)
461        lw          $13,    (UZ_T5*4)($27)
462        lw          $14,    (UZ_T6*4)($27)
463        lw          $15,    (UZ_T7*4)($27)
464        lw          $16,    (UZ_S0*4)($27)
465        lw          $17,    (UZ_S1*4)($27)
466        lw          $18,        (UZ_S2*4)($27)
467        lw          $19,    (UZ_S3*4)($27)
468        lw          $20,        (UZ_S4*4)($27)
469        lw          $21,        (UZ_S5*4)($27)
470        lw          $22,        (UZ_S6*4)($27)
471        lw          $23,        (UZ_S7*4)($27)
472        lw          $24,    (UZ_T8*4)($27)
473        lw          $25,    (UZ_T9*4)($27)     
474
475        lw          $28,        (UZ_GP*4)($27)      # restore gp_28 from uzone
476        lw          $29,        (UZ_SP*4)($27)          # restore sp_29 from uzone
477        lw          $30,        (UZ_S8*4)($27)      # restore s8_30 from uzone
478        lw          $31,        (UZ_RA*4)($27)      # restore ra_31 from uzone
479
480        lw          $26,    (UZ_MODE*4)($27)   
481    mtc2    $26,    $1                  # restore CP2_MODE from uzone
482
483# -----------------------------------------------------------------------------------
484# eret function
485# -----------------------------------------------------------------------------------
486
487hal_kentry_eret:
488    eret                                # jump to EPC, reset EXL bit
489
490    .set reorder
491    .set at
492
493#------------------------------------------------------------------------------------
494    .section .kdata
495
496msg_sp:
497    .align 2
498    .asciiz "- UZ_SP   = "
499msg_ra:
500    .align 2
501    .asciiz "- UZ_RA   = "
502msg_epc:
503    .align 2
504    .asciiz "- UZ_EPC  = "
505msg_th:
506    .align 2
507    .asciiz "- UZ_TH   = "
508msg_mode:
509    .align 2
510    .asciiz "- UZ_MODE = "
511msg_v0:
512    .align 2
513    .asciiz "- UZ_V0   = "
514msg_crlf:
515    .align 2
516    .asciiz "\n"
517msg_enter:
518    .align 2
519    .asciiz "\nenter kernel : &uzone = "
520msg_exit:
521    .align 2
522    .asciiz "\nexit kernel : &uzone = "
523msg_cycle:
524    .align 2
525    .asciiz " / cycle = "
526
Note: See TracBrowser for help on using the repository browser.