1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <asm/arcregs.h>
9*4882a593Smuzhiyun #include <asm/ptrace.h>
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun /* Bit values in STATUS32 */
12*4882a593Smuzhiyun #define E1_MASK (1 << 1) /* Level 1 interrupts enable */
13*4882a593Smuzhiyun #define E2_MASK (1 << 2) /* Level 2 interrupts enable */
14*4882a593Smuzhiyun
interrupt_init(void)15*4882a593Smuzhiyun int interrupt_init(void)
16*4882a593Smuzhiyun {
17*4882a593Smuzhiyun return 0;
18*4882a593Smuzhiyun }
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun /*
21*4882a593Smuzhiyun * returns true if interrupts had been enabled before we disabled them
22*4882a593Smuzhiyun */
disable_interrupts(void)23*4882a593Smuzhiyun int disable_interrupts(void)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun int status = read_aux_reg(ARC_AUX_STATUS32);
26*4882a593Smuzhiyun int state = (status & (E1_MASK | E2_MASK)) ? 1 : 0;
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun status &= ~(E1_MASK | E2_MASK);
29*4882a593Smuzhiyun /* STATUS32 register is updated indirectly with "FLAG" instruction */
30*4882a593Smuzhiyun __asm__("flag %0" : : "r" (status));
31*4882a593Smuzhiyun return state;
32*4882a593Smuzhiyun }
33*4882a593Smuzhiyun
enable_interrupts(void)34*4882a593Smuzhiyun void enable_interrupts(void)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun unsigned int status = read_aux_reg(ARC_AUX_STATUS32);
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun status |= E1_MASK | E2_MASK;
39*4882a593Smuzhiyun /* STATUS32 register is updated indirectly with "FLAG" instruction */
40*4882a593Smuzhiyun __asm__("flag %0" : : "r" (status));
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun
print_reg_file(long * reg_rev,int start_num)43*4882a593Smuzhiyun static void print_reg_file(long *reg_rev, int start_num)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun unsigned int i;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun /* Print 3 registers per line */
48*4882a593Smuzhiyun for (i = start_num; i < start_num + 25; i++) {
49*4882a593Smuzhiyun printf("r%02u: 0x%08lx\t", i, (unsigned long)*reg_rev);
50*4882a593Smuzhiyun if (((i + 1) % 3) == 0)
51*4882a593Smuzhiyun printf("\n");
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun /* Because pt_regs has registers reversed */
54*4882a593Smuzhiyun reg_rev--;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun /* Add new-line if none was inserted in the end of loop above */
58*4882a593Smuzhiyun if (((i + 1) % 3) != 0)
59*4882a593Smuzhiyun printf("\n");
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun
show_regs(struct pt_regs * regs)62*4882a593Smuzhiyun void show_regs(struct pt_regs *regs)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun printf("ECR:\t0x%08lx\n", regs->ecr);
65*4882a593Smuzhiyun printf("RET:\t0x%08lx\nBLINK:\t0x%08lx\nSTAT32:\t0x%08lx\n",
66*4882a593Smuzhiyun regs->ret, regs->blink, regs->status32);
67*4882a593Smuzhiyun printf("GP: 0x%08lx\t r25: 0x%08lx\t\n", regs->r26, regs->r25);
68*4882a593Smuzhiyun printf("BTA: 0x%08lx\t SP: 0x%08lx\t FP: 0x%08lx\n", regs->bta,
69*4882a593Smuzhiyun regs->sp, regs->fp);
70*4882a593Smuzhiyun printf("LPS: 0x%08lx\tLPE: 0x%08lx\tLPC: 0x%08lx\n", regs->lp_start,
71*4882a593Smuzhiyun regs->lp_end, regs->lp_count);
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun print_reg_file(&(regs->r0), 0);
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
bad_mode(struct pt_regs * regs)76*4882a593Smuzhiyun void bad_mode(struct pt_regs *regs)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun if (regs)
79*4882a593Smuzhiyun show_regs(regs);
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun panic("Resetting CPU ...\n");
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
do_memory_error(unsigned long address,struct pt_regs * regs)84*4882a593Smuzhiyun void do_memory_error(unsigned long address, struct pt_regs *regs)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun printf("Memory error exception @ 0x%lx\n", address);
87*4882a593Smuzhiyun bad_mode(regs);
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun
do_instruction_error(unsigned long address,struct pt_regs * regs)90*4882a593Smuzhiyun void do_instruction_error(unsigned long address, struct pt_regs *regs)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun printf("Instruction error exception @ 0x%lx\n", address);
93*4882a593Smuzhiyun bad_mode(regs);
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun
do_machine_check_fault(unsigned long address,struct pt_regs * regs)96*4882a593Smuzhiyun void do_machine_check_fault(unsigned long address, struct pt_regs *regs)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun printf("Machine check exception @ 0x%lx\n", address);
99*4882a593Smuzhiyun bad_mode(regs);
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
do_interrupt_handler(void)102*4882a593Smuzhiyun void do_interrupt_handler(void)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun printf("Interrupt fired\n");
105*4882a593Smuzhiyun bad_mode(0);
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun
do_itlb_miss(struct pt_regs * regs)108*4882a593Smuzhiyun void do_itlb_miss(struct pt_regs *regs)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun printf("I TLB miss exception\n");
111*4882a593Smuzhiyun bad_mode(regs);
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
do_dtlb_miss(struct pt_regs * regs)114*4882a593Smuzhiyun void do_dtlb_miss(struct pt_regs *regs)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun printf("D TLB miss exception\n");
117*4882a593Smuzhiyun bad_mode(regs);
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
do_tlb_prot_violation(unsigned long address,struct pt_regs * regs)120*4882a593Smuzhiyun void do_tlb_prot_violation(unsigned long address, struct pt_regs *regs)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun printf("TLB protection violation or misaligned access @ 0x%lx\n",
123*4882a593Smuzhiyun address);
124*4882a593Smuzhiyun bad_mode(regs);
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun
do_privilege_violation(struct pt_regs * regs)127*4882a593Smuzhiyun void do_privilege_violation(struct pt_regs *regs)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun printf("Privilege violation exception\n");
130*4882a593Smuzhiyun bad_mode(regs);
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun
do_trap(struct pt_regs * regs)133*4882a593Smuzhiyun void do_trap(struct pt_regs *regs)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun printf("Trap exception\n");
136*4882a593Smuzhiyun bad_mode(regs);
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun
do_extension(struct pt_regs * regs)139*4882a593Smuzhiyun void do_extension(struct pt_regs *regs)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun printf("Extension instruction exception\n");
142*4882a593Smuzhiyun bad_mode(regs);
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun #ifdef CONFIG_ISA_ARCV2
do_swi(struct pt_regs * regs)146*4882a593Smuzhiyun void do_swi(struct pt_regs *regs)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun printf("Software Interrupt exception\n");
149*4882a593Smuzhiyun bad_mode(regs);
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
do_divzero(unsigned long address,struct pt_regs * regs)152*4882a593Smuzhiyun void do_divzero(unsigned long address, struct pt_regs *regs)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun printf("Division by zero exception @ 0x%lx\n", address);
155*4882a593Smuzhiyun bad_mode(regs);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
do_dcerror(struct pt_regs * regs)158*4882a593Smuzhiyun void do_dcerror(struct pt_regs *regs)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun printf("Data cache consistency error exception\n");
161*4882a593Smuzhiyun bad_mode(regs);
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
do_maligned(unsigned long address,struct pt_regs * regs)164*4882a593Smuzhiyun void do_maligned(unsigned long address, struct pt_regs *regs)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun printf("Misaligned data access exception @ 0x%lx\n", address);
167*4882a593Smuzhiyun bad_mode(regs);
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun #endif
170