]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/kdp/kdp_core.c
xnu-6153.11.26.tar.gz
[apple/xnu.git] / osfmk / kdp / kdp_core.c
index ac71c806165f94d3dfd6e03c215b1f888a36fec6..5971b1cfe29116bf3b8c420e97e8cac3b2137ea0 100644 (file)
@@ -178,6 +178,10 @@ boolean_t kdp_has_polled_corefile(void)
     return (NULL != gIOPolledCoreFileVars);
 }
 
+kern_return_t kdp_polled_corefile_error(void)
+{
+    return gIOPolledCoreFileOpenRet;
+}
 #if CONFIG_EMBEDDED
 /*
  * Whenever we start a coredump, make sure the buffers
@@ -461,7 +465,7 @@ kern_dump_disk_proc(unsigned int request, __unused char *corename,
         case KDP_DATA:
            err = IOPolledFileWrite(gIOPolledCoreFileVars, data, length, NULL);
            if (kIOReturnSuccess != err) {
-                   kern_coredump_log(NULL, "IOPolledFileWrite(gIOPolledCoreFileVars, 0x%p, 0x%llx, NULL) returned 0x%x\n",
+                   kern_coredump_log(NULL, "IOPolledFileWrite(gIOPolledCoreFileVars, %p, 0x%llx, NULL) returned 0x%x\n",
                                    data, length, err);
                    break;
            }
@@ -510,7 +514,7 @@ kdp_core_zoutput(z_streamp strm, Bytef *buf, unsigned len)
     {
        if ((ret = (*vars->outproc)(KDP_DATA, NULL, len, buf)) != kIOReturnSuccess)
        { 
-           kern_coredump_log(NULL, "(kdp_core_zoutput) outproc(KDP_DATA, NULL, 0x%x, 0x%p) returned 0x%x\n",
+           kern_coredump_log(NULL, "(kdp_core_zoutput) outproc(KDP_DATA, NULL, 0x%x, %p) returned 0x%x\n",
                            len, buf, ret);
            vars->error = ret;
        }
@@ -553,7 +557,7 @@ kdp_core_zoutputbuf(z_streamp strm, Bytef *inbuf, unsigned inlen)
                                        vars->outlen - vars->outremain, 
                                        vars->outbuf)) != kIOReturnSuccess)
        { 
-           kern_coredump_log(NULL, "(kdp_core_zoutputbuf) outproc(KDP_DATA, NULL, 0x%x, 0x%p) returned 0x%x\n",
+           kern_coredump_log(NULL, "(kdp_core_zoutputbuf) outproc(KDP_DATA, NULL, 0x%x, %p) returned 0x%x\n",
                            (vars->outlen - vars->outremain), vars->outbuf, ret);
            vars->error = ret;
        }
@@ -708,7 +712,7 @@ kernel_pmap_present_mapping(uint64_t vaddr, uint64_t * pvincr, uintptr_t * pvphy
         vincr = kdp_core_ramdisk_size;
     }
     else
-#if defined(__arm64__)
+#if defined(__arm64__) && defined(CONFIG_XNUPOST)
     if (vaddr == _COMM_HIGH_PAGE64_BASE_ADDRESS)
     {
        /* not readable */
