This source file includes following definitions.
- prom_probe_memory
- probe_memory
- sparc_lvl15_nmi
- do_sparc_fault
- do_sparc_winfault
1
2
3
4
5
6
7 #include <linux/string.h>
8 #include <linux/types.h>
9 #include <linux/ptrace.h>
10 #include <linux/mman.h>
11 #include <linux/signal.h>
12 #include <linux/mm.h>
13
14 #include <asm/system.h>
15 #include <asm/segment.h>
16 #include <asm/openprom.h>
17 #include <asm/idprom.h>
18 #include <asm/page.h>
19 #include <asm/pgtable.h>
20 #include <asm/memreg.h>
21 #include <asm/openprom.h>
22 #include <asm/oplib.h>
23 #include <asm/traps.h>
24 #include <asm/kdebug.h>
25
26 #define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0]))
27
28 extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
29 extern int prom_node_root;
30
31 extern void die_if_kernel(char *,struct pt_regs *,long);
32
33 struct linux_romvec *romvec;
34
35
36
37 int tbase_needs_unmapping;
38
39
40
41
42
43 int num_segmaps, num_contexts;
44 int invalid_segment;
45
46
47
48 int vac_size, vac_linesize, vac_do_hw_vac_flushes;
49 int vac_entries_per_context, vac_entries_per_segment;
50 int vac_entries_per_page;
51
52
53
54
55
56
57 #undef CONFIG_TEST_VERIFY_AREA
58
59
60 int prom_probe_memory (void)
61 {
62 register struct linux_mlist_v0 *mlist;
63 register unsigned long bytes, base_paddr, tally;
64 register int i;
65
66 i = 0;
67 mlist= *prom_meminfo()->v0_available;
68 bytes = tally = mlist->num_bytes;
69 base_paddr = (unsigned long) mlist->start_adr;
70
71 sp_banks[0].base_addr = base_paddr;
72 sp_banks[0].num_bytes = bytes;
73
74 while (mlist->theres_more != (void *) 0){
75 i++;
76 mlist = mlist->theres_more;
77 bytes = mlist->num_bytes;
78 tally += bytes;
79 if (i >= SPARC_PHYS_BANKS-1) {
80 printk ("The machine has more banks that this kernel can support\n"
81 "Increase the SPARC_PHYS_BANKS setting (currently %d)\n",
82 SPARC_PHYS_BANKS);
83 i = SPARC_PHYS_BANKS-1;
84 break;
85 }
86
87 sp_banks[i].base_addr = (unsigned long) mlist->start_adr;
88 sp_banks[i].num_bytes = mlist->num_bytes;
89 }
90
91 i++;
92 sp_banks[i].base_addr = 0xdeadbeef;
93 sp_banks[i].num_bytes = 0;
94
95 return tally;
96 }
97
98
99
100
101 unsigned long
102 probe_memory(void)
103 {
104 int total;
105
106 total = prom_probe_memory();
107
108
109 return total;
110 }
111
112
113 asmlinkage void sparc_lvl15_nmi(struct pt_regs *regs, unsigned long serr,
114 unsigned long svaddr, unsigned long aerr,
115 unsigned long avaddr)
116 {
117 printk("FAULT: NMI received\n");
118 printk("SREGS: Synchronous Error %08lx\n", serr);
119 printk(" Synchronous Vaddr %08lx\n", svaddr);
120 printk(" Asynchronous Error %08lx\n", aerr);
121 printk(" Asynchronous Vaddr %08lx\n", avaddr);
122 printk("REGISTER DUMP:\n");
123 show_regs(regs);
124 prom_halt();
125 }
126
127
128 asmlinkage void do_sparc_fault(struct pt_regs *regs, unsigned long tbr)
129 {
130 struct vm_area_struct *vma;
131 unsigned long address, error_code, trap_type;
132 unsigned long from_user;
133
134 from_user = (((regs->psr & PSR_PS) >> 4) ^ FAULT_CODE_USER);
135 if(get_fault_info(&address, &error_code, from_user))
136 goto bad_area;
137 trap_type = ((tbr>>4)&0xff);
138 if(trap_type == SP_TRAP_TFLT) {
139
140 address = regs->pc;
141 error_code = (from_user);
142 } else if(trap_type != SP_TRAP_DFLT)
143 panic("Bad sparc trap, trap_type not data or text fault...");
144
145
146
147
148
149
150
151
152 if(!from_user && address >= KERNBASE) {
153 update_mmu_cache(0, address, __pte(0));
154 return;
155 }
156
157 vma = find_vma(current, address);
158 if(!vma)
159 goto bad_area;
160 if(vma->vm_start <= address)
161 goto good_area;
162 if(!(vma->vm_flags & VM_GROWSDOWN))
163 goto bad_area;
164 if(expand_stack(vma, address))
165 goto bad_area;
166
167
168
169
170 good_area:
171 if(error_code & FAULT_CODE_WRITE) {
172 if(!(vma->vm_flags & VM_WRITE))
173 goto bad_area;
174 } else {
175
176 if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
177 goto bad_area;
178 }
179 handle_mm_fault(vma, address, error_code & FAULT_CODE_WRITE);
180 return;
181
182
183
184
185 bad_area:
186 if(error_code & FAULT_CODE_USER) {
187 current->tss.sig_address = address;
188 current->tss.sig_desc = SUBSIG_NOMAPPING;
189 send_sig(SIGSEGV, current, 1);
190 return;
191 }
192
193 if (wp_works_ok < 0 && address == 0x0) {
194 wp_works_ok = 1;
195 printk("This Sparc honours the WP bit even when in supervisor mode. "
196 "Good.\n");
197
198 regs->pc = regs->npc;
199 regs->npc += 4;
200 return;
201 }
202 if((unsigned long) address < PAGE_SIZE) {
203 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
204 } else
205 printk(KERN_ALERT "Unable to handle kernel paging request");
206 printk(" at virtual address %08lx\n",address);
207 printk("At PC %08lx nPC %08lx\n", (unsigned long) regs->pc,
208 (unsigned long) regs->npc);
209 printk(KERN_ALERT "current->tss.pgd_ptr = %08lx\n",
210 (unsigned long) current->tss.pgd_ptr);
211 show_regs(regs);
212 panic("KERNAL FAULT");
213 }
214
215
216
217
218
219
220
221
222
223
224 extern void show_regwindow(struct reg_window *);
225 asmlinkage void do_sparc_winfault(struct pt_regs *regs, int push)
226 {
227 int wincount = 0;
228 int signal = 0;
229 struct thread_struct *tsp = ¤t->tss;
230
231 flush_user_windows();
232 #ifdef DEBUG_WINFAULT
233 {
234 int i;
235 printk("%s[%d]wfault<%d>: WINDOW DUMP --> ", current->comm,
236 current->pid, push);
237 if(push==1)
238 for(i = 0; i < tsp->w_saved; i++)
239 printk("w[%d]sp<%08lx>, ",
240 i, tsp->rwbuf_stkptrs[i]);
241 else
242 printk("w[0]sp<%08lx>", regs->u_regs[UREG_FP]);
243 if(push!=2)
244 printk("\n");
245 }
246 #endif
247 if(push==1) {
248
249 while(wincount < tsp->w_saved) {
250 if ((tsp->rwbuf_stkptrs[wincount] & 7) ||
251 (tsp->rwbuf_stkptrs[wincount] > KERNBASE) ||
252 verify_area(VERIFY_WRITE,
253 (char *) tsp->rwbuf_stkptrs[wincount],
254 sizeof(struct reg_window))) {
255 signal = SIGILL;
256 break;
257 }
258
259 memcpy((char *) tsp->rwbuf_stkptrs[wincount],
260 (char *)&tsp->reg_window[wincount],
261 sizeof(struct reg_window));
262 wincount++;
263 }
264 } else {
265
266
267
268
269
270 if((regs->u_regs[UREG_FP] & 7) ||
271 (regs->u_regs[UREG_FP] > KERNBASE) ||
272 verify_area(VERIFY_READ,
273 (char *) regs->u_regs[UREG_FP],
274 sizeof(struct reg_window)))
275 signal = SIGILL;
276 else
277 memcpy((char *)&tsp->reg_window[0],
278 (char *) regs->u_regs[UREG_FP],
279 sizeof(struct reg_window));
280 if(push==2 && !signal) {
281 unsigned long sp = tsp->reg_window[0].ins[6];
282 #ifdef DEBUG_WINFAULT
283 printk(", w[1]sp<%08lx>\n", sp);
284 show_regwindow(&tsp->reg_window[0]);
285 #endif
286 if((sp & 7) || (sp > KERNBASE) ||
287 verify_area(VERIFY_READ, (char *) sp,
288 sizeof(struct reg_window)))
289 signal = SIGILL;
290 else
291 memcpy((char *)&tsp->reg_window[1],
292 (char *) sp, sizeof(struct reg_window));
293 }
294 }
295 if(signal) {
296 printk("%s[%d]: User has trashed stack pointer pc<%08lx>sp<%08lx>\n",
297 current->comm, current->pid, regs->pc, regs->u_regs[UREG_FP]);
298 tsp->sig_address = regs->pc;
299 tsp->sig_desc = SUBSIG_STACK;
300 send_sig(signal, current, 1);
301 } else
302 tsp->w_saved = 0;
303 }