Root/mips/entry.S

1// Iris: micro-kernel for a capability-based operating system.
2// mips/entry.S: Routines which are entered from user space.
3// Copyright 2009 Bas Wijnen <wijnen@debian.org>
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18#define KERNEL_STACK_SIZE 0x1000
19    // The kernel stack.
20    .bss
21    .lcomm kernel_stack, KERNEL_STACK_SIZE
22
23    .globl run_idle
24    .globl directory
25    .set noat
26    .set noreorder
27
28    .text
29
30#define ARCH
31#define ASM
32#define __KERNEL__
33#include "arch.hh"
34
35    .org 0x000
36addr_000:
37#if 1
38    // TLB refill
39    lui $k0, 0x8000
40    lw $k1, 0x174($k0) // directory
41    mfc0 $k0, $CP0_ENTRY_HI
42    // Entry high is address: 12 bit offset in page; 1 bit even/odd; 9 bit which page pair; 10 bit which table.
43    srl $k0, $k0, 19
44    andi $k0, $k0, 0xffc // Bits 30:21 remain: which page table to get from directory.
45    addu $k0, $k0, $k1
46    lw $k0, 0($k0) // k0 is the page table.
47    beq $zero, $k0, zero_refill
48    mfc0 $k1, $CP0_ENTRY_HI
49    srl $k1, $k1, 10
50    // Bits 20:13 remain: which page pair to get from page table.
51    // (Only the lower half is used for this; the upper half contains pointers to the kPages.)
52    andi $k1, $k1, 0x7f8
53    addu $k0, $k0, $k1
54    lw $k1, 0($k0)
55    mtc0 $k1, $CP0_ENTRY_LO0
56    lw $k1, 4($k0)
57    mtc0 $k1, $CP0_ENTRY_LO1
581: tlbwr
59    move $k0, $zero
60    move $k1, $zero
61    eret
62
63zero_refill:
64    mtc0 $zero, $CP0_ENTRY_LO0
65    b 1b
66    mtc0 $zero, $CP0_ENTRY_LO1
67#else
68    // Slow refill: use C code (which calls kdebug etc)
69    move $k1, $ra
70    bal save_regs
71    nop
72    la $t9, tlb_refill
73    jr $t9
74    nop
75#endif
76
77    .org 0x100
78addr_100:
79    // Cache error
80    move $k1, $ra
81    bal save_regs
82    nop
83    la $t9, cache_error
84    jr $t9
85    nop
86
87    .org 0x180 - 3 * 4
88directory: // 0x174
89    .word 0
90current: // 0x178
91    .word idle
92        // 0x17c
93    .word _gp
94
95addr_180:
96    // General exception
97    move $k1, $ra
98    bal save_regs
99    nop
100    la $t9, exception
101    jr $t9
102    nop
103
104    .org 0x200 - 2 * 4
105    .word 0x00000012 // 1f8 EntryLo data for idle page.
106    .word 0x80000000 // 1fc A pointer to the current page.
107addr_200:
108    // Interrupt
109    move $k1, $ra
110    bal save_regs
111    nop
112    la $t9, interrupt
113    jr $t9
114    nop
115
116    .org 0x280
117start_idle: // 280
118    // Wait for the next interrupt, then the first thread will be scheduled.
119    // It is impractical to try to call schedule, because for that the
120    // idle task would need to own capabilities.
1211: wait
122    b 1b
123    nop
124
125// TODO: save only fragile registers now, the rest on task switch.
126kernel_exit:
127    move $k0, $v0
128    lui $k1, 0x8000
129    sw $v0, 0x178($k1) // current
130    lw $k1, SAVE_PC($k0)
131    mtc0 $k1, $CP0_EPC
132    lw $k1, SAVE_LO($k0)
133    mtlo $k1
134    lw $k1, SAVE_HI($k0)
135    mthi $k1
136    lw $v0, SAVE_V + 0 * 4($k0)
137    lw $v1, SAVE_V + 1 * 4($k0)
138    lw $a0, SAVE_A + 0 * 4($k0)
139    lw $a1, SAVE_A + 1 * 4($k0)
140    lw $a2, SAVE_A + 2 * 4($k0)
141    lw $a3, SAVE_A + 3 * 4($k0)
142    lw $t0, SAVE_T + 0 * 4($k0)
143    lw $t1, SAVE_T + 1 * 4($k0)
144    lw $t2, SAVE_T + 2 * 4($k0)
145    lw $t3, SAVE_T + 3 * 4($k0)
146    lw $t4, SAVE_T + 4 * 4($k0)
147    lw $t5, SAVE_T + 5 * 4($k0)
148    lw $t6, SAVE_T + 6 * 4($k0)
149    lw $t7, SAVE_T + 7 * 4($k0)
150    lw $t8, SAVE_T + 8 * 4($k0)
151    lw $t9, SAVE_T + 9 * 4($k0)
152    lw $s0, SAVE_S + 0 * 4($k0)
153    lw $s1, SAVE_S + 1 * 4($k0)
154    lw $s2, SAVE_S + 2 * 4($k0)
155    lw $s3, SAVE_S + 3 * 4($k0)
156    lw $s4, SAVE_S + 4 * 4($k0)
157    lw $s5, SAVE_S + 5 * 4($k0)
158    lw $s6, SAVE_S + 6 * 4($k0)
159    lw $s7, SAVE_S + 7 * 4($k0)
160    lw $fp, SAVE_FP($k0)
161    lw $at, SAVE_AT($k0)
162    lw $sp, SAVE_SP($k0)
163    lw $gp, SAVE_GP($k0)
164    lw $ra, SAVE_RA($k0)
165#ifndef NDEBUG
166    // Exceptions were enabled in the kernel; set them to usermode setting again.
167    mfc0 $k1, $CP0_STATUS
168    ori $k1, $k1, 0xff13
169    mtc0 $k1, $CP0_STATUS
170#endif
171    move $k0, $zero
172    move $k1, $zero
173    eret
174
175save_regs:
176    lui $k0, 0x8000
177    lw $k0, 0x178($k0) // current
178
179    sw $k1, SAVE_RA($k0)
180    sw $gp, SAVE_GP($k0)
181    sw $sp, SAVE_SP($k0)
182    sw $at, SAVE_AT($k0)
183    sw $fp, SAVE_FP($k0)
184    sw $s7, SAVE_S + 7 * 4($k0)
185    sw $s6, SAVE_S + 6 * 4($k0)
186    sw $s5, SAVE_S + 5 * 4($k0)
187    sw $s4, SAVE_S + 4 * 4($k0)
188    sw $s3, SAVE_S + 3 * 4($k0)
189    sw $s2, SAVE_S + 2 * 4($k0)
190    sw $s1, SAVE_S + 1 * 4($k0)
191    sw $s0, SAVE_S + 0 * 4($k0)
192    sw $t9, SAVE_T + 9 * 4($k0)
193    sw $t8, SAVE_T + 8 * 4($k0)
194    sw $t7, SAVE_T + 7 * 4($k0)
195    sw $t6, SAVE_T + 6 * 4($k0)
196    sw $t5, SAVE_T + 5 * 4($k0)
197    sw $t4, SAVE_T + 4 * 4($k0)
198    sw $t3, SAVE_T + 3 * 4($k0)
199    sw $t2, SAVE_T + 2 * 4($k0)
200    sw $t1, SAVE_T + 1 * 4($k0)
201    sw $t0, SAVE_T + 0 * 4($k0)
202    sw $a3, SAVE_A + 3 * 4($k0)
203    sw $a2, SAVE_A + 2 * 4($k0)
204    sw $a1, SAVE_A + 1 * 4($k0)
205    sw $a0, SAVE_A + 0 * 4($k0)
206    sw $v1, SAVE_V + 1 * 4($k0)
207    sw $v0, SAVE_V + 0 * 4($k0)
208    mfhi $k1
209    sw $k1, SAVE_HI($k0)
210    mflo $k1
211    sw $k1, SAVE_LO($k0)
212    mfc0 $k1, $CP0_EPC
213    sw $k1, SAVE_PC($k0)
214
215#ifndef NDEBUG
216    // Allow kernel bugs to set EPC and friends.
217    mfc0 $k0, $CP0_STATUS
218    lui $k1, 0x1000
219    and $k0, $k0, $k1
220    mtc0 $k0, $CP0_STATUS
221#endif
222
223    lui $k0, 0x8000
224    lw $gp, 0x17c($k0)
225    la $sp, kernel_stack + KERNEL_STACK_SIZE
226
227    move $t9, $ra
228    la $ra, kernel_exit
229    jr $t9
230    nop
231
232    .set at
233    .set reorder
234

Archive Download this file

Branches:
master



interactive