Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / arch / mips / dec / kn01-berr.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *      Bus error event handling code for DECstation/DECsystem 3100
4  *      and 2100 (KN01) systems equipped with parity error detection
5  *      logic.
6  *
7  *      Copyright (c) 2005  Maciej W. Rozycki
8  */
9
10 #include <linux/init.h>
11 #include <linux/interrupt.h>
12 #include <linux/kernel.h>
13 #include <linux/spinlock.h>
14 #include <linux/types.h>
15
16 #include <asm/inst.h>
17 #include <asm/irq_regs.h>
18 #include <asm/mipsregs.h>
19 #include <asm/page.h>
20 #include <asm/ptrace.h>
21 #include <asm/traps.h>
22 #include <linux/uaccess.h>
23
24 #include <asm/dec/kn01.h>
25
26
27 /* CP0 hazard avoidance. */
28 #define BARRIER                         \
29         __asm__ __volatile__(           \
30                 ".set   push\n\t"       \
31                 ".set   noreorder\n\t"  \
32                 "nop\n\t"               \
33                 ".set   pop\n\t")
34
35 /*
36  * Bits 7:0 of the Control Register are write-only -- the
37  * corresponding bits of the Status Register have a different
38  * meaning.  Hence we use a cache.  It speeds up things a bit
39  * as well.
40  *
41  * There is no default value -- it has to be initialized.
42  */
43 u16 cached_kn01_csr;
44 static DEFINE_RAW_SPINLOCK(kn01_lock);
45
46
47 static inline void dec_kn01_be_ack(void)
48 {
49         volatile u16 *csr = (void *)CKSEG1ADDR(KN01_SLOT_BASE + KN01_CSR);
50         unsigned long flags;
51
52         raw_spin_lock_irqsave(&kn01_lock, flags);
53
54         *csr = cached_kn01_csr | KN01_CSR_MEMERR;       /* Clear bus IRQ. */
55         iob();
56
57         raw_spin_unlock_irqrestore(&kn01_lock, flags);
58 }
59
60 static int dec_kn01_be_backend(struct pt_regs *regs, int is_fixup, int invoker)
61 {
62         volatile u32 *kn01_erraddr = (void *)CKSEG1ADDR(KN01_SLOT_BASE +
63                                                         KN01_ERRADDR);
64
65         static const char excstr[] = "exception";
66         static const char intstr[] = "interrupt";
67         static const char cpustr[] = "CPU";
68         static const char mreadstr[] = "memory read";
69         static const char readstr[] = "read";
70         static const char writestr[] = "write";
71         static const char timestr[] = "timeout";
72         static const char paritystr[] = "parity error";
73
74         int data = regs->cp0_cause & 4;
75         unsigned int __user *pc = (unsigned int __user *)regs->cp0_epc +
76                                   ((regs->cp0_cause & CAUSEF_BD) != 0);
77         union mips_instruction insn;
78         unsigned long entrylo, offset;
79         long asid, entryhi, vaddr;
80
81         const char *kind, *agent, *cycle, *event;
82         unsigned long address;
83
84         u32 erraddr = *kn01_erraddr;
85         int action = MIPS_BE_FATAL;
86
87         /* Ack ASAP, so that any subsequent errors get caught. */
88         dec_kn01_be_ack();
89
90         kind = invoker ? intstr : excstr;
91
92         agent = cpustr;
93
94         if (invoker)
95                 address = erraddr;
96         else {
97                 /* Bloody hardware doesn't record the address for reads... */
98                 if (data) {
99                         /* This never faults. */
100                         __get_user(insn.word, pc);
101                         vaddr = regs->regs[insn.i_format.rs] +
102                                 insn.i_format.simmediate;
103                 } else
104                         vaddr = (long)pc;
105                 if (KSEGX(vaddr) == CKSEG0 || KSEGX(vaddr) == CKSEG1)
106                         address = CPHYSADDR(vaddr);
107                 else {
108                         /* Peek at what physical address the CPU used. */
109                         asid = read_c0_entryhi();
110                         entryhi = asid & (PAGE_SIZE - 1);
111                         entryhi |= vaddr & ~(PAGE_SIZE - 1);
112                         write_c0_entryhi(entryhi);
113                         BARRIER;
114                         tlb_probe();
115                         /* No need to check for presence. */
116                         tlb_read();
117                         entrylo = read_c0_entrylo0();
118                         write_c0_entryhi(asid);
119                         offset = vaddr & (PAGE_SIZE - 1);
120                         address = (entrylo & ~(PAGE_SIZE - 1)) | offset;
121                 }
122         }
123
124         /* Treat low 256MB as memory, high -- as I/O. */
125         if (address < 0x10000000) {
126                 cycle = mreadstr;
127                 event = paritystr;
128         } else {
129                 cycle = invoker ? writestr : readstr;
130                 event = timestr;
131         }
132
133         if (is_fixup)
134                 action = MIPS_BE_FIXUP;
135
136         if (action != MIPS_BE_FIXUP)
137                 printk(KERN_ALERT "Bus error %s: %s %s %s at %#010lx\n",
138                         kind, agent, cycle, event, address);
139
140         return action;
141 }
142
143 int dec_kn01_be_handler(struct pt_regs *regs, int is_fixup)
144 {
145         return dec_kn01_be_backend(regs, is_fixup, 0);
146 }
147
148 irqreturn_t dec_kn01_be_interrupt(int irq, void *dev_id)
149 {
150         volatile u16 *csr = (void *)CKSEG1ADDR(KN01_SLOT_BASE + KN01_CSR);
151         struct pt_regs *regs = get_irq_regs();
152         int action;
153
154         if (!(*csr & KN01_CSR_MEMERR))
155                 return IRQ_NONE;                /* Must have been video. */
156
157         action = dec_kn01_be_backend(regs, 0, 1);
158
159         if (action == MIPS_BE_DISCARD)
160                 return IRQ_HANDLED;
161
162         /*
163          * FIXME: Find the affected processes and kill them, otherwise
164          * we must die.
165          *
166          * The interrupt is asynchronously delivered thus EPC and RA
167          * may be irrelevant, but are printed for a reference.
168          */
169         printk(KERN_ALERT "Fatal bus interrupt, epc == %08lx, ra == %08lx\n",
170                regs->cp0_epc, regs->regs[31]);
171         die("Unrecoverable bus error", regs);
172 }
173
174
175 void __init dec_kn01_be_init(void)
176 {
177         volatile u16 *csr = (void *)CKSEG1ADDR(KN01_SLOT_BASE + KN01_CSR);
178         unsigned long flags;
179
180         raw_spin_lock_irqsave(&kn01_lock, flags);
181
182         /* Preset write-only bits of the Control Register cache. */
183         cached_kn01_csr = *csr;
184         cached_kn01_csr &= KN01_CSR_STATUS | KN01_CSR_PARDIS | KN01_CSR_TXDIS;
185         cached_kn01_csr |= KN01_CSR_LEDS;
186
187         /* Enable parity error detection. */
188         cached_kn01_csr &= ~KN01_CSR_PARDIS;
189         *csr = cached_kn01_csr;
190         iob();
191
192         raw_spin_unlock_irqrestore(&kn01_lock, flags);
193
194         /* Clear any leftover errors from the firmware. */
195         dec_kn01_be_ack();
196 }