+ /* Check segment selectors are safe */
+ if (!valid_user_segment_selectors(ts->cs,
+ ts->ss,
+ ts->ds,
+ ts->es,
+ ts->fs,
+ ts->gs))
+ return(KERN_INVALID_ARGUMENT);
+
+ saved_state->eax = ts->eax;
+ saved_state->ebx = ts->ebx;
+ saved_state->ecx = ts->ecx;
+ saved_state->edx = ts->edx;
+ saved_state->edi = ts->edi;
+ saved_state->esi = ts->esi;
+ saved_state->ebp = ts->ebp;
+ saved_state->uesp = ts->esp;
+ saved_state->efl = (ts->eflags & ~EFL_USER_CLEAR) | EFL_USER_SET;
+ saved_state->eip = ts->eip;
+ saved_state->cs = ts->cs;
+ saved_state->ss = ts->ss;
+ saved_state->ds = ts->ds;
+ saved_state->es = ts->es;
+ saved_state->fs = ts->fs;
+ saved_state->gs = ts->gs;
+
+ /*
+ * If the trace trap bit is being set,
+ * ensure that the user returns via iret
+ * - which is signaled thusly:
+ */
+ if ((saved_state->efl & EFL_TF) && saved_state->cs == SYSENTER_CS)
+ saved_state->cs = SYSENTER_TF_CS;
+
+ return(KERN_SUCCESS);
+}
+
+static int
+set_thread_state64(thread_t thread, x86_thread_state64_t *ts)
+{
+ x86_saved_state64_t *saved_state;
+
+ pal_register_cache_state(thread, DIRTY);
+
+ saved_state = USER_REGS64(thread);
+
+ if (!IS_USERADDR64_CANONICAL(ts->rsp) ||
+ !IS_USERADDR64_CANONICAL(ts->rip))
+ return(KERN_INVALID_ARGUMENT);
+
+ saved_state->r8 = ts->r8;
+ saved_state->r9 = ts->r9;
+ saved_state->r10 = ts->r10;
+ saved_state->r11 = ts->r11;
+ saved_state->r12 = ts->r12;
+ saved_state->r13 = ts->r13;
+ saved_state->r14 = ts->r14;
+ saved_state->r15 = ts->r15;
+ saved_state->rax = ts->rax;
+ saved_state->rbx = ts->rbx;
+ saved_state->rcx = ts->rcx;
+ saved_state->rdx = ts->rdx;
+ saved_state->rdi = ts->rdi;
+ saved_state->rsi = ts->rsi;
+ saved_state->rbp = ts->rbp;
+ saved_state->isf.rsp = ts->rsp;
+ saved_state->isf.rflags = (ts->rflags & ~EFL_USER_CLEAR) | EFL_USER_SET;
+ saved_state->isf.rip = ts->rip;
+ saved_state->isf.cs = USER64_CS;
+ saved_state->fs = (uint32_t)ts->fs;
+ saved_state->gs = (uint32_t)ts->gs;
+
+ return(KERN_SUCCESS);
+}
+
+
+
+static void
+get_thread_state32(thread_t thread, x86_thread_state32_t *ts)
+{
+ x86_saved_state32_t *saved_state;
+
+ pal_register_cache_state(thread, VALID);
+
+ saved_state = USER_REGS32(thread);
+
+ ts->eax = saved_state->eax;
+ ts->ebx = saved_state->ebx;
+ ts->ecx = saved_state->ecx;
+ ts->edx = saved_state->edx;
+ ts->edi = saved_state->edi;
+ ts->esi = saved_state->esi;
+ ts->ebp = saved_state->ebp;
+ ts->esp = saved_state->uesp;
+ ts->eflags = saved_state->efl;
+ ts->eip = saved_state->eip;
+ ts->cs = saved_state->cs;
+ ts->ss = saved_state->ss;
+ ts->ds = saved_state->ds;
+ ts->es = saved_state->es;
+ ts->fs = saved_state->fs;
+ ts->gs = saved_state->gs;
+}
+
+
+static void
+get_thread_state64(thread_t thread, x86_thread_state64_t *ts)
+{
+ x86_saved_state64_t *saved_state;
+
+ pal_register_cache_state(thread, VALID);
+
+ saved_state = USER_REGS64(thread);
+
+ ts->r8 = saved_state->r8;
+ ts->r9 = saved_state->r9;
+ ts->r10 = saved_state->r10;
+ ts->r11 = saved_state->r11;
+ ts->r12 = saved_state->r12;
+ ts->r13 = saved_state->r13;
+ ts->r14 = saved_state->r14;
+ ts->r15 = saved_state->r15;
+ ts->rax = saved_state->rax;
+ ts->rbx = saved_state->rbx;
+ ts->rcx = saved_state->rcx;
+ ts->rdx = saved_state->rdx;
+ ts->rdi = saved_state->rdi;
+ ts->rsi = saved_state->rsi;
+ ts->rbp = saved_state->rbp;
+ ts->rsp = saved_state->isf.rsp;
+ ts->rflags = saved_state->isf.rflags;
+ ts->rip = saved_state->isf.rip;
+ ts->cs = saved_state->isf.cs;
+ ts->fs = saved_state->fs;
+ ts->gs = saved_state->gs;
+}
+
+