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 #include <asm/thread_info.h>
12
13 static const char *processor_modes[] = {
14 "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" ,
15 "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
16 "UK8_26" , "UK9_26" , "UK10_26", "UK11_26",
17 "UK12_26", "UK13_26", "UK14_26", "UK15_26",
18 "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" ,
19 "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" ,
20 "UK8_32" , "UK9_32" , "UK10_32", "UND_32" ,
21 "UK12_32", "UK13_32", "UK14_32", "SYS_32"
22 };
23
24 static const char *vector_names[] = {
25 "rst", "und", "svc", "pabt", "dabt", "addrexcptn", "irq", "fiq"
26 };
27
show_regs(struct pt_regs * regs)28 void show_regs(struct pt_regs *regs)
29 {
30 unsigned long flags;
31 char buf[64];
32
33 printf("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n"
34 "sp : %08lx ip : %08lx fp : %08lx\n",
35 regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr,
36 regs->ARM_sp, regs->ARM_ip, regs->ARM_fp);
37 printf("r10: %08lx r9 : %08lx r8 : %08lx\n",
38 regs->ARM_r10, regs->ARM_r9, regs->ARM_r8);
39 printf("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n",
40 regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4);
41 printf("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
42 regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0);
43
44 flags = regs->ARM_cpsr;
45 buf[0] = flags & PSR_N_BIT ? 'N' : 'n';
46 buf[1] = flags & PSR_Z_BIT ? 'Z' : 'z';
47 buf[2] = flags & PSR_C_BIT ? 'C' : 'c';
48 buf[3] = flags & PSR_V_BIT ? 'V' : 'v';
49 buf[4] = '\0';
50
51 printf("Flags: %s IRQs o%s FIQs o%s Mode %s\n",
52 buf, interrupts_enabled(regs) ? "n" : "ff",
53 fast_interrupts_enabled(regs) ? "n" : "ff",
54 processor_modes[processor_mode(regs)]);
55
56 if (!user_mode(regs)) {
57 unsigned int ctrl, transbase, dac;
58 asm volatile(
59 "mrc p15, 0, %0, c1, c0\n"
60 "mrc p15, 0, %1, c2, c0\n"
61 "mrc p15, 0, %2, c3, c0\n"
62 : "=r" (ctrl), "=r" (transbase), "=r" (dac));
63 printf("Control: %08x Table: %08x DAC: %08x\n",
64 ctrl, transbase, dac);
65 }
66 }
67
install_exception_handler(enum vector v,exception_fn fn)68 void install_exception_handler(enum vector v, exception_fn fn)
69 {
70 struct thread_info *ti = current_thread_info();
71
72 if (v < EXCPTN_MAX)
73 ti->exception_handlers[v] = fn;
74 }
75
76 /* Needed to compile with -Wmissing-prototypes */
77 void do_handle_exception(enum vector v, struct pt_regs *regs);
78
do_handle_exception(enum vector v,struct pt_regs * regs)79 void do_handle_exception(enum vector v, struct pt_regs *regs)
80 {
81 struct thread_info *ti = thread_info_sp(regs->ARM_sp);
82
83 if (ti->flags & TIF_USER_MODE) {
84 if (v < EXCPTN_MAX && ti->exception_handlers[v]) {
85 ti->exception_handlers[v](regs);
86 return;
87 }
88 ti = current_thread_info();
89 }
90
91 if (v < EXCPTN_MAX && ti->exception_handlers[v]) {
92 ti->exception_handlers[v](regs);
93 return;
94 }
95
96 if (v < EXCPTN_MAX)
97 printf("Unhandled exception %d (%s)\n", v, vector_names[v]);
98 else
99 printf("%s called with vector=%d\n", __func__, v);
100
101 printf("Exception frame registers:\n");
102 show_regs(regs);
103 if (v == EXCPTN_DABT) {
104 unsigned long far, fsr;
105 asm volatile("mrc p15, 0, %0, c6, c0, 0": "=r" (far));
106 asm volatile("mrc p15, 0, %0, c5, c0, 0": "=r" (fsr));
107 printf("DFAR: %08lx DFSR: %08lx\n", far, fsr);
108 } else if (v == EXCPTN_PABT) {
109 unsigned long far, fsr;
110 asm volatile("mrc p15, 0, %0, c6, c0, 2": "=r" (far));
111 asm volatile("mrc p15, 0, %0, c5, c0, 1": "=r" (fsr));
112 printf("IFAR: %08lx IFSR: %08lx\n", far, fsr);
113 }
114 dump_frame_stack((void *)regs->ARM_pc, (void *)regs->ARM_fp);
115 abort();
116 }
117
thread_info_init(struct thread_info * ti,unsigned int flags)118 void thread_info_init(struct thread_info *ti, unsigned int flags)
119 {
120 memset(ti, 0, sizeof(struct thread_info));
121 ti->cpu = mpidr_to_cpu(get_mpidr());
122 ti->flags = flags;
123 }
124
start_usr(void (* func)(void * arg),void * arg,unsigned long sp_usr)125 void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr)
126 {
127 sp_usr &= (~7UL); /* stack ptr needs 8-byte alignment */
128
129 thread_info_init(thread_info_sp(sp_usr), TIF_USER_MODE);
130 thread_info_sp(sp_usr)->pgtable = current_thread_info()->pgtable;
131
132 asm volatile(
133 "mrs r0, cpsr\n"
134 "bic r0, #" xstr(MODE_MASK) "\n"
135 "orr r0, #" xstr(USR_MODE) "\n"
136 "msr cpsr_c, r0\n"
137 "isb\n"
138 "mov r0, %0\n"
139 "mov sp, %1\n"
140 "mov pc, %2\n"
141 :: "r" (arg), "r" (sp_usr), "r" (func) : "r0");
142 }
143
is_user(void)144 bool is_user(void)
145 {
146 return current_thread_info()->flags & TIF_USER_MODE;
147 }
148
__mmu_enabled(void)149 bool __mmu_enabled(void)
150 {
151 return read_sysreg(SCTRL) & CR_M;
152 }
153