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