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