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

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

This version executed successfully the user "init" process on a mono-processor TSAR architecture.

File size: 10.0 KB
RevLine 
[16]1/*
[279]2 * hal_kentry.S - Interrupt / Exception / Syscall kernel entry point for MIPS32
[16]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
[406]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_T8           16
43#define      UZ_T9           17
44#define      UZ_S0           18
45#define      UZ_S1           19
46#define      UZ_S2           20
47#define      UZ_S3           21
48#define      UZ_S4           22
49#define      UZ_S5           23
50#define      UZ_S6           24
51#define      UZ_S7           25
52#define      UZ_S8           26
53#define      UZ_GP           27
54#define      UZ_RA           28
55#define      UZ_EPC          29
56#define      UZ_CR           30
57#define      UZ_SP           31
58#define      UZ_SR           32
59#define      UZ_LO           33
60#define      UZ_HI           34
[16]61
[406]62#define      UZ_REGS         35
[16]63
[406]64#include <kernel_config.h>
65
[296]66        .section   .kentry, "ax", @progbits
[279]67
68        .extern    hal_do_interrupt
69        .extern    hal_do_exception
70        .extern    hal_do_syscall
71        .extern    cluster_core_kernel_enter
[406]72        .extern    cluster_core_kentry_exit
[279]73
[16]74        .org       0x180
[279]75
[406]76        .global    hal_kentry_enter
77    .global    hal_kentry_eret
78
[16]79        .set       noat
80        .set       noreorder
81
82#---------------------------------------------------------------------------------
[279]83# Kernel Entry point for Interrupt / Exception / Syscall
[406]84# The c2_dext and c2_iext CP2 registers must have been previously set
85# to "local_cxy", because the kernel run with MMU desactivated.
[16]86#---------------------------------------------------------------------------------
87
[406]88hal_kentry_enter:
89
90        mfc0    $26,    $12                 # get c0_sr
91        andi    $26,    $26,  0x10          # test User Mode bit
92        beq     $26,    $0,       kernel_mode   # jump if core already in kernel
93        ori     $27,    $0,       0x3           # $27 <= code for MMU OFF
[16]94       
95#---------------------------------------------------------------------------------------       
[406]96# This code is executed when the core is in user mode:
97# - save current c2_mode in $26.
98# - set MMU OFF.
99# - save user stack pointer in $27.
100# - set kernel stack pointer in $29.
[16]101
102user_mode:
103
[406]104    mfc2    $26,    $1                  # $26 <= c2_mode
105        mtc2    $27,    $1                              # set MMU OFF
106    move    $27,    $29                 # $27 <= user stack pointer
107        mfc0    $29,    $4,   2             # get pointer on thread descriptor from c0_th
108    addi    $29,    $29,    CONFIG_THREAD_DESC_SIZE
109    addi    $29,    $29,    -8          # $29 <= kernel stack pointer
110    j       unified_mode
111    nop
[16]112
113#---------------------------------------------------------------------------------------       
[406]114# This code is executed when the core is already in kernel mode:
115# - save current c2_mode in $26.
116# - set MMU OFF.
117# - save current kernel stack pointer in $27.
[16]118
119kernel_mode:
120
[406]121    mfc2    $26,    $1                  # $26 <= c2_mode
[16]122        mtc2    $27,    $1                              # set MMU OFF
[406]123    move    $27,    $29                 # $27 <= current kernel stack pointer
[16]124
[406]125#---------------------------------------------------------------------------------------       
126# This code is executed in both modes (user or kernel):
127# The assumptions are:
128# - c2_mode contains the MMU OFF value.
129# - $26 contains the previous c2_mode value.
130# - $27 contains the previous sp value (can be usp or ksp).
131# - $29 contains the kernel stack pointer.
132# We execute the following actions:
133# - allocate an uzone in kernel stack, incrementing $29
134# - save relevant registers to uzone.
135# - set the SR in kernel mode: IRQ disabled, clear exl.
136# - signal the kernel entry.
[16]137
[406]138unified_mode:
[16]139
[406]140        addiu   $29,    $29,  -(UZ_REGS*4)      # allocate uzone in kernel stack
[16]141
[406]142        sw      $1,         (UZ_AT*4)($29)
143        sw      $2,     (UZ_V0*4)($29)
144        sw      $3,     (UZ_V1*4)($29)
145        sw      $4,     (UZ_A0*4)($29)
146        sw      $5,     (UZ_A1*4)($29)
147        sw      $6,     (UZ_A2*4)($29)
148        sw      $7,     (UZ_A3*4)($29)
149        sw      $8,     (UZ_T0*4)($29)
150        sw      $9,     (UZ_T1*4)($29)
151        sw      $10,    (UZ_T2*4)($29)
152        sw      $11,    (UZ_T3*4)($29)
153        sw      $12,    (UZ_T4*4)($29)
154        sw      $13,    (UZ_T5*4)($29)
155        sw      $14,    (UZ_T6*4)($29)
156        sw      $15,    (UZ_T7*4)($29)
157        sw      $16,    (UZ_S0*4)($29)
158        sw      $17,    (UZ_S1*4)($29)
159        sw          $18,        (UZ_S2*4)($29)
160        sw          $19,        (UZ_S3*4)($29)
161        sw          $20,        (UZ_S4*4)($29)
162        sw          $21,        (UZ_S5*4)($29)
163        sw          $22,        (UZ_S6*4)($29)
164        sw          $23,        (UZ_S7*4)($29)
165        sw      $24,    (UZ_T8*4)($29)
166        sw      $25,    (UZ_T9*4)($29)
[16]167
[406]168        sw      $26,    (UZ_MODE*4)($29)    # save c2_mode
169        sw      $27,    (UZ_SP*4)($29)      # save sp
[16]170
[406]171        sw          $28,        (UZ_GP*4)($29)
172        sw          $30,        (UZ_S8*4)($29)
173        sw          $31,        (UZ_RA*4)($29)
[16]174
175        mfc0    $16,    $14
[406]176        sw      $16,    (UZ_EPC*4)($29)     # save c0_epc
[16]177        mflo    $14
[406]178        sw      $14,    (UZ_LO*4)($29)      # save lo
[16]179        mfhi    $15
[406]180        sw      $15,    (UZ_HI*4)($29)          # save hi
[16]181        mfc0    $18,    $12
[406]182        sw          $18,        (UZ_SR*4)($29)          # save c0_sr
[16]183        mfc0    $17,    $13
[406]184        sw      $17,    (UZ_CR*4)($29)          # save c0_cr
185        mfc2    $26,    $1
[16]186
[279]187        srl         $3,     $18,  5
[16]188        sll     $3,         $3,   5     
[406]189        mtc0    $3,         $12                         # set new sr
[16]190
191        # signal that core enters kernel
[279]192        la      $1,     cluster_core_kernel_enter
[406]193        jalr    $1
[16]194    nop
195
196#---------------------------------------------------------------------------------------
[279]197# This code call the relevant Interrupt / Exception / Syscall handler,
[406]198# depending on XCODE in CP0_CR.
199# assumption: $29 contains the kernel stack pointer, that is the uzone base.
[279]200# The three handlers take the same two arguments: thread pointer and uzone pointer.
[406]201# The uzone pointer is saved in $19 to be used by kentry_exit.
[16]202
[296]203        mfc0    $17,    $13                 # $17 <= CR
204        andi    $17,    $17,   0x3F         # $17 <= XCODE
[279]205
[16]206        mfc0    $4,     $4,   2             # $4 <= thread pointer (first arg)
[406]207        or          $5,     $0,   $29               # $5 <= uzone pointer (second arg)
208        or          $19,    $0,   $29           # $19 <= &uzone (for kentry_exit)
[16]209
210        ori         $8,     $0,   0x20          # $8 <= cause syscall
[296]211    beq     $8,     $17,  cause_sys     # go to syscall handler
[16]212    nop
[296]213        beq     $17,    $0,       cause_int     # go to interrupt handler
[16]214    nop
215
216cause_excp:
217        la      $1,         hal_do_exception
218        jalr    $1                              # call exception handler
219        addiu   $29,    $29,  -8                # hal_do_exception has 2 args
220        addiu   $29,    $29,  8
[406]221        j       kentry_exit                 # jump to kentry_exit
[16]222    nop
223
224cause_sys:
225        la          $1,         hal_do_syscall
226        jalr    $1                          # call syscall handler                 
227        addiu   $29,    $29,  -8            # hal_do_syscall has 2 args
228        addiu   $29,    $29,  8
[406]229        j           kentry_exit                 # jump to kentry_exit
[279]230        nop
[16]231       
232cause_int:
233        la          $1,     hal_do_interrupt
234        jalr    $1                          # call interrupt handler
235        addiu   $29,    $29,  -8            # hal_do_interrupt has 2 args
236        addiu   $29,    $29,  8
237
238# -----------------------------------------------------------------------------------
[279]239# Kernel exit
240# The pointer on uzone is supposed to be stored in $19
[16]241# -----------------------------------------------------------------------------------
[406]242kentry_exit:
[16]243
244        # signal that core exit kernel
[279]245    la      $1,     cluster_core_kernel_exit
246    jalr    $1
247    nop
[16]248
[406]249        # restore registers from uzone
[16]250        or          $27,    $0, $19             # $27 <= &uzone
251
252        lw          $29,        (UZ_SP*4)($27)          # restore SP from uzone
253        lw          $16,        (UZ_EPC*4)($27)       
254        mtc0    $16,    $14                             # restore EPC from uzone
255        lw          $16,    (UZ_HI*4)($27)
256        mthi    $16                                         # restore HI from uzone
257        lw          $16,    (UZ_LO*4)($27)
258        mtlo    $16                                         # restore LO from uzone
259
260        lw          $17,        (UZ_SR*4)($27)          # get saved SR value from uzone
261        andi    $17,    $17,    0x1F        # keep only the 5 LSB bits
262        mfc0    $26,    $12                             # get current SR value from CP0
263        or          $26,    $26,        $17         # merge the two values
264        mtc0    $26,    $12                             # setup new SR to CP0
265
266        lw          $1,     (UZ_AT*4)($27)             
267        lw          $2,     (UZ_V0*4)($27)
268        lw          $3,     (UZ_V1*4)($27)
269        lw          $4,     (UZ_A0*4)($27)
270        lw          $5,     (UZ_A1*4)($27)
271        lw          $6,     (UZ_A2*4)($27)
272        lw          $7,     (UZ_A3*4)($27)
273        lw          $8,     (UZ_T0*4)($27)
274        lw          $9,     (UZ_T1*4)($27)
275        lw          $10,    (UZ_T2*4)($27)
276        lw          $11,    (UZ_T3*4)($27)
277        lw          $12,    (UZ_T4*4)($27)
278        lw          $13,    (UZ_T5*4)($27)
279        lw          $14,    (UZ_T6*4)($27)
280        lw          $15,    (UZ_T7*4)($27)
281        lw          $16,    (UZ_S0*4)($27)
282        lw          $17,    (UZ_S1*4)($27)
283        lw          $18,        (UZ_S2*4)($27)
284        lw          $19,    (UZ_S3*4)($27)
285        lw          $20,        (UZ_S4*4)($27)
286        lw          $21,        (UZ_S5*4)($27)
287        lw          $22,        (UZ_S6*4)($27)
288        lw          $23,        (UZ_S7*4)($27)
289        lw          $24,    (UZ_T8*4)($27)
290        lw          $25,    (UZ_T9*4)($27)     
291        lw          $28,        (UZ_GP*4)($27)
292        lw          $30,        (UZ_S8*4)($27)
293        lw          $31,        (UZ_RA*4)($27)
294
[279]295        lw          $26,    (UZ_MODE*4)($27)   
296    mtc2    $26,    $1                  # restore CP2_MODE from uzone
[16]297
[406]298# -----------------------------------------------------------------------------------
299# eret function
300# -----------------------------------------------------------------------------------
301
302hal_kentry_eret:
[16]303        nop
304    eret
305
306    .set reorder
307    .set at
308
[406]309#------------------------------------------------------------------------------------
[16]310
Note: See TracBrowser for help on using the repository browser.