+
+ case x86_PAGEIN_STATE:
+ {
+ if (*count < x86_PAGEIN_STATE_COUNT) {
+ return KERN_INVALID_ARGUMENT;
+ }
+
+ x86_pagein_state_t *state = (void *)tstate;
+
+ state->__pagein_error = thr_act->t_pagein_error;
+
+ *count = x86_PAGEIN_STATE_COUNT;
+ break;
+ }
+
+ case x86_INSTRUCTION_STATE:
+ {
+ if (*count < x86_INSTRUCTION_STATE_COUNT) {
+ return KERN_INVALID_ARGUMENT;
+ }
+
+ x86_instruction_state_t *state = (void *)tstate;
+ x86_instruction_state_t *src_state = THREAD_TO_PCB(thr_act)->insn_state;
+
+ if (src_state != 0 && (src_state->insn_stream_valid_bytes > 0 || src_state->out_of_synch)) {
+#if DEVELOPMENT || DEBUG
+ extern int insnstream_force_cacheline_mismatch;
+#endif
+ size_t byte_count = (src_state->insn_stream_valid_bytes > x86_INSTRUCTION_STATE_MAX_INSN_BYTES)
+ ? x86_INSTRUCTION_STATE_MAX_INSN_BYTES : src_state->insn_stream_valid_bytes;
+ if (byte_count > 0) {
+ bcopy(src_state->insn_bytes, state->insn_bytes, byte_count);
+ }
+ state->insn_offset = src_state->insn_offset;
+ state->insn_stream_valid_bytes = byte_count;
+#if DEVELOPMENT || DEBUG
+ state->out_of_synch = src_state->out_of_synch || insnstream_force_cacheline_mismatch;
+ insnstream_force_cacheline_mismatch = 0; /* One-shot, reset after use */
+
+ if (state->out_of_synch) {
+ bcopy(&src_state->insn_cacheline[0], &state->insn_cacheline[0],
+ x86_INSTRUCTION_STATE_CACHELINE_SIZE);
+ } else {
+ bzero(&state->insn_cacheline[0], x86_INSTRUCTION_STATE_CACHELINE_SIZE);
+ }
+#else
+ state->out_of_synch = src_state->out_of_synch;
+#endif
+ *count = x86_INSTRUCTION_STATE_COUNT;
+ } else {
+ *count = 0;
+ }
+ break;
+ }
+
+ case x86_LAST_BRANCH_STATE:
+ {
+ boolean_t istate;
+
+ if (!last_branch_support_enabled || *count < x86_LAST_BRANCH_STATE_COUNT) {
+ return KERN_INVALID_ARGUMENT;
+ }
+
+ istate = ml_set_interrupts_enabled(FALSE);
+ /* If the current thread is asking for its own LBR data, synch the LBRs first */
+ if (thr_act == current_thread()) {
+ i386_lbr_synch(thr_act);
+ }
+ ml_set_interrupts_enabled(istate);
+
+ if (i386_lbr_native_state_to_mach_thread_state(THREAD_TO_PCB(thr_act), (last_branch_state_t *)tstate) < 0) {
+ *count = 0;
+ return KERN_INVALID_ARGUMENT;
+ }
+
+ *count = x86_LAST_BRANCH_STATE_COUNT;
+ break;
+ }
+