+ pcb->insn_state->insn_stream_valid_bytes = (int)(end_addr - start_addr);
+ pcb->insn_state->insn_offset = (int)insn_offset;
+
+#if DEVELOPMENT || DEBUG
+ /* Now try to validate the cacheline we read at early-fault time matches the code
+ * copied in. Before we do that, we have to make sure the buffer contains a valid
+ * cacheline by looking for the 2 sentinel values written in the event the cacheline
+ * could not be copied.
+ */
+#define CACHELINE_DATA_NOT_PRESENT 0xdeadc0debeefcafeULL
+#define CACHELINE_MASK (CACHELINE_SIZE - 1)
+
+ if (inspect_cacheline &&
+ (*(uint64_t *)(uintptr_t)&pcb->insn_cacheline[0] != CACHELINE_DATA_NOT_PRESENT &&
+ *(uint64_t *)(uintptr_t)&pcb->insn_cacheline[8] != CACHELINE_DATA_NOT_PRESENT)) {
+ /*
+ * The position of the cacheline in the instruction buffer is at offset
+ * insn_offset - (rip & CACHELINE_MASK)
+ */
+ if (__improbable((rip & CACHELINE_MASK) > insn_offset)) {
+ printf("thread %p code cacheline @ %p clipped wrt copied-in code (offset %d)\n",
+ thread, (void *)(rip & ~CACHELINE_MASK), (int)(rip & CACHELINE_MASK));
+ } else if (bcmp(&pcb->insn_state->insn_bytes[insn_offset - (rip & CACHELINE_MASK)],
+ &pcb->insn_cacheline[0], CACHELINE_SIZE) != 0
+ || insnstream_force_cacheline_mismatch
+ ) {
+#if x86_INSTRUCTION_STATE_CACHELINE_SIZE != CACHELINE_SIZE
+#error cacheline size mismatch
+#endif
+ bcopy(&pcb->insn_cacheline[0], &pcb->insn_state->insn_cacheline[0],
+ x86_INSTRUCTION_STATE_CACHELINE_SIZE);
+ /* Mark the instruction stream as being out-of-synch */
+ pcb->insn_state->out_of_synch = 1;
+
+ printf("thread %p code cacheline @ %p mismatches with copied-in code [trap 0x%x]\n",
+ thread, (void *)(rip & ~CACHELINE_MASK), trap_code);
+ for (int i = 0; i < 8; i++) {
+ printf("\t[%d] cl=0x%08llx vs. ci=0x%08llx\n", i, *(uint64_t *)(uintptr_t)&pcb->insn_cacheline[i * 8],
+ *(uint64_t *)(uintptr_t)&pcb->insn_state->insn_bytes[(i * 8) + insn_offset - (rip & CACHELINE_MASK)]);
+ }
+ if (panic_on_cacheline_mismatch) {
+ panic("Cacheline mismatch while processing unhandled exception.");
+ }
+ } else {
+ printf("thread %p code cacheline @ %p DOES match with copied-in code\n",
+ thread, (void *)(rip & ~CACHELINE_MASK));
+ pcb->insn_state->out_of_synch = 0;
+ }
+ } else if (inspect_cacheline) {
+ printf("thread %p could not capture code cacheline at fault IP %p [offset %d]\n",
+ (void *)thread, (void *)rip, (int)(insn_offset - (rip & CACHELINE_MASK)));
+ pcb->insn_state->out_of_synch = 0;
+ }
+#else
+ pcb->insn_state->out_of_synch = 0;
+#endif /* DEVELOPMENT || DEBUG */
+
+#if defined(MACH_BSD) && (DEVELOPMENT || DEBUG)
+ if (panic_on_trap_procname[0] != 0) {
+ char procnamebuf[65] = {0};
+
+ if (thread->task->bsd_info != NULL) {
+ procname = proc_name_address(thread->task->bsd_info);
+ strlcpy(procnamebuf, procname, sizeof(procnamebuf));
+
+ if (strcasecmp(panic_on_trap_procname, procnamebuf) == 0 &&
+ ((1U << trap_code) & panic_on_trap_mask) != 0) {
+ panic("Panic requested on trap type 0x%x for process `%s'", trap_code,
+ panic_on_trap_procname);
+ /*NORETURN*/
+ }
+ }
+ }
+#endif /* MACH_BSD && (DEVELOPMENT || DEBUG) */
+ }
+ } else {
+ enable_preemption();