12edfe428SAndrew Jones /* 22edfe428SAndrew Jones * processor control and status functions 32edfe428SAndrew Jones * 42edfe428SAndrew Jones * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com> 52edfe428SAndrew Jones * 62edfe428SAndrew Jones * This work is licensed under the terms of the GNU LGPL, version 2. 72edfe428SAndrew Jones */ 82edfe428SAndrew Jones #include "libcflat.h" 92edfe428SAndrew Jones #include "asm/ptrace.h" 102edfe428SAndrew Jones #include "asm/processor.h" 112edfe428SAndrew Jones 122edfe428SAndrew Jones static const char *processor_modes[] = { 132edfe428SAndrew Jones "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , 142edfe428SAndrew Jones "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , 152edfe428SAndrew Jones "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", 162edfe428SAndrew Jones "UK12_26", "UK13_26", "UK14_26", "UK15_26", 172edfe428SAndrew Jones "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , 182edfe428SAndrew Jones "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" , 192edfe428SAndrew Jones "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , 202edfe428SAndrew Jones "UK12_32", "UK13_32", "UK14_32", "SYS_32" 212edfe428SAndrew Jones }; 222edfe428SAndrew Jones 232edfe428SAndrew Jones static char *vector_names[] = { 242edfe428SAndrew Jones "rst", "und", "svc", "pabt", "dabt", "addrexcptn", "irq", "fiq" 252edfe428SAndrew Jones }; 262edfe428SAndrew Jones 272edfe428SAndrew Jones void show_regs(struct pt_regs *regs) 282edfe428SAndrew Jones { 292edfe428SAndrew Jones unsigned long flags; 302edfe428SAndrew Jones char buf[64]; 312edfe428SAndrew Jones 322edfe428SAndrew Jones printf("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n" 332edfe428SAndrew Jones "sp : %08lx ip : %08lx fp : %08lx\n", 342edfe428SAndrew Jones regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr, 352edfe428SAndrew Jones regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); 362edfe428SAndrew Jones printf("r10: %08lx r9 : %08lx r8 : %08lx\n", 372edfe428SAndrew Jones regs->ARM_r10, regs->ARM_r9, regs->ARM_r8); 382edfe428SAndrew Jones printf("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", 392edfe428SAndrew Jones regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4); 402edfe428SAndrew Jones printf("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", 412edfe428SAndrew Jones regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0); 422edfe428SAndrew Jones 432edfe428SAndrew Jones flags = regs->ARM_cpsr; 442edfe428SAndrew Jones buf[0] = flags & PSR_N_BIT ? 'N' : 'n'; 452edfe428SAndrew Jones buf[1] = flags & PSR_Z_BIT ? 'Z' : 'z'; 462edfe428SAndrew Jones buf[2] = flags & PSR_C_BIT ? 'C' : 'c'; 472edfe428SAndrew Jones buf[3] = flags & PSR_V_BIT ? 'V' : 'v'; 482edfe428SAndrew Jones buf[4] = '\0'; 492edfe428SAndrew Jones 502edfe428SAndrew Jones printf("Flags: %s IRQs o%s FIQs o%s Mode %s\n", 512edfe428SAndrew Jones buf, interrupts_enabled(regs) ? "n" : "ff", 522edfe428SAndrew Jones fast_interrupts_enabled(regs) ? "n" : "ff", 532edfe428SAndrew Jones processor_modes[processor_mode(regs)]); 542edfe428SAndrew Jones 552edfe428SAndrew Jones if (!user_mode(regs)) { 562edfe428SAndrew Jones unsigned int ctrl, transbase, dac; 572edfe428SAndrew Jones asm volatile( 582edfe428SAndrew Jones "mrc p15, 0, %0, c1, c0\n" 592edfe428SAndrew Jones "mrc p15, 0, %1, c2, c0\n" 602edfe428SAndrew Jones "mrc p15, 0, %2, c3, c0\n" 612edfe428SAndrew Jones : "=r" (ctrl), "=r" (transbase), "=r" (dac)); 622edfe428SAndrew Jones printf("Control: %08x Table: %08x DAC: %08x\n", 632edfe428SAndrew Jones ctrl, transbase, dac); 642edfe428SAndrew Jones } 652edfe428SAndrew Jones } 662edfe428SAndrew Jones 672edfe428SAndrew Jones void *get_sp(void) 682edfe428SAndrew Jones { 692edfe428SAndrew Jones register unsigned long sp asm("sp"); 702edfe428SAndrew Jones return (void *)sp; 712edfe428SAndrew Jones } 722edfe428SAndrew Jones 732edfe428SAndrew Jones static exception_fn exception_handlers[EXCPTN_MAX]; 742edfe428SAndrew Jones 752edfe428SAndrew Jones void install_exception_handler(enum vector v, exception_fn fn) 762edfe428SAndrew Jones { 772edfe428SAndrew Jones if (v < EXCPTN_MAX) 782edfe428SAndrew Jones exception_handlers[v] = fn; 792edfe428SAndrew Jones } 802edfe428SAndrew Jones 812edfe428SAndrew Jones void do_handle_exception(enum vector v, struct pt_regs *regs) 822edfe428SAndrew Jones { 832edfe428SAndrew Jones if (v < EXCPTN_MAX && exception_handlers[v]) { 842edfe428SAndrew Jones exception_handlers[v](regs); 852edfe428SAndrew Jones return; 862edfe428SAndrew Jones } 872edfe428SAndrew Jones 882edfe428SAndrew Jones if (v < EXCPTN_MAX) 892edfe428SAndrew Jones printf("Unhandled exception %d (%s)\n", v, vector_names[v]); 902edfe428SAndrew Jones else 912edfe428SAndrew Jones printf("%s called with vector=%d\n", __func__, v); 922edfe428SAndrew Jones 932edfe428SAndrew Jones printf("Exception frame registers:\n"); 942edfe428SAndrew Jones show_regs(regs); 95*153d1936SAndrew Jones if (v == EXCPTN_DABT) { 96*153d1936SAndrew Jones unsigned long far, fsr; 97*153d1936SAndrew Jones asm volatile("mrc p15, 0, %0, c6, c0, 0": "=r" (far)); 98*153d1936SAndrew Jones asm volatile("mrc p15, 0, %0, c5, c0, 0": "=r" (fsr)); 99*153d1936SAndrew Jones printf("DFAR: %08lx DFSR: %08lx\n", far, fsr); 100*153d1936SAndrew Jones } else if (v == EXCPTN_PABT) { 101*153d1936SAndrew Jones unsigned long far, fsr; 102*153d1936SAndrew Jones asm volatile("mrc p15, 0, %0, c6, c0, 2": "=r" (far)); 103*153d1936SAndrew Jones asm volatile("mrc p15, 0, %0, c5, c0, 1": "=r" (fsr)); 104*153d1936SAndrew Jones printf("IFAR: %08lx IFSR: %08lx\n", far, fsr); 105*153d1936SAndrew Jones } 1062edfe428SAndrew Jones abort(); 1072edfe428SAndrew Jones } 1082edfe428SAndrew Jones 1092edfe428SAndrew Jones void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr) 1102edfe428SAndrew Jones { 1112edfe428SAndrew Jones sp_usr &= (~7UL); /* stack ptr needs 8-byte alignment */ 1122edfe428SAndrew Jones 1132edfe428SAndrew Jones asm volatile( 1142edfe428SAndrew Jones "mrs r0, cpsr\n" 1152edfe428SAndrew Jones "bic r0, #" xstr(MODE_MASK) "\n" 1162edfe428SAndrew Jones "orr r0, #" xstr(USR_MODE) "\n" 1172edfe428SAndrew Jones "msr cpsr_c, r0\n" 1182edfe428SAndrew Jones "mov r0, %0\n" 1192edfe428SAndrew Jones "mov sp, %1\n" 1202edfe428SAndrew Jones "mov pc, %2\n" 1212edfe428SAndrew Jones :: "r" (arg), "r" (sp_usr), "r" (func) : "r0"); 1222edfe428SAndrew Jones } 123