@@ -733,12 +737,11 @@ kernel_pmap_present_mapping(uint64_t vaddr, uint64_t * pvincr, uintptr_t * pvphy
     if (ppn && pvphysaddr)
     {
         uint64_t phys = ptoa_64(ppn);
-#if defined(__arm__) || defined(__arm64__)
-        if (isphysmem(phys))        *pvphysaddr = phystokv(phys);
-#else
-        if (physmap_enclosed(phys)) *pvphysaddr = (uintptr_t)PHYSMAP_PTOV(phys);
-#endif
-        else                        ppn = 0;
+        if (physmap_enclosed(phys)) {
+               *pvphysaddr = phystokv(phys);
+        } else {
+               ppn = 0;
+       }
     }
 
     return (ppn);
@@ -754,16 +757,18 @@ pmap_traverse_present_mappings(pmap_t __unused pmap,
     IOReturn        ret;
     vm_map_offset_t vcurstart, vcur;
     uint64_t        vincr = 0;
-    vm_map_offset_t debug_start;
-    vm_map_offset_t debug_end;
+    vm_map_offset_t debug_start = trunc_page((vm_map_offset_t) debug_buf_base);
+    vm_map_offset_t debug_end = round_page((vm_map_offset_t) (debug_buf_base + debug_buf_size));
+#if defined(XNU_TARGET_OS_BRIDGE)
+    vm_map_offset_t macos_panic_start = trunc_page((vm_map_offset_t) macos_panic_base);
+    vm_map_offset_t macos_panic_end = round_page((vm_map_offset_t) (macos_panic_base + macos_panic_size));
+#endif
+
     boolean_t       lastvavalid;
 #if defined(__arm__) || defined(__arm64__)
     vm_page_t m = VM_PAGE_NULL;
 #endif
 
-    debug_start = trunc_page((vm_map_offset_t) debug_buf_base);
-    debug_end   = round_page((vm_map_offset_t) (debug_buf_base + debug_buf_size));
-
 #if defined(__x86_64__)
     assert(!is_ept_pmap(pmap));
 #endif
@@ -795,22 +800,25 @@ pmap_traverse_present_mappings(pmap_t __unused pmap,
                    ppn = VM_PAGE_GET_PHYS_PAGE(m);
                    break;
                }
-               m = (vm_page_t)vm_page_queue_next(&m->listq);
-           }
-           vcur = phystokv(ptoa(ppn));
-           if (vcur != vprev)
-           {
-               ret = callback(vcurstart, vprev, context);
-               lastvavalid = FALSE;
+               m = (vm_page_t)vm_page_queue_next(&m->vmp_listq);
            }
            vincr = PAGE_SIZE_64;
            if (ppn == atop(avail_end))
            {
                vm_object_unlock(&pmap_object_store);
                m = VM_PAGE_NULL;
+               // avail_end is not a valid physical address,
+               // so phystokv(avail_end) may not produce the expected result.
+               vcur = phystokv(avail_start) + (avail_end - avail_start);
+           } else {
+               m = (vm_page_t)vm_page_queue_next(&m->vmp_listq);
+               vcur = phystokv(ptoa(ppn));
+           }
+           if (vcur != vprev)
+           {
+               ret = callback(vcurstart, vprev, context);
+               lastvavalid = FALSE;
            }
-           else
-               m = (vm_page_t)vm_page_queue_next(&m->listq);
        }
        if (m == VM_PAGE_NULL)
            ppn = kernel_pmap_present_mapping(vcur, &vincr, NULL);
