]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ppc/Diagnostics.c
xnu-517.7.21.tar.gz
[apple/xnu.git] / osfmk / ppc / Diagnostics.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
e5568f75
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
1c79356b 11 *
e5568f75
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
e5568f75
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * @OSF_FREE_COPYRIGHT@
24 */
25/*
26 * @APPLE_FREE_COPYRIGHT@
27 */
28
29/*
30 * Author: Bill Angell, Apple
31 * Date: 9/auht-aught
32 *
33 * Random diagnostics
34 */
35
36
37#include <kern/machine.h>
38#include <kern/processor.h>
39#include <mach/machine.h>
40#include <mach/processor_info.h>
41#include <mach/mach_types.h>
42#include <mach/boolean.h>
43#include <kern/thread.h>
44#include <kern/task.h>
45#include <mach/vm_param.h>
46#include <vm/vm_kern.h>
47#include <vm/vm_map.h>
48#include <vm/vm_page.h>
49#include <vm/pmap.h>
50#include <ppc/exception.h>
51#include <ppc/Firmware.h>
52#include <ppc/low_trace.h>
53#include <ppc/db_low_trace.h>
54#include <ppc/mappings.h>
55#include <ppc/pmap.h>
56#include <ppc/mem.h>
1c79356b
A
57#include <ppc/savearea.h>
58#include <ppc/Diagnostics.h>
59#include <ppc/machine_cpu.h>
60#include <pexpert/pexpert.h>
55e303ae 61#include <console/video_console.h>
9bccf70c 62#include <ppc/trap.h>
0b4e3aa0
A
63
64extern struct vc_info vinfo;
1c79356b 65
9bccf70c 66kern_return_t testPerfTrap(int trapno, struct savearea *ss,
55e303ae 67 unsigned int dsisr, addr64_t dar);
9bccf70c 68
1c79356b
A
69int diagCall(struct savearea *save) {
70
71 union {
72 unsigned long long tbase;
73 unsigned int tb[2];
74 } ttt, adj;
75 natural_t tbu, tbu2, tbl;
76 struct per_proc_info *per_proc; /* Area for my per_proc address */
55e303ae 77 int cpu, ret;
9bccf70c 78 unsigned int tstrt, tend, temp, temp2;
55e303ae
A
79 addr64_t src, snk;
80 uint64_t scom, hid1, hid4, srrwrk, stat;
81 scomcomm sarea;
1c79356b
A
82
83 if(!(dgWork.dgFlags & enaDiagSCs)) return 0; /* If not enabled, cause an exception */
84
85 switch(save->save_r3) { /* Select the routine */
86
87/*
88 * Adjust the timebase for drift recovery testing
89 */
90 case dgAdjTB: /* Adjust the timebase */
91
92 adj.tb[0] = 0; /* Clear high part */
93 adj.tb[1] = save->save_r4; /* Set low order */
94 if(adj.tb[1] & 0x80000000) adj.tb[0] = 0xFFFFFFFF; /* Propagate sign bit */
95
96 do { /* Read current time */
97 asm volatile(" mftbu %0" : "=r" (tbu));
98 asm volatile(" mftb %0" : "=r" (tbl));
99 asm volatile(" mftbu %0" : "=r" (tbu2));
100 } while (tbu != tbu2);
101
102 ttt.tb[0] = tbu; /* Set high */
103 ttt.tb[1] = tbl; /* Set low */
104
105 ttt.tbase = ttt.tbase + adj.tbase; /* Increment or decrement the TB */
106
107 tbu = ttt.tb[0]; /* Save in regular variable */
108 tbl = ttt.tb[1]; /* Save in regular variable */
109
110 mttb(0); /* Set low to keep from ticking */
111 mttbu(tbu); /* Set adjusted high */
112 mttb(tbl); /* Set adjusted low */
113
114 return -1; /* Return no AST checking... */
115
116/*
117 * Return physical address of a page
118 */
119 case dgLRA:
120
55e303ae 121 save->save_r3 = pmap_find_phys(current_act()->map->pmap, save->save_r4); /* Get read address */
1c79356b
A
122
123 return -1; /* Return no AST checking... */
124
125/*
126 * Copy physical to virtual
127 */
128 case dgpcpy:
129
55e303ae
A
130
131#if 1
132 src = (save->save_r4 << 32) | (0x00000000FFFFFFFFULL & save->save_r5); /* Merge into 64-bit */
133 snk = (save->save_r6 << 32) | (0x00000000FFFFFFFFULL & save->save_r7); /* Merge into 64-bit */
134 save->save_r3 = copypv(src, snk, save->save_r8, save->save_r9); /* Copy the physical page */
1c79356b
A
135#endif
136 return 1; /* Return and check for ASTs... */
137
55e303ae
A
138/*
139 * Read/Write physical memory
140 */
141 case dgprw:
142
143 src = (save->save_r5 << 32) | (0x00000000FFFFFFFFULL & save->save_r6); /* Merge into 64-bit */
144
145 switch(save->save_r4) { /* Select the actual function */
146
147 case 0:
148 save->save_r3 = (uint64_t)ml_phys_read_byte((unsigned int)src);
149 break;
150
151 case 1:
152 save->save_r3 = (uint64_t)ml_phys_read_byte_64(src);
153 break;
154
155 case 2:
156 save->save_r3 = (uint64_t)ml_phys_read((unsigned int)src);
157 break;
158
159 case 3:
160 save->save_r3 = (uint64_t)ml_phys_read_64(src);
161 break;
162
163 case 4:
164 ml_phys_write_byte((unsigned int)src, (unsigned int)save->save_r7);
165 break;
166
167 case 5:
168 ml_phys_write_byte_64(src, (unsigned int)save->save_r7);
169 break;
170
171 case 6:
172 ml_phys_write((unsigned int)src, (unsigned int)save->save_r7);
173 break;
174
175 case 7:
176 ml_phys_write_64(src, (unsigned int)save->save_r7);
177 break;
178 }
179
180 return 1; /* Return and check for ASTs... */
181
1c79356b
A
182
183/*
184 * Soft reset processor
185 */
186 case dgreset:
187
188 cpu = save->save_r4; /* Get the requested CPU number */
189
190 if(cpu >= NCPUS) { /* Check for bogus cpu */
191 save->save_r3 = KERN_FAILURE; /* Set failure */
192 return 1;
193 }
194
195 if(!machine_slot[cpu].running) return KERN_FAILURE; /* It is not running */
196
197 per_proc = &per_proc_info[cpu]; /* Point to the processor */
198
199 (void)PE_cpu_start(per_proc->cpu_id,
200 per_proc->start_paddr, (vm_offset_t)per_proc);
201
202 save->save_r3 = KERN_SUCCESS; /* Set scuuess */
203
204 return 1; /* Return and check for ASTs... */
205
0b4e3aa0
A
206/*
207 * Force cache flush
208 */
9bccf70c 209 case dgFlush:
0b4e3aa0 210
0b4e3aa0 211 cacheInit(); /* Blow cache */
0b4e3aa0
A
212 return 1; /* Return and check for ASTs... */
213
1c79356b
A
214/*
215 * various hack tests
216 */
217 case dgtest:
218
9bccf70c
A
219 if(save->save_r4) perfTrapHook = testPerfTrap;
220 else perfTrapHook = 0;
1c79356b
A
221
222 return 1; /* Return and check for ASTs... */
223
224
0b4e3aa0
A
225
226/*
227 * Create a physical block map into the current task
228 * Don't bother to check for any errors.
229 * parms - vaddr, paddr, size, prot, attributes
230 */
231 case dgBMphys:
55e303ae
A
232
233 pmap_map_block(current_act()->map->pmap, (addr64_t)save->save_r4, /* Map in the block */
234 save->save_r5, save->save_r6, save->save_r7, save->save_r8, 0);
0b4e3aa0
A
235
236 return 1; /* Return and check for ASTs... */
237
238
239/*
240 * Remove any mapping from the current task
241 * Don't bother to check for any errors.
242 * parms - vaddr
243 */
244 case dgUnMap:
245
246 (void)mapping_remove(current_act()->map->pmap, save->save_r4); /* Remove mapping */
247 return 1; /* Return and check for ASTs... */
9bccf70c
A
248
249
250/*
251 * Allows direct control of alignment handling.
252 *
55e303ae 253 * The bottom bit of the parameter is used to set the control bit, enaNotifyEM.
9bccf70c
A
254 */
255 case dgAlign:
256
55e303ae 257 temp = dgWork.dgFlags; /* Save the old values */
de355530 258
55e303ae
A
259 temp2 = (save->save_r4 & 1) << (31 - enaNotifyEMb); /* Move parms into flag format */
260 dgWork.dgFlags = (temp & ~enaNotifyEM) | temp2; /* Set the flag */
261
262 save->save_r3 = (temp >> (31 - enaNotifyEMb)) & 1; /* Return the original */
9bccf70c
A
263
264 return 1; /* Return and check for ASTs... */
0b4e3aa0
A
265
266/*
267 * Return info for boot screen
268 */
269 case dgBootScreen:
270
0b4e3aa0 271 ml_set_interrupts_enabled(1);
55e303ae
A
272 (void)copyout((char *)&vinfo, CAST_DOWN(char *, save->save_r4), sizeof(struct vc_info)); /* Copy out the video info */
273 ml_set_interrupts_enabled(0);
274 return 1; /* Return and check for ASTs... */
275
276/*
277 * Don't return info for boot screen
278 */
279 case dgCPNull:
280
281 ml_set_interrupts_enabled(1);
282 (void)copyout((char *)&vinfo, CAST_DOWN(char *, save->save_r4), 0); /* Copy out nothing */
0b4e3aa0 283 ml_set_interrupts_enabled(0);
0b4e3aa0
A
284 return 1; /* Return and check for ASTs... */
285
55e303ae
A
286/*
287 * Test machine check handler - only on 64-bit machines
288 */
289 case dgmck:
290 if(!(per_proc_info[0].pf.Available & pf64Bit)) return 0; /* Leave if not correct machine */
291
292 fwEmMck(save->save_r4, save->save_r5, save->save_r6, save->save_r7, save->save_r8, save->save_r9); /* Start injecting */
293
294 return -1; /* Return and don't check for ASTs... */
295
296/*
297 * Set 64-bit on or off - only on 64-bit machines
298 */
299 case dg64:
300 if(!(per_proc_info[0].pf.Available & pf64Bit)) return 0; /* Leave if not correct machine */
301
302 srrwrk = save->save_srr1 >> 63; /* Save the old 64-bit bit */
303
304 save->save_srr1 = (save->save_srr1 & 0x7FFFFFFFFFFFFFFFULL) | (save->save_r4 << 63); /* Set the requested mode */
305 save->save_r3 = srrwrk; /* Return the old value */
306
307 return -1; /* Return and don't check for ASTs... */
308
309/*
310 * Test the probe read function
311 */
312
313 case dgProbeRead:
314
315 src = (save->save_r4 << 32) | (0x00000000FFFFFFFFULL & save->save_r5); /* Merge into 64-bit */
316 save->save_r3 = ml_probe_read_64(src, &temp); /* Try the address */
317 save->save_r4 = temp; /* Return the data */
318 return -1; /* Regurn and don't check for ASTs */
319
320/*
321 * Do perf monitor stuff
322 */
323
324 case dgPerfMon:
0b4e3aa0 325
55e303ae
A
326 setPmon(save->save_r4, save->save_r5); /* Go load up MMCR0 and MMCR1 */
327 return -1; /* Regurn and don't check for ASTs */
328
329/*
330 * Map a page
331 * Don't bother to check for any errors.
332 * parms - vaddr, paddr, prot, attributes
333 */
334 case dgMapPage:
335
336 (void)mapping_map(current_act()->map->pmap, /* Map in the page */
337 (addr64_t)(((save->save_r5 & 0xFFFFFFFF) << 32) | (save->save_r5 & 0xFFFFFFFF)), save->save_r6, 0, 1, VM_PROT_READ|VM_PROT_WRITE);
338
339 return -1; /* Return and check for ASTs... */
340
341/*
342 * SCOM interface
343 * parms - pointer to scomcomm
344 */
345 case dgScom:
346
347 ret = copyin((unsigned int)(save->save_r4), &sarea, sizeof(scomcomm)); /* Get the data */
348 if(ret) return 0; /* Copyin failed - return an exception */
349
350 sarea.scomstat = 0xFFFFFFFFFFFFFFFFULL; /* Clear status */
351 cpu = cpu_number(); /* Get us */
352
353 if((sarea.scomcpu < NCPUS) && machine_slot[sarea.scomcpu].running) {
483a1d10
A
354 if(sarea.scomcpu == cpu) { /* Is it us? */
355 if(sarea.scomfunc) { /* Are we writing */
356 sarea.scomstat = ml_scom_write(sarea.scomreg, sarea.scomdata); /* Write scom */
357 }
358 else {
359 sarea.scomstat = ml_scom_read(sarea.scomreg, &sarea.scomdata); /* Read scom */
360 }
361 }
55e303ae
A
362 else { /* Otherwise, tell the other processor */
363 (void)cpu_signal(sarea.scomcpu, SIGPcpureq, CPRQscom ,(unsigned int)&sarea); /* Ask him to do this */
364 (void)hw_cpu_sync((unsigned long)&sarea.scomstat, LockTimeOut); /* Wait for the other processor to get its temperature */
365 }
366 }
367
368 ret = copyout(&sarea, (unsigned int)(save->save_r4), sizeof(scomcomm)); /* Get the data */
369 if(ret) return 0; /* Copyin failed - return an exception */
370
371 return -1; /* Return and check for ASTs... */
372
373
1c79356b
A
374 default: /* Handle invalid ones */
375 return 0; /* Return an exception */
376
9bccf70c
A
377 }
378
379};
380
381kern_return_t testPerfTrap(int trapno, struct savearea *ss,
55e303ae 382 unsigned int dsisr, addr64_t dar) {
9bccf70c
A
383
384 if(trapno != T_ALIGNMENT) return KERN_FAILURE;
385
386 kprintf("alignment exception at %08X, srr1 = %08X, dsisr = %08X, dar = %08X\n", ss->save_srr0,
387 ss->save_srr1, dsisr, dar);
388
389 return KERN_SUCCESS;
1c79356b
A
390
391}