1 /* 2 * processor control and status functions 3 * 4 * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com> 5 * 6 * This work is licensed under the terms of the GNU LGPL, version 2. 7 */ 8 #include <libcflat.h> 9 #include <asm/ptrace.h> 10 #include <asm/processor.h> 11 12 static const char *processor_modes[] = { 13 "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , 14 "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , 15 "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", 16 "UK12_26", "UK13_26", "UK14_26", "UK15_26", 17 "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , 18 "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" , 19 "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , 20 "UK12_32", "UK13_32", "UK14_32", "SYS_32" 21 }; 22 23 static const char *vector_names[] = { 24 "rst", "und", "svc", "pabt", "dabt", "addrexcptn", "irq", "fiq" 25 }; 26 27 void show_regs(struct pt_regs *regs) 28 { 29 unsigned long flags; 30 char buf[64]; 31 32 printf("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n" 33 "sp : %08lx ip : %08lx fp : %08lx\n", 34 regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr, 35 regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); 36 printf("r10: %08lx r9 : %08lx r8 : %08lx\n", 37 regs->ARM_r10, regs->ARM_r9, regs->ARM_r8); 38 printf("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", 39 regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4); 40 printf("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", 41 regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0); 42 43 flags = regs->ARM_cpsr; 44 buf[0] = flags & PSR_N_BIT ? 'N' : 'n'; 45 buf[1] = flags & PSR_Z_BIT ? 'Z' : 'z'; 46 buf[2] = flags & PSR_C_BIT ? 'C' : 'c'; 47 buf[3] = flags & PSR_V_BIT ? 'V' : 'v'; 48 buf[4] = '\0'; 49 50 printf("Flags: %s IRQs o%s FIQs o%s Mode %s\n", 51 buf, interrupts_enabled(regs) ? "n" : "ff", 52 fast_interrupts_enabled(regs) ? "n" : "ff", 53 processor_modes[processor_mode(regs)]); 54 55 if (!user_mode(regs)) { 56 unsigned int ctrl, transbase, dac; 57 asm volatile( 58 "mrc p15, 0, %0, c1, c0\n" 59 "mrc p15, 0, %1, c2, c0\n" 60 "mrc p15, 0, %2, c3, c0\n" 61 : "=r" (ctrl), "=r" (transbase), "=r" (dac)); 62 printf("Control: %08x Table: %08x DAC: %08x\n", 63 ctrl, transbase, dac); 64 } 65 } 66 67 void *get_sp(void) 68 { 69 register unsigned long sp asm("sp"); 70 return (void *)sp; 71 } 72 73 static exception_fn exception_handlers[EXCPTN_MAX]; 74 75 void install_exception_handler(enum vector v, exception_fn fn) 76 { 77 if (v < EXCPTN_MAX) 78 exception_handlers[v] = fn; 79 } 80 81 void do_handle_exception(enum vector v, struct pt_regs *regs) 82 { 83 if (v < EXCPTN_MAX && exception_handlers[v]) { 84 exception_handlers[v](regs); 85 return; 86 } 87 88 if (v < EXCPTN_MAX) 89 printf("Unhandled exception %d (%s)\n", v, vector_names[v]); 90 else 91 printf("%s called with vector=%d\n", __func__, v); 92 93 printf("Exception frame registers:\n"); 94 show_regs(regs); 95 if (v == EXCPTN_DABT) { 96 unsigned long far, fsr; 97 asm volatile("mrc p15, 0, %0, c6, c0, 0": "=r" (far)); 98 asm volatile("mrc p15, 0, %0, c5, c0, 0": "=r" (fsr)); 99 printf("DFAR: %08lx DFSR: %08lx\n", far, fsr); 100 } else if (v == EXCPTN_PABT) { 101 unsigned long far, fsr; 102 asm volatile("mrc p15, 0, %0, c6, c0, 2": "=r" (far)); 103 asm volatile("mrc p15, 0, %0, c5, c0, 1": "=r" (fsr)); 104 printf("IFAR: %08lx IFSR: %08lx\n", far, fsr); 105 } 106 abort(); 107 } 108 109 void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr) 110 { 111 sp_usr &= (~7UL); /* stack ptr needs 8-byte alignment */ 112 113 asm volatile( 114 "mrs r0, cpsr\n" 115 "bic r0, #" xstr(MODE_MASK) "\n" 116 "orr r0, #" xstr(USR_MODE) "\n" 117 "msr cpsr_c, r0\n" 118 "isb\n" 119 "mov r0, %0\n" 120 "mov sp, %1\n" 121 "mov pc, %2\n" 122 :: "r" (arg), "r" (sp_usr), "r" (func) : "r0"); 123 } 124