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

Last change on this file since 625 was 625, checked in by alain, 5 years ago

Fix a bug in the vmm_remove_vseg() function: the physical pages
associated to an user DATA vseg were released to the kernel when
the target process descriptor was in the reference cluster.
This physical pages release should be done only when the page
forks counter value is zero.
All other modifications are cosmetic.

File size: 15.3 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 (2016,2017,2018,2019)
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 CP2 register must have been previously set
90# to "local_cxy", because the kernel run with data 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,       0xB           # $27 <= code data 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 data MMU OFF.
105# - copy user stack pointer in $27 to be saved in uzone.
106# - set kernel stack pointer in $29 (kernel stack empty at firts entry).
107
108user_mode:
109
110    mfc2    $26,    $1                  # $26 <= c2_mode
111        mtc2    $27,    $1                              # set data 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 data 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 data 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 data 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 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                 # $3 <= c0_sr
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     putd
219    nop
220    la      $4,     msg_crlf
221    jal     puts
222    nop   
223    # display saved CR value
224    la      $4,     msg_cr
225    jal     puts
226    nop
227    lw      $4,         (UZ_CR*4)($29)
228    jal     putx
229    nop
230    la      $4,     msg_crlf
231    jal     puts
232    nop   
233    # display saved SP value
234    la      $4,     msg_sp
235    jal     puts
236    nop
237    lw      $4,         (UZ_SP*4)($29)
238    jal     putx
239    nop
240    la      $4,     msg_crlf
241    jal     puts
242    nop   
243    # display saved RA value
244    la      $4,     msg_ra
245    jal     puts
246    nop
247    lw      $4,         (UZ_RA*4)($29)
248    jal     putx
249    nop
250    la      $4,     msg_crlf
251    jal     puts
252    nop   
253    # display saved TH value
254    la      $4,     msg_th
255    jal     puts
256    nop
257    lw      $4,         (UZ_TH*4)($29)
258    jal     putx
259    nop
260    la      $4,     msg_crlf
261    jal     puts
262    nop   
263    # display saved EPC value
264    la      $4,     msg_epc
265    jal     puts
266    nop
267    lw      $4,         (UZ_EPC*4)($29)
268    jal     putx
269    nop
270    la      $4,     msg_crlf
271    jal     puts
272    nop   
273    # display saved MODE value
274    la      $4,     msg_mode
275    jal     puts
276    nop
277    lw      $4,         (UZ_MODE*4)($29)
278    jal     putx
279    nop
280    la      $4,     msg_crlf
281    jal     puts
282    nop   
283    # display saved V0 value
284    la      $4,     msg_v0
285    jal     puts
286    nop
287    lw      $4,         (UZ_V0*4)($29)
288    jal     putx
289    nop
290    la      $4,     msg_crlf
291    jal     puts
292    nop   
293
294#endif
295#-----
296   
297#------------------------------------------------------------------------------------
298# This code handle the two-slots uzone pointers stack, and calls the relevant
299# Interrupt / Exception / Syscall handler, depending on XCODE in CP0_CR.
300# Both the hal_do_syscall() and the hal_do_exception() functions use
301# the values saved in the "uzone", but a syscall can be interrupted
302# by an interrupt, or by a non-fatal exception. Therefore, we need
303# to handle a two-slots "stack of uzones", implemented in the kernel stack,
304# using the two "current_uzone" and "previous_uzone" pointers in thread descriptor.
305# - at kernel_entry, we copy the "current_uzone" pointer to the "previous_uzone"
306#   slot, and copy the "$29" stack pointer to the "current_uzone" slot.
307# - at kernel_exit, we simply restore the "previous_uzone" value to the
308#   "current_uzone" slot.
309# For a syscall, the hal_do_syscall() function increment the uzone[EPC]
310# slot and set the return value in the uzone[V0] slot before returning.
311
312    # update "current_uzone" and "previous_uzone" pointers
313        mfc0    $4,     $4,   2             # $4 <= pointer on thread desc
314    lw      $5,     8($4)               # $5 <= current uzone pointer trom thread
315    sw      $29,    8($4)               # current uzone pointer <= $29
316    sw      $5,    12($4)               # previous uzone pointer <= current
317
318    # analyse XCODE to call relevant handler
319        mfc0    $17,    $13                 # $17 <= CR
320        andi    $17,    $17,  0x3F          # $17 <= XCODE
321        ori         $8,     $0,   0x20
322    beq     $8,     $17,  cause_sys     # go to syscall handler
323    nop
324        beq     $17,    $0,       cause_int     # go to interrupt handler
325    nop
326
327cause_excp:
328
329        jal     hal_do_exception            # call exception handler
330        nop
331        j       kentry_exit                 # jump to kentry_exit
332    nop
333
334cause_sys:
335
336        jal     hal_do_syscall              # call syscall handler                 
337    nop
338        j           kentry_exit                 # jump to kentry_exit
339        nop
340       
341cause_int:
342
343        jal     hal_do_interrupt            # call interrupt handler
344    nop
345
346# -----------------------------------------------------------------------------------
347# Kernel exit
348# - All registers saved in the uzone are restored, using the pointer on uzone,
349#   that is contained in $29.
350# - The "current_uzone" pointer in thread descriptor, that has beeen modified at
351#   kernel entry is restored from value contained in the uzone[UZ_SP] slot.
352# -----------------------------------------------------------------------------------
353
354kentry_exit:
355
356    # restore "current_uzone" pointer
357        mfc0    $4,      $4,   2            # $4 <= pointer on thread desc
358    lw      $5,   12($4)                # $5 <= previous uzone pointer from thread
359    sw      $5,    8($4)                # current uzone pointer <= previous
360
361#-------------------
362#if DEBUG_HAL_KENTRY
363
364    # display "exit" message
365    la      $4,     msg_exit
366    jal     puts
367    nop
368    move    $4,     $29
369    jal     putx
370    nop
371    la      $4,     msg_cycle
372    jal     puts
373    nop
374    jal     hal_time_stamp
375    nop
376    move    $4,     $2
377    jal     putd
378    nop
379    la      $4,     msg_crlf
380    jal     puts
381    nop   
382    # display saved CR value
383    la      $4,     msg_cr
384    jal     puts
385    nop
386    lw      $4,         (UZ_CR*4)($29)
387    jal     putx
388    nop
389    la      $4,     msg_crlf
390    jal     puts
391    nop   
392    # display saved SP value
393    la      $4,     msg_sp
394    jal     puts
395    nop
396    lw      $4,         (UZ_SP*4)($29)
397    jal     putx
398    nop
399    la      $4,     msg_crlf
400    jal     puts
401    nop   
402    # display saved RA value
403    la      $4,     msg_ra
404    jal     puts
405    nop
406    lw      $4,         (UZ_RA*4)($29)
407    jal     putx
408    nop
409    la      $4,     msg_crlf
410    jal     puts
411    nop   
412    # display saved TH value
413    la      $4,     msg_th
414    jal     puts
415    nop
416    lw      $4,         (UZ_TH*4)($29)
417    jal     putx
418    nop
419    la      $4,     msg_crlf
420    jal     puts
421    nop   
422    # display saved EPC value
423    la      $4,     msg_epc
424    jal     puts
425    nop
426    lw      $4,         (UZ_EPC*4)($29)
427    jal     putx
428    nop
429    la      $4,     msg_crlf
430    jal     puts
431    nop   
432    # display saved MODE value
433    la      $4,     msg_mode
434    jal     puts
435    nop
436    lw      $4,         (UZ_MODE*4)($29)
437    jal     putx
438    nop
439    la      $4,     msg_crlf
440    jal     puts
441    nop   
442    # display saved V0 value
443    la      $4,     msg_v0
444    jal     puts
445    nop
446    lw      $4,         (UZ_V0*4)($29)
447    jal     putx
448    nop
449    la      $4,     msg_crlf
450    jal     puts
451    nop   
452       
453#endif
454#-----
455   
456        # restore registers from uzone
457        or          $27,    $0, $29             # $27 <= ksp (contains &uzone)
458
459        lw          $1,     (UZ_EPC*4)($27)           
460        mtc0    $1,         $14                         # restore c0_epc from uzone
461        lw          $1,     (UZ_SR*4)($27)
462        mtc0    $1,     $12                             # restore c0_sr from uzone
463
464        lw          $26,    (UZ_HI*4)($27)
465        mthi    $26                                         # restore hi from uzone
466        lw          $26,    (UZ_LO*4)($27)
467        mtlo    $26                                         # restore lo from uzone
468
469        lw          $1,     (UZ_AT*4)($27)             
470    lw      $2,     (UZ_V0*4)($27)
471    lw      $3,     (UZ_V1*4)($27)
472        lw          $4,     (UZ_A0*4)($27)
473        lw          $5,     (UZ_A1*4)($27)
474        lw          $6,     (UZ_A2*4)($27)
475        lw          $7,     (UZ_A3*4)($27)
476        lw          $8,     (UZ_T0*4)($27)
477        lw          $9,     (UZ_T1*4)($27)
478        lw          $10,    (UZ_T2*4)($27)
479        lw          $11,    (UZ_T3*4)($27)
480        lw          $12,    (UZ_T4*4)($27)
481        lw          $13,    (UZ_T5*4)($27)
482        lw          $14,    (UZ_T6*4)($27)
483        lw          $15,    (UZ_T7*4)($27)
484        lw          $16,    (UZ_S0*4)($27)
485        lw          $17,    (UZ_S1*4)($27)
486        lw          $18,        (UZ_S2*4)($27)
487        lw          $19,    (UZ_S3*4)($27)
488        lw          $20,        (UZ_S4*4)($27)
489        lw          $21,        (UZ_S5*4)($27)
490        lw          $22,        (UZ_S6*4)($27)
491        lw          $23,        (UZ_S7*4)($27)
492        lw          $24,    (UZ_T8*4)($27)
493        lw          $25,    (UZ_T9*4)($27)     
494
495        lw          $28,        (UZ_GP*4)($27)      # restore gp_28 from uzone
496        lw          $29,        (UZ_SP*4)($27)          # restore sp_29 from uzone
497        lw          $30,        (UZ_S8*4)($27)      # restore s8_30 from uzone
498        lw          $31,        (UZ_RA*4)($27)      # restore ra_31 from uzone
499
500        lw          $26,    (UZ_MODE*4)($27)   
501    mtc2    $26,    $1                  # restore c2_mode from uzone
502
503# -----------------------------------------------------------------------------------
504# eret function
505# -----------------------------------------------------------------------------------
506
507hal_kentry_eret:
508    eret                                # jump to EPC, reset EXL bit
509
510    .set reorder
511    .set at
512
513#------------------------------------------------------------------------------------
514    .section .kdata
515
516msg_cr:
517    .align 2
518    .asciiz "- UZ_CR   = "
519msg_sp:
520    .align 2
521    .asciiz "- UZ_SP   = "
522msg_ra:
523    .align 2
524    .asciiz "- UZ_RA   = "
525msg_epc:
526    .align 2
527    .asciiz "- UZ_EPC  = "
528msg_th:
529    .align 2
530    .asciiz "- UZ_TH   = "
531msg_mode:
532    .align 2
533    .asciiz "- UZ_MODE = "
534msg_v0:
535    .align 2
536    .asciiz "- UZ_V0   = "
537msg_crlf:
538    .align 2
539    .asciiz "\n"
540msg_enter:
541    .align 2
542    .asciiz "\nenter kernel : &uzone = "
543msg_exit:
544    .align 2
545    .asciiz "\nexit kernel : &uzone = "
546msg_cycle:
547    .align 2
548    .asciiz " / cycle = "
549
Note: See TracBrowser for help on using the repository browser.