@@ -820,8 +828,12 @@ pmap_traverse_present_mappings(pmap_t __unused pmap,
        if (ppn != 0)
        {
            if (((vcur < debug_start) || (vcur >= debug_end))
-               && !(EFI_VALID_PAGE(ppn) ||
-                    pmap_valid_page(ppn)))
+               && !(EFI_VALID_PAGE(ppn) || pmap_valid_page(ppn))
+#if defined(XNU_TARGET_OS_BRIDGE)
+               // include the macOS panic region if it's mapped
+               && ((vcur < macos_panic_start) || (vcur >= macos_panic_end))
+#endif
+               )
            {
                /* not something we want */
                ppn = 0;
@@ -843,7 +855,7 @@ pmap_traverse_present_mappings(pmap_t __unused pmap,
 
 #if defined(__x86_64__)
            /* Try to skip by 2MB if possible */
-           if (((vcur & PDMASK) == 0) && cpu_64bit) {
+           if ((vcur & PDMASK) == 0) {
                pd_entry_t *pde;
                pde = pmap_pde(pmap, vcur);
                if (0 == pde || ((*pde & INTEL_PTE_VALID) == 0)) {
@@ -862,6 +874,13 @@ pmap_traverse_present_mappings(pmap_t __unused pmap,
        /* send previous run */
        ret = callback(vcurstart, vcur, context);
     }
+
+#if KASAN
+    if (ret == KERN_SUCCESS) {
+       ret = kasan_traverse_mappings(callback, context);
+    }
+#endif
+
     return (ret);
 }
 
@@ -1059,13 +1078,13 @@ kern_dump_update_header(struct kdp_core_out_vars *outvars)
        /* Write the file header -- first seek to the beginning of the file */
        foffset = 0;
        if ((ret = (outvars->outproc)(KDP_SEEK, NULL, sizeof(foffset), &foffset)) != kIOReturnSuccess) {
-               kern_coredump_log(NULL, "(kern_dump_update_header) outproc(KDP_SEEK, NULL, %lu, 0x%p) foffset = 0x%llx returned 0x%x\n",
+               kern_coredump_log(NULL, "(kern_dump_update_header) outproc(KDP_SEEK, NULL, %lu, %p) foffset = 0x%llx returned 0x%x\n",
                                sizeof(foffset), &foffset, foffset, ret);
                return ret;
        }
 
        if ((ret = (outvars->outproc)(KDP_DATA, NULL, sizeof(kdp_core_header), &kdp_core_header)) != kIOReturnSuccess) {
-               kern_coredump_log(NULL, "(kern_dump_update_header) outproc(KDP_DATA, NULL, %lu, 0x%p) returned 0x%x\n",
+               kern_coredump_log(NULL, "(kern_dump_update_header) outproc(KDP_DATA, NULL, %lu, %p) returned 0x%x\n",
                                sizeof(kdp_core_header), &kdp_core_header, ret);
                 return ret;
        }
@@ -1118,7 +1137,7 @@ kern_dump_seek_to_next_file(void *kdp_core_out_vars, uint64_t next_file_offset)
        int ret;
 
        if ((ret = (outvars->outproc)(KDP_SEEK, NULL, sizeof(next_file_offset), &next_file_offset)) != kIOReturnSuccess) {
-               kern_coredump_log(NULL, "(kern_dump_seek_to_next_file) outproc(KDP_SEEK, NULL, %lu, 0x%p) foffset = 0x%llx returned 0x%x\n",
+               kern_coredump_log(NULL, "(kern_dump_seek_to_next_file) outproc(KDP_SEEK, NULL, %lu, %p) foffset = 0x%llx returned 0x%x\n",
                                sizeof(next_file_offset), &next_file_offset, next_file_offset, ret);
        }
 
@@ -1156,7 +1175,7 @@ do_kern_dump(kern_dump_output_proc outproc, enum kern_dump_type kd_variant)
 
        assert (existing_log_size <= debug_buf_size);
 
-       if (kd_variant == KERN_DUMP_DISK) {
+       if ((kd_variant == KERN_DUMP_DISK) || (kd_variant == KERN_DUMP_STACKSHOT_DISK)) {
                /* Open the file for output */
                if ((ret = (*outproc)(KDP_WRQ, NULL, 0, NULL)) != kIOReturnSuccess) {
                        kern_coredump_log(NULL, "outproc(KDP_WRQ, NULL, 0, NULL) returned 0x%x\n", ret);
@@ -1170,7 +1189,7 @@ do_kern_dump(kern_dump_output_proc outproc, enum kern_dump_type kd_variant)
        bzero(&outvars, sizeof(outvars));
        outvars.outproc = outproc;
 
-       if (kd_variant == KERN_DUMP_DISK) {
+       if ((kd_variant == KERN_DUMP_DISK) || (kd_variant == KERN_DUMP_STACKSHOT_DISK)) {
                outvars.zoutput     = kdp_core_zoutput;
                /* Space for file header, panic log, core log */
                foffset = (KERN_COREDUMP_HEADERSIZE + existing_log_size + KERN_COREDUMP_MAXDEBUGLOGSIZE +
@@ -1179,7 +1198,7 @@ do_kern_dump(kern_dump_output_proc outproc, enum kern_dump_type kd_variant)
 
                /* Seek the calculated offset (we'll scrollback later to flush the logs and header) */
                if ((ret = (*outproc)(KDP_SEEK, NULL, sizeof(foffset), &foffset)) != kIOReturnSuccess) {
-                       kern_coredump_log(NULL, "(do_kern_dump seek begin) outproc(KDP_SEEK, NULL, %lu, 0x%p) foffset = 0x%llx returned 0x%x\n",
+                       kern_coredump_log(NULL, "(do_kern_dump seek begin) outproc(KDP_SEEK, NULL, %lu, %p) foffset = 0x%llx returned 0x%x\n",
                                        sizeof(foffset), &foffset, foffset, ret);
                        dump_succeeded = FALSE;
                        goto exit;
@@ -1201,6 +1220,35 @@ do_kern_dump(kern_dump_output_proc outproc, enum kern_dump_type kd_variant)
        kern_coredump_log(NULL, "%s", (kd_variant == KERN_DUMP_DISK) ? "Writing local cores..." :
                       "Transmitting kernel state, please wait:\n");
 
+
+#if defined(__x86_64__)
+       if (((kd_variant == KERN_DUMP_STACKSHOT_DISK) || (kd_variant == KERN_DUMP_DISK)) && ((panic_stackshot_buf != 0) && (panic_stackshot_len != 0))) {
+               uint64_t compressed_stackshot_len = 0;
+
+               if ((ret = kdp_reset_output_vars(&outvars, panic_stackshot_len)) != KERN_SUCCESS) {
+                       kern_coredump_log(NULL, "Failed to reset outvars for stackshot with len 0x%zx, returned 0x%x\n", panic_stackshot_len, ret);
+                       dump_succeeded = FALSE;
+               } else if ((ret = kdp_core_output(&outvars, panic_stackshot_len, (void *)panic_stackshot_buf)) != KERN_SUCCESS) {
+                       kern_coredump_log(NULL, "Failed to write panic stackshot to file, kdp_coreoutput(outvars, %lu, %p) returned 0x%x\n",
+                                      panic_stackshot_len, (void *) panic_stackshot_buf, ret);
+                       dump_succeeded = FALSE;
+               } else if ((ret = kdp_core_output(&outvars, 0, NULL)) != KERN_SUCCESS) {
+                       kern_coredump_log(NULL, "Failed to flush stackshot data : kdp_core_output(%p, 0, NULL) returned 0x%x\n", &outvars, ret);
+                       dump_succeeded = FALSE;
+               } else if ((ret = kern_dump_record_file(&outvars, "panic_stackshot.kcdata", foffset, &compressed_stackshot_len)) != KERN_SUCCESS) {
+                       kern_coredump_log(NULL, "Failed to record panic stackshot in corefile header, kern_dump_record_file returned 0x%x\n", ret);
+                       dump_succeeded = FALSE;
+               } else {
+                       kern_coredump_log(NULL, "Recorded panic stackshot in corefile at offset 0x%llx, compressed to %llu bytes\n", foffset, compressed_stackshot_len);
+                       foffset = roundup((foffset + compressed_stackshot_len), KERN_COREDUMP_BEGIN_FILEBYTES_ALIGN);
+                       if ((ret = kern_dump_seek_to_next_file(&outvars, foffset)) != kIOReturnSuccess) {
+                               kern_coredump_log(NULL, "Failed to seek to stackshot file offset 0x%llx, kern_dump_seek_to_next_file returned 0x%x\n", foffset, ret);
+                               dump_succeeded = FALSE;
+                       }
+               }
+       }
+#endif
+
        if (kd_variant == KERN_DUMP_DISK) {
                /*
                 * Dump co-processors as well, foffset will be overwritten with the
@@ -1209,7 +1257,7 @@ do_kern_dump(kern_dump_output_proc outproc, enum kern_dump_type kd_variant)
                if (kern_do_coredump(&outvars, FALSE, foffset, &foffset) != 0) {
                        dump_succeeded = FALSE;
                }
-       } else {
+       } else if (kd_variant != KERN_DUMP_STACKSHOT_DISK) {
                /* Only the kernel */
                if (kern_do_coredump(&outvars, TRUE, foffset, &foffset) != 0) {
                        dump_succeeded = FALSE;
@@ -1217,38 +1265,10 @@ do_kern_dump(kern_dump_output_proc outproc, enum kern_dump_type kd_variant)
        }
 
        if (kd_variant == KERN_DUMP_DISK) {
-#if defined(__x86_64__) && (DEVELOPMENT || DEBUG)
-               /* Write the macOS panic stackshot on its own to a separate 'corefile' */
-               if (panic_stackshot_buf && panic_stackshot_len) {
-                       uint64_t compressed_stackshot_len = 0;
-
-                       /* Seek to the offset of the next 'file' (foffset provided/updated from kern_do_coredump) */
-                       if ((ret = kern_dump_seek_to_next_file(&outvars, foffset)) != kIOReturnSuccess) {
-                               kern_coredump_log(NULL, "Failed to seek to stackshot file offset 0x%llx, kern_dump_seek_to_next_file returned 0x%x\n", foffset, ret);
-                               dump_succeeded = FALSE;
-                       } else if ((ret = kdp_reset_output_vars(&outvars, panic_stackshot_len)) != KERN_SUCCESS) {
-                               kern_coredump_log(NULL, "Failed to reset outvars for stackshot with len 0x%zx, returned 0x%x\n", panic_stackshot_len, ret);
-                               dump_succeeded = FALSE;
-                       } else if ((ret = kdp_core_output(&outvars, panic_stackshot_len, (void *)panic_stackshot_buf)) != KERN_SUCCESS) {
-                               kern_coredump_log(NULL, "Failed to write panic stackshot to file, kdp_coreoutput(outvars, %lu, 0x%p) returned 0x%x\n",
-                                              panic_stackshot_len, (void *) panic_stackshot_buf, ret);
-                               dump_succeeded = FALSE;
-                       } else if ((ret = kdp_core_output(&outvars, 0, NULL)) != KERN_SUCCESS) {
-                               kern_coredump_log(NULL, "Failed to flush stackshot data : kdp_core_output(0x%p, 0, NULL) returned 0x%x\n", &outvars, ret);
-                               dump_succeeded = FALSE;
-                       } else if ((ret = kern_dump_record_file(&outvars, "panic_stackshot.kcdata", foffset, &compressed_stackshot_len)) != KERN_SUCCESS) {
-                               kern_coredump_log(NULL, "Failed to record panic stackshot in corefile header, kern_dump_record_file returned 0x%x\n", ret);
-                               dump_succeeded = FALSE;
-                       } else {
-                               kern_coredump_log(NULL, "Recorded panic stackshot in corefile at offset 0x%llx, compressed to %llu bytes\n", foffset, compressed_stackshot_len);
-                       }
-               }
-#endif /* defined(__x86_64__) && (DEVELOPMENT || DEBUG) */
-
                /* Write the debug log -- first seek to the end of the corefile header */
                foffset = KERN_COREDUMP_HEADERSIZE;
                if ((ret = (*outproc)(KDP_SEEK, NULL, sizeof(foffset), &foffset)) != kIOReturnSuccess) {
-                       kern_coredump_log(NULL, "(do_kern_dump seek logfile) outproc(KDP_SEEK, NULL, %lu, 0x%p) foffset = 0x%llx returned 0x%x\n",
+                       kern_coredump_log(NULL, "(do_kern_dump seek logfile) outproc(KDP_SEEK, NULL, %lu, %p) foffset = 0x%llx returned 0x%x\n",
                                        sizeof(foffset), &foffset, foffset, ret);
                        dump_succeeded = FALSE;
                        goto exit;
@@ -1274,7 +1294,7 @@ do_kern_dump(kern_dump_output_proc outproc, enum kern_dump_type kd_variant)
                 */
                buf = debug_buf_base;
                if ((ret = (*outproc)(KDP_DATA, NULL, existing_log_size, buf)) != kIOReturnSuccess) {
-                               kern_coredump_log(NULL, "(do_kern_dump paniclog) outproc(KDP_DATA, NULL, %lu, 0x%p) returned 0x%x\n",
+                               kern_coredump_log(NULL, "(do_kern_dump paniclog) outproc(KDP_DATA, NULL, %lu, %p) returned 0x%x\n",
                                                existing_log_size, buf, ret);
                                dump_succeeded = FALSE;
                                goto exit;
@@ -1295,7 +1315,7 @@ do_kern_dump(kern_dump_output_proc outproc, enum kern_dump_type kd_variant)
 
                /* Write the coredump log */
                if ((ret = (*outproc)(KDP_DATA, NULL, new_log_len, buf)) != kIOReturnSuccess) {
-                       kern_coredump_log(NULL, "(do_kern_dump coredump log) outproc(KDP_DATA, NULL, %lu, 0x%p) returned 0x%x\n",
+                       kern_coredump_log(NULL, "(do_kern_dump coredump log) outproc(KDP_DATA, NULL, %lu, %p) returned 0x%x\n",
                                        new_log_len, buf, ret);
                        dump_succeeded = FALSE;
                        goto exit;
@@ -1342,14 +1362,14 @@ kern_dump(enum kern_dump_type kd_variant)
 #if KASAN
        kasan_disable();
 #endif
-       if (kd_variant == KERN_DUMP_DISK) {
+       if ((kd_variant == KERN_DUMP_DISK) || (kd_variant == KERN_DUMP_STACKSHOT_DISK)) {
                if (dumped_local) return (0);
                if (local_dump_in_progress) return (-1);
                local_dump_in_progress = TRUE;
 #if CONFIG_EMBEDDED
                hwsd_info->xhsdci_status = XHSDCI_STATUS_KERNEL_BUSY;
 #endif
-               ret = do_kern_dump(&kern_dump_disk_proc, KERN_DUMP_DISK);
+               ret = do_kern_dump(&kern_dump_disk_proc, kd_variant);
                if (ret == 0) {
                        dumped_local = TRUE;
                        kern_dump_successful = TRUE;
@@ -1375,17 +1395,18 @@ kern_dump(enum kern_dump_type kd_variant)
 }
 
 #if CONFIG_EMBEDDED
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wmissing-noreturn"
 void
 panic_spin_shmcon()
 {
-#pragma clang diagnostic pop
+       if (hwsd_info == NULL) {
+               kern_coredump_log(NULL, "handshake structure not initialized\n");
+               return;
+       }
+
        kern_coredump_log(NULL, "\nPlease go to https://panic.apple.com to report this panic\n");
        kern_coredump_log(NULL, "Waiting for hardware shared memory debugger, handshake structure is at virt: %p, phys %p\n",
                        hwsd_info, (void *)kvtophys((vm_offset_t)hwsd_info));
 
-       assert(hwsd_info != NULL);
        hwsd_info->xhsdci_status = XHSDCI_STATUS_KERNEL_READY;
        hwsd_info->xhsdci_seq_no = 0;
        FlushPoC_DcacheRegion((vm_offset_t) hwsd_info, sizeof(*hwsd_info));
@@ -1533,12 +1554,6 @@ kdp_core_init(void)
        PE_consistent_debug_register(kDbgIdAstrisConnection, kvtophys((vm_offset_t) hwsd_info), sizeof(pmap_paddr_t));
        PE_consistent_debug_register(kDbgIdAstrisConnectionVers, CUR_XNU_HWSDCI_STRUCT_VERS, sizeof(uint32_t));
 #endif /* CONFIG_EMBEDDED */
-
-#if defined(__x86_64__) && (DEVELOPMENT || DEBUG)
-       /* Allocate space in the kernel map for the panic stackshot */
-       kr = kmem_alloc(kernel_map, &panic_stackshot_buf, PANIC_STACKSHOT_BUFSIZE, VM_KERN_MEMORY_DIAG);
-       assert (KERN_SUCCESS == kr);
-#endif /* defined(__x86_64__) && (DEVELOPMENT || DEBUG) */
 }
 
 #endif /* CONFIG_KDP_INTERACTIVE_DEBUGGING */