1/* 2 * Copyright (c) 2000-2012 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 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. 14 * 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 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 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. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29#include <mach/mach_types.h> 30#include <mach/vm_param.h> 31#include <sys/appleapiopts.h> 32#include <kern/debug.h> 33#include <uuid/uuid.h> 34 35#include <kdp/kdp_internal.h> 36#include <kdp/kdp_private.h> 37#include <kdp/kdp_core.h> 38 39#include <libsa/types.h> 40#include <libkern/version.h> 41 42#include <string.h> /* bcopy */ 43 44#include <kern/processor.h> 45#include <kern/thread.h> 46#include <kern/clock.h> 47#include <vm/vm_map.h> 48#include <vm/vm_kern.h> 49#include <vm/vm_pageout.h> 50#include <vm/vm_shared_region.h> 51#include <libkern/OSKextLibPrivate.h> 52 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 63 dispatch_table[KDP_INVALID_REQUEST-KDP_CONNECT] = 64 { 65/* 0 */ kdp_connect, 66/* 1 */ kdp_disconnect, 67/* 2 */ kdp_hostinfo, 68/* 3 */ kdp_version, 69/* 4 */ kdp_maxbytes, 70/* 5 */ kdp_readmem, 71/* 6 */ kdp_writemem, 72/* 7 */ kdp_readregs, 73/* 8 */ kdp_writeregs, 74/* 9 */ kdp_unknown, 75/* A */ kdp_unknown, 76/* B */ kdp_suspend, 77/* C */ kdp_resumecpus, 78/* D */ kdp_unknown, 79/* E */ kdp_unknown, 80/* F */ kdp_breakpoint_set, 81/*10 */ kdp_breakpoint_remove, 82/*11 */ kdp_regions, 83/*12 */ kdp_reattach, 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, 91/*1A */ kdp_writephysmem64, 92/*1B */ kdp_readioport, 93/*1C */ kdp_writeioport, 94/*1D */ kdp_readmsr64, 95/*1E */ kdp_writemsr64, 96/*1F */ kdp_dumpinfo, 97 }; 98 99kdp_glob_t kdp; 100 101#define MAX_BREAKPOINTS 100 102 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 107 * memory with 64-bit wide memory addresses. 108 */ 109#define KDP_VERSION 12 110 111typedef struct{ 112 mach_vm_address_t address; 113 uint32_t bytesused; 114 uint8_t oldbytes[MAX_BREAKINSN_BYTES]; 115} kdp_breakpoint_record_t; 116 117static kdp_breakpoint_record_t breakpoint_list[MAX_BREAKPOINTS]; 118static unsigned int breakpoints_initialized = 0; 119 120int reattach_wait = 0; 121int noresume_on_disconnect = 0; 122extern unsigned int return_on_panic; 123 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 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; 143 size_t plen = *len; 144 kdp_req_t req; 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) { 153 printf("kdp_packet bad len pkt %lu hdr %d\n", plen, rd->hdr.len); 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; 166 if (req >= KDP_INVALID_REQUEST) { 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, 183 __unused int *len, 184 __unused unsigned short *reply_port 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; 203 size_t plen = *len; 204 kdp_connect_reply_t *rp = &pkt->connect_reply; 205 uint16_t rport, eport; 206 uint32_t key; 207 uint8_t seq; 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 214 rport = rq->req_reply_port; 215 eport = rq->exc_note_port; 216 key = rq->hdr.key; 217 seq = rq->hdr.seq; 218 if (kdp.is_conn) { 219 if ((seq == kdp.conn_seq) && /* duplicate request */ 220 (rport == kdp.reply_port) && 221 (eport == kdp.exception_port) && 222 (key == kdp.session_key)) 223 rp->error = KDPERR_NO_ERROR; 224 else 225 rp->error = KDPERR_ALREADY_CONNECTED; 226 } 227 else { 228 kdp.reply_port = rport; 229 kdp.exception_port = eport; 230 kdp.is_conn = TRUE; 231 kdp.conn_seq = seq; 232 kdp.session_key = key; 233 234 rp->error = KDPERR_NO_ERROR; 235 } 236 237 rp->hdr.is_reply = 1; 238 rp->hdr.len = sizeof (*rp); 239 240 *reply_port = rport; 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; 257 size_t plen = *len; 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; 273 kdp.session_key = 0; 274 275 if ((panicstr != NULL) && (return_on_panic == 0)) 276 reattach_wait = 1; 277 278 if (noresume_on_disconnect == 1) { 279 reattach_wait = 1; 280 noresume_on_disconnect = 0; 281 } 282 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 294static boolean_t 295kdp_reattach( 296 kdp_pkt_t *pkt, 297 int *len, 298 unsigned short *reply_port 299) 300{ 301 kdp_reattach_req_t *rq = &pkt->reattach_req; 302 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); 308} 309 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; 318 size_t plen = *len; 319 kdp_hostinfo_reply_t *rp = &pkt->hostinfo_reply; 320 321 if (plen < sizeof (*rq)) 322 return (FALSE); 323 324 dprintf(("kdp_hostinfo\n")); 325 326 rp->hdr.is_reply = 1; 327 rp->hdr.len = sizeof (*rp); 328 329 kdp_machine_hostinfo(&rp->hostinfo); 330 331 *reply_port = kdp.reply_port; 332 *len = rp->hdr.len; 333 334 return (TRUE); 335} 336 337static boolean_t 338kdp_kernelversion( 339 kdp_pkt_t *pkt, 340 int *len, 341 unsigned short *reply_port 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")); 356 slen = strlcpy(rp->version, kdp_kernelversion_string, MAX_KDP_DATA_SIZE); 357 358 rp->hdr.len += slen + 1; /* strlcpy returns the amount copied with NUL */ 359 360 *reply_port = kdp.reply_port; 361 *len = rp->hdr.len; 362 363 return (TRUE); 364} 365 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; 374 size_t plen = *len; 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; 401 size_t plen = *len; 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)); 411 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; 428 size_t plen = *len; 429 kdp_writemem_reply_t *rp = &pkt->writemem_reply; 430 mach_vm_size_t cnt; 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)); 439 cnt = kdp_machine_vm_write((caddr_t)rq->data, (mach_vm_address_t)rq->address, rq->nbytes); 440 rp->error = KDPERR_ACCESS(rq->nbytes, cnt); 441 dprintf((" cnt %lld error %d\n", cnt, rp->error)); 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 453static boolean_t 454kdp_writemem64( 455 kdp_pkt_t *pkt, 456 int *len, 457 unsigned short *reply_port 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) 469 rp->error = KDPERR_BAD_NBYTES; 470 else { 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)); 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( 488 kdp_pkt_t *pkt, 489 int *len, 490 unsigned short *reply_port 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; 496 mach_vm_size_t cnt; 497 unsigned int size; 498 499 if (plen < sizeof (*rq)) 500 return (FALSE); 501 502 size = rq->nbytes; 503 if (size > MAX_KDP_DATA_SIZE) 504 rp->error = KDPERR_BAD_NBYTES; 505 else { 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)); 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 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; 529 size_t plen = *len; 530 kdp_readmem_reply_t *rp = &pkt->readmem_reply; 531 mach_vm_size_t cnt; 532 unsigned int size; 533 534 if (plen < sizeof (*rq)) 535 return (FALSE); 536 537 rp->hdr.is_reply = 1; 538 rp->hdr.len = sizeof (*rp); 539 540 size = rq->nbytes; 541 if (size > MAX_KDP_DATA_SIZE) 542 rp->error = KDPERR_BAD_NBYTES; 543 else { 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)); 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 558static boolean_t 559kdp_readmem64( 560 kdp_pkt_t *pkt, 561 int *len, 562 unsigned short *reply_port 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; 568 mach_vm_size_t cnt; 569 unsigned int size; 570 571 if (plen < sizeof (*rq)) 572 return (FALSE); 573 574 rp->hdr.is_reply = 1; 575 rp->hdr.len = sizeof (*rp); 576 577 size = rq->nbytes; 578 if (size > MAX_KDP_DATA_SIZE) 579 rp->error = KDPERR_BAD_NBYTES; 580 else { 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)); 585 586 rp->hdr.len += cnt; 587 } 588 589 *reply_port = kdp.reply_port; 590 *len = rp->hdr.len; 591 592 return (TRUE); 593} 594 595static boolean_t 596kdp_readphysmem64( 597 kdp_pkt_t *pkt, 598 int *len, 599 unsigned short *reply_port 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; 605 mach_vm_size_t cnt; 606 unsigned int size; 607 608 if (plen < sizeof (*rq)) 609 return (FALSE); 610 611 rp->hdr.is_reply = 1; 612 rp->hdr.len = sizeof (*rp); 613 614 size = rq->nbytes; 615 if (size > MAX_KDP_DATA_SIZE) 616 rp->error = KDPERR_BAD_NBYTES; 617 else { 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)); 622 623 rp->hdr.len += cnt; 624 } 625 626 *reply_port = kdp.reply_port; 627 *len = rp->hdr.len; 628 629 return (TRUE); 630} 631 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; 640 size_t plen = *len; 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 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; 667 size_t plen = *len; 668 kdp_version_reply_t *rp = &pkt->version_reply; 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; 679 if (!(kdp_flag & KDP_BP_DIS)) 680 rp->feature = KDP_FEATURE_BP; 681 else 682 rp->feature = 0; 683 684 *reply_port = kdp.reply_port; 685 *len = rp->hdr.len; 686 687 return (TRUE); 688} 689 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; 698 size_t plen = *len; 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 713 r->address = 0; 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; 734 size_t plen = *len; 735 int size; 736 kdp_writeregs_reply_t *rp = &pkt->writeregs_reply; 737 738 if (plen < sizeof (*rq)) 739 return (FALSE); 740 741 size = rq->hdr.len - (unsigned)sizeof(kdp_hdr_t) - (unsigned)sizeof(unsigned int); 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; 761 size_t plen = *len; 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} 779 780 781boolean_t 782kdp_breakpoint_set( 783 kdp_pkt_t *pkt, 784 int *len, 785 unsigned short *reply_port 786) 787{ 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)); 797 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} 809 810boolean_t 811kdp_breakpoint64_set( 812 kdp_pkt_t *pkt, 813 int *len, 814 unsigned short *reply_port 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)); 826 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} 838 839boolean_t 840kdp_breakpoint_remove( 841 kdp_pkt_t *pkt, 842 int *len, 843 unsigned short *reply_port 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)); 854 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); 865} 866 867boolean_t 868kdp_breakpoint64_remove( 869 kdp_pkt_t *pkt, 870 int *len, 871 unsigned short *reply_port 872) 873{ 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)); 883 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} 895 896 897kdp_error_t 898kdp_set_breakpoint_internal( 899 mach_vm_address_t address 900) 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++; 914 } 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} 938 939kdp_error_t 940kdp_remove_breakpoint_internal( 941 mach_vm_address_t address 942) 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) 950 { 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; 958} 959 960boolean_t 961kdp_remove_all_breakpoints(void) 962{ 963 int i; 964 boolean_t breakpoint_found = FALSE; 965 966 if (breakpoints_initialized) 967 { 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"); 980 } 981 return breakpoint_found; 982} 983 984boolean_t 985kdp_reboot( 986 __unused kdp_pkt_t *pkt, 987 __unused int *len, 988 __unused unsigned short *reply_port 989) 990{ 991 dprintf(("kdp_reboot\n")); 992 993 kdp_machine_reboot(); 994 995 return (TRUE); // no, not really, we won't return 996} 997 998static boolean_t 999kdp_readioport( 1000 kdp_pkt_t *pkt, 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 1068kdp_readmsr64( 1069 kdp_pkt_t *pkt, 1070 int *len, 1071 unsigned short *reply_port 1072) 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} 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} 1153 1154