]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - arch/openrisc/kernel/head.S
treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 151
[mirror_ubuntu-jammy-kernel.git] / arch / openrisc / kernel / head.S
CommitLineData
9d02a428
JB
1/*
2 * OpenRISC head.S
3 *
4 * Linux architectural port borrowing liberally from similar works of
5 * others. All original copyrights apply as per the original source
6 * declaration.
7 *
8 * Modifications for the OpenRISC architecture:
9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18#include <linux/linkage.h>
19#include <linux/threads.h>
20#include <linux/errno.h>
21#include <linux/init.h>
160d8378 22#include <linux/serial_reg.h>
9d02a428
JB
23#include <asm/processor.h>
24#include <asm/page.h>
25#include <asm/mmu.h>
26#include <asm/pgtable.h>
c2dc7243 27#include <asm/thread_info.h>
9d02a428
JB
28#include <asm/cache.h>
29#include <asm/spr_defs.h>
30#include <asm/asm-offsets.h>
dec83018 31#include <linux/of_fdt.h>
9d02a428
JB
32
33#define tophys(rd,rs) \
34 l.movhi rd,hi(-KERNELBASE) ;\
35 l.add rd,rd,rs
36
37#define CLEAR_GPR(gpr) \
a4d44266 38 l.movhi gpr,0x0
9d02a428
JB
39
40#define LOAD_SYMBOL_2_GPR(gpr,symbol) \
41 l.movhi gpr,hi(symbol) ;\
42 l.ori gpr,gpr,lo(symbol)
43
44
45#define UART_BASE_ADD 0x90000000
46
47#define EXCEPTION_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_DCE | SPR_SR_ICE | SPR_SR_SM)
48#define SYSCALL_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_DCE | SPR_SR_ICE | SPR_SR_IEE | SPR_SR_TEE | SPR_SR_SM)
49
50/* ============================================[ tmp store locations ]=== */
51
91993c8c
SK
52#define SPR_SHADOW_GPR(x) ((x) + SPR_GPR_BASE + 32)
53
9d02a428
JB
54/*
55 * emergency_print temporary stores
56 */
91993c8c
SK
57#ifdef CONFIG_OPENRISC_HAVE_SHADOW_GPRS
58#define EMERGENCY_PRINT_STORE_GPR4 l.mtspr r0,r4,SPR_SHADOW_GPR(14)
59#define EMERGENCY_PRINT_LOAD_GPR4 l.mfspr r4,r0,SPR_SHADOW_GPR(14)
60
61#define EMERGENCY_PRINT_STORE_GPR5 l.mtspr r0,r5,SPR_SHADOW_GPR(15)
62#define EMERGENCY_PRINT_LOAD_GPR5 l.mfspr r5,r0,SPR_SHADOW_GPR(15)
63
64#define EMERGENCY_PRINT_STORE_GPR6 l.mtspr r0,r6,SPR_SHADOW_GPR(16)
65#define EMERGENCY_PRINT_LOAD_GPR6 l.mfspr r6,r0,SPR_SHADOW_GPR(16)
66
67#define EMERGENCY_PRINT_STORE_GPR7 l.mtspr r0,r7,SPR_SHADOW_GPR(7)
68#define EMERGENCY_PRINT_LOAD_GPR7 l.mfspr r7,r0,SPR_SHADOW_GPR(7)
69
70#define EMERGENCY_PRINT_STORE_GPR8 l.mtspr r0,r8,SPR_SHADOW_GPR(8)
71#define EMERGENCY_PRINT_LOAD_GPR8 l.mfspr r8,r0,SPR_SHADOW_GPR(8)
72
73#define EMERGENCY_PRINT_STORE_GPR9 l.mtspr r0,r9,SPR_SHADOW_GPR(9)
74#define EMERGENCY_PRINT_LOAD_GPR9 l.mfspr r9,r0,SPR_SHADOW_GPR(9)
75
76#else /* !CONFIG_OPENRISC_HAVE_SHADOW_GPRS */
9d02a428
JB
77#define EMERGENCY_PRINT_STORE_GPR4 l.sw 0x20(r0),r4
78#define EMERGENCY_PRINT_LOAD_GPR4 l.lwz r4,0x20(r0)
79
80#define EMERGENCY_PRINT_STORE_GPR5 l.sw 0x24(r0),r5
81#define EMERGENCY_PRINT_LOAD_GPR5 l.lwz r5,0x24(r0)
82
83#define EMERGENCY_PRINT_STORE_GPR6 l.sw 0x28(r0),r6
84#define EMERGENCY_PRINT_LOAD_GPR6 l.lwz r6,0x28(r0)
85
86#define EMERGENCY_PRINT_STORE_GPR7 l.sw 0x2c(r0),r7
87#define EMERGENCY_PRINT_LOAD_GPR7 l.lwz r7,0x2c(r0)
88
89#define EMERGENCY_PRINT_STORE_GPR8 l.sw 0x30(r0),r8
90#define EMERGENCY_PRINT_LOAD_GPR8 l.lwz r8,0x30(r0)
91
92#define EMERGENCY_PRINT_STORE_GPR9 l.sw 0x34(r0),r9
93#define EMERGENCY_PRINT_LOAD_GPR9 l.lwz r9,0x34(r0)
94
91993c8c 95#endif
9d02a428
JB
96
97/*
98 * TLB miss handlers temorary stores
99 */
91993c8c
SK
100#ifdef CONFIG_OPENRISC_HAVE_SHADOW_GPRS
101#define EXCEPTION_STORE_GPR2 l.mtspr r0,r2,SPR_SHADOW_GPR(2)
102#define EXCEPTION_LOAD_GPR2 l.mfspr r2,r0,SPR_SHADOW_GPR(2)
103
104#define EXCEPTION_STORE_GPR3 l.mtspr r0,r3,SPR_SHADOW_GPR(3)
105#define EXCEPTION_LOAD_GPR3 l.mfspr r3,r0,SPR_SHADOW_GPR(3)
9d02a428 106
91993c8c
SK
107#define EXCEPTION_STORE_GPR4 l.mtspr r0,r4,SPR_SHADOW_GPR(4)
108#define EXCEPTION_LOAD_GPR4 l.mfspr r4,r0,SPR_SHADOW_GPR(4)
109
110#define EXCEPTION_STORE_GPR5 l.mtspr r0,r5,SPR_SHADOW_GPR(5)
111#define EXCEPTION_LOAD_GPR5 l.mfspr r5,r0,SPR_SHADOW_GPR(5)
112
113#define EXCEPTION_STORE_GPR6 l.mtspr r0,r6,SPR_SHADOW_GPR(6)
114#define EXCEPTION_LOAD_GPR6 l.mfspr r6,r0,SPR_SHADOW_GPR(6)
115
116#else /* !CONFIG_OPENRISC_HAVE_SHADOW_GPRS */
9d02a428
JB
117#define EXCEPTION_STORE_GPR2 l.sw 0x64(r0),r2
118#define EXCEPTION_LOAD_GPR2 l.lwz r2,0x64(r0)
119
120#define EXCEPTION_STORE_GPR3 l.sw 0x68(r0),r3
121#define EXCEPTION_LOAD_GPR3 l.lwz r3,0x68(r0)
122
123#define EXCEPTION_STORE_GPR4 l.sw 0x6c(r0),r4
124#define EXCEPTION_LOAD_GPR4 l.lwz r4,0x6c(r0)
125
126#define EXCEPTION_STORE_GPR5 l.sw 0x70(r0),r5
127#define EXCEPTION_LOAD_GPR5 l.lwz r5,0x70(r0)
128
129#define EXCEPTION_STORE_GPR6 l.sw 0x74(r0),r6
130#define EXCEPTION_LOAD_GPR6 l.lwz r6,0x74(r0)
131
91993c8c 132#endif
9d02a428
JB
133
134/*
135 * EXCEPTION_HANDLE temporary stores
136 */
137
91993c8c
SK
138#ifdef CONFIG_OPENRISC_HAVE_SHADOW_GPRS
139#define EXCEPTION_T_STORE_GPR30 l.mtspr r0,r30,SPR_SHADOW_GPR(30)
140#define EXCEPTION_T_LOAD_GPR30(reg) l.mfspr reg,r0,SPR_SHADOW_GPR(30)
141
142#define EXCEPTION_T_STORE_GPR10 l.mtspr r0,r10,SPR_SHADOW_GPR(10)
143#define EXCEPTION_T_LOAD_GPR10(reg) l.mfspr reg,r0,SPR_SHADOW_GPR(10)
144
145#define EXCEPTION_T_STORE_SP l.mtspr r0,r1,SPR_SHADOW_GPR(1)
146#define EXCEPTION_T_LOAD_SP(reg) l.mfspr reg,r0,SPR_SHADOW_GPR(1)
147
148#else /* !CONFIG_OPENRISC_HAVE_SHADOW_GPRS */
9d02a428
JB
149#define EXCEPTION_T_STORE_GPR30 l.sw 0x78(r0),r30
150#define EXCEPTION_T_LOAD_GPR30(reg) l.lwz reg,0x78(r0)
151
152#define EXCEPTION_T_STORE_GPR10 l.sw 0x7c(r0),r10
153#define EXCEPTION_T_LOAD_GPR10(reg) l.lwz reg,0x7c(r0)
154
91993c8c 155#define EXCEPTION_T_STORE_SP l.sw 0x80(r0),r1
9d02a428 156#define EXCEPTION_T_LOAD_SP(reg) l.lwz reg,0x80(r0)
91993c8c 157#endif
9d02a428
JB
158
159/* =========================================================[ macros ]=== */
160
8e6d08e0 161#ifdef CONFIG_SMP
9d02a428
JB
162#define GET_CURRENT_PGD(reg,t1) \
163 LOAD_SYMBOL_2_GPR(reg,current_pgd) ;\
8e6d08e0
SK
164 l.mfspr t1,r0,SPR_COREID ;\
165 l.slli t1,t1,2 ;\
166 l.add reg,reg,t1 ;\
9d02a428
JB
167 tophys (t1,reg) ;\
168 l.lwz reg,0(t1)
8e6d08e0
SK
169#else
170#define GET_CURRENT_PGD(reg,t1) \
171 LOAD_SYMBOL_2_GPR(reg,current_pgd) ;\
172 tophys (t1,reg) ;\
173 l.lwz reg,0(t1)
174#endif
9d02a428 175
8e6d08e0
SK
176/* Load r10 from current_thread_info_set - clobbers r1 and r30 */
177#ifdef CONFIG_SMP
178#define GET_CURRENT_THREAD_INFO \
179 LOAD_SYMBOL_2_GPR(r1,current_thread_info_set) ;\
180 tophys (r30,r1) ;\
181 l.mfspr r10,r0,SPR_COREID ;\
182 l.slli r10,r10,2 ;\
183 l.add r30,r30,r10 ;\
184 /* r10: current_thread_info */ ;\
185 l.lwz r10,0(r30)
186#else
187#define GET_CURRENT_THREAD_INFO \
188 LOAD_SYMBOL_2_GPR(r1,current_thread_info_set) ;\
189 tophys (r30,r1) ;\
190 /* r10: current_thread_info */ ;\
191 l.lwz r10,0(r30)
192#endif
9d02a428
JB
193
194/*
195 * DSCR: this is a common hook for handling exceptions. it will save
196 * the needed registers, set up stack and pointer to current
197 * then jump to the handler while enabling MMU
198 *
199 * PRMS: handler - a function to jump to. it has to save the
200 * remaining registers to kernel stack, call
201 * appropriate arch-independant exception handler
202 * and finaly jump to ret_from_except
203 *
204 * PREQ: unchanged state from the time exception happened
205 *
206 * POST: SAVED the following registers original value
207 * to the new created exception frame pointed to by r1
208 *
209 * r1 - ksp pointing to the new (exception) frame
210 * r4 - EEAR exception EA
211 * r10 - current pointing to current_thread_info struct
212 * r12 - syscall 0, since we didn't come from syscall
ae15a41a 213 * r30 - handler address of the handler we'll jump to
9d02a428
JB
214 *
215 * handler has to save remaining registers to the exception
216 * ksp frame *before* tainting them!
217 *
218 * NOTE: this function is not reentrant per se. reentrancy is guaranteed
219 * by processor disabling all exceptions/interrupts when exception
220 * accours.
221 *
222 * OPTM: no need to make it so wasteful to extract ksp when in user mode
223 */
224
225#define EXCEPTION_HANDLE(handler) \
226 EXCEPTION_T_STORE_GPR30 ;\
227 l.mfspr r30,r0,SPR_ESR_BASE ;\
228 l.andi r30,r30,SPR_SR_SM ;\
229 l.sfeqi r30,0 ;\
230 EXCEPTION_T_STORE_GPR10 ;\
231 l.bnf 2f /* kernel_mode */ ;\
232 EXCEPTION_T_STORE_SP /* delay slot */ ;\
2331: /* user_mode: */ ;\
8e6d08e0 234 GET_CURRENT_THREAD_INFO ;\
9d02a428
JB
235 tophys (r30,r10) ;\
236 l.lwz r1,(TI_KSP)(r30) ;\
237 /* fall through */ ;\
2382: /* kernel_mode: */ ;\
239 /* create new stack frame, save only needed gprs */ ;\
240 /* r1: KSP, r10: current, r4: EEAR, r31: __pa(KSP) */ ;\
241 /* r12: temp, syscall indicator */ ;\
242 l.addi r1,r1,-(INT_FRAME_SIZE) ;\
243 /* r1 is KSP, r30 is __pa(KSP) */ ;\
244 tophys (r30,r1) ;\
245 l.sw PT_GPR12(r30),r12 ;\
ae15a41a 246 /* r4 use for tmp before EA */ ;\
9d02a428
JB
247 l.mfspr r12,r0,SPR_EPCR_BASE ;\
248 l.sw PT_PC(r30),r12 ;\
249 l.mfspr r12,r0,SPR_ESR_BASE ;\
250 l.sw PT_SR(r30),r12 ;\
251 /* save r30 */ ;\
252 EXCEPTION_T_LOAD_GPR30(r12) ;\
253 l.sw PT_GPR30(r30),r12 ;\
254 /* save r10 as was prior to exception */ ;\
255 EXCEPTION_T_LOAD_GPR10(r12) ;\
256 l.sw PT_GPR10(r30),r12 ;\
257 /* save PT_SP as was prior to exception */ ;\
258 EXCEPTION_T_LOAD_SP(r12) ;\
259 l.sw PT_SP(r30),r12 ;\
260 /* save exception r4, set r4 = EA */ ;\
261 l.sw PT_GPR4(r30),r4 ;\
262 l.mfspr r4,r0,SPR_EEAR_BASE ;\
263 /* r12 == 1 if we come from syscall */ ;\
264 CLEAR_GPR(r12) ;\
265 /* ----- turn on MMU ----- */ ;\
ae15a41a
SH
266 /* Carry DSX into exception SR */ ;\
267 l.mfspr r30,r0,SPR_SR ;\
268 l.andi r30,r30,SPR_SR_DSX ;\
269 l.ori r30,r30,(EXCEPTION_SR) ;\
9d02a428
JB
270 l.mtspr r0,r30,SPR_ESR_BASE ;\
271 /* r30: EA address of handler */ ;\
272 LOAD_SYMBOL_2_GPR(r30,handler) ;\
273 l.mtspr r0,r30,SPR_EPCR_BASE ;\
274 l.rfe
275
276/*
277 * this doesn't work
278 *
279 *
280 * #ifdef CONFIG_JUMP_UPON_UNHANDLED_EXCEPTION
281 * #define UNHANDLED_EXCEPTION(handler) \
282 * l.ori r3,r0,0x1 ;\
283 * l.mtspr r0,r3,SPR_SR ;\
284 * l.movhi r3,hi(0xf0000100) ;\
285 * l.ori r3,r3,lo(0xf0000100) ;\
286 * l.jr r3 ;\
287 * l.nop 1
288 *
289 * #endif
290 */
291
292/* DSCR: this is the same as EXCEPTION_HANDLE(), we are just
293 * a bit more carefull (if we have a PT_SP or current pointer
294 * corruption) and set them up from 'current_set'
295 *
296 */
297#define UNHANDLED_EXCEPTION(handler) \
91993c8c 298 EXCEPTION_T_STORE_GPR30 ;\
9d02a428
JB
299 EXCEPTION_T_STORE_GPR10 ;\
300 EXCEPTION_T_STORE_SP ;\
301 /* temporary store r3, r9 into r1, r10 */ ;\
302 l.addi r1,r3,0x0 ;\
303 l.addi r10,r9,0x0 ;\
304 /* the string referenced by r3 must be low enough */ ;\
305 l.jal _emergency_print ;\
306 l.ori r3,r0,lo(_string_unhandled_exception) ;\
307 l.mfspr r3,r0,SPR_NPC ;\
308 l.jal _emergency_print_nr ;\
309 l.andi r3,r3,0x1f00 ;\
310 /* the string referenced by r3 must be low enough */ ;\
311 l.jal _emergency_print ;\
312 l.ori r3,r0,lo(_string_epc_prefix) ;\
313 l.jal _emergency_print_nr ;\
314 l.mfspr r3,r0,SPR_EPCR_BASE ;\
315 l.jal _emergency_print ;\
316 l.ori r3,r0,lo(_string_nl) ;\
317 /* end of printing */ ;\
318 l.addi r3,r1,0x0 ;\
319 l.addi r9,r10,0x0 ;\
320 /* extract current, ksp from current_set */ ;\
321 LOAD_SYMBOL_2_GPR(r1,_unhandled_stack_top) ;\
322 LOAD_SYMBOL_2_GPR(r10,init_thread_union) ;\
323 /* create new stack frame, save only needed gprs */ ;\
324 /* r1: KSP, r10: current, r31: __pa(KSP) */ ;\
325 /* r12: temp, syscall indicator, r13 temp */ ;\
326 l.addi r1,r1,-(INT_FRAME_SIZE) ;\
91993c8c
SK
327 /* r1 is KSP, r30 is __pa(KSP) */ ;\
328 tophys (r30,r1) ;\
329 l.sw PT_GPR12(r30),r12 ;\
9d02a428 330 l.mfspr r12,r0,SPR_EPCR_BASE ;\
91993c8c 331 l.sw PT_PC(r30),r12 ;\
9d02a428 332 l.mfspr r12,r0,SPR_ESR_BASE ;\
91993c8c 333 l.sw PT_SR(r30),r12 ;\
9d02a428 334 /* save r31 */ ;\
91993c8c
SK
335 EXCEPTION_T_LOAD_GPR30(r12) ;\
336 l.sw PT_GPR30(r30),r12 ;\
9d02a428
JB
337 /* save r10 as was prior to exception */ ;\
338 EXCEPTION_T_LOAD_GPR10(r12) ;\
91993c8c 339 l.sw PT_GPR10(r30),r12 ;\
9d02a428
JB
340 /* save PT_SP as was prior to exception */ ;\
341 EXCEPTION_T_LOAD_SP(r12) ;\
91993c8c
SK
342 l.sw PT_SP(r30),r12 ;\
343 l.sw PT_GPR13(r30),r13 ;\
9d02a428
JB
344 /* --> */ ;\
345 /* save exception r4, set r4 = EA */ ;\
91993c8c 346 l.sw PT_GPR4(r30),r4 ;\
9d02a428
JB
347 l.mfspr r4,r0,SPR_EEAR_BASE ;\
348 /* r12 == 1 if we come from syscall */ ;\
349 CLEAR_GPR(r12) ;\
350 /* ----- play a MMU trick ----- */ ;\
91993c8c
SK
351 l.ori r30,r0,(EXCEPTION_SR) ;\
352 l.mtspr r0,r30,SPR_ESR_BASE ;\
9d02a428 353 /* r31: EA address of handler */ ;\
91993c8c
SK
354 LOAD_SYMBOL_2_GPR(r30,handler) ;\
355 l.mtspr r0,r30,SPR_EPCR_BASE ;\
9d02a428
JB
356 l.rfe
357
358/* =====================================================[ exceptions] === */
359
360/* ---[ 0x100: RESET exception ]----------------------------------------- */
361 .org 0x100
362 /* Jump to .init code at _start which lives in the .head section
363 * and will be discarded after boot.
364 */
54bd7c51
SK
365 LOAD_SYMBOL_2_GPR(r15, _start)
366 tophys (r13,r15) /* MMU disabled */
367 l.jr r13
9d02a428
JB
368 l.nop
369
370/* ---[ 0x200: BUS exception ]------------------------------------------- */
371 .org 0x200
372_dispatch_bus_fault:
373 EXCEPTION_HANDLE(_bus_fault_handler)
374
375/* ---[ 0x300: Data Page Fault exception ]------------------------------- */
376 .org 0x300
377_dispatch_do_dpage_fault:
378// totaly disable timer interrupt
379// l.mtspr r0,r0,SPR_TTMR
380// DEBUG_TLB_PROBE(0x300)
381// EXCEPTION_DEBUG_VALUE_ER_ENABLED(0x300)
382 EXCEPTION_HANDLE(_data_page_fault_handler)
383
384/* ---[ 0x400: Insn Page Fault exception ]------------------------------- */
385 .org 0x400
386_dispatch_do_ipage_fault:
387// totaly disable timer interrupt
388// l.mtspr r0,r0,SPR_TTMR
389// DEBUG_TLB_PROBE(0x400)
390// EXCEPTION_DEBUG_VALUE_ER_ENABLED(0x400)
391 EXCEPTION_HANDLE(_insn_page_fault_handler)
392
393/* ---[ 0x500: Timer exception ]----------------------------------------- */
394 .org 0x500
395 EXCEPTION_HANDLE(_timer_handler)
396
550116d2 397/* ---[ 0x600: Alignment exception ]-------------------------------------- */
9d02a428
JB
398 .org 0x600
399 EXCEPTION_HANDLE(_alignment_handler)
400
401/* ---[ 0x700: Illegal insn exception ]---------------------------------- */
402 .org 0x700
403 EXCEPTION_HANDLE(_illegal_instruction_handler)
404
405/* ---[ 0x800: External interrupt exception ]---------------------------- */
406 .org 0x800
407 EXCEPTION_HANDLE(_external_irq_handler)
408
409/* ---[ 0x900: DTLB miss exception ]------------------------------------- */
410 .org 0x900
411 l.j boot_dtlb_miss_handler
412 l.nop
413
414/* ---[ 0xa00: ITLB miss exception ]------------------------------------- */
415 .org 0xa00
416 l.j boot_itlb_miss_handler
417 l.nop
418
419/* ---[ 0xb00: Range exception ]----------------------------------------- */
420 .org 0xb00
421 UNHANDLED_EXCEPTION(_vector_0xb00)
422
423/* ---[ 0xc00: Syscall exception ]--------------------------------------- */
424 .org 0xc00
425 EXCEPTION_HANDLE(_sys_call_handler)
426
427/* ---[ 0xd00: Trap exception ]------------------------------------------ */
428 .org 0xd00
429 UNHANDLED_EXCEPTION(_vector_0xd00)
430
431/* ---[ 0xe00: Trap exception ]------------------------------------------ */
432 .org 0xe00
433// UNHANDLED_EXCEPTION(_vector_0xe00)
434 EXCEPTION_HANDLE(_trap_handler)
435
436/* ---[ 0xf00: Reserved exception ]-------------------------------------- */
437 .org 0xf00
438 UNHANDLED_EXCEPTION(_vector_0xf00)
439
440/* ---[ 0x1000: Reserved exception ]------------------------------------- */
441 .org 0x1000
442 UNHANDLED_EXCEPTION(_vector_0x1000)
443
444/* ---[ 0x1100: Reserved exception ]------------------------------------- */
445 .org 0x1100
446 UNHANDLED_EXCEPTION(_vector_0x1100)
447
448/* ---[ 0x1200: Reserved exception ]------------------------------------- */
449 .org 0x1200
450 UNHANDLED_EXCEPTION(_vector_0x1200)
451
452/* ---[ 0x1300: Reserved exception ]------------------------------------- */
453 .org 0x1300
454 UNHANDLED_EXCEPTION(_vector_0x1300)
455
456/* ---[ 0x1400: Reserved exception ]------------------------------------- */
457 .org 0x1400
458 UNHANDLED_EXCEPTION(_vector_0x1400)
459
460/* ---[ 0x1500: Reserved exception ]------------------------------------- */
461 .org 0x1500
462 UNHANDLED_EXCEPTION(_vector_0x1500)
463
464/* ---[ 0x1600: Reserved exception ]------------------------------------- */
465 .org 0x1600
466 UNHANDLED_EXCEPTION(_vector_0x1600)
467
468/* ---[ 0x1700: Reserved exception ]------------------------------------- */
469 .org 0x1700
470 UNHANDLED_EXCEPTION(_vector_0x1700)
471
472/* ---[ 0x1800: Reserved exception ]------------------------------------- */
473 .org 0x1800
474 UNHANDLED_EXCEPTION(_vector_0x1800)
475
476/* ---[ 0x1900: Reserved exception ]------------------------------------- */
477 .org 0x1900
478 UNHANDLED_EXCEPTION(_vector_0x1900)
479
480/* ---[ 0x1a00: Reserved exception ]------------------------------------- */
481 .org 0x1a00
482 UNHANDLED_EXCEPTION(_vector_0x1a00)
483
484/* ---[ 0x1b00: Reserved exception ]------------------------------------- */
485 .org 0x1b00
486 UNHANDLED_EXCEPTION(_vector_0x1b00)
487
488/* ---[ 0x1c00: Reserved exception ]------------------------------------- */
489 .org 0x1c00
490 UNHANDLED_EXCEPTION(_vector_0x1c00)
491
492/* ---[ 0x1d00: Reserved exception ]------------------------------------- */
493 .org 0x1d00
494 UNHANDLED_EXCEPTION(_vector_0x1d00)
495
496/* ---[ 0x1e00: Reserved exception ]------------------------------------- */
497 .org 0x1e00
498 UNHANDLED_EXCEPTION(_vector_0x1e00)
499
500/* ---[ 0x1f00: Reserved exception ]------------------------------------- */
501 .org 0x1f00
502 UNHANDLED_EXCEPTION(_vector_0x1f00)
503
504 .org 0x2000
505/* ===================================================[ kernel start ]=== */
506
507/* .text*/
508
509/* This early stuff belongs in HEAD, but some of the functions below definitely
510 * don't... */
511
512 __HEAD
513 .global _start
514_start:
a4d44266
SH
515 /* Init r0 to zero as per spec */
516 CLEAR_GPR(r0)
517
dec83018
SK
518 /* save kernel parameters */
519 l.or r25,r0,r3 /* pointer to fdt */
520
9d02a428
JB
521 /*
522 * ensure a deterministic start
523 */
524
525 l.ori r3,r0,0x1
526 l.mtspr r0,r3,SPR_SR
527
528 CLEAR_GPR(r1)
529 CLEAR_GPR(r2)
530 CLEAR_GPR(r3)
531 CLEAR_GPR(r4)
532 CLEAR_GPR(r5)
533 CLEAR_GPR(r6)
534 CLEAR_GPR(r7)
535 CLEAR_GPR(r8)
536 CLEAR_GPR(r9)
537 CLEAR_GPR(r10)
538 CLEAR_GPR(r11)
539 CLEAR_GPR(r12)
540 CLEAR_GPR(r13)
541 CLEAR_GPR(r14)
542 CLEAR_GPR(r15)
543 CLEAR_GPR(r16)
544 CLEAR_GPR(r17)
545 CLEAR_GPR(r18)
546 CLEAR_GPR(r19)
547 CLEAR_GPR(r20)
548 CLEAR_GPR(r21)
549 CLEAR_GPR(r22)
550 CLEAR_GPR(r23)
551 CLEAR_GPR(r24)
9d02a428
JB
552 CLEAR_GPR(r26)
553 CLEAR_GPR(r27)
554 CLEAR_GPR(r28)
555 CLEAR_GPR(r29)
556 CLEAR_GPR(r30)
557 CLEAR_GPR(r31)
558
8e6d08e0
SK
559#ifdef CONFIG_SMP
560 l.mfspr r26,r0,SPR_COREID
561 l.sfeq r26,r0
562 l.bnf secondary_wait
563 l.nop
564#endif
9d02a428
JB
565 /*
566 * set up initial ksp and current
567 */
c2dc7243
SK
568 /* setup kernel stack */
569 LOAD_SYMBOL_2_GPR(r1,init_thread_union + THREAD_SIZE)
9d02a428
JB
570 LOAD_SYMBOL_2_GPR(r10,init_thread_union) // setup current
571 tophys (r31,r10)
572 l.sw TI_KSP(r31), r1
573
574 l.ori r4,r0,0x0
575
576
577 /*
578 * .data contains initialized data,
579 * .bss contains uninitialized data - clear it up
580 */
581clear_bss:
582 LOAD_SYMBOL_2_GPR(r24, __bss_start)
583 LOAD_SYMBOL_2_GPR(r26, _end)
584 tophys(r28,r24)
585 tophys(r30,r26)
586 CLEAR_GPR(r24)
587 CLEAR_GPR(r26)
5881:
589 l.sw (0)(r28),r0
590 l.sfltu r28,r30
591 l.bf 1b
592 l.addi r28,r28,4
593
594enable_ic:
595 l.jal _ic_enable
596 l.nop
597
598enable_dc:
599 l.jal _dc_enable
600 l.nop
601
602flush_tlb:
8c9b7db0
SK
603 l.jal _flush_tlb
604 l.nop
9d02a428
JB
605
606/* The MMU needs to be enabled before or32_early_setup is called */
607
608enable_mmu:
609 /*
610 * enable dmmu & immu
611 * SR[5] = 0, SR[6] = 0, 6th and 7th bit of SR set to 0
612 */
613 l.mfspr r30,r0,SPR_SR
614 l.movhi r28,hi(SPR_SR_DME | SPR_SR_IME)
615 l.ori r28,r28,lo(SPR_SR_DME | SPR_SR_IME)
616 l.or r30,r30,r28
617 l.mtspr r0,r30,SPR_SR
618 l.nop
619 l.nop
620 l.nop
621 l.nop
622 l.nop
623 l.nop
624 l.nop
625 l.nop
626 l.nop
627 l.nop
628 l.nop
629 l.nop
630 l.nop
631 l.nop
632 l.nop
633 l.nop
634
635 // reset the simulation counters
636 l.nop 5
637
dec83018
SK
638 /* check fdt header magic word */
639 l.lwz r3,0(r25) /* load magic from fdt into r3 */
640 l.movhi r4,hi(OF_DT_HEADER)
641 l.ori r4,r4,lo(OF_DT_HEADER)
642 l.sfeq r3,r4
643 l.bf _fdt_found
644 l.nop
645 /* magic number mismatch, set fdt pointer to null */
646 l.or r25,r0,r0
647_fdt_found:
648 /* pass fdt pointer to or32_early_setup in r3 */
649 l.or r3,r0,r25
9d02a428
JB
650 LOAD_SYMBOL_2_GPR(r24, or32_early_setup)
651 l.jalr r24
652 l.nop
653
654clear_regs:
655 /*
656 * clear all GPRS to increase determinism
657 */
658 CLEAR_GPR(r2)
659 CLEAR_GPR(r3)
660 CLEAR_GPR(r4)
661 CLEAR_GPR(r5)
662 CLEAR_GPR(r6)
663 CLEAR_GPR(r7)
664 CLEAR_GPR(r8)
665 CLEAR_GPR(r9)
666 CLEAR_GPR(r11)
667 CLEAR_GPR(r12)
668 CLEAR_GPR(r13)
669 CLEAR_GPR(r14)
670 CLEAR_GPR(r15)
671 CLEAR_GPR(r16)
672 CLEAR_GPR(r17)
673 CLEAR_GPR(r18)
674 CLEAR_GPR(r19)
675 CLEAR_GPR(r20)
676 CLEAR_GPR(r21)
677 CLEAR_GPR(r22)
678 CLEAR_GPR(r23)
679 CLEAR_GPR(r24)
680 CLEAR_GPR(r25)
681 CLEAR_GPR(r26)
682 CLEAR_GPR(r27)
683 CLEAR_GPR(r28)
684 CLEAR_GPR(r29)
685 CLEAR_GPR(r30)
686 CLEAR_GPR(r31)
687
688jump_start_kernel:
689 /*
690 * jump to kernel entry (start_kernel)
691 */
692 LOAD_SYMBOL_2_GPR(r30, start_kernel)
693 l.jr r30
694 l.nop
695
8c9b7db0
SK
696_flush_tlb:
697 /*
698 * I N V A L I D A T E T L B e n t r i e s
699 */
700 LOAD_SYMBOL_2_GPR(r5,SPR_DTLBMR_BASE(0))
701 LOAD_SYMBOL_2_GPR(r6,SPR_ITLBMR_BASE(0))
702 l.addi r7,r0,128 /* Maximum number of sets */
7031:
704 l.mtspr r5,r0,0x0
705 l.mtspr r6,r0,0x0
706
707 l.addi r5,r5,1
708 l.addi r6,r6,1
709 l.sfeq r7,r0
710 l.bnf 1b
711 l.addi r7,r7,-1
712
713 l.jr r9
714 l.nop
715
8e6d08e0
SK
716#ifdef CONFIG_SMP
717secondary_wait:
c0567184
SH
718 /* Doze the cpu until we are asked to run */
719 /* If we dont have power management skip doze */
720 l.mfspr r25,r0,SPR_UPR
721 l.andi r25,r25,SPR_UPR_PMP
722 l.sfeq r25,r0
723 l.bf secondary_check_release
724 l.nop
725
726 /* Setup special secondary exception handler */
727 LOAD_SYMBOL_2_GPR(r3, _secondary_evbar)
728 tophys(r25,r3)
729 l.mtspr r0,r25,SPR_EVBAR
730
731 /* Enable Interrupts */
732 l.mfspr r25,r0,SPR_SR
733 l.ori r25,r25,SPR_SR_IEE
734 l.mtspr r0,r25,SPR_SR
735
736 /* Unmask interrupts interrupts */
737 l.mfspr r25,r0,SPR_PICMR
738 l.ori r25,r25,0xffff
739 l.mtspr r0,r25,SPR_PICMR
740
741 /* Doze */
742 l.mfspr r25,r0,SPR_PMR
743 LOAD_SYMBOL_2_GPR(r3, SPR_PMR_DME)
744 l.or r25,r25,r3
745 l.mtspr r0,r25,SPR_PMR
746
747 /* Wakeup - Restore exception handler */
748 l.mtspr r0,r0,SPR_EVBAR
749
750secondary_check_release:
751 /*
752 * Check if we actually got the release signal, if not go-back to
753 * sleep.
754 */
8e6d08e0 755 l.mfspr r25,r0,SPR_COREID
c0567184 756 LOAD_SYMBOL_2_GPR(r3, secondary_release)
8e6d08e0
SK
757 tophys(r4, r3)
758 l.lwz r3,0(r4)
759 l.sfeq r25,r3
760 l.bnf secondary_wait
761 l.nop
762 /* fall through to secondary_init */
763
764secondary_init:
765 /*
766 * set up initial ksp and current
767 */
768 LOAD_SYMBOL_2_GPR(r10, secondary_thread_info)
769 tophys (r30,r10)
770 l.lwz r10,0(r30)
771 l.addi r1,r10,THREAD_SIZE
772 tophys (r30,r10)
773 l.sw TI_KSP(r30),r1
774
775 l.jal _ic_enable
776 l.nop
777
778 l.jal _dc_enable
779 l.nop
780
781 l.jal _flush_tlb
782 l.nop
783
784 /*
785 * enable dmmu & immu
786 */
787 l.mfspr r30,r0,SPR_SR
788 l.movhi r28,hi(SPR_SR_DME | SPR_SR_IME)
789 l.ori r28,r28,lo(SPR_SR_DME | SPR_SR_IME)
790 l.or r30,r30,r28
791 /*
792 * This is a bit tricky, we need to switch over from physical addresses
793 * to virtual addresses on the fly.
794 * To do that, we first set up ESR with the IME and DME bits set.
795 * Then EPCR is set to secondary_start and then a l.rfe is issued to
796 * "jump" to that.
797 */
798 l.mtspr r0,r30,SPR_ESR_BASE
799 LOAD_SYMBOL_2_GPR(r30, secondary_start)
800 l.mtspr r0,r30,SPR_EPCR_BASE
801 l.rfe
802
803secondary_start:
804 LOAD_SYMBOL_2_GPR(r30, secondary_start_kernel)
805 l.jr r30
806 l.nop
807
808#endif
809
9d02a428
JB
810/* ========================================[ cache ]=== */
811
550116d2
MY
812 /* alignment here so we don't change memory offsets with
813 * memory controller defined
9d02a428
JB
814 */
815 .align 0x2000
816
817_ic_enable:
818 /* Check if IC present and skip enabling otherwise */
819 l.mfspr r24,r0,SPR_UPR
820 l.andi r26,r24,SPR_UPR_ICP
821 l.sfeq r26,r0
822 l.bf 9f
823 l.nop
824
825 /* Disable IC */
826 l.mfspr r6,r0,SPR_SR
827 l.addi r5,r0,-1
828 l.xori r5,r5,SPR_SR_ICE
829 l.and r5,r6,r5
830 l.mtspr r0,r5,SPR_SR
831
832 /* Establish cache block size
833 If BS=0, 16;
834 If BS=1, 32;
835 r14 contain block size
836 */
837 l.mfspr r24,r0,SPR_ICCFGR
838 l.andi r26,r24,SPR_ICCFGR_CBS
839 l.srli r28,r26,7
840 l.ori r30,r0,16
841 l.sll r14,r30,r28
842
843 /* Establish number of cache sets
844 r16 contains number of cache sets
845 r28 contains log(# of cache sets)
846 */
847 l.andi r26,r24,SPR_ICCFGR_NCS
848 l.srli r28,r26,3
849 l.ori r30,r0,1
850 l.sll r16,r30,r28
851
852 /* Invalidate IC */
853 l.addi r6,r0,0
854 l.sll r5,r14,r28
855// l.mul r5,r14,r16
856// l.trap 1
857// l.addi r5,r0,IC_SIZE
8581:
859 l.mtspr r0,r6,SPR_ICBIR
860 l.sfne r6,r5
861 l.bf 1b
862 l.add r6,r6,r14
863 // l.addi r6,r6,IC_LINE
864
865 /* Enable IC */
866 l.mfspr r6,r0,SPR_SR
867 l.ori r6,r6,SPR_SR_ICE
868 l.mtspr r0,r6,SPR_SR
869 l.nop
870 l.nop
871 l.nop
872 l.nop
873 l.nop
874 l.nop
875 l.nop
876 l.nop
877 l.nop
878 l.nop
8799:
880 l.jr r9
881 l.nop
882
883_dc_enable:
884 /* Check if DC present and skip enabling otherwise */
885 l.mfspr r24,r0,SPR_UPR
886 l.andi r26,r24,SPR_UPR_DCP
887 l.sfeq r26,r0
888 l.bf 9f
889 l.nop
890
891 /* Disable DC */
892 l.mfspr r6,r0,SPR_SR
893 l.addi r5,r0,-1
894 l.xori r5,r5,SPR_SR_DCE
895 l.and r5,r6,r5
896 l.mtspr r0,r5,SPR_SR
897
898 /* Establish cache block size
899 If BS=0, 16;
900 If BS=1, 32;
901 r14 contain block size
902 */
903 l.mfspr r24,r0,SPR_DCCFGR
904 l.andi r26,r24,SPR_DCCFGR_CBS
905 l.srli r28,r26,7
906 l.ori r30,r0,16
907 l.sll r14,r30,r28
908
909 /* Establish number of cache sets
910 r16 contains number of cache sets
911 r28 contains log(# of cache sets)
912 */
913 l.andi r26,r24,SPR_DCCFGR_NCS
914 l.srli r28,r26,3
915 l.ori r30,r0,1
916 l.sll r16,r30,r28
917
918 /* Invalidate DC */
919 l.addi r6,r0,0
920 l.sll r5,r14,r28
9211:
922 l.mtspr r0,r6,SPR_DCBIR
923 l.sfne r6,r5
924 l.bf 1b
925 l.add r6,r6,r14
926
927 /* Enable DC */
928 l.mfspr r6,r0,SPR_SR
929 l.ori r6,r6,SPR_SR_DCE
930 l.mtspr r0,r6,SPR_SR
9319:
932 l.jr r9
933 l.nop
934
935/* ===============================================[ page table masks ]=== */
936
9d02a428
JB
937#define DTLB_UP_CONVERT_MASK 0x3fa
938#define ITLB_UP_CONVERT_MASK 0x3a
939
940/* for SMP we'd have (this is a bit subtle, CC must be always set
941 * for SMP, but since we have _PAGE_PRESENT bit always defined
942 * we can just modify the mask)
943 */
944#define DTLB_SMP_CONVERT_MASK 0x3fb
945#define ITLB_SMP_CONVERT_MASK 0x3b
946
947/* ---[ boot dtlb miss handler ]----------------------------------------- */
948
949boot_dtlb_miss_handler:
950
951/* mask for DTLB_MR register: - (0) sets V (valid) bit,
952 * - (31-12) sets bits belonging to VPN (31-12)
953 */
954#define DTLB_MR_MASK 0xfffff001
955
956/* mask for DTLB_TR register: - (2) sets CI (cache inhibit) bit,
957 * - (4) sets A (access) bit,
958 * - (5) sets D (dirty) bit,
959 * - (8) sets SRE (superuser read) bit
960 * - (9) sets SWE (superuser write) bit
961 * - (31-12) sets bits belonging to VPN (31-12)
962 */
963#define DTLB_TR_MASK 0xfffff332
964
965/* These are for masking out the VPN/PPN value from the MR/TR registers...
966 * it's not the same as the PFN */
967#define VPN_MASK 0xfffff000
968#define PPN_MASK 0xfffff000
969
970
971 EXCEPTION_STORE_GPR6
972
973#if 0
974 l.mfspr r6,r0,SPR_ESR_BASE //
975 l.andi r6,r6,SPR_SR_SM // are we in kernel mode ?
976 l.sfeqi r6,0 // r6 == 0x1 --> SM
977 l.bf exit_with_no_dtranslation //
978 l.nop
979#endif
980
981 /* this could be optimized by moving storing of
982 * non r6 registers here, and jumping r6 restore
983 * if not in supervisor mode
984 */
985
986 EXCEPTION_STORE_GPR2
987 EXCEPTION_STORE_GPR3
988 EXCEPTION_STORE_GPR4
989 EXCEPTION_STORE_GPR5
990
991 l.mfspr r4,r0,SPR_EEAR_BASE // get the offending EA
992
993immediate_translation:
994 CLEAR_GPR(r6)
995
996 l.srli r3,r4,0xd // r3 <- r4 / 8192 (sets are relative to page size (8Kb) NOT VPN size (4Kb)
997
998 l.mfspr r6, r0, SPR_DMMUCFGR
999 l.andi r6, r6, SPR_DMMUCFGR_NTS
1000 l.srli r6, r6, SPR_DMMUCFGR_NTS_OFF
1001 l.ori r5, r0, 0x1
1002 l.sll r5, r5, r6 // r5 = number DMMU sets
1003 l.addi r6, r5, -1 // r6 = nsets mask
1004 l.and r2, r3, r6 // r2 <- r3 % NSETS_MASK
1005
1006 l.or r6,r6,r4 // r6 <- r4
1007 l.ori r6,r6,~(VPN_MASK) // r6 <- VPN :VPN .xfff - clear up lo(r6) to 0x**** *fff
1008 l.movhi r5,hi(DTLB_MR_MASK) // r5 <- ffff:0000.x000
1009 l.ori r5,r5,lo(DTLB_MR_MASK) // r5 <- ffff:1111.x001 - apply DTLB_MR_MASK
1010 l.and r5,r5,r6 // r5 <- VPN :VPN .x001 - we have DTLBMR entry
1011 l.mtspr r2,r5,SPR_DTLBMR_BASE(0) // set DTLBMR
1012
1013 /* set up DTLB with no translation for EA <= 0xbfffffff */
1014 LOAD_SYMBOL_2_GPR(r6,0xbfffffff)
1015 l.sfgeu r6,r4 // flag if r6 >= r4 (if 0xbfffffff >= EA)
1016 l.bf 1f // goto out
1017 l.and r3,r4,r4 // delay slot :: 24 <- r4 (if flag==1)
1018
1019 tophys(r3,r4) // r3 <- PA
10201:
1021 l.ori r3,r3,~(PPN_MASK) // r3 <- PPN :PPN .xfff - clear up lo(r6) to 0x**** *fff
1022 l.movhi r5,hi(DTLB_TR_MASK) // r5 <- ffff:0000.x000
1023 l.ori r5,r5,lo(DTLB_TR_MASK) // r5 <- ffff:1111.x330 - apply DTLB_MR_MASK
1024 l.and r5,r5,r3 // r5 <- PPN :PPN .x330 - we have DTLBTR entry
1025 l.mtspr r2,r5,SPR_DTLBTR_BASE(0) // set DTLBTR
1026
1027 EXCEPTION_LOAD_GPR6
1028 EXCEPTION_LOAD_GPR5
1029 EXCEPTION_LOAD_GPR4
1030 EXCEPTION_LOAD_GPR3
1031 EXCEPTION_LOAD_GPR2
1032
1033 l.rfe // SR <- ESR, PC <- EPC
1034
1035exit_with_no_dtranslation:
1036 /* EA out of memory or not in supervisor mode */
1037 EXCEPTION_LOAD_GPR6
1038 EXCEPTION_LOAD_GPR4
1039 l.j _dispatch_bus_fault
1040
1041/* ---[ boot itlb miss handler ]----------------------------------------- */
1042
1043boot_itlb_miss_handler:
1044
1045/* mask for ITLB_MR register: - sets V (valid) bit,
1046 * - sets bits belonging to VPN (15-12)
1047 */
1048#define ITLB_MR_MASK 0xfffff001
1049
1050/* mask for ITLB_TR register: - sets A (access) bit,
1051 * - sets SXE (superuser execute) bit
1052 * - sets bits belonging to VPN (15-12)
1053 */
1054#define ITLB_TR_MASK 0xfffff050
1055
1056/*
1057#define VPN_MASK 0xffffe000
1058#define PPN_MASK 0xffffe000
1059*/
1060
1061
1062
1063 EXCEPTION_STORE_GPR2
1064 EXCEPTION_STORE_GPR3
1065 EXCEPTION_STORE_GPR4
1066 EXCEPTION_STORE_GPR5
1067 EXCEPTION_STORE_GPR6
1068
1069#if 0
1070 l.mfspr r6,r0,SPR_ESR_BASE //
1071 l.andi r6,r6,SPR_SR_SM // are we in kernel mode ?
1072 l.sfeqi r6,0 // r6 == 0x1 --> SM
1073 l.bf exit_with_no_itranslation
1074 l.nop
1075#endif
1076
1077
1078 l.mfspr r4,r0,SPR_EEAR_BASE // get the offending EA
1079
1080earlyearly:
1081 CLEAR_GPR(r6)
1082
1083 l.srli r3,r4,0xd // r3 <- r4 / 8192 (sets are relative to page size (8Kb) NOT VPN size (4Kb)
1084
1085 l.mfspr r6, r0, SPR_IMMUCFGR
1086 l.andi r6, r6, SPR_IMMUCFGR_NTS
1087 l.srli r6, r6, SPR_IMMUCFGR_NTS_OFF
1088 l.ori r5, r0, 0x1
1089 l.sll r5, r5, r6 // r5 = number IMMU sets from IMMUCFGR
1090 l.addi r6, r5, -1 // r6 = nsets mask
1091 l.and r2, r3, r6 // r2 <- r3 % NSETS_MASK
1092
1093 l.or r6,r6,r4 // r6 <- r4
1094 l.ori r6,r6,~(VPN_MASK) // r6 <- VPN :VPN .xfff - clear up lo(r6) to 0x**** *fff
1095 l.movhi r5,hi(ITLB_MR_MASK) // r5 <- ffff:0000.x000
1096 l.ori r5,r5,lo(ITLB_MR_MASK) // r5 <- ffff:1111.x001 - apply ITLB_MR_MASK
1097 l.and r5,r5,r6 // r5 <- VPN :VPN .x001 - we have ITLBMR entry
1098 l.mtspr r2,r5,SPR_ITLBMR_BASE(0) // set ITLBMR
1099
1100 /*
1101 * set up ITLB with no translation for EA <= 0x0fffffff
1102 *
1103 * we need this for head.S mapping (EA = PA). if we move all functions
1104 * which run with mmu enabled into entry.S, we might be able to eliminate this.
1105 *
1106 */
1107 LOAD_SYMBOL_2_GPR(r6,0x0fffffff)
1108 l.sfgeu r6,r4 // flag if r6 >= r4 (if 0xb0ffffff >= EA)
1109 l.bf 1f // goto out
1110 l.and r3,r4,r4 // delay slot :: 24 <- r4 (if flag==1)
1111
1112 tophys(r3,r4) // r3 <- PA
11131:
1114 l.ori r3,r3,~(PPN_MASK) // r3 <- PPN :PPN .xfff - clear up lo(r6) to 0x**** *fff
1115 l.movhi r5,hi(ITLB_TR_MASK) // r5 <- ffff:0000.x000
1116 l.ori r5,r5,lo(ITLB_TR_MASK) // r5 <- ffff:1111.x050 - apply ITLB_MR_MASK
1117 l.and r5,r5,r3 // r5 <- PPN :PPN .x050 - we have ITLBTR entry
1118 l.mtspr r2,r5,SPR_ITLBTR_BASE(0) // set ITLBTR
1119
1120 EXCEPTION_LOAD_GPR6
1121 EXCEPTION_LOAD_GPR5
1122 EXCEPTION_LOAD_GPR4
1123 EXCEPTION_LOAD_GPR3
1124 EXCEPTION_LOAD_GPR2
1125
1126 l.rfe // SR <- ESR, PC <- EPC
1127
1128exit_with_no_itranslation:
1129 EXCEPTION_LOAD_GPR4
1130 EXCEPTION_LOAD_GPR6
1131 l.j _dispatch_bus_fault
1132 l.nop
1133
1134/* ====================================================================== */
1135/*
1136 * Stuff below here shouldn't go into .head section... maybe this stuff
1137 * can be moved to entry.S ???
1138 */
1139
1140/* ==============================================[ DTLB miss handler ]=== */
1141
1142/*
1143 * Comments:
1144 * Exception handlers are entered with MMU off so the following handler
1145 * needs to use physical addressing
1146 *
1147 */
1148
1149 .text
1150ENTRY(dtlb_miss_handler)
1151 EXCEPTION_STORE_GPR2
1152 EXCEPTION_STORE_GPR3
1153 EXCEPTION_STORE_GPR4
9d02a428
JB
1154 /*
1155 * get EA of the miss
1156 */
1157 l.mfspr r2,r0,SPR_EEAR_BASE
1158 /*
1159 * pmd = (pmd_t *)(current_pgd + pgd_index(daddr));
1160 */
742fb582 1161 GET_CURRENT_PGD(r3,r4) // r3 is current_pgd, r4 is temp
9d02a428
JB
1162 l.srli r4,r2,0x18 // >> PAGE_SHIFT + (PAGE_SHIFT - 2)
1163 l.slli r4,r4,0x2 // to get address << 2
742fb582 1164 l.add r3,r4,r3 // r4 is pgd_index(daddr)
9d02a428
JB
1165 /*
1166 * if (pmd_none(*pmd))
1167 * goto pmd_none:
1168 */
742fb582 1169 tophys (r4,r3)
9d02a428
JB
1170 l.lwz r3,0x0(r4) // get *pmd value
1171 l.sfne r3,r0
1172 l.bnf d_pmd_none
742fb582
SK
1173 l.addi r3,r0,0xffffe000 // PAGE_MASK
1174
9d02a428
JB
1175d_pmd_good:
1176 /*
1177 * pte = *pte_offset(pmd, daddr);
1178 */
1179 l.lwz r4,0x0(r4) // get **pmd value
1180 l.and r4,r4,r3 // & PAGE_MASK
742fb582
SK
1181 l.srli r2,r2,0xd // >> PAGE_SHIFT, r2 == EEAR
1182 l.andi r3,r2,0x7ff // (1UL << PAGE_SHIFT - 2) - 1
9d02a428
JB
1183 l.slli r3,r3,0x2 // to get address << 2
1184 l.add r3,r3,r4
742fb582 1185 l.lwz r3,0x0(r3) // this is pte at last
9d02a428
JB
1186 /*
1187 * if (!pte_present(pte))
1188 */
742fb582 1189 l.andi r4,r3,0x1
9d02a428
JB
1190 l.sfne r4,r0 // is pte present
1191 l.bnf d_pte_not_present
742fb582 1192 l.addi r4,r0,0xffffe3fa // PAGE_MASK | DTLB_UP_CONVERT_MASK
9d02a428
JB
1193 /*
1194 * fill DTLB TR register
1195 */
742fb582 1196 l.and r4,r3,r4 // apply the mask
9d02a428 1197 // Determine number of DMMU sets
742fb582
SK
1198 l.mfspr r2, r0, SPR_DMMUCFGR
1199 l.andi r2, r2, SPR_DMMUCFGR_NTS
1200 l.srli r2, r2, SPR_DMMUCFGR_NTS_OFF
9d02a428 1201 l.ori r3, r0, 0x1
742fb582
SK
1202 l.sll r3, r3, r2 // r3 = number DMMU sets DMMUCFGR
1203 l.addi r2, r3, -1 // r2 = nsets mask
1204 l.mfspr r3, r0, SPR_EEAR_BASE
1205 l.srli r3, r3, 0xd // >> PAGE_SHIFT
1206 l.and r2, r3, r2 // calc offset: & (NUM_TLB_ENTRIES-1)
9d02a428 1207 //NUM_TLB_ENTRIES
742fb582 1208 l.mtspr r2,r4,SPR_DTLBTR_BASE(0)
9d02a428
JB
1209 /*
1210 * fill DTLB MR register
1211 */
742fb582
SK
1212 l.slli r3, r3, 0xd /* << PAGE_SHIFT => EA & PAGE_MASK */
1213 l.ori r4,r3,0x1 // set hardware valid bit: DTBL_MR entry
1214 l.mtspr r2,r4,SPR_DTLBMR_BASE(0)
9d02a428
JB
1215
1216 EXCEPTION_LOAD_GPR2
1217 EXCEPTION_LOAD_GPR3
1218 EXCEPTION_LOAD_GPR4
9d02a428
JB
1219 l.rfe
1220d_pmd_none:
1221d_pte_not_present:
1222 EXCEPTION_LOAD_GPR2
1223 EXCEPTION_LOAD_GPR3
1224 EXCEPTION_LOAD_GPR4
a81252d7 1225 EXCEPTION_HANDLE(_dtlb_miss_page_fault_handler)
9d02a428
JB
1226
1227/* ==============================================[ ITLB miss handler ]=== */
1228ENTRY(itlb_miss_handler)
1229 EXCEPTION_STORE_GPR2
1230 EXCEPTION_STORE_GPR3
1231 EXCEPTION_STORE_GPR4
9d02a428
JB
1232 /*
1233 * get EA of the miss
1234 */
1235 l.mfspr r2,r0,SPR_EEAR_BASE
1236
1237 /*
1238 * pmd = (pmd_t *)(current_pgd + pgd_index(daddr));
1239 *
1240 */
742fb582 1241 GET_CURRENT_PGD(r3,r4) // r3 is current_pgd, r5 is temp
9d02a428
JB
1242 l.srli r4,r2,0x18 // >> PAGE_SHIFT + (PAGE_SHIFT - 2)
1243 l.slli r4,r4,0x2 // to get address << 2
742fb582 1244 l.add r3,r4,r3 // r4 is pgd_index(daddr)
9d02a428
JB
1245 /*
1246 * if (pmd_none(*pmd))
1247 * goto pmd_none:
1248 */
742fb582 1249 tophys (r4,r3)
9d02a428
JB
1250 l.lwz r3,0x0(r4) // get *pmd value
1251 l.sfne r3,r0
1252 l.bnf i_pmd_none
742fb582 1253 l.addi r3,r0,0xffffe000 // PAGE_MASK
9d02a428
JB
1254
1255i_pmd_good:
1256 /*
1257 * pte = *pte_offset(pmd, iaddr);
1258 *
1259 */
1260 l.lwz r4,0x0(r4) // get **pmd value
1261 l.and r4,r4,r3 // & PAGE_MASK
742fb582
SK
1262 l.srli r2,r2,0xd // >> PAGE_SHIFT, r2 == EEAR
1263 l.andi r3,r2,0x7ff // (1UL << PAGE_SHIFT - 2) - 1
9d02a428
JB
1264 l.slli r3,r3,0x2 // to get address << 2
1265 l.add r3,r3,r4
742fb582 1266 l.lwz r3,0x0(r3) // this is pte at last
9d02a428
JB
1267 /*
1268 * if (!pte_present(pte))
1269 *
1270 */
742fb582 1271 l.andi r4,r3,0x1
9d02a428
JB
1272 l.sfne r4,r0 // is pte present
1273 l.bnf i_pte_not_present
742fb582 1274 l.addi r4,r0,0xffffe03a // PAGE_MASK | ITLB_UP_CONVERT_MASK
9d02a428
JB
1275 /*
1276 * fill ITLB TR register
1277 */
742fb582
SK
1278 l.and r4,r3,r4 // apply the mask
1279 l.andi r3,r3,0x7c0 // _PAGE_EXEC | _PAGE_SRE | _PAGE_SWE | _PAGE_URE | _PAGE_UWE
9d02a428
JB
1280 l.sfeq r3,r0
1281 l.bf itlb_tr_fill //_workaround
1282 // Determine number of IMMU sets
742fb582
SK
1283 l.mfspr r2, r0, SPR_IMMUCFGR
1284 l.andi r2, r2, SPR_IMMUCFGR_NTS
1285 l.srli r2, r2, SPR_IMMUCFGR_NTS_OFF
9d02a428 1286 l.ori r3, r0, 0x1
742fb582
SK
1287 l.sll r3, r3, r2 // r3 = number IMMU sets IMMUCFGR
1288 l.addi r2, r3, -1 // r2 = nsets mask
1289 l.mfspr r3, r0, SPR_EEAR_BASE
1290 l.srli r3, r3, 0xd // >> PAGE_SHIFT
1291 l.and r2, r3, r2 // calc offset: & (NUM_TLB_ENTRIES-1)
9d02a428
JB
1292
1293/*
1294 * __PHX__ :: fixme
1295 * we should not just blindly set executable flags,
1296 * but it does help with ping. the clean way would be to find out
1297 * (and fix it) why stack doesn't have execution permissions
1298 */
1299
1300itlb_tr_fill_workaround:
1301 l.ori r4,r4,0xc0 // | (SPR_ITLBTR_UXE | ITLBTR_SXE)
1302itlb_tr_fill:
742fb582 1303 l.mtspr r2,r4,SPR_ITLBTR_BASE(0)
9d02a428
JB
1304 /*
1305 * fill DTLB MR register
1306 */
742fb582
SK
1307 l.slli r3, r3, 0xd /* << PAGE_SHIFT => EA & PAGE_MASK */
1308 l.ori r4,r3,0x1 // set hardware valid bit: ITBL_MR entry
1309 l.mtspr r2,r4,SPR_ITLBMR_BASE(0)
9d02a428
JB
1310
1311 EXCEPTION_LOAD_GPR2
1312 EXCEPTION_LOAD_GPR3
1313 EXCEPTION_LOAD_GPR4
9d02a428
JB
1314 l.rfe
1315
9d02a428
JB
1316i_pmd_none:
1317i_pte_not_present:
1318 EXCEPTION_LOAD_GPR2
1319 EXCEPTION_LOAD_GPR3
1320 EXCEPTION_LOAD_GPR4
a81252d7 1321 EXCEPTION_HANDLE(_itlb_miss_page_fault_handler)
9d02a428
JB
1322
1323/* ==============================================[ boot tlb handlers ]=== */
1324
1325
1326/* =================================================[ debugging aids ]=== */
1327
1328 .align 64
1329_immu_trampoline:
1330 .space 64
1331_immu_trampoline_top:
1332
1333#define TRAMP_SLOT_0 (0x0)
1334#define TRAMP_SLOT_1 (0x4)
1335#define TRAMP_SLOT_2 (0x8)
1336#define TRAMP_SLOT_3 (0xc)
1337#define TRAMP_SLOT_4 (0x10)
1338#define TRAMP_SLOT_5 (0x14)
1339#define TRAMP_FRAME_SIZE (0x18)
1340
1341ENTRY(_immu_trampoline_workaround)
1342 // r2 EEA
1343 // r6 is physical EEA
1344 tophys(r6,r2)
1345
1346 LOAD_SYMBOL_2_GPR(r5,_immu_trampoline)
1347 tophys (r3,r5) // r3 is trampoline (physical)
1348
1349 LOAD_SYMBOL_2_GPR(r4,0x15000000)
1350 l.sw TRAMP_SLOT_0(r3),r4
1351 l.sw TRAMP_SLOT_1(r3),r4
1352 l.sw TRAMP_SLOT_4(r3),r4
1353 l.sw TRAMP_SLOT_5(r3),r4
1354
1355 // EPC = EEA - 0x4
1356 l.lwz r4,0x0(r6) // load op @ EEA + 0x0 (fc address)
1357 l.sw TRAMP_SLOT_3(r3),r4 // store it to _immu_trampoline_data
1358 l.lwz r4,-0x4(r6) // load op @ EEA - 0x4 (f8 address)
1359 l.sw TRAMP_SLOT_2(r3),r4 // store it to _immu_trampoline_data
1360
1361 l.srli r5,r4,26 // check opcode for write access
1362 l.sfeqi r5,0 // l.j
1363 l.bf 0f
1364 l.sfeqi r5,0x11 // l.jr
1365 l.bf 1f
1366 l.sfeqi r5,1 // l.jal
1367 l.bf 2f
1368 l.sfeqi r5,0x12 // l.jalr
1369 l.bf 3f
1370 l.sfeqi r5,3 // l.bnf
1371 l.bf 4f
1372 l.sfeqi r5,4 // l.bf
1373 l.bf 5f
137499:
1375 l.nop
1376 l.j 99b // should never happen
1377 l.nop 1
1378
1379 // r2 is EEA
1380 // r3 is trampoline address (physical)
1381 // r4 is instruction
1382 // r6 is physical(EEA)
1383 //
1384 // r5
1385
13862: // l.jal
1387
1388 /* 19 20 aa aa l.movhi r9,0xaaaa
1389 * a9 29 bb bb l.ori r9,0xbbbb
1390 *
1391 * where 0xaaaabbbb is EEA + 0x4 shifted right 2
1392 */
1393
1394 l.addi r6,r2,0x4 // this is 0xaaaabbbb
1395
1396 // l.movhi r9,0xaaaa
1397 l.ori r5,r0,0x1920 // 0x1920 == l.movhi r9
1398 l.sh (TRAMP_SLOT_0+0x0)(r3),r5
1399 l.srli r5,r6,16
1400 l.sh (TRAMP_SLOT_0+0x2)(r3),r5
1401
1402 // l.ori r9,0xbbbb
1403 l.ori r5,r0,0xa929 // 0xa929 == l.ori r9
1404 l.sh (TRAMP_SLOT_1+0x0)(r3),r5
1405 l.andi r5,r6,0xffff
1406 l.sh (TRAMP_SLOT_1+0x2)(r3),r5
1407
1408 /* falthrough, need to set up new jump offset */
1409
1410
14110: // l.j
1412 l.slli r6,r4,6 // original offset shifted left 6 - 2
1413// l.srli r6,r6,6 // original offset shifted right 2
1414
1415 l.slli r4,r2,4 // old jump position: EEA shifted left 4
1416// l.srli r4,r4,6 // old jump position: shifted right 2
1417
1418 l.addi r5,r3,0xc // new jump position (physical)
1419 l.slli r5,r5,4 // new jump position: shifted left 4
1420
1421 // calculate new jump offset
1422 // new_off = old_off + (old_jump - new_jump)
1423
1424 l.sub r5,r4,r5 // old_jump - new_jump
1425 l.add r5,r6,r5 // orig_off + (old_jump - new_jump)
1426 l.srli r5,r5,6 // new offset shifted right 2
1427
1428 // r5 is new jump offset
1429 // l.j has opcode 0x0...
1430 l.sw TRAMP_SLOT_2(r3),r5 // write it back
1431
1432 l.j trampoline_out
1433 l.nop
1434
1435/* ----------------------------- */
1436
14373: // l.jalr
1438
1439 /* 19 20 aa aa l.movhi r9,0xaaaa
1440 * a9 29 bb bb l.ori r9,0xbbbb
1441 *
1442 * where 0xaaaabbbb is EEA + 0x4 shifted right 2
1443 */
1444
1445 l.addi r6,r2,0x4 // this is 0xaaaabbbb
1446
1447 // l.movhi r9,0xaaaa
1448 l.ori r5,r0,0x1920 // 0x1920 == l.movhi r9
1449 l.sh (TRAMP_SLOT_0+0x0)(r3),r5
1450 l.srli r5,r6,16
1451 l.sh (TRAMP_SLOT_0+0x2)(r3),r5
1452
1453 // l.ori r9,0xbbbb
1454 l.ori r5,r0,0xa929 // 0xa929 == l.ori r9
1455 l.sh (TRAMP_SLOT_1+0x0)(r3),r5
1456 l.andi r5,r6,0xffff
1457 l.sh (TRAMP_SLOT_1+0x2)(r3),r5
1458
1459 l.lhz r5,(TRAMP_SLOT_2+0x0)(r3) // load hi part of jump instruction
1460 l.andi r5,r5,0x3ff // clear out opcode part
1461 l.ori r5,r5,0x4400 // opcode changed from l.jalr -> l.jr
1462 l.sh (TRAMP_SLOT_2+0x0)(r3),r5 // write it back
1463
1464 /* falthrough */
1465
14661: // l.jr
1467 l.j trampoline_out
1468 l.nop
1469
1470/* ----------------------------- */
1471
14724: // l.bnf
14735: // l.bf
1474 l.slli r6,r4,6 // original offset shifted left 6 - 2
1475// l.srli r6,r6,6 // original offset shifted right 2
1476
1477 l.slli r4,r2,4 // old jump position: EEA shifted left 4
1478// l.srli r4,r4,6 // old jump position: shifted right 2
1479
1480 l.addi r5,r3,0xc // new jump position (physical)
1481 l.slli r5,r5,4 // new jump position: shifted left 4
1482
1483 // calculate new jump offset
1484 // new_off = old_off + (old_jump - new_jump)
1485
1486 l.add r6,r6,r4 // (orig_off + old_jump)
1487 l.sub r6,r6,r5 // (orig_off + old_jump) - new_jump
1488 l.srli r6,r6,6 // new offset shifted right 2
1489
1490 // r6 is new jump offset
1491 l.lwz r4,(TRAMP_SLOT_2+0x0)(r3) // load jump instruction
1492 l.srli r4,r4,16
1493 l.andi r4,r4,0xfc00 // get opcode part
1494 l.slli r4,r4,16
1495 l.or r6,r4,r6 // l.b(n)f new offset
1496 l.sw TRAMP_SLOT_2(r3),r6 // write it back
1497
1498 /* we need to add l.j to EEA + 0x8 */
1499 tophys (r4,r2) // may not be needed (due to shifts down_
1500 l.addi r4,r4,(0x8 - 0x8) // jump target = r2 + 0x8 (compensate for 0x8)
1501 // jump position = r5 + 0x8 (0x8 compensated)
1502 l.sub r4,r4,r5 // jump offset = target - new_position + 0x8
1503
1504 l.slli r4,r4,4 // the amount of info in imediate of jump
1505 l.srli r4,r4,6 // jump instruction with offset
1506 l.sw TRAMP_SLOT_4(r3),r4 // write it to 4th slot
1507
1508 /* fallthrough */
1509
1510trampoline_out:
1511 // set up new EPC to point to our trampoline code
1512 LOAD_SYMBOL_2_GPR(r5,_immu_trampoline)
1513 l.mtspr r0,r5,SPR_EPCR_BASE
1514
1515 // immu_trampoline is (4x) CACHE_LINE aligned
1516 // and only 6 instructions long,
1517 // so we need to invalidate only 2 lines
1518
1519 /* Establish cache block size
1520 If BS=0, 16;
1521 If BS=1, 32;
1522 r14 contain block size
1523 */
1524 l.mfspr r21,r0,SPR_ICCFGR
1525 l.andi r21,r21,SPR_ICCFGR_CBS
1526 l.srli r21,r21,7
1527 l.ori r23,r0,16
1528 l.sll r14,r23,r21
1529
1530 l.mtspr r0,r5,SPR_ICBIR
1531 l.add r5,r5,r14
1532 l.mtspr r0,r5,SPR_ICBIR
1533
1534 l.jr r9
1535 l.nop
1536
1537
1538/*
1539 * DSCR: prints a string referenced by r3.
1540 *
1541 * PRMS: r3 - address of the first character of null
1542 * terminated string to be printed
1543 *
1544 * PREQ: UART at UART_BASE_ADD has to be initialized
1545 *
1546 * POST: caller should be aware that r3, r9 are changed
1547 */
1548ENTRY(_emergency_print)
1549 EMERGENCY_PRINT_STORE_GPR4
1550 EMERGENCY_PRINT_STORE_GPR5
1551 EMERGENCY_PRINT_STORE_GPR6
1552 EMERGENCY_PRINT_STORE_GPR7
15532:
1554 l.lbz r7,0(r3)
1555 l.sfeq r7,r0
1556 l.bf 9f
1557 l.nop
1558
1559// putc:
1560 l.movhi r4,hi(UART_BASE_ADD)
1561
1562 l.addi r6,r0,0x20
15631: l.lbz r5,5(r4)
1564 l.andi r5,r5,0x20
1565 l.sfeq r5,r6
1566 l.bnf 1b
1567 l.nop
1568
1569 l.sb 0(r4),r7
1570
1571 l.addi r6,r0,0x60
15721: l.lbz r5,5(r4)
1573 l.andi r5,r5,0x60
1574 l.sfeq r5,r6
1575 l.bnf 1b
1576 l.nop
1577
1578 /* next character */
1579 l.j 2b
1580 l.addi r3,r3,0x1
1581
15829:
1583 EMERGENCY_PRINT_LOAD_GPR7
1584 EMERGENCY_PRINT_LOAD_GPR6
1585 EMERGENCY_PRINT_LOAD_GPR5
1586 EMERGENCY_PRINT_LOAD_GPR4
1587 l.jr r9
1588 l.nop
1589
1590ENTRY(_emergency_print_nr)
1591 EMERGENCY_PRINT_STORE_GPR4
1592 EMERGENCY_PRINT_STORE_GPR5
1593 EMERGENCY_PRINT_STORE_GPR6
1594 EMERGENCY_PRINT_STORE_GPR7
1595 EMERGENCY_PRINT_STORE_GPR8
1596
1597 l.addi r8,r0,32 // shift register
1598
15991: /* remove leading zeros */
1600 l.addi r8,r8,-0x4
1601 l.srl r7,r3,r8
1602 l.andi r7,r7,0xf
1603
1604 /* don't skip the last zero if number == 0x0 */
1605 l.sfeqi r8,0x4
1606 l.bf 2f
1607 l.nop
1608
1609 l.sfeq r7,r0
1610 l.bf 1b
1611 l.nop
1612
16132:
1614 l.srl r7,r3,r8
1615
1616 l.andi r7,r7,0xf
1617 l.sflts r8,r0
1618 l.bf 9f
1619
1620 l.sfgtui r7,0x9
1621 l.bnf 8f
1622 l.nop
1623 l.addi r7,r7,0x27
1624
16258:
1626 l.addi r7,r7,0x30
1627// putc:
1628 l.movhi r4,hi(UART_BASE_ADD)
1629
1630 l.addi r6,r0,0x20
16311: l.lbz r5,5(r4)
1632 l.andi r5,r5,0x20
1633 l.sfeq r5,r6
1634 l.bnf 1b
1635 l.nop
1636
1637 l.sb 0(r4),r7
1638
1639 l.addi r6,r0,0x60
16401: l.lbz r5,5(r4)
1641 l.andi r5,r5,0x60
1642 l.sfeq r5,r6
1643 l.bnf 1b
1644 l.nop
1645
1646 /* next character */
1647 l.j 2b
1648 l.addi r8,r8,-0x4
1649
16509:
1651 EMERGENCY_PRINT_LOAD_GPR8
1652 EMERGENCY_PRINT_LOAD_GPR7
1653 EMERGENCY_PRINT_LOAD_GPR6
1654 EMERGENCY_PRINT_LOAD_GPR5
1655 EMERGENCY_PRINT_LOAD_GPR4
1656 l.jr r9
1657 l.nop
1658
1659
1660/*
1661 * This should be used for debugging only.
1662 * It messes up the Linux early serial output
1663 * somehow, so use it sparingly and essentially
1664 * only if you need to debug something that goes wrong
1665 * before Linux gets the early serial going.
1666 *
1667 * Furthermore, you'll have to make sure you set the
1668 * UART_DEVISOR correctly according to the system
1669 * clock rate.
1670 *
1671 *
1672 */
1673
1674
1675
1676#define SYS_CLK 20000000
1677//#define SYS_CLK 1843200
1678#define OR32_CONSOLE_BAUD 115200
1679#define UART_DIVISOR SYS_CLK/(16*OR32_CONSOLE_BAUD)
1680
1681ENTRY(_early_uart_init)
1682 l.movhi r3,hi(UART_BASE_ADD)
1683
1684 l.addi r4,r0,0x7
1685 l.sb 0x2(r3),r4
1686
1687 l.addi r4,r0,0x0
1688 l.sb 0x1(r3),r4
1689
1690 l.addi r4,r0,0x3
1691 l.sb 0x3(r3),r4
1692
1693 l.lbz r5,3(r3)
1694 l.ori r4,r5,0x80
1695 l.sb 0x3(r3),r4
1696 l.addi r4,r0,((UART_DIVISOR>>8) & 0x000000ff)
1697 l.sb UART_DLM(r3),r4
1698 l.addi r4,r0,((UART_DIVISOR) & 0x000000ff)
1699 l.sb UART_DLL(r3),r4
1700 l.sb 0x3(r3),r5
1701
1702 l.jr r9
1703 l.nop
1704
c0567184
SH
1705 .align 0x1000
1706 .global _secondary_evbar
1707_secondary_evbar:
1708
1709 .space 0x800
1710 /* Just disable interrupts and Return */
1711 l.ori r3,r0,SPR_SR_SM
1712 l.mtspr r0,r3,SPR_ESR_BASE
1713 l.rfe
1714
1715
da99f00e 1716 .section .rodata
9d02a428
JB
1717_string_unhandled_exception:
1718 .string "\n\rRunarunaround: Unhandled exception 0x\0"
1719
1720_string_epc_prefix:
1721 .string ": EPC=0x\0"
1722
1723_string_nl:
1724 .string "\n\r\0"
1725
9d02a428
JB
1726
1727/* ========================================[ page aligned structures ]=== */
1728
1729/*
1730 * .data section should be page aligned
57ce8ba0 1731 * (look into arch/openrisc/kernel/vmlinux.lds.S)
9d02a428
JB
1732 */
1733 .section .data,"aw"
1734 .align 8192
1735 .global empty_zero_page
1736empty_zero_page:
1737 .space 8192
1738
1739 .global swapper_pg_dir
1740swapper_pg_dir:
1741 .space 8192
1742
1743 .global _unhandled_stack
1744_unhandled_stack:
1745 .space 8192
1746_unhandled_stack_top:
1747
1748/* ============================================================[ EOF ]=== */