]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kdp/kdp.c
xnu-3248.60.10.tar.gz
[apple/xnu.git] / osfmk / kdp / kdp.c
CommitLineData
1c79356b 1/*
39236c6e 2 * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b 27 */
1c79356b
A
28
29#include <mach/mach_types.h>
316670eb 30#include <mach/vm_param.h>
b0d623f7 31#include <sys/appleapiopts.h>
1c79356b 32#include <kern/debug.h>
b7266188 33#include <uuid/uuid.h>
1c79356b
A
34
35#include <kdp/kdp_internal.h>
36#include <kdp/kdp_private.h>
7e4a7d39 37#include <kdp/kdp_core.h>
1c79356b 38
9bccf70c 39#include <libsa/types.h>
6d2010ae 40#include <libkern/version.h>
9bccf70c 41
91447636
A
42#include <string.h> /* bcopy */
43
0c530ab8
A
44#include <kern/processor.h>
45#include <kern/thread.h>
6d2010ae 46#include <kern/clock.h>
0c530ab8
A
47#include <vm/vm_map.h>
48#include <vm/vm_kern.h>
316670eb 49#include <vm/vm_pageout.h>
39236c6e
A
50#include <vm/vm_shared_region.h>
51#include <libkern/OSKextLibPrivate.h>
316670eb 52
1c79356b
A
53#define DO_ALIGN 1 /* align all packet data accesses */
54
55#define KDP_TEST_HARNESS 0
56#if KDP_TEST_HARNESS
57#define dprintf(x) kprintf x
58#else
59#define dprintf(x)
60#endif
61
62static kdp_dispatch_t
b0d623f7 63 dispatch_table[KDP_INVALID_REQUEST-KDP_CONNECT] =
1c79356b
A
64 {
65/* 0 */ kdp_connect,
66/* 1 */ kdp_disconnect,
67/* 2 */ kdp_hostinfo,
9bccf70c 68/* 3 */ kdp_version,
1c79356b
A
69/* 4 */ kdp_maxbytes,
70/* 5 */ kdp_readmem,
71/* 6 */ kdp_writemem,
72/* 7 */ kdp_readregs,
73/* 8 */ kdp_writeregs,
9bccf70c
A
74/* 9 */ kdp_unknown,
75/* A */ kdp_unknown,
1c79356b
A
76/* B */ kdp_suspend,
77/* C */ kdp_resumecpus,
78/* D */ kdp_unknown,
9bccf70c
A
79/* E */ kdp_unknown,
80/* F */ kdp_breakpoint_set,
81/*10 */ kdp_breakpoint_remove,
82/*11 */ kdp_regions,
91447636 83/*12 */ kdp_reattach,
b0d623f7
A
84/*13 */ kdp_reboot,
85/*14 */ kdp_readmem64,
86/*15 */ kdp_writemem64,
87/*16 */ kdp_breakpoint64_set,
88/*17 */ kdp_breakpoint64_remove,
89/*18 */ kdp_kernelversion,
90/*19 */ kdp_readphysmem64,
7e4a7d39
A
91/*1A */ kdp_writephysmem64,
92/*1B */ kdp_readioport,
93/*1C */ kdp_writeioport,
94/*1D */ kdp_readmsr64,
95/*1E */ kdp_writemsr64,
96/*1F */ kdp_dumpinfo,
1c79356b
A
97 };
98
99kdp_glob_t kdp;
9bccf70c 100
9bccf70c 101#define MAX_BREAKPOINTS 100
9bccf70c 102
b0d623f7
A
103/*
104 * Version 11 of the KDP Protocol adds support for 64-bit wide memory
105 * addresses (read/write and breakpoints) as well as a dedicated
106 * kernelversion request. Version 12 adds read/writing of physical
7e4a7d39 107 * memory with 64-bit wide memory addresses.
b0d623f7
A
108 */
109#define KDP_VERSION 12
9bccf70c
A
110
111typedef struct{
b0d623f7
A
112 mach_vm_address_t address;
113 uint32_t bytesused;
114 uint8_t oldbytes[MAX_BREAKINSN_BYTES];
9bccf70c
A
115} kdp_breakpoint_record_t;
116
117static kdp_breakpoint_record_t breakpoint_list[MAX_BREAKPOINTS];
118static unsigned int breakpoints_initialized = 0;
55e303ae 119
9bccf70c 120int reattach_wait = 0;
55e303ae 121int noresume_on_disconnect = 0;
2d21ac55 122extern unsigned int return_on_panic;
1c79356b 123
b0d623f7
A
124kdp_error_t
125kdp_set_breakpoint_internal(
126 mach_vm_address_t address
127 );
128
129kdp_error_t
130kdp_remove_breakpoint_internal(
131 mach_vm_address_t address
132 );
133
1c79356b
A
134boolean_t
135kdp_packet(
136 unsigned char *pkt,
137 int *len,
138 unsigned short *reply_port
139)
140{
141 static unsigned aligned_pkt[1538/sizeof(unsigned)+1]; // max ether pkt
142 kdp_pkt_t *rd = (kdp_pkt_t *)&aligned_pkt;
2d21ac55
A
143 size_t plen = *len;
144 kdp_req_t req;
1c79356b
A
145 boolean_t ret;
146
147#if DO_ALIGN
148 bcopy((char *)pkt, (char *)rd, sizeof(aligned_pkt));
149#else
150 rd = (kdp_pkt_t *)pkt;
151#endif
152 if (plen < sizeof (rd->hdr) || rd->hdr.len != plen) {
2d21ac55 153 printf("kdp_packet bad len pkt %lu hdr %d\n", plen, rd->hdr.len);
1c79356b
A
154
155 return (FALSE);
156 }
157
158 if (rd->hdr.is_reply) {
159 printf("kdp_packet reply recvd req %x seq %x\n",
160 rd->hdr.request, rd->hdr.seq);
161
162 return (FALSE);
163 }
164
165 req = rd->hdr.request;
b0d623f7 166 if (req >= KDP_INVALID_REQUEST) {
1c79356b
A
167 printf("kdp_packet bad request %x len %d seq %x key %x\n",
168 rd->hdr.request, rd->hdr.len, rd->hdr.seq, rd->hdr.key);
169
170 return (FALSE);
171 }
172
173 ret = ((*dispatch_table[req - KDP_CONNECT])(rd, len, reply_port));
174#if DO_ALIGN
175 bcopy((char *)rd, (char *) pkt, *len);
176#endif
177 return ret;
178}
179
180static boolean_t
181kdp_unknown(
182 kdp_pkt_t *pkt,
2d21ac55
A
183 __unused int *len,
184 __unused unsigned short *reply_port
1c79356b
A
185)
186{
187 kdp_pkt_t *rd = (kdp_pkt_t *)pkt;
188
189 printf("kdp_unknown request %x len %d seq %x key %x\n",
190 rd->hdr.request, rd->hdr.len, rd->hdr.seq, rd->hdr.key);
191
192 return (FALSE);
193}
194
195static boolean_t
196kdp_connect(
197 kdp_pkt_t *pkt,
198 int *len,
199 unsigned short *reply_port
200)
201{
202 kdp_connect_req_t *rq = &pkt->connect_req;
2d21ac55 203 size_t plen = *len;
1c79356b 204 kdp_connect_reply_t *rp = &pkt->connect_reply;
7e4a7d39
A
205 uint16_t rport, eport;
206 uint32_t key;
207 uint8_t seq;
1c79356b
A
208
209 if (plen < sizeof (*rq))
210 return (FALSE);
211
212 dprintf(("kdp_connect seq %x greeting %s\n", rq->hdr.seq, rq->greeting));
213
7e4a7d39
A
214 rport = rq->req_reply_port;
215 eport = rq->exc_note_port;
216 key = rq->hdr.key;
217 seq = rq->hdr.seq;
1c79356b 218 if (kdp.is_conn) {
7e4a7d39
A
219 if ((seq == kdp.conn_seq) && /* duplicate request */
220 (rport == kdp.reply_port) &&
221 (eport == kdp.exception_port) &&
222 (key == kdp.session_key))
1c79356b 223 rp->error = KDPERR_NO_ERROR;
7e4a7d39 224 else
1c79356b
A
225 rp->error = KDPERR_ALREADY_CONNECTED;
226 }
227 else {
39236c6e
A
228 kdp.reply_port = rport;
229 kdp.exception_port = eport;
230 kdp.is_conn = TRUE;
231 kdp.conn_seq = seq;
7e4a7d39
A
232 kdp.session_key = key;
233
1c79356b
A
234 rp->error = KDPERR_NO_ERROR;
235 }
236
237 rp->hdr.is_reply = 1;
238 rp->hdr.len = sizeof (*rp);
239
7e4a7d39 240 *reply_port = rport;
1c79356b
A
241 *len = rp->hdr.len;
242
243 if (current_debugger == KDP_CUR_DB)
244 active_debugger=1;
245
246 return (TRUE);
247}
248
249static boolean_t
250kdp_disconnect(
251 kdp_pkt_t *pkt,
252 int *len,
253 unsigned short *reply_port
254)
255{
256 kdp_disconnect_req_t *rq = &pkt->disconnect_req;
2d21ac55 257 size_t plen = *len;
1c79356b
A
258 kdp_disconnect_reply_t *rp = &pkt->disconnect_reply;
259
260 if (plen < sizeof (*rq))
261 return (FALSE);
262
263 if (!kdp.is_conn)
264 return (FALSE);
265
266 dprintf(("kdp_disconnect\n"));
267
268 *reply_port = kdp.reply_port;
269
270 kdp.reply_port = kdp.exception_port = 0;
271 kdp.is_halted = kdp.is_conn = FALSE;
272 kdp.exception_seq = kdp.conn_seq = 0;
7e4a7d39 273 kdp.session_key = 0;
1c79356b 274
2d21ac55 275 if ((panicstr != NULL) && (return_on_panic == 0))
39236c6e 276 reattach_wait = 1;
2d21ac55 277
55e303ae
A
278 if (noresume_on_disconnect == 1) {
279 reattach_wait = 1;
280 noresume_on_disconnect = 0;
281 }
282
1c79356b
A
283 rp->hdr.is_reply = 1;
284 rp->hdr.len = sizeof (*rp);
285
286 *len = rp->hdr.len;
287
288 if (current_debugger == KDP_CUR_DB)
289 active_debugger=0;
290
291 return (TRUE);
292}
293
9bccf70c
A
294static boolean_t
295kdp_reattach(
296 kdp_pkt_t *pkt,
297 int *len,
298 unsigned short *reply_port
299)
300{
39236c6e 301 kdp_reattach_req_t *rq = &pkt->reattach_req;
9bccf70c 302
39236c6e
A
303 kdp.is_conn = TRUE;
304 kdp_disconnect(pkt, len, reply_port);
305 *reply_port = rq->req_reply_port;
306 reattach_wait = 1;
307 return (TRUE);
9bccf70c
A
308}
309
1c79356b
A
310static boolean_t
311kdp_hostinfo(
312 kdp_pkt_t *pkt,
313 int *len,
314 unsigned short *reply_port
315)
316{
317 kdp_hostinfo_req_t *rq = &pkt->hostinfo_req;
2d21ac55 318 size_t plen = *len;
1c79356b
A
319 kdp_hostinfo_reply_t *rp = &pkt->hostinfo_reply;
320
321 if (plen < sizeof (*rq))
322 return (FALSE);
323
39236c6e 324 dprintf(("kdp_hostinfo\n"));
b0d623f7 325
1c79356b
A
326 rp->hdr.is_reply = 1;
327 rp->hdr.len = sizeof (*rp);
328
329 kdp_machine_hostinfo(&rp->hostinfo);
9bccf70c 330
1c79356b
A
331 *reply_port = kdp.reply_port;
332 *len = rp->hdr.len;
333
334 return (TRUE);
335}
336
b0d623f7
A
337static boolean_t
338kdp_kernelversion(
39236c6e
A
339 kdp_pkt_t *pkt,
340 int *len,
341 unsigned short *reply_port
b0d623f7
A
342)
343{
344 kdp_kernelversion_req_t *rq = &pkt->kernelversion_req;
345 size_t plen = *len;
346 kdp_kernelversion_reply_t *rp = &pkt->kernelversion_reply;
347 size_t slen;
348
349 if (plen < sizeof (*rq))
350 return (FALSE);
351
352 rp->hdr.is_reply = 1;
353 rp->hdr.len = sizeof (*rp);
354
355 dprintf(("kdp_kernelversion\n"));
39236c6e 356 slen = strlcpy(rp->version, kdp_kernelversion_string, MAX_KDP_DATA_SIZE);
b0d623f7 357
39236c6e 358 rp->hdr.len += slen + 1; /* strlcpy returns the amount copied with NUL */
b0d623f7
A
359
360 *reply_port = kdp.reply_port;
361 *len = rp->hdr.len;
362
363 return (TRUE);
364}
365
1c79356b
A
366static boolean_t
367kdp_suspend(
368 kdp_pkt_t *pkt,
369 int *len,
370 unsigned short *reply_port
371)
372{
373 kdp_suspend_req_t *rq = &pkt->suspend_req;
2d21ac55 374 size_t plen = *len;
1c79356b
A
375 kdp_suspend_reply_t *rp = &pkt->suspend_reply;
376
377 if (plen < sizeof (*rq))
378 return (FALSE);
379
380 rp->hdr.is_reply = 1;
381 rp->hdr.len = sizeof (*rp);
382
383 dprintf(("kdp_suspend\n"));
384
385 kdp.is_halted = TRUE;
386
387 *reply_port = kdp.reply_port;
388 *len = rp->hdr.len;
389
390 return (TRUE);
391}
392
393static boolean_t
394kdp_resumecpus(
395 kdp_pkt_t *pkt,
396 int *len,
397 unsigned short *reply_port
398)
399{
400 kdp_resumecpus_req_t *rq = &pkt->resumecpus_req;
2d21ac55 401 size_t plen = *len;
1c79356b
A
402 kdp_resumecpus_reply_t *rp = &pkt->resumecpus_reply;
403
404 if (plen < sizeof (*rq))
405 return (FALSE);
406
407 rp->hdr.is_reply = 1;
408 rp->hdr.len = sizeof (*rp);
409
410 dprintf(("kdp_resumecpus %x\n", rq->cpu_mask));
9bccf70c 411
1c79356b
A
412 kdp.is_halted = FALSE;
413
414 *reply_port = kdp.reply_port;
415 *len = rp->hdr.len;
416
417 return (TRUE);
418}
419
420static boolean_t
421kdp_writemem(
422 kdp_pkt_t *pkt,
423 int *len,
424 unsigned short *reply_port
425)
426{
427 kdp_writemem_req_t *rq = &pkt->writemem_req;
2d21ac55 428 size_t plen = *len;
1c79356b 429 kdp_writemem_reply_t *rp = &pkt->writemem_reply;
39236c6e 430 mach_vm_size_t cnt;
1c79356b
A
431
432 if (plen < sizeof (*rq))
433 return (FALSE);
434
435 if (rq->nbytes > MAX_KDP_DATA_SIZE)
436 rp->error = KDPERR_BAD_NBYTES;
437 else {
438 dprintf(("kdp_writemem addr %x size %d\n", rq->address, rq->nbytes));
b0d623f7 439 cnt = kdp_machine_vm_write((caddr_t)rq->data, (mach_vm_address_t)rq->address, rq->nbytes);
39236c6e
A
440 rp->error = KDPERR_ACCESS(rq->nbytes, cnt);
441 dprintf((" cnt %lld error %d\n", cnt, rp->error));
1c79356b
A
442 }
443
444 rp->hdr.is_reply = 1;
445 rp->hdr.len = sizeof (*rp);
446
447 *reply_port = kdp.reply_port;
448 *len = rp->hdr.len;
449
450 return (TRUE);
451}
452
b0d623f7
A
453static boolean_t
454kdp_writemem64(
39236c6e
A
455 kdp_pkt_t *pkt,
456 int *len,
457 unsigned short *reply_port
b0d623f7
A
458)
459{
460 kdp_writemem64_req_t *rq = &pkt->writemem64_req;
461 size_t plen = *len;
462 kdp_writemem64_reply_t *rp = &pkt->writemem64_reply;
463 mach_vm_size_t cnt;
464
465 if (plen < sizeof (*rq))
466 return (FALSE);
467
468 if (rq->nbytes > MAX_KDP_DATA_SIZE)
39236c6e 469 rp->error = KDPERR_BAD_NBYTES;
b0d623f7 470 else {
39236c6e
A
471 dprintf(("kdp_writemem64 addr %llx size %d\n", rq->address, rq->nbytes));
472 cnt = kdp_machine_vm_write((caddr_t)rq->data, (mach_vm_address_t)rq->address, (mach_vm_size_t)rq->nbytes);
473 rp->error = KDPERR_ACCESS(rq->nbytes, cnt);
474 dprintf((" cnt %lld error %d\n", cnt, rp->error));
b0d623f7
A
475 }
476
477 rp->hdr.is_reply = 1;
478 rp->hdr.len = sizeof (*rp);
479
480 *reply_port = kdp.reply_port;
481 *len = rp->hdr.len;
482
483 return (TRUE);
484}
485
486static boolean_t
487kdp_writephysmem64(
39236c6e
A
488 kdp_pkt_t *pkt,
489 int *len,
490 unsigned short *reply_port
b0d623f7
A
491)
492{
493 kdp_writephysmem64_req_t *rq = &pkt->writephysmem64_req;
494 size_t plen = *len;
495 kdp_writephysmem64_reply_t *rp = &pkt->writephysmem64_reply;
39236c6e
A
496 mach_vm_size_t cnt;
497 unsigned int size;
b0d623f7
A
498
499 if (plen < sizeof (*rq))
39236c6e 500 return (FALSE);
b0d623f7 501
39236c6e
A
502 size = rq->nbytes;
503 if (size > MAX_KDP_DATA_SIZE)
504 rp->error = KDPERR_BAD_NBYTES;
b0d623f7 505 else {
39236c6e
A
506 dprintf(("kdp_writephysmem64 addr %llx size %d\n", rq->address, size));
507 cnt = kdp_machine_phys_write(rq, rq->data, rq->lcpu);
508 rp->error = KDPERR_ACCESS(size, cnt);
509 dprintf((" cnt %lld error %d\n", cnt, rp->error));
b0d623f7
A
510 }
511
512 rp->hdr.is_reply = 1;
513 rp->hdr.len = sizeof (*rp);
514
515 *reply_port = kdp.reply_port;
516 *len = rp->hdr.len;
517
518 return (TRUE);
519}
520
1c79356b
A
521static boolean_t
522kdp_readmem(
523 kdp_pkt_t *pkt,
524 int *len,
525 unsigned short *reply_port
526)
527{
528 kdp_readmem_req_t *rq = &pkt->readmem_req;
2d21ac55 529 size_t plen = *len;
1c79356b 530 kdp_readmem_reply_t *rp = &pkt->readmem_reply;
39236c6e
A
531 mach_vm_size_t cnt;
532 unsigned int size;
b0d623f7 533
1c79356b
A
534 if (plen < sizeof (*rq))
535 return (FALSE);
536
537 rp->hdr.is_reply = 1;
538 rp->hdr.len = sizeof (*rp);
539
39236c6e
A
540 size = rq->nbytes;
541 if (size > MAX_KDP_DATA_SIZE)
1c79356b
A
542 rp->error = KDPERR_BAD_NBYTES;
543 else {
39236c6e
A
544 dprintf(("kdp_readmem addr %x size %d\n", rq->address, size));
545 cnt = kdp_machine_vm_read((mach_vm_address_t)rq->address, (caddr_t)rp->data, rq->nbytes);
546 rp->error = KDPERR_ACCESS(size, cnt);
547 dprintf((" cnt %lld error %d\n", cnt, rp->error));
1c79356b
A
548
549 rp->hdr.len += cnt;
550 }
551
552 *reply_port = kdp.reply_port;
553 *len = rp->hdr.len;
554
555 return (TRUE);
556}
557
b0d623f7
A
558static boolean_t
559kdp_readmem64(
39236c6e
A
560 kdp_pkt_t *pkt,
561 int *len,
562 unsigned short *reply_port
b0d623f7
A
563)
564{
565 kdp_readmem64_req_t *rq = &pkt->readmem64_req;
566 size_t plen = *len;
567 kdp_readmem64_reply_t *rp = &pkt->readmem64_reply;
39236c6e
A
568 mach_vm_size_t cnt;
569 unsigned int size;
b0d623f7
A
570
571 if (plen < sizeof (*rq))
572 return (FALSE);
573
574 rp->hdr.is_reply = 1;
575 rp->hdr.len = sizeof (*rp);
576
39236c6e
A
577 size = rq->nbytes;
578 if (size > MAX_KDP_DATA_SIZE)
579 rp->error = KDPERR_BAD_NBYTES;
b0d623f7 580 else {
39236c6e
A
581 dprintf(("kdp_readmem64 addr %llx size %d\n", rq->address, size));
582 cnt = kdp_machine_vm_read((mach_vm_address_t)rq->address, (caddr_t)rp->data, rq->nbytes);
583 rp->error = KDPERR_ACCESS(size, cnt);
584 dprintf((" cnt %lld error %d\n", cnt, rp->error));
b0d623f7 585
39236c6e 586 rp->hdr.len += cnt;
b0d623f7
A
587 }
588
589 *reply_port = kdp.reply_port;
590 *len = rp->hdr.len;
591
592 return (TRUE);
593}
594
595static boolean_t
596kdp_readphysmem64(
39236c6e
A
597 kdp_pkt_t *pkt,
598 int *len,
599 unsigned short *reply_port
b0d623f7
A
600)
601{
602 kdp_readphysmem64_req_t *rq = &pkt->readphysmem64_req;
603 size_t plen = *len;
604 kdp_readphysmem64_reply_t *rp = &pkt->readphysmem64_reply;
39236c6e
A
605 mach_vm_size_t cnt;
606 unsigned int size;
b0d623f7
A
607
608 if (plen < sizeof (*rq))
39236c6e 609 return (FALSE);
b0d623f7
A
610
611 rp->hdr.is_reply = 1;
612 rp->hdr.len = sizeof (*rp);
613
39236c6e
A
614 size = rq->nbytes;
615 if (size > MAX_KDP_DATA_SIZE)
616 rp->error = KDPERR_BAD_NBYTES;
b0d623f7 617 else {
39236c6e
A
618 dprintf(("kdp_readphysmem64 addr %llx size %d\n", rq->address, size));
619 cnt = kdp_machine_phys_read(rq, rp->data, rq->lcpu);
620 rp->error = KDPERR_ACCESS(size, cnt);
621 dprintf((" cnt %lld error %d\n", cnt, rp->error));
b0d623f7 622
39236c6e 623 rp->hdr.len += cnt;
b0d623f7
A
624 }
625
626 *reply_port = kdp.reply_port;
627 *len = rp->hdr.len;
628
629 return (TRUE);
630}
631
1c79356b
A
632static boolean_t
633kdp_maxbytes(
634 kdp_pkt_t *pkt,
635 int *len,
636 unsigned short *reply_port
637)
638{
639 kdp_maxbytes_req_t *rq = &pkt->maxbytes_req;
2d21ac55 640 size_t plen = *len;
1c79356b
A
641 kdp_maxbytes_reply_t *rp = &pkt->maxbytes_reply;
642
643 if (plen < sizeof (*rq))
644 return (FALSE);
645
646 rp->hdr.is_reply = 1;
647 rp->hdr.len = sizeof (*rp);
648
649 dprintf(("kdp_maxbytes\n"));
650
651 rp->max_bytes = MAX_KDP_DATA_SIZE;
652
653 *reply_port = kdp.reply_port;
654 *len = rp->hdr.len;
655
656 return (TRUE);
657}
658
9bccf70c
A
659static boolean_t
660kdp_version(
661 kdp_pkt_t *pkt,
662 int *len,
663 unsigned short *reply_port
664)
665{
666 kdp_version_req_t *rq = &pkt->version_req;
2d21ac55 667 size_t plen = *len;
9bccf70c 668 kdp_version_reply_t *rp = &pkt->version_reply;
9bccf70c
A
669
670 if (plen < sizeof (*rq))
671 return (FALSE);
672
673 rp->hdr.is_reply = 1;
674 rp->hdr.len = sizeof (*rp);
675
676 dprintf(("kdp_version\n"));
677
678 rp->version = KDP_VERSION;
9bccf70c
A
679 if (!(kdp_flag & KDP_BP_DIS))
680 rp->feature = KDP_FEATURE_BP;
681 else
682 rp->feature = 0;
b0d623f7 683
9bccf70c
A
684 *reply_port = kdp.reply_port;
685 *len = rp->hdr.len;
686
687 return (TRUE);
688}
689
1c79356b
A
690static boolean_t
691kdp_regions(
692 kdp_pkt_t *pkt,
693 int *len,
694 unsigned short *reply_port
695)
696{
697 kdp_regions_req_t *rq = &pkt->regions_req;
2d21ac55 698 size_t plen = *len;
1c79356b
A
699 kdp_regions_reply_t *rp = &pkt->regions_reply;
700 kdp_region_t *r;
701
702 if (plen < sizeof (*rq))
703 return (FALSE);
704
705 rp->hdr.is_reply = 1;
706 rp->hdr.len = sizeof (*rp);
707
708 dprintf(("kdp_regions\n"));
709
710 r = rp->regions;
711 rp->nregions = 0;
712
b0d623f7 713 r->address = 0;
1c79356b
A
714 r->nbytes = 0xffffffff;
715
716 r->protection = VM_PROT_ALL; r++; rp->nregions++;
717
718 rp->hdr.len += rp->nregions * sizeof (kdp_region_t);
719
720 *reply_port = kdp.reply_port;
721 *len = rp->hdr.len;
722
723 return (TRUE);
724}
725
726static boolean_t
727kdp_writeregs(
728 kdp_pkt_t *pkt,
729 int *len,
730 unsigned short *reply_port
731)
732{
733 kdp_writeregs_req_t *rq = &pkt->writeregs_req;
2d21ac55 734 size_t plen = *len;
1c79356b
A
735 int size;
736 kdp_writeregs_reply_t *rp = &pkt->writeregs_reply;
737
738 if (plen < sizeof (*rq))
739 return (FALSE);
740
b0d623f7 741 size = rq->hdr.len - (unsigned)sizeof(kdp_hdr_t) - (unsigned)sizeof(unsigned int);
1c79356b
A
742 rp->error = kdp_machine_write_regs(rq->cpu, rq->flavor, rq->data, &size);
743
744 rp->hdr.is_reply = 1;
745 rp->hdr.len = sizeof (*rp);
746
747 *reply_port = kdp.reply_port;
748 *len = rp->hdr.len;
749
750 return (TRUE);
751}
752
753static boolean_t
754kdp_readregs(
755 kdp_pkt_t *pkt,
756 int *len,
757 unsigned short *reply_port
758)
759{
760 kdp_readregs_req_t *rq = &pkt->readregs_req;
2d21ac55 761 size_t plen = *len;
1c79356b
A
762 kdp_readregs_reply_t *rp = &pkt->readregs_reply;
763 int size;
764
765 if (plen < sizeof (*rq))
766 return (FALSE);
767
768 rp->hdr.is_reply = 1;
769 rp->hdr.len = sizeof (*rp);
770
771 rp->error = kdp_machine_read_regs(rq->cpu, rq->flavor, rp->data, &size);
772 rp->hdr.len += size;
773
774 *reply_port = kdp.reply_port;
775 *len = rp->hdr.len;
776
777 return (TRUE);
778}
9bccf70c 779
b0d623f7
A
780
781boolean_t
9bccf70c 782kdp_breakpoint_set(
39236c6e
A
783 kdp_pkt_t *pkt,
784 int *len,
785 unsigned short *reply_port
9bccf70c
A
786)
787{
b0d623f7
A
788 kdp_breakpoint_req_t *rq = &pkt->breakpoint_req;
789 kdp_breakpoint_reply_t *rp = &pkt->breakpoint_reply;
790 size_t plen = *len;
791 kdp_error_t kerr;
792
793 if (plen < sizeof (*rq))
794 return (FALSE);
795
796 dprintf(("kdp_breakpoint_set %x\n", rq->address));
9bccf70c 797
b0d623f7
A
798 kerr = kdp_set_breakpoint_internal((mach_vm_address_t)rq->address);
799
800 rp->error = kerr;
801
802 rp->hdr.is_reply = 1;
803 rp->hdr.len = sizeof (*rp);
804 *reply_port = kdp.reply_port;
805 *len = rp->hdr.len;
806
807 return (TRUE);
808}
9bccf70c 809
b0d623f7
A
810boolean_t
811kdp_breakpoint64_set(
39236c6e
A
812 kdp_pkt_t *pkt,
813 int *len,
814 unsigned short *reply_port
b0d623f7
A
815)
816{
817 kdp_breakpoint64_req_t *rq = &pkt->breakpoint64_req;
818 kdp_breakpoint64_reply_t *rp = &pkt->breakpoint64_reply;
819 size_t plen = *len;
820 kdp_error_t kerr;
821
822 if (plen < sizeof (*rq))
823 return (FALSE);
824
825 dprintf(("kdp_breakpoint64_set %llx\n", rq->address));
9bccf70c 826
b0d623f7
A
827 kerr = kdp_set_breakpoint_internal((mach_vm_address_t)rq->address);
828
829 rp->error = kerr;
830
831 rp->hdr.is_reply = 1;
832 rp->hdr.len = sizeof (*rp);
833 *reply_port = kdp.reply_port;
834 *len = rp->hdr.len;
835
836 return (TRUE);
837}
9bccf70c 838
b0d623f7
A
839boolean_t
840kdp_breakpoint_remove(
39236c6e
A
841 kdp_pkt_t *pkt,
842 int *len,
843 unsigned short *reply_port
b0d623f7
A
844)
845{
846 kdp_breakpoint_req_t *rq = &pkt->breakpoint_req;
847 kdp_breakpoint_reply_t *rp = &pkt->breakpoint_reply;
848 size_t plen = *len;
849 kdp_error_t kerr;
850 if (plen < sizeof (*rq))
851 return (FALSE);
852
853 dprintf(("kdp_breakpoint_remove %x\n", rq->address));
9bccf70c 854
b0d623f7
A
855 kerr = kdp_remove_breakpoint_internal((mach_vm_address_t)rq->address);
856
857 rp->error = kerr;
858
859 rp->hdr.is_reply = 1;
860 rp->hdr.len = sizeof (*rp);
861 *reply_port = kdp.reply_port;
862 *len = rp->hdr.len;
863
864 return (TRUE);
9bccf70c
A
865}
866
b0d623f7
A
867boolean_t
868kdp_breakpoint64_remove(
39236c6e
A
869 kdp_pkt_t *pkt,
870 int *len,
871 unsigned short *reply_port
9bccf70c
A
872)
873{
b0d623f7
A
874 kdp_breakpoint64_req_t *rq = &pkt->breakpoint64_req;
875 kdp_breakpoint64_reply_t *rp = &pkt->breakpoint64_reply;
876 size_t plen = *len;
877 kdp_error_t kerr;
878
879 if (plen < sizeof (*rq))
880 return (FALSE);
881
882 dprintf(("kdp_breakpoint64_remove %llx\n", rq->address));
9bccf70c 883
b0d623f7
A
884 kerr = kdp_remove_breakpoint_internal((mach_vm_address_t)rq->address);
885
886 rp->error = kerr;
887
888 rp->hdr.is_reply = 1;
889 rp->hdr.len = sizeof (*rp);
890 *reply_port = kdp.reply_port;
891 *len = rp->hdr.len;
892
893 return (TRUE);
894}
9bccf70c 895
9bccf70c 896
b0d623f7
A
897kdp_error_t
898kdp_set_breakpoint_internal(
39236c6e
A
899 mach_vm_address_t address
900)
b0d623f7
A
901{
902
903 uint8_t breakinstr[MAX_BREAKINSN_BYTES], oldinstr[MAX_BREAKINSN_BYTES];
904 uint32_t breakinstrsize = sizeof(breakinstr);
905 mach_vm_size_t cnt;
906 int i;
907
908 kdp_machine_get_breakinsn(breakinstr, &breakinstrsize);
909
910 if(breakpoints_initialized == 0)
911 {
912 for(i=0;(i < MAX_BREAKPOINTS); breakpoint_list[i].address=0, i++);
913 breakpoints_initialized++;
9bccf70c 914 }
b0d623f7
A
915
916 cnt = kdp_machine_vm_read(address, (caddr_t)&oldinstr, (mach_vm_size_t)breakinstrsize);
917
918 if (0 == memcmp(oldinstr, breakinstr, breakinstrsize)) {
919 printf("A trap was already set at that address, not setting new breakpoint\n");
920
921 return KDPERR_BREAKPOINT_ALREADY_SET;
922 }
923
924 for(i=0;(i < MAX_BREAKPOINTS) && (breakpoint_list[i].address != 0); i++);
925
926 if (i == MAX_BREAKPOINTS) {
927 return KDPERR_MAX_BREAKPOINTS;
928 }
929
930 breakpoint_list[i].address = address;
931 memcpy(breakpoint_list[i].oldbytes, oldinstr, breakinstrsize);
932 breakpoint_list[i].bytesused = breakinstrsize;
933
934 cnt = kdp_machine_vm_write((caddr_t)&breakinstr, address, breakinstrsize);
935
936 return KDPERR_NO_ERROR;
937}
9bccf70c 938
b0d623f7
A
939kdp_error_t
940kdp_remove_breakpoint_internal(
39236c6e
A
941 mach_vm_address_t address
942)
b0d623f7
A
943{
944 mach_vm_size_t cnt;
945 int i;
946
947 for(i=0;(i < MAX_BREAKPOINTS) && (breakpoint_list[i].address != address); i++);
948
949 if (i == MAX_BREAKPOINTS)
39236c6e 950 {
b0d623f7
A
951 return KDPERR_BREAKPOINT_NOT_FOUND;
952 }
953
954 breakpoint_list[i].address = 0;
955 cnt = kdp_machine_vm_write((caddr_t)&breakpoint_list[i].oldbytes, address, breakpoint_list[i].bytesused);
956
957 return KDPERR_NO_ERROR;
9bccf70c
A
958}
959
960boolean_t
2d21ac55 961kdp_remove_all_breakpoints(void)
9bccf70c 962{
b0d623f7
A
963 int i;
964 boolean_t breakpoint_found = FALSE;
965
966 if (breakpoints_initialized)
39236c6e 967 {
b0d623f7
A
968 for(i=0;i < MAX_BREAKPOINTS; i++)
969 {
970 if (breakpoint_list[i].address)
971 {
972 kdp_machine_vm_write((caddr_t)&(breakpoint_list[i].oldbytes), (mach_vm_address_t)breakpoint_list[i].address, (mach_vm_size_t)breakpoint_list[i].bytesused);
973 breakpoint_found = TRUE;
974 breakpoint_list[i].address = 0;
975 }
976 }
977
978 if (breakpoint_found)
979 printf("kdp_remove_all_breakpoints: found extant breakpoints, removing them.\n");
39236c6e 980 }
b0d623f7 981 return breakpoint_found;
9bccf70c 982}
0c530ab8 983
b0d623f7
A
984boolean_t
985kdp_reboot(
39236c6e
A
986 __unused kdp_pkt_t *pkt,
987 __unused int *len,
988 __unused unsigned short *reply_port
b0d623f7
A
989)
990{
991 dprintf(("kdp_reboot\n"));
992
993 kdp_machine_reboot();
994
995 return (TRUE); // no, not really, we won't return
996}
0c530ab8 997
b0d623f7 998static boolean_t
39236c6e
A
999kdp_readioport(
1000 kdp_pkt_t *pkt,
b0d623f7
A
1001 int *len,
1002 unsigned short *reply_port
1003 )
1004{
1005 kdp_readioport_req_t *rq = &pkt->readioport_req;
1006 kdp_readioport_reply_t *rp = &pkt->readioport_reply;
1007 size_t plen = *len;
1008
1009 if (plen < sizeof (*rq))
1010 return (FALSE);
1011
1012 rp->hdr.is_reply = 1;
1013 rp->hdr.len = sizeof (*rp);
1014
1015 if (rq->nbytes > MAX_KDP_DATA_SIZE)
1016 rp->error = KDPERR_BAD_NBYTES;
1017 else {
1018#if KDP_TEST_HARNESS
1019 uint16_t addr = rq->address;
1020#endif
1021 uint16_t size = rq->nbytes;
1022 dprintf(("kdp_readioport addr %x size %d\n", addr, size));
1023
1024 rp->error = kdp_machine_ioport_read(rq, rp->data, rq->lcpu);
1025 if (rp->error == KDPERR_NO_ERROR)
1026 rp->hdr.len += size;
1027 }
1028
1029 *reply_port = kdp.reply_port;
1030 *len = rp->hdr.len;
1031
1032 return (TRUE);
1033}
1034
1035static boolean_t
1036kdp_writeioport(
1037 kdp_pkt_t *pkt,
1038 int *len,
1039 unsigned short *reply_port
1040 )
1041{
1042 kdp_writeioport_req_t *rq = &pkt->writeioport_req;
1043 kdp_writeioport_reply_t *rp = &pkt->writeioport_reply;
1044 size_t plen = *len;
1045
1046 if (plen < sizeof (*rq))
1047 return (FALSE);
1048
1049 if (rq->nbytes > MAX_KDP_DATA_SIZE)
1050 rp->error = KDPERR_BAD_NBYTES;
1051 else {
1052 dprintf(("kdp_writeioport addr %x size %d\n", rq->address,
1053 rq->nbytes));
1054
1055 rp->error = kdp_machine_ioport_write(rq, rq->data, rq->lcpu);
1056 }
1057
1058 rp->hdr.is_reply = 1;
1059 rp->hdr.len = sizeof (*rp);
1060
1061 *reply_port = kdp.reply_port;
1062 *len = rp->hdr.len;
1063
1064 return (TRUE);
1065}
1066
1067static boolean_t
39236c6e
A
1068kdp_readmsr64(
1069 kdp_pkt_t *pkt,
1070 int *len,
1071 unsigned short *reply_port
1072)
b0d623f7
A
1073{
1074 kdp_readmsr64_req_t *rq = &pkt->readmsr64_req;
1075 kdp_readmsr64_reply_t *rp = &pkt->readmsr64_reply;
1076 size_t plen = *len;
1077
1078 if (plen < sizeof (*rq))
1079 return (FALSE);
1080
1081 rp->hdr.is_reply = 1;
1082 rp->hdr.len = sizeof (*rp);
1083
1084 dprintf(("kdp_readmsr64 lcpu %x addr %x\n", rq->lcpu, rq->address));
1085 rp->error = kdp_machine_msr64_read(rq, rp->data, rq->lcpu);
1086 if (rp->error == KDPERR_NO_ERROR)
1087 rp->hdr.len += sizeof(uint64_t);
1088
1089 *reply_port = kdp.reply_port;
1090 *len = rp->hdr.len;
1091
1092 return (TRUE);
1093}
1094
1095static boolean_t
1096kdp_writemsr64(
1097 kdp_pkt_t *pkt,
1098 int *len,
1099 unsigned short *reply_port
1100 )
1101{
1102 kdp_writemsr64_req_t *rq = &pkt->writemsr64_req;
1103 kdp_writemsr64_reply_t *rp = &pkt->writemsr64_reply;
1104 size_t plen = *len;
1105
1106 if (plen < sizeof (*rq))
1107 return (FALSE);
1108
1109 dprintf(("kdp_writemsr64 lcpu %x addr %x\n", rq->lcpu, rq->address));
1110 rp->error = kdp_machine_msr64_write(rq, rq->data, rq->lcpu);
1111
1112 rp->hdr.is_reply = 1;
1113 rp->hdr.len = sizeof (*rp);
1114
1115 *reply_port = kdp.reply_port;
1116 *len = rp->hdr.len;
1117
1118 return (TRUE);
1119}
7e4a7d39
A
1120
1121static boolean_t
1122kdp_dumpinfo(
1123 kdp_pkt_t *pkt,
1124 int *len,
1125 unsigned short *reply_port
1126 )
1127{
1128 kdp_dumpinfo_req_t *rq = &pkt->dumpinfo_req;
1129 kdp_dumpinfo_reply_t *rp = &pkt->dumpinfo_reply;
1130 size_t plen = *len;
1131
1132 if (plen < sizeof (*rq))
1133 return (FALSE);
1134
1135 dprintf(("kdp_dumpinfo file=%s destip=%s routerip=%s\n", rq->name, rq->destip, rq->routerip));
1136 rp->hdr.is_reply = 1;
1137 rp->hdr.len = sizeof (*rp);
1138
1139 if ((rq->type & KDP_DUMPINFO_MASK) != KDP_DUMPINFO_GETINFO) {
1140 kdp_set_dump_info(rq->type, rq->name, rq->destip, rq->routerip,
1141 rq->port);
1142 }
1143
1144 /* gather some stats for reply */
1145 kdp_get_dump_info(&rp->type, rp->name, rp->destip, rp->routerip,
1146 &rp->port);
1147
1148 *reply_port = kdp.reply_port;
1149 *len = rp->hdr.len;
1150
1151 return (TRUE);
1152}
fe8ab488 1153