| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2004-2006 Atmel Corporation | 
|  | 3 | * | 
|  | 4 | * This program is free software; you can redistribute it and/or modify | 
|  | 5 | * it under the terms of the GNU General Public License version 2 as | 
|  | 6 | * published by the Free Software Foundation. | 
|  | 7 | */ | 
|  | 8 |  | 
|  | 9 | /* | 
|  | 10 | * This file contains the low-level entry-points into the kernel, that is, | 
|  | 11 | * exception handlers, debug trap handlers, interrupt handlers and the | 
|  | 12 | * system call handler. | 
|  | 13 | */ | 
|  | 14 | #include <linux/errno.h> | 
|  | 15 |  | 
|  | 16 | #include <asm/asm.h> | 
|  | 17 | #include <asm/hardirq.h> | 
|  | 18 | #include <asm/irq.h> | 
|  | 19 | #include <asm/ocd.h> | 
|  | 20 | #include <asm/page.h> | 
|  | 21 | #include <asm/pgtable.h> | 
|  | 22 | #include <asm/ptrace.h> | 
|  | 23 | #include <asm/sysreg.h> | 
|  | 24 | #include <asm/thread_info.h> | 
|  | 25 | #include <asm/unistd.h> | 
|  | 26 |  | 
|  | 27 | #ifdef CONFIG_PREEMPT | 
|  | 28 | # define preempt_stop		mask_interrupts | 
|  | 29 | #else | 
|  | 30 | # define preempt_stop | 
|  | 31 | # define fault_resume_kernel	fault_restore_all | 
|  | 32 | #endif | 
|  | 33 |  | 
|  | 34 | #define __MASK(x)	((1 << (x)) - 1) | 
|  | 35 | #define IRQ_MASK	((__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT) | \ | 
|  | 36 | (__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)) | 
|  | 37 |  | 
|  | 38 | .section .ex.text,"ax",@progbits | 
|  | 39 | .align	2 | 
|  | 40 | exception_vectors: | 
|  | 41 | bral	handle_critical | 
|  | 42 | .align	2 | 
|  | 43 | bral	handle_critical | 
|  | 44 | .align	2 | 
|  | 45 | bral	do_bus_error_write | 
|  | 46 | .align	2 | 
|  | 47 | bral	do_bus_error_read | 
|  | 48 | .align	2 | 
|  | 49 | bral	do_nmi_ll | 
|  | 50 | .align	2 | 
|  | 51 | bral	handle_address_fault | 
|  | 52 | .align	2 | 
|  | 53 | bral	handle_protection_fault | 
|  | 54 | .align	2 | 
|  | 55 | bral	handle_debug | 
|  | 56 | .align	2 | 
|  | 57 | bral	do_illegal_opcode_ll | 
|  | 58 | .align	2 | 
|  | 59 | bral	do_illegal_opcode_ll | 
|  | 60 | .align	2 | 
|  | 61 | bral	do_illegal_opcode_ll | 
|  | 62 | .align	2 | 
|  | 63 | bral	do_fpe_ll | 
|  | 64 | .align	2 | 
|  | 65 | bral	do_illegal_opcode_ll | 
|  | 66 | .align	2 | 
|  | 67 | bral	handle_address_fault | 
|  | 68 | .align	2 | 
|  | 69 | bral	handle_address_fault | 
|  | 70 | .align	2 | 
|  | 71 | bral	handle_protection_fault | 
|  | 72 | .align	2 | 
|  | 73 | bral	handle_protection_fault | 
|  | 74 | .align	2 | 
|  | 75 | bral	do_dtlb_modified | 
|  | 76 |  | 
|  | 77 | /* | 
|  | 78 | * r0 :	PGD/PT/PTE | 
|  | 79 | * r1 : Offending address | 
|  | 80 | * r2 : Scratch register | 
|  | 81 | * r3 : Cause (5, 12 or 13) | 
|  | 82 | */ | 
|  | 83 | #define	tlbmiss_save	pushm	r0-r3 | 
|  | 84 | #define tlbmiss_restore	popm	r0-r3 | 
|  | 85 |  | 
|  | 86 | .section .tlbx.ex.text,"ax",@progbits | 
|  | 87 | .global	itlb_miss | 
|  | 88 | itlb_miss: | 
|  | 89 | tlbmiss_save | 
|  | 90 | rjmp	tlb_miss_common | 
|  | 91 |  | 
|  | 92 | .section .tlbr.ex.text,"ax",@progbits | 
|  | 93 | dtlb_miss_read: | 
|  | 94 | tlbmiss_save | 
|  | 95 | rjmp	tlb_miss_common | 
|  | 96 |  | 
|  | 97 | .section .tlbw.ex.text,"ax",@progbits | 
|  | 98 | dtlb_miss_write: | 
|  | 99 | tlbmiss_save | 
|  | 100 |  | 
|  | 101 | .global	tlb_miss_common | 
|  | 102 | tlb_miss_common: | 
| Haavard Skinnemoen | c0c3e81 | 2007-03-14 13:59:13 +0100 | [diff] [blame] | 103 | mfsr	r0, SYSREG_TLBEAR | 
|  | 104 | mfsr	r1, SYSREG_PTBR | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 105 |  | 
|  | 106 | /* Is it the vmalloc space? */ | 
| Haavard Skinnemoen | c0c3e81 | 2007-03-14 13:59:13 +0100 | [diff] [blame] | 107 | bld	r0, 31 | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 108 | brcs	handle_vmalloc_miss | 
|  | 109 |  | 
|  | 110 | /* First level lookup */ | 
|  | 111 | pgtbl_lookup: | 
| Haavard Skinnemoen | c0c3e81 | 2007-03-14 13:59:13 +0100 | [diff] [blame] | 112 | lsr	r2, r0, PGDIR_SHIFT | 
|  | 113 | ld.w	r3, r1[r2 << 2] | 
|  | 114 | bfextu	r1, r0, PAGE_SHIFT, PGDIR_SHIFT - PAGE_SHIFT | 
|  | 115 | bld	r3, _PAGE_BIT_PRESENT | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 116 | brcc	page_table_not_present | 
|  | 117 |  | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 118 | /* Translate to virtual address in P1. */ | 
| Haavard Skinnemoen | c0c3e81 | 2007-03-14 13:59:13 +0100 | [diff] [blame] | 119 | andl	r3, 0xf000 | 
|  | 120 | sbr	r3, 31 | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 121 |  | 
|  | 122 | /* Second level lookup */ | 
| Haavard Skinnemoen | c0c3e81 | 2007-03-14 13:59:13 +0100 | [diff] [blame] | 123 | ld.w	r2, r3[r1 << 2] | 
|  | 124 | mfsr	r0, SYSREG_TLBARLO | 
|  | 125 | bld	r2, _PAGE_BIT_PRESENT | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 126 | brcc	page_not_present | 
|  | 127 |  | 
|  | 128 | /* Mark the page as accessed */ | 
| Haavard Skinnemoen | c0c3e81 | 2007-03-14 13:59:13 +0100 | [diff] [blame] | 129 | sbr	r2, _PAGE_BIT_ACCESSED | 
|  | 130 | st.w	r3[r1 << 2], r2 | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 131 |  | 
|  | 132 | /* Drop software flags */ | 
| Haavard Skinnemoen | c0c3e81 | 2007-03-14 13:59:13 +0100 | [diff] [blame] | 133 | andl	r2, _PAGE_FLAGS_HARDWARE_MASK & 0xffff | 
|  | 134 | mtsr	SYSREG_TLBELO, r2 | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 135 |  | 
|  | 136 | /* Figure out which entry we want to replace */ | 
| Haavard Skinnemoen | c0c3e81 | 2007-03-14 13:59:13 +0100 | [diff] [blame] | 137 | mfsr	r1, SYSREG_MMUCR | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 138 | clz	r2, r0 | 
|  | 139 | brcc	1f | 
| Haavard Skinnemoen | c0c3e81 | 2007-03-14 13:59:13 +0100 | [diff] [blame] | 140 | mov	r3, -1			/* All entries have been accessed, */ | 
|  | 141 | mov	r2, 0			/* so start at 0 */ | 
|  | 142 | mtsr	SYSREG_TLBARLO, r3	/* and reset TLBAR */ | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 143 |  | 
| Haavard Skinnemoen | c0c3e81 | 2007-03-14 13:59:13 +0100 | [diff] [blame] | 144 | 1:	bfins	r1, r2, SYSREG_DRP_OFFSET, SYSREG_DRP_SIZE | 
|  | 145 | mtsr	SYSREG_MMUCR, r1 | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 146 | tlbw | 
|  | 147 |  | 
|  | 148 | tlbmiss_restore | 
|  | 149 | rete | 
|  | 150 |  | 
|  | 151 | handle_vmalloc_miss: | 
|  | 152 | /* Simply do the lookup in init's page table */ | 
| Haavard Skinnemoen | c0c3e81 | 2007-03-14 13:59:13 +0100 | [diff] [blame] | 153 | mov	r1, lo(swapper_pg_dir) | 
|  | 154 | orh	r1, hi(swapper_pg_dir) | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 155 | rjmp	pgtbl_lookup | 
|  | 156 |  | 
|  | 157 |  | 
|  | 158 | /* ---                    System Call                    --- */ | 
|  | 159 |  | 
|  | 160 | .section .scall.text,"ax",@progbits | 
|  | 161 | system_call: | 
| Philippe Rétornaz | a7e30b8 | 2007-10-10 18:52:24 -0400 | [diff] [blame] | 162 | #ifdef CONFIG_PREEMPT | 
|  | 163 | mask_interrupts | 
|  | 164 | #endif | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 165 | pushm	r12		/* r12_orig */ | 
|  | 166 | stmts	--sp, r0-lr | 
| Philippe Rétornaz | a7e30b8 | 2007-10-10 18:52:24 -0400 | [diff] [blame] | 167 |  | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 168 | mfsr	r0, SYSREG_RAR_SUP | 
|  | 169 | mfsr	r1, SYSREG_RSR_SUP | 
| Philippe Rétornaz | a7e30b8 | 2007-10-10 18:52:24 -0400 | [diff] [blame] | 170 | #ifdef CONFIG_PREEMPT | 
|  | 171 | unmask_interrupts | 
|  | 172 | #endif | 
|  | 173 | zero_fp | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 174 | stm	--sp, r0-r1 | 
|  | 175 |  | 
|  | 176 | /* check for syscall tracing */ | 
|  | 177 | get_thread_info r0 | 
|  | 178 | ld.w	r1, r0[TI_flags] | 
|  | 179 | bld	r1, TIF_SYSCALL_TRACE | 
|  | 180 | brcs	syscall_trace_enter | 
|  | 181 |  | 
|  | 182 | syscall_trace_cont: | 
|  | 183 | cp.w	r8, NR_syscalls | 
|  | 184 | brhs	syscall_badsys | 
|  | 185 |  | 
|  | 186 | lddpc   lr, syscall_table_addr | 
|  | 187 | ld.w    lr, lr[r8 << 2] | 
|  | 188 | mov	r8, r5		/* 5th argument (6th is pushed by stub) */ | 
|  | 189 | icall   lr | 
|  | 190 |  | 
|  | 191 | .global	syscall_return | 
|  | 192 | syscall_return: | 
|  | 193 | get_thread_info r0 | 
|  | 194 | mask_interrupts		/* make sure we don't miss an interrupt | 
|  | 195 | setting need_resched or sigpending | 
|  | 196 | between sampling and the rets */ | 
|  | 197 |  | 
|  | 198 | /* Store the return value so that the correct value is loaded below */ | 
|  | 199 | stdsp   sp[REG_R12], r12 | 
|  | 200 |  | 
|  | 201 | ld.w	r1, r0[TI_flags] | 
|  | 202 | andl	r1, _TIF_ALLWORK_MASK, COH | 
|  | 203 | brne	syscall_exit_work | 
|  | 204 |  | 
|  | 205 | syscall_exit_cont: | 
|  | 206 | popm	r8-r9 | 
|  | 207 | mtsr	SYSREG_RAR_SUP, r8 | 
|  | 208 | mtsr	SYSREG_RSR_SUP, r9 | 
|  | 209 | ldmts	sp++, r0-lr | 
|  | 210 | sub	sp, -4		/* r12_orig */ | 
|  | 211 | rets | 
|  | 212 |  | 
|  | 213 | .align	2 | 
|  | 214 | syscall_table_addr: | 
|  | 215 | .long   sys_call_table | 
|  | 216 |  | 
|  | 217 | syscall_badsys: | 
|  | 218 | mov	r12, -ENOSYS | 
|  | 219 | rjmp	syscall_return | 
|  | 220 |  | 
|  | 221 | .global ret_from_fork | 
|  | 222 | ret_from_fork: | 
|  | 223 | rcall   schedule_tail | 
|  | 224 |  | 
|  | 225 | /* check for syscall tracing */ | 
|  | 226 | get_thread_info r0 | 
|  | 227 | ld.w	r1, r0[TI_flags] | 
|  | 228 | andl	r1, _TIF_ALLWORK_MASK, COH | 
|  | 229 | brne	syscall_exit_work | 
|  | 230 | rjmp    syscall_exit_cont | 
|  | 231 |  | 
|  | 232 | syscall_trace_enter: | 
|  | 233 | pushm	r8-r12 | 
|  | 234 | rcall	syscall_trace | 
|  | 235 | popm	r8-r12 | 
|  | 236 | rjmp	syscall_trace_cont | 
|  | 237 |  | 
|  | 238 | syscall_exit_work: | 
|  | 239 | bld	r1, TIF_SYSCALL_TRACE | 
|  | 240 | brcc	1f | 
|  | 241 | unmask_interrupts | 
|  | 242 | rcall	syscall_trace | 
|  | 243 | mask_interrupts | 
|  | 244 | ld.w	r1, r0[TI_flags] | 
|  | 245 |  | 
|  | 246 | 1:	bld	r1, TIF_NEED_RESCHED | 
|  | 247 | brcc	2f | 
|  | 248 | unmask_interrupts | 
|  | 249 | rcall	schedule | 
|  | 250 | mask_interrupts | 
|  | 251 | ld.w	r1, r0[TI_flags] | 
|  | 252 | rjmp	1b | 
|  | 253 |  | 
|  | 254 | 2:	mov	r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | 
|  | 255 | tst	r1, r2 | 
|  | 256 | breq	3f | 
|  | 257 | unmask_interrupts | 
|  | 258 | mov	r12, sp | 
|  | 259 | mov	r11, r0 | 
|  | 260 | rcall	do_notify_resume | 
|  | 261 | mask_interrupts | 
|  | 262 | ld.w	r1, r0[TI_flags] | 
|  | 263 | rjmp	1b | 
|  | 264 |  | 
|  | 265 | 3:	bld	r1, TIF_BREAKPOINT | 
|  | 266 | brcc	syscall_exit_cont | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 267 | rjmp	enter_monitor_mode | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 268 |  | 
|  | 269 | /* The slow path of the TLB miss handler */ | 
|  | 270 | page_table_not_present: | 
|  | 271 | page_not_present: | 
|  | 272 | tlbmiss_restore | 
|  | 273 | sub	sp, 4 | 
|  | 274 | stmts	--sp, r0-lr | 
|  | 275 | rcall	save_full_context_ex | 
|  | 276 | mfsr	r12, SYSREG_ECR | 
|  | 277 | mov	r11, sp | 
|  | 278 | rcall	do_page_fault | 
|  | 279 | rjmp	ret_from_exception | 
|  | 280 |  | 
|  | 281 | /* This function expects to find offending PC in SYSREG_RAR_EX */ | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 282 | .type	save_full_context_ex, @function | 
|  | 283 | .align	2 | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 284 | save_full_context_ex: | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 285 | mfsr	r11, SYSREG_RAR_EX | 
|  | 286 | sub	r9, pc, . - debug_trampoline | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 287 | mfsr	r8, SYSREG_RSR_EX | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 288 | cp.w	r9, r11 | 
|  | 289 | breq	3f | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 290 | mov	r12, r8 | 
|  | 291 | andh	r8, (MODE_MASK >> 16), COH | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 292 | brne	2f | 
|  | 293 |  | 
|  | 294 | 1:	pushm	r11, r12	/* PC and SR */ | 
|  | 295 | unmask_exceptions | 
|  | 296 | ret	r12 | 
|  | 297 |  | 
|  | 298 | 2:	sub	r10, sp, -(FRAME_SIZE_FULL - REG_LR) | 
|  | 299 | stdsp	sp[4], r10	/* replace saved SP */ | 
|  | 300 | rjmp	1b | 
|  | 301 |  | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 302 | /* | 
|  | 303 | * The debug handler set up a trampoline to make us | 
|  | 304 | * automatically enter monitor mode upon return, but since | 
|  | 305 | * we're saving the full context, we must assume that the | 
|  | 306 | * exception handler might want to alter the return address | 
|  | 307 | * and/or status register. So we need to restore the original | 
|  | 308 | * context and enter monitor mode manually after the exception | 
|  | 309 | * has been handled. | 
|  | 310 | */ | 
|  | 311 | 3:	get_thread_info r8 | 
|  | 312 | ld.w	r11, r8[TI_rar_saved] | 
|  | 313 | ld.w	r12, r8[TI_rsr_saved] | 
|  | 314 | rjmp	1b | 
|  | 315 | .size	save_full_context_ex, . - save_full_context_ex | 
|  | 316 |  | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 317 | /* Low-level exception handlers */ | 
|  | 318 | handle_critical: | 
| Haavard Skinnemoen | 5998a3c | 2007-12-03 18:30:15 +0100 | [diff] [blame] | 319 | sub	sp, 4 | 
|  | 320 | stmts	--sp, r0-lr | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 321 | rcall	save_full_context_ex | 
|  | 322 | mfsr	r12, SYSREG_ECR | 
|  | 323 | mov	r11, sp | 
|  | 324 | rcall	do_critical_exception | 
|  | 325 |  | 
|  | 326 | /* We should never get here... */ | 
|  | 327 | bad_return: | 
|  | 328 | sub	r12, pc, (. - 1f) | 
|  | 329 | bral	panic | 
|  | 330 | .align	2 | 
|  | 331 | 1:	.asciz	"Return from critical exception!" | 
|  | 332 |  | 
|  | 333 | .align	1 | 
|  | 334 | do_bus_error_write: | 
|  | 335 | sub	sp, 4 | 
|  | 336 | stmts	--sp, r0-lr | 
|  | 337 | rcall	save_full_context_ex | 
|  | 338 | mov	r11, 1 | 
|  | 339 | rjmp	1f | 
|  | 340 |  | 
|  | 341 | do_bus_error_read: | 
|  | 342 | sub	sp, 4 | 
|  | 343 | stmts	--sp, r0-lr | 
|  | 344 | rcall	save_full_context_ex | 
|  | 345 | mov	r11, 0 | 
|  | 346 | 1:	mfsr	r12, SYSREG_BEAR | 
|  | 347 | mov	r10, sp | 
|  | 348 | rcall	do_bus_error | 
|  | 349 | rjmp	ret_from_exception | 
|  | 350 |  | 
|  | 351 | .align	1 | 
|  | 352 | do_nmi_ll: | 
|  | 353 | sub	sp, 4 | 
|  | 354 | stmts	--sp, r0-lr | 
| Haavard Skinnemoen | 92b728c | 2007-03-13 10:06:37 +0100 | [diff] [blame] | 355 | mfsr	r9, SYSREG_RSR_NMI | 
|  | 356 | mfsr	r8, SYSREG_RAR_NMI | 
|  | 357 | bfextu	r0, r9, MODE_SHIFT, 3 | 
|  | 358 | brne	2f | 
|  | 359 |  | 
|  | 360 | 1:	pushm	r8, r9	/* PC and SR */ | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 361 | mfsr	r12, SYSREG_ECR | 
|  | 362 | mov	r11, sp | 
|  | 363 | rcall	do_nmi | 
| Haavard Skinnemoen | 92b728c | 2007-03-13 10:06:37 +0100 | [diff] [blame] | 364 | popm	r8-r9 | 
|  | 365 | mtsr	SYSREG_RAR_NMI, r8 | 
|  | 366 | tst	r0, r0 | 
|  | 367 | mtsr	SYSREG_RSR_NMI, r9 | 
|  | 368 | brne	3f | 
|  | 369 |  | 
|  | 370 | ldmts	sp++, r0-lr | 
|  | 371 | sub	sp, -4		/* skip r12_orig */ | 
|  | 372 | rete | 
|  | 373 |  | 
|  | 374 | 2:	sub	r10, sp, -(FRAME_SIZE_FULL - REG_LR) | 
|  | 375 | stdsp	sp[4], r10	/* replace saved SP */ | 
|  | 376 | rjmp	1b | 
|  | 377 |  | 
|  | 378 | 3:	popm	lr | 
|  | 379 | sub	sp, -4		/* skip sp */ | 
|  | 380 | popm	r0-r12 | 
|  | 381 | sub	sp, -4		/* skip r12_orig */ | 
|  | 382 | rete | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 383 |  | 
|  | 384 | handle_address_fault: | 
|  | 385 | sub	sp, 4 | 
|  | 386 | stmts	--sp, r0-lr | 
|  | 387 | rcall	save_full_context_ex | 
|  | 388 | mfsr	r12, SYSREG_ECR | 
|  | 389 | mov	r11, sp | 
|  | 390 | rcall	do_address_exception | 
|  | 391 | rjmp	ret_from_exception | 
|  | 392 |  | 
|  | 393 | handle_protection_fault: | 
|  | 394 | sub	sp, 4 | 
|  | 395 | stmts	--sp, r0-lr | 
|  | 396 | rcall	save_full_context_ex | 
|  | 397 | mfsr	r12, SYSREG_ECR | 
|  | 398 | mov	r11, sp | 
|  | 399 | rcall	do_page_fault | 
|  | 400 | rjmp	ret_from_exception | 
|  | 401 |  | 
|  | 402 | .align	1 | 
|  | 403 | do_illegal_opcode_ll: | 
|  | 404 | sub	sp, 4 | 
|  | 405 | stmts	--sp, r0-lr | 
|  | 406 | rcall	save_full_context_ex | 
|  | 407 | mfsr	r12, SYSREG_ECR | 
|  | 408 | mov	r11, sp | 
|  | 409 | rcall	do_illegal_opcode | 
|  | 410 | rjmp	ret_from_exception | 
|  | 411 |  | 
|  | 412 | do_dtlb_modified: | 
|  | 413 | pushm	r0-r3 | 
|  | 414 | mfsr	r1, SYSREG_TLBEAR | 
|  | 415 | mfsr	r0, SYSREG_PTBR | 
|  | 416 | lsr	r2, r1, PGDIR_SHIFT | 
|  | 417 | ld.w	r0, r0[r2 << 2] | 
|  | 418 | lsl	r1, (32 - PGDIR_SHIFT) | 
|  | 419 | lsr	r1, (32 - PGDIR_SHIFT) + PAGE_SHIFT | 
|  | 420 |  | 
|  | 421 | /* Translate to virtual address in P1 */ | 
|  | 422 | andl	r0, 0xf000 | 
|  | 423 | sbr	r0, 31 | 
|  | 424 | add	r2, r0, r1 << 2 | 
|  | 425 | ld.w	r3, r2[0] | 
|  | 426 | sbr	r3, _PAGE_BIT_DIRTY | 
|  | 427 | mov	r0, r3 | 
|  | 428 | st.w	r2[0], r3 | 
|  | 429 |  | 
|  | 430 | /* The page table is up-to-date. Update the TLB entry as well */ | 
|  | 431 | andl	r0, lo(_PAGE_FLAGS_HARDWARE_MASK) | 
|  | 432 | mtsr	SYSREG_TLBELO, r0 | 
|  | 433 |  | 
|  | 434 | /* MMUCR[DRP] is updated automatically, so let's go... */ | 
|  | 435 | tlbw | 
|  | 436 |  | 
|  | 437 | popm	r0-r3 | 
|  | 438 | rete | 
|  | 439 |  | 
|  | 440 | do_fpe_ll: | 
|  | 441 | sub	sp, 4 | 
|  | 442 | stmts	--sp, r0-lr | 
|  | 443 | rcall	save_full_context_ex | 
|  | 444 | unmask_interrupts | 
|  | 445 | mov	r12, 26 | 
|  | 446 | mov	r11, sp | 
|  | 447 | rcall	do_fpe | 
|  | 448 | rjmp	ret_from_exception | 
|  | 449 |  | 
|  | 450 | ret_from_exception: | 
|  | 451 | mask_interrupts | 
|  | 452 | lddsp	r4, sp[REG_SR] | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 453 |  | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 454 | andh	r4, (MODE_MASK >> 16), COH | 
|  | 455 | brne	fault_resume_kernel | 
|  | 456 |  | 
|  | 457 | get_thread_info r0 | 
|  | 458 | ld.w	r1, r0[TI_flags] | 
|  | 459 | andl	r1, _TIF_WORK_MASK, COH | 
|  | 460 | brne	fault_exit_work | 
|  | 461 |  | 
|  | 462 | fault_resume_user: | 
|  | 463 | popm	r8-r9 | 
|  | 464 | mask_exceptions | 
|  | 465 | mtsr	SYSREG_RAR_EX, r8 | 
|  | 466 | mtsr	SYSREG_RSR_EX, r9 | 
|  | 467 | ldmts	sp++, r0-lr | 
|  | 468 | sub	sp, -4 | 
|  | 469 | rete | 
|  | 470 |  | 
|  | 471 | fault_resume_kernel: | 
|  | 472 | #ifdef CONFIG_PREEMPT | 
|  | 473 | get_thread_info	r0 | 
|  | 474 | ld.w	r2, r0[TI_preempt_count] | 
|  | 475 | cp.w	r2, 0 | 
|  | 476 | brne	1f | 
|  | 477 | ld.w	r1, r0[TI_flags] | 
|  | 478 | bld	r1, TIF_NEED_RESCHED | 
|  | 479 | brcc	1f | 
|  | 480 | lddsp	r4, sp[REG_SR] | 
|  | 481 | bld	r4, SYSREG_GM_OFFSET | 
|  | 482 | brcs	1f | 
|  | 483 | rcall	preempt_schedule_irq | 
|  | 484 | 1: | 
|  | 485 | #endif | 
|  | 486 |  | 
|  | 487 | popm	r8-r9 | 
|  | 488 | mask_exceptions | 
|  | 489 | mfsr	r1, SYSREG_SR | 
|  | 490 | mtsr	SYSREG_RAR_EX, r8 | 
|  | 491 | mtsr	SYSREG_RSR_EX, r9 | 
|  | 492 | popm	lr | 
|  | 493 | sub	sp, -4		/* ignore SP */ | 
|  | 494 | popm	r0-r12 | 
|  | 495 | sub	sp, -4		/* ignore r12_orig */ | 
|  | 496 | rete | 
|  | 497 |  | 
|  | 498 | irq_exit_work: | 
|  | 499 | /* Switch to exception mode so that we can share the same code. */ | 
|  | 500 | mfsr	r8, SYSREG_SR | 
|  | 501 | cbr	r8, SYSREG_M0_OFFSET | 
|  | 502 | orh	r8, hi(SYSREG_BIT(M1) | SYSREG_BIT(M2)) | 
|  | 503 | mtsr	SYSREG_SR, r8 | 
|  | 504 | sub	pc, -2 | 
|  | 505 | get_thread_info r0 | 
|  | 506 | ld.w	r1, r0[TI_flags] | 
|  | 507 |  | 
|  | 508 | fault_exit_work: | 
|  | 509 | bld	r1, TIF_NEED_RESCHED | 
|  | 510 | brcc	1f | 
|  | 511 | unmask_interrupts | 
|  | 512 | rcall	schedule | 
|  | 513 | mask_interrupts | 
|  | 514 | ld.w	r1, r0[TI_flags] | 
|  | 515 | rjmp	fault_exit_work | 
|  | 516 |  | 
|  | 517 | 1:	mov	r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | 
|  | 518 | tst	r1, r2 | 
|  | 519 | breq	2f | 
|  | 520 | unmask_interrupts | 
|  | 521 | mov	r12, sp | 
|  | 522 | mov	r11, r0 | 
|  | 523 | rcall	do_notify_resume | 
|  | 524 | mask_interrupts | 
|  | 525 | ld.w	r1, r0[TI_flags] | 
|  | 526 | rjmp	fault_exit_work | 
|  | 527 |  | 
|  | 528 | 2:	bld	r1, TIF_BREAKPOINT | 
|  | 529 | brcc	fault_resume_user | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 530 | rjmp	enter_monitor_mode | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 531 |  | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 532 | .section .kprobes.text, "ax", @progbits | 
|  | 533 | .type	handle_debug, @function | 
|  | 534 | handle_debug: | 
|  | 535 | sub	sp, 4		/* r12_orig */ | 
|  | 536 | stmts	--sp, r0-lr | 
|  | 537 | mfsr	r8, SYSREG_RAR_DBG | 
|  | 538 | mfsr	r9, SYSREG_RSR_DBG | 
|  | 539 | unmask_exceptions | 
|  | 540 | pushm	r8-r9 | 
|  | 541 | bfextu	r9, r9, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE | 
|  | 542 | brne	debug_fixup_regs | 
|  | 543 |  | 
|  | 544 | .Ldebug_fixup_cont: | 
|  | 545 | #ifdef CONFIG_TRACE_IRQFLAGS | 
|  | 546 | rcall	trace_hardirqs_off | 
|  | 547 | #endif | 
|  | 548 | mov	r12, sp | 
|  | 549 | rcall	do_debug | 
|  | 550 | mov	sp, r12 | 
|  | 551 |  | 
|  | 552 | lddsp	r2, sp[REG_SR] | 
|  | 553 | bfextu	r3, r2, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE | 
|  | 554 | brne	debug_resume_kernel | 
|  | 555 |  | 
|  | 556 | get_thread_info r0 | 
|  | 557 | ld.w	r1, r0[TI_flags] | 
|  | 558 | mov	r2, _TIF_DBGWORK_MASK | 
|  | 559 | tst	r1, r2 | 
|  | 560 | brne	debug_exit_work | 
|  | 561 |  | 
|  | 562 | bld	r1, TIF_SINGLE_STEP | 
|  | 563 | brcc	1f | 
|  | 564 | mfdr	r4, OCD_DC | 
|  | 565 | sbr	r4, OCD_DC_SS_BIT | 
|  | 566 | mtdr	OCD_DC, r4 | 
|  | 567 |  | 
|  | 568 | 1:	popm	r10,r11 | 
|  | 569 | mask_exceptions | 
|  | 570 | mtsr	SYSREG_RSR_DBG, r11 | 
|  | 571 | mtsr	SYSREG_RAR_DBG, r10 | 
|  | 572 | #ifdef CONFIG_TRACE_IRQFLAGS | 
|  | 573 | rcall	trace_hardirqs_on | 
|  | 574 | 1: | 
|  | 575 | #endif | 
|  | 576 | ldmts	sp++, r0-lr | 
|  | 577 | sub	sp, -4 | 
|  | 578 | retd | 
|  | 579 | .size	handle_debug, . - handle_debug | 
|  | 580 |  | 
|  | 581 | /* Mode of the trapped context is in r9 */ | 
|  | 582 | .type	debug_fixup_regs, @function | 
|  | 583 | debug_fixup_regs: | 
|  | 584 | mfsr	r8, SYSREG_SR | 
|  | 585 | mov	r10, r8 | 
|  | 586 | bfins	r8, r9, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE | 
|  | 587 | mtsr	SYSREG_SR, r8 | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 588 | sub	pc, -2 | 
|  | 589 | stdsp	sp[REG_LR], lr | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 590 | mtsr	SYSREG_SR, r10 | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 591 | sub	pc, -2 | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 592 | sub	r8, sp, -FRAME_SIZE_FULL | 
|  | 593 | stdsp	sp[REG_SP], r8 | 
|  | 594 | rjmp	.Ldebug_fixup_cont | 
|  | 595 | .size	debug_fixup_regs, . - debug_fixup_regs | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 596 |  | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 597 | .type	debug_resume_kernel, @function | 
|  | 598 | debug_resume_kernel: | 
|  | 599 | mask_exceptions | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 600 | popm	r10, r11 | 
|  | 601 | mtsr	SYSREG_RAR_DBG, r10 | 
|  | 602 | mtsr	SYSREG_RSR_DBG, r11 | 
| Haavard Skinnemoen | 320516b | 2007-11-26 14:34:57 +0100 | [diff] [blame] | 603 | #ifdef CONFIG_TRACE_IRQFLAGS | 
|  | 604 | bld	r11, SYSREG_GM_OFFSET | 
|  | 605 | brcc	1f | 
|  | 606 | rcall	trace_hardirqs_on | 
|  | 607 | 1: | 
|  | 608 | #endif | 
|  | 609 | mfsr	r2, SYSREG_SR | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 610 | mov	r1, r2 | 
|  | 611 | bfins	r2, r3, SYSREG_MODE_OFFSET, SYSREG_MODE_SIZE | 
| Haavard Skinnemoen | 320516b | 2007-11-26 14:34:57 +0100 | [diff] [blame] | 612 | mtsr	SYSREG_SR, r2 | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 613 | sub	pc, -2 | 
|  | 614 | popm	lr | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 615 | mtsr	SYSREG_SR, r1 | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 616 | sub	pc, -2 | 
|  | 617 | sub	sp, -4		/* skip SP */ | 
|  | 618 | popm	r0-r12 | 
|  | 619 | sub	sp, -4 | 
|  | 620 | retd | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 621 | .size	debug_resume_kernel, . - debug_resume_kernel | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 622 |  | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 623 | .type	debug_exit_work, @function | 
|  | 624 | debug_exit_work: | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 625 | /* | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 626 | * We must return from Monitor Mode using a retd, and we must | 
|  | 627 | * not schedule since that involves the D bit in SR getting | 
|  | 628 | * cleared by something other than the debug hardware. This | 
|  | 629 | * may cause undefined behaviour according to the Architecture | 
|  | 630 | * manual. | 
|  | 631 | * | 
|  | 632 | * So we fix up the return address and status and return to a | 
|  | 633 | * stub below in Exception mode. From there, we can follow the | 
|  | 634 | * normal exception return path. | 
|  | 635 | * | 
|  | 636 | * The real return address and status registers are stored on | 
|  | 637 | * the stack in the way the exception return path understands, | 
|  | 638 | * so no need to fix anything up there. | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 639 | */ | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 640 | sub	r8, pc, . - fault_exit_work | 
|  | 641 | mtsr	SYSREG_RAR_DBG, r8 | 
|  | 642 | mov	r9, 0 | 
|  | 643 | orh	r9, hi(SR_EM | SR_GM | MODE_EXCEPTION) | 
|  | 644 | mtsr	SYSREG_RSR_DBG, r9 | 
|  | 645 | sub	pc, -2 | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 646 | retd | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 647 | .size	debug_exit_work, . - debug_exit_work | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 648 |  | 
|  | 649 | .set	rsr_int0,	SYSREG_RSR_INT0 | 
|  | 650 | .set	rsr_int1,	SYSREG_RSR_INT1 | 
|  | 651 | .set	rsr_int2,	SYSREG_RSR_INT2 | 
|  | 652 | .set	rsr_int3,	SYSREG_RSR_INT3 | 
|  | 653 | .set	rar_int0,	SYSREG_RAR_INT0 | 
|  | 654 | .set	rar_int1,	SYSREG_RAR_INT1 | 
|  | 655 | .set	rar_int2,	SYSREG_RAR_INT2 | 
|  | 656 | .set	rar_int3,	SYSREG_RAR_INT3 | 
|  | 657 |  | 
|  | 658 | .macro	IRQ_LEVEL level | 
|  | 659 | .type	irq_level\level, @function | 
|  | 660 | irq_level\level: | 
|  | 661 | sub	sp, 4		/* r12_orig */ | 
|  | 662 | stmts	--sp,r0-lr | 
|  | 663 | mfsr	r8, rar_int\level | 
|  | 664 | mfsr	r9, rsr_int\level | 
| Philippe Rétornaz | a7e30b8 | 2007-10-10 18:52:24 -0400 | [diff] [blame] | 665 |  | 
|  | 666 | #ifdef CONFIG_PREEMPT | 
|  | 667 | sub	r11, pc, (. - system_call) | 
|  | 668 | cp.w	r11, r8 | 
|  | 669 | breq	4f | 
|  | 670 | #endif | 
|  | 671 |  | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 672 | pushm	r8-r9 | 
|  | 673 |  | 
|  | 674 | mov	r11, sp | 
|  | 675 | mov	r12, \level | 
|  | 676 |  | 
|  | 677 | rcall	do_IRQ | 
|  | 678 |  | 
|  | 679 | lddsp	r4, sp[REG_SR] | 
| Hans-Christian Egtvedt | 19b7ce8 | 2007-02-26 13:50:43 +0100 | [diff] [blame] | 680 | bfextu	r4, r4, SYSREG_M0_OFFSET, 3 | 
|  | 681 | cp.w	r4, MODE_SUPERVISOR >> SYSREG_M0_OFFSET | 
|  | 682 | breq	2f | 
|  | 683 | cp.w	r4, MODE_USER >> SYSREG_M0_OFFSET | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 684 | #ifdef CONFIG_PREEMPT | 
| Hans-Christian Egtvedt | 19b7ce8 | 2007-02-26 13:50:43 +0100 | [diff] [blame] | 685 | brne	3f | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 686 | #else | 
|  | 687 | brne	1f | 
|  | 688 | #endif | 
|  | 689 |  | 
|  | 690 | get_thread_info	r0 | 
|  | 691 | ld.w	r1, r0[TI_flags] | 
|  | 692 | andl	r1, _TIF_WORK_MASK, COH | 
|  | 693 | brne	irq_exit_work | 
|  | 694 |  | 
| Haavard Skinnemoen | 320516b | 2007-11-26 14:34:57 +0100 | [diff] [blame] | 695 | 1: | 
|  | 696 | #ifdef CONFIG_TRACE_IRQFLAGS | 
|  | 697 | rcall	trace_hardirqs_on | 
|  | 698 | #endif | 
|  | 699 | popm	r8-r9 | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 700 | mtsr	rar_int\level, r8 | 
|  | 701 | mtsr	rsr_int\level, r9 | 
|  | 702 | ldmts	sp++,r0-lr | 
|  | 703 | sub	sp, -4		/* ignore r12_orig */ | 
|  | 704 | rete | 
|  | 705 |  | 
| Philippe Rétornaz | a7e30b8 | 2007-10-10 18:52:24 -0400 | [diff] [blame] | 706 | #ifdef CONFIG_PREEMPT | 
|  | 707 | 4:	mask_interrupts | 
|  | 708 | mfsr	r8, rsr_int\level | 
|  | 709 | sbr	r8, 16 | 
|  | 710 | mtsr	rsr_int\level, r8 | 
|  | 711 | ldmts	sp++, r0-lr | 
|  | 712 | sub	sp, -4		/* ignore r12_orig */ | 
|  | 713 | rete | 
|  | 714 | #endif | 
|  | 715 |  | 
| Hans-Christian Egtvedt | 19b7ce8 | 2007-02-26 13:50:43 +0100 | [diff] [blame] | 716 | 2:	get_thread_info	r0 | 
|  | 717 | ld.w	r1, r0[TI_flags] | 
|  | 718 | bld	r1, TIF_CPU_GOING_TO_SLEEP | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 719 | #ifdef CONFIG_PREEMPT | 
| Hans-Christian Egtvedt | 19b7ce8 | 2007-02-26 13:50:43 +0100 | [diff] [blame] | 720 | brcc	3f | 
|  | 721 | #else | 
|  | 722 | brcc	1b | 
|  | 723 | #endif | 
|  | 724 | sub	r1, pc, . - cpu_idle_skip_sleep | 
|  | 725 | stdsp	sp[REG_PC], r1 | 
|  | 726 | #ifdef CONFIG_PREEMPT | 
|  | 727 | 3:	get_thread_info r0 | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 728 | ld.w	r2, r0[TI_preempt_count] | 
|  | 729 | cp.w	r2, 0 | 
|  | 730 | brne	1b | 
|  | 731 | ld.w	r1, r0[TI_flags] | 
|  | 732 | bld	r1, TIF_NEED_RESCHED | 
|  | 733 | brcc	1b | 
|  | 734 | lddsp	r4, sp[REG_SR] | 
|  | 735 | bld	r4, SYSREG_GM_OFFSET | 
|  | 736 | brcs	1b | 
|  | 737 | rcall	preempt_schedule_irq | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 738 | #endif | 
| Hans-Christian Egtvedt | 19b7ce8 | 2007-02-26 13:50:43 +0100 | [diff] [blame] | 739 | rjmp	1b | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 740 | .endm | 
|  | 741 |  | 
|  | 742 | .section .irq.text,"ax",@progbits | 
|  | 743 |  | 
| Hans-Christian Egtvedt | 19b7ce8 | 2007-02-26 13:50:43 +0100 | [diff] [blame] | 744 | .global cpu_idle_sleep | 
|  | 745 | cpu_idle_sleep: | 
|  | 746 | mask_interrupts | 
|  | 747 | get_thread_info r8 | 
|  | 748 | ld.w	r9, r8[TI_flags] | 
|  | 749 | bld	r9, TIF_NEED_RESCHED | 
|  | 750 | brcs	cpu_idle_enable_int_and_exit | 
|  | 751 | sbr	r9, TIF_CPU_GOING_TO_SLEEP | 
|  | 752 | st.w	r8[TI_flags], r9 | 
|  | 753 | unmask_interrupts | 
|  | 754 | sleep 0 | 
|  | 755 | cpu_idle_skip_sleep: | 
|  | 756 | mask_interrupts | 
|  | 757 | ld.w	r9, r8[TI_flags] | 
|  | 758 | cbr	r9, TIF_CPU_GOING_TO_SLEEP | 
|  | 759 | st.w	r8[TI_flags], r9 | 
|  | 760 | cpu_idle_enable_int_and_exit: | 
|  | 761 | unmask_interrupts | 
|  | 762 | retal	r12 | 
|  | 763 |  | 
| Haavard Skinnemoen | 5f97f7f | 2006-09-25 23:32:13 -0700 | [diff] [blame] | 764 | .global	irq_level0 | 
|  | 765 | .global	irq_level1 | 
|  | 766 | .global	irq_level2 | 
|  | 767 | .global	irq_level3 | 
|  | 768 | IRQ_LEVEL 0 | 
|  | 769 | IRQ_LEVEL 1 | 
|  | 770 | IRQ_LEVEL 2 | 
|  | 771 | IRQ_LEVEL 3 | 
| Haavard Skinnemoen | 2507bc1 | 2007-11-28 15:04:01 +0100 | [diff] [blame] | 772 |  | 
|  | 773 | .section .kprobes.text, "ax", @progbits | 
|  | 774 | .type	enter_monitor_mode, @function | 
|  | 775 | enter_monitor_mode: | 
|  | 776 | /* | 
|  | 777 | * We need to enter monitor mode to do a single step. The | 
|  | 778 | * monitor code will alter the return address so that we | 
|  | 779 | * return directly to the user instead of returning here. | 
|  | 780 | */ | 
|  | 781 | breakpoint | 
|  | 782 | rjmp	breakpoint_failed | 
|  | 783 |  | 
|  | 784 | .size	enter_monitor_mode, . - enter_monitor_mode | 
|  | 785 |  | 
|  | 786 | .type	debug_trampoline, @function | 
|  | 787 | .global	debug_trampoline | 
|  | 788 | debug_trampoline: | 
|  | 789 | /* | 
|  | 790 | * Save the registers on the stack so that the monitor code | 
|  | 791 | * can find them easily. | 
|  | 792 | */ | 
|  | 793 | sub	sp, 4		/* r12_orig */ | 
|  | 794 | stmts	--sp, r0-lr | 
|  | 795 | get_thread_info	r0 | 
|  | 796 | ld.w	r8, r0[TI_rar_saved] | 
|  | 797 | ld.w	r9, r0[TI_rsr_saved] | 
|  | 798 | pushm	r8-r9 | 
|  | 799 |  | 
|  | 800 | /* | 
|  | 801 | * The monitor code will alter the return address so we don't | 
|  | 802 | * return here. | 
|  | 803 | */ | 
|  | 804 | breakpoint | 
|  | 805 | rjmp	breakpoint_failed | 
|  | 806 | .size	debug_trampoline, . - debug_trampoline | 
|  | 807 |  | 
|  | 808 | .type breakpoint_failed, @function | 
|  | 809 | breakpoint_failed: | 
|  | 810 | /* | 
|  | 811 | * Something went wrong. Perhaps the debug hardware isn't | 
|  | 812 | * enabled? | 
|  | 813 | */ | 
|  | 814 | lda.w	r12, msg_breakpoint_failed | 
|  | 815 | mov	r11, sp | 
|  | 816 | mov	r10, 9		/* SIGKILL */ | 
|  | 817 | call	die | 
|  | 818 | 1:	rjmp	1b | 
|  | 819 |  | 
|  | 820 | msg_breakpoint_failed: | 
|  | 821 | .asciz	"Failed to enter Debug Mode" |