]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kdp/ml/ppc/kdp_vm.c
xnu-517.tar.gz
[apple/xnu.git] / osfmk / kdp / ml / ppc / kdp_vm.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25#include <mach/mach_types.h>
26#include <mach/vm_attributes.h>
27#include <mach/vm_param.h>
28
29#include <vm/pmap.h>
30
31#include <ppc/proc_reg.h>
32#include <ppc/machparam.h>
33#include <ppc/mem.h>
34#include <ppc/pmap.h>
1c79356b
A
35#include <ppc/mappings.h>
36
55e303ae
A
37#include <mach/thread_status.h>
38#include <mach-o/loader.h>
39#include <mach/vm_region.h>
40#include <mach/vm_statistics.h>
41
42#include <vm/vm_kern.h>
43#include <kdp/kdp_core.h>
44#include <kdp/kdp_udp.h>
45#include <kdp/kdp_internal.h>
46
47
1c79356b
A
48pmap_t kdp_pmap=0;
49boolean_t kdp_trans_off=0;
55e303ae 50boolean_t kdp_read_io =0;
1c79356b 51
1c79356b
A
52unsigned kdp_vm_read( caddr_t, caddr_t, unsigned);
53unsigned kdp_vm_write( caddr_t, caddr_t, unsigned);
54
1c79356b 55
55e303ae
A
56typedef struct {
57 int flavor; /* the number for this flavor */
58 int count; /* count of ints in this flavor */
59} mythread_state_flavor_t;
de355530 60
55e303ae
A
61/* These will need to be uncommented and completed
62 *if we support other architectures
63 */
de355530 64
55e303ae
A
65/*
66#if defined (__ppc__)
67*/
68static mythread_state_flavor_t thread_flavor_array[] = {
69 {PPC_THREAD_STATE , PPC_THREAD_STATE_COUNT},
70};
71/*
72#elif defined (__i386__)
73mythread_state_flavor_t thread_flavor_array [] = {
74 {i386_THREAD_STATE, i386_THREAD_STATE_COUNT},
75};
76#else
77#error architecture not supported
78#endif
79*/
80static int kdp_mynum_flavors = 1;
81static int MAX_TSTATE_FLAVORS = 1;
de355530 82
55e303ae
A
83typedef struct {
84 vm_offset_t header;
85 int hoffset;
86 mythread_state_flavor_t *flavors;
87 int tstate_size;
88} tir_t;
de355530 89
55e303ae 90unsigned int not_in_kdp = 1; /* Cleared when we begin to access vm functions in kdp */
de355530 91
55e303ae 92char command_buffer[512];
1c79356b 93
55e303ae 94static struct vm_object test_object;
1c79356b 95
de355530
A
96/*
97 *
98 */
55e303ae
A
99addr64_t kdp_vtophys(
100 pmap_t pmap,
101 addr64_t va)
de355530 102{
55e303ae
A
103 addr64_t pa;
104 ppnum_t pp;
105
106 pp = pmap_find_phys(pmap, va); /* Get the page number */
107 if(!pp) return 0; /* Just return if no translation */
108
109 pa = ((addr64_t)pp << 12) | (va & 0x0000000000000FFFULL); /* Shove in the page offset */
110 return(pa);
de355530
A
111}
112
1c79356b 113/*
55e303ae
A
114 * Note that kdp_vm_read() does not translate the destination address.Therefore
115 * there's an implicit assumption that the destination will be a statically
116 * allocated structure, since those map to the same phys. and virt. addresses
1c79356b
A
117 */
118unsigned kdp_vm_read(
119 caddr_t src,
120 caddr_t dst,
121 unsigned len)
122{
55e303ae
A
123 addr64_t cur_virt_src, cur_virt_dst;
124 addr64_t cur_phys_src;
1c79356b 125 unsigned resid, cnt;
55e303ae
A
126 unsigned int dummy;
127 pmap_t pmap;
1c79356b
A
128
129#ifdef KDP_VM_READ_DEBUG
130 kprintf("kdp_vm_read1: src %x dst %x len %x - %08X %08X\n", src, dst, len, ((unsigned long *)src)[0], ((unsigned long *)src)[1]);
131#endif
55e303ae
A
132
133 cur_virt_src = (addr64_t)((unsigned int)src);
134 cur_virt_dst = (addr64_t)((unsigned int)dst);
135
1c79356b 136 if (kdp_trans_off) {
55e303ae
A
137
138
139 resid = len; /* Get the length to copy */
1c79356b
A
140
141 while (resid != 0) {
55e303ae
A
142
143 if(kdp_read_io == 0)
144 if(!mapping_phys_lookup((ppnum_t)(cur_virt_src >> 12), &dummy)) return 0; /* Can't read where there's not any memory */
145
146 cnt = 4096 - (cur_virt_src & 0xFFF); /* Get length left on page */
147
1c79356b 148 if (cnt > resid) cnt = resid;
55e303ae
A
149
150 bcopy_phys(cur_virt_src, cur_virt_dst, cnt); /* Copy stuff over */
151
152 cur_virt_src += cnt;
153 cur_virt_dst += cnt;
1c79356b
A
154 resid -= cnt;
155 }
55e303ae 156
1c79356b 157 } else {
55e303ae 158
1c79356b
A
159 resid = len;
160
55e303ae
A
161 if(kdp_pmap) pmap = kdp_pmap; /* If special pmap, use it */
162 else pmap = kernel_pmap; /* otherwise, use kernel's */
163
1c79356b 164 while (resid != 0) {
55e303ae
A
165
166 if((cur_phys_src = kdp_vtophys(pmap, cur_virt_src)) == 0) goto exit;
167 if(kdp_read_io == 0)
168 if(!mapping_phys_lookup((ppnum_t)(cur_phys_src >> 12), &dummy)) goto exit; /* Can't read where there's not any memory */
169
170 cnt = 4096 - (cur_virt_src & 0xFFF); /* Get length left on page */
1c79356b 171 if (cnt > resid) cnt = resid;
55e303ae 172
1c79356b 173#ifdef KDP_VM_READ_DEBUG
55e303ae
A
174 kprintf("kdp_vm_read2: pmap %08X, virt %016LLX, phys %016LLX\n",
175 pmap, cur_virt_src, cur_phys_src);
1c79356b 176#endif
55e303ae
A
177
178 bcopy_phys(cur_phys_src, cur_virt_dst, cnt); /* Copy stuff over */
179
1c79356b
A
180 cur_virt_src +=cnt;
181 cur_virt_dst +=cnt;
182 resid -= cnt;
183 }
184 }
185exit:
186#ifdef KDP_VM_READ_DEBUG
187 kprintf("kdp_vm_read: ret %08X\n", len-resid);
188#endif
55e303ae 189 return (len - resid);
1c79356b
A
190}
191
192/*
193 *
194 */
195unsigned kdp_vm_write(
196 caddr_t src,
197 caddr_t dst,
198 unsigned len)
199{
55e303ae
A
200 addr64_t cur_virt_src, cur_virt_dst;
201 addr64_t cur_phys_src, cur_phys_dst;
202 unsigned resid, cnt, cnt_src, cnt_dst;
1c79356b
A
203
204#ifdef KDP_VM_WRITE_DEBUG
205 printf("kdp_vm_write: src %x dst %x len %x - %08X %08X\n", src, dst, len, ((unsigned long *)src)[0], ((unsigned long *)src)[1]);
206#endif
207
55e303ae
A
208 cur_virt_src = (addr64_t)((unsigned int)src);
209 cur_virt_dst = (addr64_t)((unsigned int)dst);
210
1c79356b
A
211 resid = len;
212
213 while (resid != 0) {
214 if ((cur_phys_dst = kdp_vtophys(kernel_pmap, cur_virt_dst)) == 0)
215 goto exit;
216 if ((cur_phys_src = kdp_vtophys(kernel_pmap, cur_virt_src)) == 0)
217 goto exit;
218
219 cnt_src = ((cur_phys_src + NBPG) & (-NBPG)) - cur_phys_src;
220 cnt_dst = ((cur_phys_dst + NBPG) & (-NBPG)) - cur_phys_dst;
221
222 if (cnt_src > cnt_dst)
223 cnt = cnt_dst;
224 else
225 cnt = cnt_src;
226 if (cnt > resid)
227 cnt = resid;
228
55e303ae
A
229 bcopy_phys(cur_phys_src, cur_phys_dst, cnt); /* Copy stuff over */
230 sync_cache64(cur_phys_dst, cnt); /* Sync caches */
1c79356b
A
231
232 cur_virt_src +=cnt;
233 cur_virt_dst +=cnt;
234 resid -= cnt;
235 }
236exit:
55e303ae
A
237 return (len - resid);
238}
239
240
241static void
242kern_collectth_state(thread_act_t th_act, tir_t *t)
243{
244 vm_offset_t header;
245 int hoffset, i ;
246 mythread_state_flavor_t *flavors;
247 struct thread_command *tc;
248 /*
249 * Fill in thread command structure.
250 */
251 header = t->header;
252 hoffset = t->hoffset;
253 flavors = t->flavors;
254
255 tc = (struct thread_command *) (header + hoffset);
256 tc->cmd = LC_THREAD;
257 tc->cmdsize = sizeof(struct thread_command)
258 + t->tstate_size;
259 hoffset += sizeof(struct thread_command);
260 /*
261 * Follow with a struct thread_state_flavor and
262 * the appropriate thread state struct for each
263 * thread state flavor.
264 */
265 for (i = 0; i < kdp_mynum_flavors; i++) {
266 *(mythread_state_flavor_t *)(header+hoffset) =
267 flavors[i];
268 hoffset += sizeof(mythread_state_flavor_t);
269
270 if (machine_thread_get_kern_state(th_act, flavors[i].flavor,
271 (thread_state_t) (header+hoffset),
272 &flavors[i].count) != KERN_SUCCESS)
273 printf ("Failure in machine_thread_get_kern_state()\n");
274 hoffset += flavors[i].count*sizeof(int);
275 }
276
277 t->hoffset = hoffset;
1c79356b
A
278}
279
55e303ae
A
280int
281kdp_dump_trap(
282 int type,
283 struct savearea *regs)
284{
285 extern int kdp_flag;
286
287 printf ("An unexpected trap (type %d) occurred during the kernel dump, terminating.\n", type);
288 kdp_send_panic_pkt (KDP_EOF, NULL, 0, ((void *) 0));
289 abort_panic_transfer();
290 kdp_flag &= ~KDP_PANIC_DUMP_ENABLED;
291 kdp_flag &= ~PANIC_CORE_ON_NMI;
292 kdp_flag &= ~PANIC_LOG_DUMP;
293
294 kdp_reset();
295
296 kdp_raise_exception(EXC_BAD_ACCESS, 0, 0, kdp.saved_state);
297 return;
298}
299
300int
301kern_dump()
302{
303 int error = 0;
304 vm_map_t map;
305 unsigned int thread_count, segment_count;
306 unsigned int command_size = 0, header_size = 0, tstate_size = 0;
307 unsigned int hoffset = 0, foffset = 0, nfoffset = 0, vmoffset = 0;
308 unsigned int max_header_size = 0;
309 vm_offset_t header;
310 struct machine_slot *ms;
311 struct mach_header *mh;
312 struct segment_command *sc;
313 struct thread_command *tc;
314 vm_size_t size;
315 vm_prot_t prot = 0;
316 vm_prot_t maxprot = 0;
317 vm_inherit_t inherit = 0;
318 vm_offset_t offset;
319 int error1;
320 mythread_state_flavor_t flavors[MAX_TSTATE_FLAVORS];
321 vm_size_t nflavors;
322 int i;
323 int nesting_depth = 0;
324 kern_return_t kret;
325 struct vm_region_submap_info_64 vbr;
326 int vbrcount = 0;
327 tir_t tir1;
328
329 int panic_error = 0;
330 unsigned int txstart = 0;
331 unsigned int mach_section_count = 4;
332 unsigned int num_sects_txed = 0;
333
334
335 extern int SEGSIZE;
336
337 extern vm_offset_t sectTEXTB, sectDATAB, sectLINKB, sectPRELINKB;
338 extern int sectSizeTEXT, sectSizeDATA, sectSizeLINK, sectSizePRELINK;
339
340 map = kernel_map;
341 not_in_kdp = 0; /* Tell vm functions not to acquire locks */
342
343 thread_count = 1;
344 segment_count = get_vmmap_entries(map);
345
346 printf("Kernel map has %d entries\n", segment_count);
347
348 nflavors = kdp_mynum_flavors;
349 bcopy((char *)thread_flavor_array,(char *) flavors,sizeof(thread_flavor_array));
350
351 for (i = 0; i < nflavors; i++)
352 tstate_size += sizeof(mythread_state_flavor_t) +
353 (flavors[i].count * sizeof(int));
354
355 command_size = (segment_count + mach_section_count) *
356 sizeof(struct segment_command) +
357 thread_count*sizeof(struct thread_command) +
358 tstate_size*thread_count;
359
360 header_size = command_size + sizeof(struct mach_header);
361 header = (vm_offset_t) command_buffer;
362
363 /*
364 * Set up Mach-O header.
365 */
366 printf ("Generated Mach-O header size was %d\n", header_size);
367
368 mh = (struct mach_header *) header;
369 ms = &machine_slot[cpu_number()];
370 mh->magic = MH_MAGIC;
371 mh->cputype = ms->cpu_type;
372 mh->cpusubtype = ms->cpu_subtype;
373 mh->filetype = MH_CORE;
374 mh->ncmds = segment_count + thread_count + mach_section_count;
375 mh->sizeofcmds = command_size;
376 mh->flags = 0;
377
378 hoffset = sizeof(struct mach_header); /* offset into header */
379 foffset = round_page_32(header_size); /* offset into file */
380 /* Padding.. */
381 if ((foffset - header_size) < (4*sizeof(struct segment_command))) {
382 /* Hack */
383 foffset += ((4*sizeof(struct segment_command)) - (foffset-header_size));
384 }
385
386 max_header_size = foffset;
387
388 vmoffset = VM_MIN_ADDRESS; /* offset into VM */
389
390 /* Transmit the Mach-O MH_CORE header, and seek forward past the
391 * area reserved for the segment and thread commands
392 * to begin data transmission
393 */
394
395 if ((panic_error = kdp_send_panic_pkt (KDP_SEEK, NULL, sizeof(nfoffset) , &nfoffset)) < 0) {
396 printf ("kdp_send_panic_pkt failed with error %d\n", panic_error);
397 return -1;
398 }
399
400 if ((panic_error = kdp_send_panic_packets (KDP_DATA, NULL, sizeof(struct mach_header), (caddr_t) mh) < 0)) {
401 printf ("kdp_send_panic_packets failed with error %d\n", panic_error);
402 return -1 ;
403 }
404
405 if ((panic_error = kdp_send_panic_pkt (KDP_SEEK, NULL, sizeof(foffset) , &foffset) < 0)) {
406 printf ("kdp_send_panic_pkt failed with error %d\n", panic_error);
407 return (-1);
408 }
409 printf ("Transmitting kernel state, please wait: ");
410
411 while ((segment_count > 0) || (kret == KERN_SUCCESS)){
412 /* Check if we've transmitted all the kernel sections */
413 if (num_sects_txed == mach_section_count-1) {
414
415 while (1) {
416
417 /*
418 * Get region information for next region.
419 */
420
421 vbrcount = VM_REGION_SUBMAP_INFO_COUNT_64;
422 if((kret = vm_region_recurse_64(map,
423 &vmoffset, &size, &nesting_depth,
424 &vbr, &vbrcount)) != KERN_SUCCESS) {
425 break;
426 }
427
428 if(vbr.is_submap) {
429 nesting_depth++;
430 continue;
431 } else {
432 break;
433 }
434 }
435
436 if(kret != KERN_SUCCESS)
437 break;
438
439 prot = vbr.protection;
440 maxprot = vbr.max_protection;
441 inherit = vbr.inheritance;
442 }
443 else
444 {
445 switch (num_sects_txed) {
446 case 0:
447 {
448 /* Transmit the kernel text section */
449 vmoffset = sectTEXTB;
450 size = sectSizeTEXT;
451 }
452 break;
453 case 1:
454 {
455 vmoffset = sectDATAB;
456 size = sectSizeDATA;
457 }
458 break;
459 case 2:
460 {
461 vmoffset = sectPRELINKB;
462 size = sectSizePRELINK;
463 }
464 break;
465 case 3:
466 {
467 vmoffset = sectLINKB;
468 size = sectSizeLINK;
469 }
470 break;
471 /* TODO the lowmem vector area may be useful, but its transmission is
472 * disabled for now. The traceback table area should be transmitted
473 * as well - that's indirected from 0x5080.
474 */
475 }
476 num_sects_txed++;
477 }
478 /*
479 * Fill in segment command structure.
480 */
481
482 if (hoffset > max_header_size)
483 break;
484 sc = (struct segment_command *) (header);
485 sc->cmd = LC_SEGMENT;
486 sc->cmdsize = sizeof(struct segment_command);
487 sc->segname[0] = 0;
488 sc->vmaddr = vmoffset;
489 sc->vmsize = size;
490 sc->fileoff = foffset;
491 sc->filesize = size;
492 sc->maxprot = maxprot;
493 sc->initprot = prot;
494 sc->nsects = 0;
495
496 if ((panic_error = kdp_send_panic_pkt (KDP_SEEK, NULL, sizeof(hoffset) , &hoffset)) < 0) {
497 printf ("kdp_send_panic_pkt failed with error %d\n", panic_error);
498 return -1;
499 }
500
501 if ((panic_error = kdp_send_panic_packets (KDP_DATA, NULL, sizeof(struct segment_command) , (caddr_t) sc)) < 0) {
502 printf ("kdp_send_panic_packets failed with error %d\n", panic_error);
503 return -1 ;
504 }
505
506 /* Do not transmit memory tagged VM_MEMORY_IOKIT - instead, seek past that
507 * region on the server - this creates a hole in the file
508 */
509
510 if ((vbr.user_tag != VM_MEMORY_IOKIT)) {
511
512 if ((panic_error = kdp_send_panic_pkt (KDP_SEEK, NULL, sizeof(foffset) , &foffset)) < 0) {
513 printf ("kdp_send_panic_pkt failed with error %d\n", panic_error);
514 return (-1);
515 }
516
517 txstart = vmoffset;
518
519 if ((panic_error = kdp_send_panic_packets (KDP_DATA, NULL, size, (caddr_t) txstart)) < 0) {
520 printf ("kdp_send_panic_packets failed with error %d\n", panic_error);
521 return -1 ;
522 }
523 }
524
525 hoffset += sizeof(struct segment_command);
526 foffset += size;
527 vmoffset += size;
528 segment_count--;
529 }
530 tir1.header = header;
531 tir1.hoffset = 0;
532 tir1.flavors = flavors;
533 tir1.tstate_size = tstate_size;
534
535 /* Now send out the LC_THREAD load command, with the thread information
536 * for the current activation.
537 * Note that the corefile can contain LC_SEGMENT commands with file offsets
538 * that point past the edge of the corefile, in the event that the last N
539 * VM regions were all I/O mapped or otherwise non-transferable memory,
540 * not followed by a normal VM region; i.e. there will be no hole that
541 * reaches to the end of the core file.
542 */
543 kern_collectth_state (current_act(), &tir1);
544
545 if ((panic_error = kdp_send_panic_pkt (KDP_SEEK, NULL, sizeof(hoffset) , &hoffset)) < 0) {
546 printf ("kdp_send_panic_pkt failed with error %d\n", panic_error);
547 return -1;
548 }
549
550 if ((panic_error = kdp_send_panic_packets (KDP_DATA, NULL, tir1.hoffset , (caddr_t) header)) < 0) {
551 printf ("kdp_send_panic_packets failed with error %d\n", panic_error);
552 return -1 ;
553 }
554
555 /* last packet */
556 if ((panic_error = kdp_send_panic_pkt (KDP_EOF, NULL, 0, ((void *) 0))) < 0)
557 {
558 printf ("kdp_send_panic_pkt failed with error %d\n", panic_error);
559 return (-1) ;
560 }
561
562 out:
563 if (error == 0)
564 error = error1;
565 return (error);
566}