blob: 5af80faf7a9f13eff6d1c1fdbfd70c27151ee2e6 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2015 Stefan Kristiansson
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#include <asm.h>
24#include <arch/ops.h>
25#include <arch/or1k/mmu.h>
26#include <kernel/vm.h>
27
28#define RED_ZONE 128
29#define EXCEPTION_FRAME (128 + RED_ZONE)
30
31/* clobbers r9 and rd, result will be in rd */
32#define get_va_to_pa_offs(rd) \
33 l.movhi rd, hi(.+12) ;\
34 l.jal .+8 ;\
35 l.ori rd, rd, lo(.+4) ;\
36 l.sub rd, rd, r9
37
38/* clobbers r9 and rd, result will be in rd */
39#define to_phys(sym, rd) \
40 get_va_to_pa_offs(rd) ;\
41 l.movhi r9, hi(sym) ;\
42 l.ori r9, r9, lo(sym) ;\
43 l.sub rd, r9, rd
44
45.macro exception_entry
46#if WITH_KERNEL_VM
47 l.sw 0(r0), r31
48 l.sw 4(r0), r9
49 get_va_to_pa_offs(r31)
50 l.sub r1, r1, r31
51 l.lwz r9, 4(r0)
52#endif
53 l.addi r1, r1, -EXCEPTION_FRAME
54 l.sw 0(r1), r2
55 l.sw 4(r1), r3
56 l.sw 8(r1), r4
57 l.sw 12(r1), r5
58 l.sw 16(r1), r6
59 l.sw 20(r1), r7
60 l.sw 24(r1), r8
61 l.sw 28(r1), r9
62 l.sw 32(r1), r10
63 l.sw 36(r1), r11
64 l.sw 40(r1), r12
65 l.sw 44(r1), r13
66 l.sw 48(r1), r14
67 l.sw 52(r1), r15
68 l.sw 56(r1), r16
69 l.sw 60(r1), r17
70 l.sw 64(r1), r18
71 l.sw 68(r1), r19
72 l.sw 72(r1), r20
73 l.sw 76(r1), r21
74 l.sw 80(r1), r22
75 l.sw 84(r1), r23
76 l.sw 88(r1), r24
77 l.sw 92(r1), r25
78 l.sw 96(r1), r26
79 l.sw 100(r1), r27
80 l.sw 104(r1), r28
81 l.sw 108(r1), r29
82 l.sw 112(r1), r30
83 l.mfspr r3, r0, OR1K_SPR_SYS_EPCR_ADDR(0)
84 l.sw 120(r1), r3
85 l.mfspr r3, r0, OR1K_SPR_SYS_ESR_ADDR(0)
86 l.sw 124(r1), r3
87#if WITH_KERNEL_VM
88 l.add r1, r1, r31
89 l.lwz r31, 0(r0)
90
91 /* enable dmmu and immu */
92 l.mfspr r9, r0, OR1K_SPR_SYS_SR_ADDR
93 l.ori r9, r9, OR1K_SPR_SYS_SR_DME_MASK | OR1K_SPR_SYS_SR_IME_MASK
94 l.mtspr r0, r9, OR1K_SPR_SYS_ESR_ADDR(0)
95
96 l.movhi r9, hi(.+16)
97 l.ori r9, r9, lo(.+12)
98 l.mtspr r0, r9, OR1K_SPR_SYS_EPCR_ADDR(0)
99 l.rfe
100#endif
101 l.sw 116(r1), r31
102.endm
103
104.section ".vectors", "ax"
105.org 0x100
106.global _reset
107_reset:
108 l.jal start
109 l.nop
110
111.org 0x200
112bus_error_exception:
113 exception_entry
114 l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
115 l.jal or1k_busfault_handler
116 l.ori r3, r1, 0
117 l.j return_from_exception
118 l.nop
119
120.org 0x300
121data_pagefault_exception:
122 exception_entry
123 l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
124 l.jal or1k_data_pagefault_handler
125 l.ori r3, r1, 0
126 l.j return_from_exception
127 l.nop
128
129.org 0x400
130instruction_pagefault_exception:
131 exception_entry
132 l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
133 l.jal or1k_instruction_pagefault_handler
134 l.ori r3, r1, 0
135 l.j return_from_exception
136 l.nop
137
138.org 0x500
139tick_timer_exception:
140 exception_entry
141 l.jal or1k_tick
142 l.nop
143 l.j return_from_exception
144 l.nop
145
146.org 0x600
147alignment_exception:
148 exception_entry
149 l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
150 l.jal or1k_alignment_handler
151 l.ori r3, r1, 0
152 l.j return_from_exception
153 l.nop
154
155.org 0x700
156illegal_instruction_exception:
157 exception_entry
158 l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
159 l.jal or1k_illegal_instruction_handler
160 l.ori r3, r1, 0
161 l.j return_from_exception
162 l.nop
163
164.org 0x800
165external_interrupt_exception:
166 exception_entry
167 l.jal or1k_irq
168 l.nop
169 l.j return_from_exception
170 l.nop
171
172.org 0x900
173dtlb_miss_exception:
174#if WITH_KERNEL_VM
175 l.sw 0(r0), r3
176 l.sw 4(r0), r4
177 l.sw 8(r0), r9
178
179 to_phys(or1k_kernel_translation_table, r3)
180 l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
181 /* l1 index */
182 l.srli r9, r4, 24
183 l.slli r9, r9, 2
184
185 l.add r3, r3, r9
186
187 l.lwz r3, 0(r3) /* l1 entry */
188 l.andi r9, r3, OR1K_MMU_PG_PRESENT
189 l.sfnei r9, OR1K_MMU_PG_PRESENT
190 l.bf dtlb_miss_fault
191 l.andi r9, r3, OR1K_MMU_PG_L
192
193 l.sfeqi r9, OR1K_MMU_PG_L
194 /* l2_index */
195 l.srli r4, r4, 13
196 l.bf 1f
197 l.andi r4, r4, 0x7ff
198 l.slli r4, r4, 2
199 l.addi r9, r0, 0xffffe000 /* PAGE_SIZE-1 */
200 l.and r9, r3, r9
201 l.add r9, r9, r4
202 l.j 2f
203 l.lwz r9, 0(r9) /* l2 entry */
204
205/* use bits [23:13] from EEAR */
2061: l.slli r4, r4, 13
207 l.or r9, r3, r4
208
2092: l.ori r3,r0,0xf351 /* sw emulation of dmmupr */
210 l.srli r4,r9,4 /* get PP Index * 4 */
211 l.andi r4,r4,0xc /* mask everything but PPI (without X) (& 0b01100)*/
212 l.srl r3,r3,r4 /* get protection bits from "dmmupr" */
213 /*
214 * The protection bits are unconvienently the "wrong" way in DMMUPR
215 * compared to DTLBR (UWE|URE|SWE|SRE vs SWE|SRE|UWE|URE), so we have
216 * to swap their places...
217 */
218 l.andi r4,r3,0x3 /* SWE|SRE */
219 l.slli r4,r4,8 /* 1:0 -> 9:8 */
220 l.andi r3,r3,0xc /* UWE|URE */
221 l.slli r3,r3,4 /* 3:2 -> 7:6 */
222 l.or r3,r3,r4
223
224 l.addi r4,r0,0xffffe03f /* protection bit mask */
225 l.and r4,r9,r4 /* apply the mask */
226 l.or r9,r4,r3 /* apply protection bits */
227
228 l.mfspr r3, r0, OR1K_SPR_SYS_DMMUCFGR_ADDR
229 l.slli r3, r3, 31-OR1K_SPR_SYS_DMMUCFGR_NTS_MSB
230 l.srli r3, r3, 31-OR1K_SPR_SYS_DMMUCFGR_NTS_LSB
231 l.ori r4, r0, 1
232 l.sll r3, r4, r3
233 l.addi r3, r3, -1
234 l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
235 l.srli r4, r4, 13
236 l.and r3, r4, r3
237 l.mtspr r3, r9, OR1K_SPR_DMMU_DTLBW_TR_ADDR(0,0)
238 l.slli r4, r4, 13
239 l.ori r4, r4, OR1K_SPR_DMMU_DTLBW_MR_V_MASK
240 l.mtspr r3, r4, OR1K_SPR_DMMU_DTLBW_MR_ADDR(0,0)
241
242 l.lwz r3, 0(r0)
243 l.lwz r4, 4(r0)
244 l.lwz r9, 8(r0)
245 l.rfe
246#endif /* WITH_KERNEL_VM */
247
248dtlb_miss_fault:
249 l.lwz r3, 0(r0)
250 l.lwz r4, 4(r0)
251 l.j data_pagefault_exception
252 l.lwz r9, 8(r0)
253
254.org 0xa00
255itlb_miss_exception:
256#if WITH_KERNEL_VM
257 l.sw 0(r0), r3
258 l.sw 4(r0), r4
259 l.sw 8(r0), r9
260
261 to_phys(or1k_kernel_translation_table, r3)
262 l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
263 /* l1 index */
264 l.srli r9, r4, 24
265 l.slli r9, r9, 2
266
267 l.add r3, r3, r9
268 l.lwz r3, 0(r3) /* l1 entry */
269
270 l.andi r9, r3, OR1K_MMU_PG_PRESENT
271 l.sfnei r9, OR1K_MMU_PG_PRESENT
272 l.bf itlb_miss_fault
273 l.andi r9, r3, OR1K_MMU_PG_L
274 l.sfeqi r9, OR1K_MMU_PG_L
275 /* l2 index */
276 l.srli r4, r4, 13
277 l.bf 1f
278 l.andi r4, r4, 0x7ff
279
280 l.slli r4, r4, 2
281 l.addi r9, r0, 0xffffe000 /* PAGE_SIZE-1 */
282 l.and r9, r3, r9
283 l.add r9, r9, r4
284 l.j 2f
285 l.lwz r9, 0(r9) /* l2 entry */
286
287 /* use bits [23:13] from EEAR */
2881: l.slli r4, r4, 13
289 l.or r9, r3, r4
290
2912: l.ori r3, r0, 0xd00 /* sw emulation of immupr */
292 l.srli r4, r9, 5 /* get PP Index * 2 */
293 l.andi r4, r4, 0xa /* mask everything but PPI (without W) (& 0b1010)*/
294 l.srl r3, r3, r4 /* get protection bits from "immupr" */
295 l.andi r3, r3, 0x3 /* mask everything else out */
296 l.slli r3, r3, 6 /* and put them in their spot */
297 l.addi r4, r0, 0xffffe03f /* protection bit mask */
298 l.and r4, r9, r4 /* apply the mask */
299 l.or r9, r4, r3 /* apply protection bits */
300
301 l.mfspr r3, r0, OR1K_SPR_SYS_IMMUCFGR_ADDR
302 l.slli r3, r3, 31-OR1K_SPR_SYS_IMMUCFGR_NTS_MSB
303 l.srli r3, r3, 31-OR1K_SPR_SYS_IMMUCFGR_NTS_LSB
304 l.ori r4, r0, 1
305 l.sll r3, r4, r3
306 l.addi r3, r3, -1
307 l.mfspr r4, r0, OR1K_SPR_SYS_EEAR_ADDR(0)
308 l.srli r4, r4, 13
309 l.and r3, r4, r3
310 l.mtspr r3, r9, OR1K_SPR_IMMU_ITLBW_TR_ADDR(0,0)
311
312 l.slli r4, r4, 13
313 l.ori r4, r4, OR1K_SPR_IMMU_ITLBW_MR_V_MASK
314 l.mtspr r3, r4, OR1K_SPR_IMMU_ITLBW_MR_ADDR(0,0)
315
316 l.lwz r3, 0(r0)
317 l.lwz r4, 4(r0)
318 l.lwz r9, 8(r0)
319 l.rfe
320#endif /* WITH_KERNEL_VM */
321
322itlb_miss_fault:
323 l.lwz r3, 0(r0)
324 l.lwz r4, 4(r0)
325 l.j instruction_pagefault_exception
326 l.lwz r9, 8(r0)
327
328.org 0xb00
329range_exception:
330 exception_entry
331 l.ori r4, r0, 0xb00
332 l.jal or1k_unhandled_exception
333 l.ori r3, r1, 0
334 l.j return_from_exception
335 l.nop
336
337.org 0xc00
338syscall_exception:
339 exception_entry
340 l.jal or1k_syscall_handler
341 l.ori r3, r1, 0
342 l.j return_from_exception
343 l.nop
344
345.org 0xd00
346fpu_exception:
347 exception_entry
348 l.ori r4, r0, 0xd00
349 l.jal or1k_unhandled_exception
350 l.ori r3, r1, 0
351 l.j return_from_exception
352 l.nop
353
354.org 0xe00
355trap_exception:
356 exception_entry
357 l.ori r4, r0, 0xe00
358 l.jal or1k_unhandled_exception
359 l.ori r3, r1, 0
360 l.j return_from_exception
361 l.nop
362
363.section ".text.boot"
364FUNCTION(start)
365 /* set stack pointer to point at top of default stack */
366 l.movhi r1, hi(default_stack_top)
367 l.ori r1, r1, lo(default_stack_top)
368
369#if WITH_KERNEL_VM
370 /* invalidate tlbs */
371 l.ori r3, r0, OR1K_SPR_DMMU_DTLBW_MR_ADDR(0, 0)
372 l.ori r4, r0, OR1K_SPR_IMMU_ITLBW_MR_ADDR(0, 0)
373 l.addi r6, r0, 3 /* Maximum number of ways - 1 */
374
3751: l.addi r5, r0, 127 /* Maximum number of sets - 1 */
3762: l.mtspr r3, r0, 0x0
377 l.mtspr r4, r0, 0x0
378
379 l.addi r3, r3, 1
380 l.addi r4, r4, 1
381 l.sfeq r5, r0
382 l.bnf 2b
383 l.addi r5, r5, -1
384
385 l.addi r3, r3, 128
386 l.addi r4, r4, 128
387
388 l.sfeq r6, r0
389 l.bnf 1b
390 l.addi r6, r6, -1
391
392 /* setup initial mappings */
393 get_va_to_pa_offs(r3)
394 l.movhi r4, hi(or1k_kernel_translation_table)
395 l.ori r4, r4, lo(or1k_kernel_translation_table)
396 l.sub r4, r4, r3 /* to phys */
397 l.movhi r5, hi(mmu_initial_mappings)
398 l.ori r5, r5, lo(mmu_initial_mappings)
399 l.sub r5, r5, r3 /* to phys */
400
401 /* clear the translation table */
402 l.addi r3, r4, 255*4
4030: l.sw 0(r3), r0
404 l.sfeq r3, r4
405 l.bnf 0b
406 l.addi r3, r3, -4
407
4081: l.lwz r6, 0(r5) /* phys */
409 l.lwz r7, 4(r5) /* virt */
410 l.lwz r8, 8(r5) /* size */
411 l.lwz r9, 12(r5) /* flags */
412 l.lwz r10, 16(r5) /* name */
413 l.addi r5, r5, 20
414
415 /* divide with 16MB */
416 l.srli r6, r6, 24
417 l.srli r7, r7, 24
418 l.srli r8, r8, 24
419
420 l.sfeqi r8, 0
421 l.bf .Linitial_mapping_done
422 l.nop
423
4242: l.slli r3, r7, 2
425 l.add r3, r4, r3
426 l.slli r10, r6, 24
427 l.ori r10, r10, OR1K_MMU_PG_PRESENT | OR1K_MMU_PG_X | OR1K_MMU_PG_W | OR1K_MMU_PG_L
428 l.sfeqi r9, MMU_INITIAL_MAPPING_FLAG_UNCACHED
429 l.bf 3f
430 l.sfeqi r9, MMU_INITIAL_MAPPING_FLAG_DEVICE
431 l.bnf 4f
432 l.nop
4333: l.ori r10, r10, OR1K_MMU_PG_CI
4344: l.sw 0(r3), r10
435 l.addi r6, r6, 1
436 l.addi r8, r8, -1
437 l.sfeqi r8, 0
438 l.bnf 2b
439 l.addi r7, r7, 1
440
441 l.j 1b
442 l.nop
443
444.Linitial_mapping_done:
445 /* enable mmu */
446 l.mfspr r3, r0, OR1K_SPR_SYS_SR_ADDR
447 l.ori r3, r3, OR1K_SPR_SYS_SR_DME_MASK | OR1K_SPR_SYS_SR_IME_MASK
448 l.mtspr r0, r3, OR1K_SPR_SYS_ESR_ADDR(0)
449 /* setup pc to use virtual addresses */
450 l.movhi r3, hi(.+16)
451 l.ori r3, r3, lo(.+12)
452 l.mtspr r0, r3, OR1K_SPR_SYS_EPCR_ADDR(0)
453 l.rfe
454#endif
455
456 /* invalidate and enable caches */
457 l.jal arch_invalidate_cache_all
458 l.nop
459 l.jal arch_enable_cache
460 l.ori r3, r0, UCACHE
461
462 /* clear bss */
463 l.movhi r3, hi(__bss_start)
464 l.ori r3, r3, lo(__bss_start)
465 l.movhi r4, hi(__bss_end)
466 l.ori r4, r4, lo(__bss_end)
4671: l.sw 0(r3), r0
468 l.sfltu r3, r4
469 l.bf 1b
470 l.addi r3, r3, 4
471
472 /* arguments to main */
473 l.ori r3, r0, 1
474 l.ori r4, r0, 2
475 l.ori r5, r0, 3
476 l.jal lk_main
477 l.ori r6, r0, 4
478
479 /* shouldn't happen, but loop if it does */
480 l.j 0
481 l.nop
482
483FUNCTION(return_from_exception)
484 l.lwz r3, 120(r1)
485 l.mtspr r0, r3, OR1K_SPR_SYS_EPCR_BASE
486 l.lwz r3, 124(r1)
487 l.mtspr r0, r3, OR1K_SPR_SYS_ESR_BASE
488 l.lwz r2, 0(r1)
489 l.lwz r3, 4(r1)
490 l.lwz r4, 8(r1)
491 l.lwz r5, 12(r1)
492 l.lwz r6, 16(r1)
493 l.lwz r7, 20(r1)
494 l.lwz r8, 24(r1)
495 l.lwz r9, 28(r1)
496 l.lwz r10, 32(r1)
497 l.lwz r11, 36(r1)
498 l.lwz r12, 40(r1)
499 l.lwz r13, 44(r1)
500 l.lwz r14, 48(r1)
501 l.lwz r15, 52(r1)
502 l.lwz r16, 56(r1)
503 l.lwz r17, 60(r1)
504 l.lwz r18, 64(r1)
505 l.lwz r19, 68(r1)
506 l.lwz r20, 72(r1)
507 l.lwz r21, 76(r1)
508 l.lwz r22, 80(r1)
509 l.lwz r23, 84(r1)
510 l.lwz r24, 88(r1)
511 l.lwz r25, 92(r1)
512 l.lwz r26, 96(r1)
513 l.lwz r27, 100(r1)
514 l.lwz r28, 104(r1)
515 l.lwz r29, 108(r1)
516 l.lwz r30, 112(r1)
517 l.lwz r31, 116(r1)
518 l.addi r1, r1, EXCEPTION_FRAME
519 l.rfe
520
521.section ".bss"
522.align 8
523LOCAL_DATA(default_stack)
524.skip 8192
525LOCAL_DATA(default_stack_top)