2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
26 #include <mach_debug.h>
28 #include <mach/ppc/thread_status.h>
29 #include <mach/vm_types.h>
30 #include <kern/thread.h>
31 #include <kern/misc_protos.h>
32 #include <ppc/proc_reg.h>
34 #include <ppc/misc_protos.h>
35 #include <ppc/exception.h>
38 * copyin/out_multiple - the assembler copyin/out functions jump to C for
39 * help when the copyin lies over a segment boundary. The C breaks
40 * down the copy into two sub-copies and re-calls the assembler with
41 * these sub-copies. Very rare occurrance. Warning: These functions are
42 * called whilst active_thread->thread_recover is still set.
45 extern boolean_t
copyin_multiple(const char *src
,
49 boolean_t
copyin_multiple(const char *src
,
54 vm_size_t first_count
;
55 boolean_t first_result
;
57 /* Assert that we've been called because of a segment boundary,
58 * this function is more expensive than the assembler, and should
59 * only be called in this difficult case.
61 assert(((vm_offset_t
)src
& 0xF0000000) !=
62 ((vm_offset_t
)(src
+ count
-1) & 0xF0000000));
64 /* TODO NMGS define sensible constants for segments, and apply
65 * to C and assembler (assembler is much harder)
67 midpoint
= (const char*) ((vm_offset_t
)(src
+ count
) & 0xF0000000);
68 first_count
= (midpoint
- src
);
70 first_result
= copyin(src
, dst
, first_count
);
72 /* If there was an error, stop now and return error */
73 if (first_result
!= 0)
76 /* otherwise finish the job and return result */
77 return copyin(midpoint
, dst
+ first_count
, count
-first_count
);
80 extern int copyout_multiple(const char *src
, char *dst
, vm_size_t count
);
82 int copyout_multiple(const char *src
, char *dst
, vm_size_t count
)
85 vm_size_t first_count
;
86 boolean_t first_result
;
88 /* Assert that we've been called because of a segment boundary,
89 * this function is more expensive than the assembler, and should
90 * only be called in this difficult case. For copyout, the
91 * segment boundary is on the dst
93 assert(((vm_offset_t
)dst
& 0xF0000000) !=
94 ((vm_offset_t
)(dst
+ count
- 1) & 0xF0000000));
96 /* TODO NMGS define sensible constants for segments, and apply
97 * to C and assembler (assembler is much harder)
99 midpoint
= (char *) ((vm_offset_t
)(dst
+ count
) & 0xF0000000);
100 first_count
= (midpoint
- dst
);
102 first_result
= copyout(src
, dst
, first_count
);
104 /* If there was an error, stop now and return error */
105 if (first_result
!= 0)
108 /* otherwise finish the job and return result */
110 return copyout(src
+ first_count
, midpoint
, count
-first_count
);
113 #define HAVE_ASSEMBLY_BCMP
114 #ifndef HAVE_ASSEMBLY_BCMP
130 #endif /* HAVE_ASSEMBLY_BCMP */
132 #define HAVE_ASSEMBLY_MEMCMP
133 #ifndef HAVE_ASSEMBLY_MEMCMP
136 register char *s1
, *s2
;
141 return (*--s1
- *--s2
);
144 #endif /* HAVE_ASSEMBLY_MEMCMP */
146 #define HAVE_ASSEMBLY_STRLEN
147 #ifndef HAVE_ASSEMBLY_STRLEN
150 * strlen returns the number of characters in "string" preceeding
151 * the terminating null character.
156 register const char *string
)
158 register const char *ret
= string
;
160 while (*string
++ != '\0')
162 return string
- 1 - ret
;
164 #endif /* HAVE_ASSEMBLY_STRLEN */
167 void regDump(struct ppc_saved_state
*state
)
171 for (i
=0; i
<32; i
++) {
173 kprintf("\n%4d :",i
);
174 kprintf(" %08x",*(&state
->r0
+i
));
178 kprintf("cr = 0x%08x\t\t",state
->cr
);
179 kprintf("xer = 0x%08x\n",state
->xer
);
180 kprintf("lr = 0x%08x\t\t",state
->lr
);
181 kprintf("ctr = 0x%08x\n",state
->ctr
);
182 kprintf("srr0(iar) = 0x%08x\t\t",state
->srr0
);
183 kprintf("srr1(msr) = 0x%08B\n",state
->srr1
,
184 "\x10\x11""EE\x12PR\x13""FP\x14ME\x15""FE0\x16SE\x18"
185 "FE1\x19""AL\x1a""EP\x1bIT\x1c""DT");
186 kprintf("mq = 0x%08x\t\t",state
->mq
);
187 kprintf("sr_copyin = 0x%08x\n",state
->sr_copyin
);
190 /* Be nice - for user tasks, generate some stack trace */
191 if (state
->srr1
& MASK(MSR_PR
)) {
192 char *addr
= (char*)state
->r1
;
194 for (i
= 0; i
< 8; i
++) {
195 if (addr
== (char*)NULL
)
197 if (!copyin(addr
,(char*)buf
, 2 * sizeof(int))) {
198 printf("0x%08x : %08x\n",buf
[0],buf
[1]);
199 addr
= (char*)buf
[0];
210 * invalidate_cache_for_io
212 * Takes cache of those requests which may require to flush the
213 * data cache first before invalidation.
218 invalidate_cache_for_io(vm_offset_t area
, unsigned count
, boolean_t phys
)
220 vm_offset_t aligned_start
, aligned_end
, end
;
222 /* For unaligned reads we need to flush any
223 * unaligned cache lines. We invalidate the
224 * rest as this is faster
227 aligned_start
= area
& ~(CACHE_LINE_SIZE
-1);
228 if (aligned_start
!= area
)
229 flush_dcache(aligned_start
, CACHE_LINE_SIZE
, phys
);
232 aligned_end
= (end
& ~(CACHE_LINE_SIZE
-1));
233 if (aligned_end
!= end
)
234 flush_dcache(aligned_end
, CACHE_LINE_SIZE
, phys
);
236 invalidate_dcache(area
, count
, phys
);
239 extern void tracecopyin(unsigned int src
, unsigned int dest
, unsigned int lgn
, unsigned int from
);
240 void tracecopyin(unsigned int src
, unsigned int dest
, unsigned int lgn
, unsigned int from
) {
245 printf("Copy in called from %08X: src=%08X; dest=%08X; lgn=%08X\n", from
, src
, dest
, lgn
);
250 extern void tracecopyout(unsigned int src
, unsigned int dest
, unsigned int lgn
, unsigned int from
);
251 void tracecopyout(unsigned int src
, unsigned int dest
, unsigned int lgn
, unsigned int from
) {
256 printf("Copy out called from %08X: src=%08X; dest=%08X; lgn=%08X\n", from
, src
, dest
, lgn
);
261 extern void tracecopystr(unsigned int src
, unsigned int dest
, unsigned int max
,
262 unsigned int lgn
, unsigned int from
);
263 void tracecopystr(unsigned int src
, unsigned int dest
, unsigned int max
,
264 unsigned int lgn
, unsigned int from
) {
269 printf("Copy in string called from %08X: src=%08X; dest=%08X; max=%08X; lgnadr=%08X\n",
270 from
, src
, dest
, max
, lgn
);
275 unsigned int ExceptionTrace
= 0;
276 extern void ExceptionTracePrint(struct savearea
*sv
, int type
);
277 void ExceptionTracePrint(struct savearea
*sv
, int type
) {
284 printf(" Trap from %08X, type=%08X, R0=%08X, R1=%08X, R3=%08X, LR=%08X, AST=%08X\n",
285 sv
->save_srr0
, sv
->save_exception
, sv
->save_r0
, sv
->save_r1
, sv
->save_r3
,
286 sv
->save_lr
, need_ast
[0]);
289 printf("Syscall from %08X, type=%08X, R0=%08X, R1=%08X, R3=%08X, LR=%08X, AST=%08X\n",
290 sv
->save_srr0
, sv
->save_exception
, sv
->save_r0
, sv
->save_r1
, sv
->save_r3
,
291 sv
->save_lr
, need_ast
[0]);