diff options
author | davidxu <davidxu@FreeBSD.org> | 2003-07-24 08:52:44 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2003-07-24 08:52:44 +0000 |
commit | 28420f22f746f5c9bcaa97310e39e206c789b1ef (patch) | |
tree | fdbdc15cfc6c0ce1d68827987b2892af51f91e53 /sys/amd64 | |
parent | 181093ade7e06086c04e2ecab88d6f11b2550cb2 (diff) | |
download | FreeBSD-src-28420f22f746f5c9bcaa97310e39e206c789b1ef.zip FreeBSD-src-28420f22f746f5c9bcaa97310e39e206c789b1ef.tar.gz |
Implement cpu_set_upcall and cpu_set_upcall_kse.
Reviewed by: peter
Diffstat (limited to 'sys/amd64')
-rw-r--r-- | sys/amd64/amd64/vm_machdep.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c index d3a544e..21dc35e 100644 --- a/sys/amd64/amd64/vm_machdep.c +++ b/sys/amd64/amd64/vm_machdep.c @@ -221,6 +221,51 @@ cpu_thread_setup(struct thread *td) void cpu_set_upcall(struct thread *td, struct thread *td0) { + struct pcb *pcb2; + + /* Point the pcb to the top of the stack. */ + pcb2 = td->td_pcb; + + /* + * Copy the upcall pcb. This loads kernel regs. + * Those not loaded individually below get their default + * values here. + * + * XXXKSE It might be a good idea to simply skip this as + * the values of the other registers may be unimportant. + * This would remove any requirement for knowing the KSE + * at this time (see the matching comment below for + * more analysis) (need a good safe default). + */ + bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); + + /* + * Create a new fresh stack for the new thread. + * Don't forget to set this stack value into whatever supplies + * the address for the fault handlers. + * The contexts are filled in at the time we actually DO the + * upcall as only then do we know which KSE we got. + */ + bcopy(td0->td_frame, td->td_frame, sizeof(struct trapframe)); + + /* + * Set registers for trampoline to user mode. Leave space for the + * return address on stack. These are the kernel mode register values. + */ + pcb2->pcb_cr3 = vtophys(vmspace_pmap(td->td_proc->p_vmspace)->pm_pml4); + pcb2->pcb_r12 = (register_t)fork_return; /* trampoline arg */ + pcb2->pcb_rbp = 0; + pcb2->pcb_rsp = (register_t)td->td_frame - sizeof(void *); /* trampoline arg */ + pcb2->pcb_rbx = (register_t)td; /* trampoline arg */ + pcb2->pcb_rip = (register_t)fork_trampoline; + pcb2->pcb_rflags = td->td_frame->tf_rflags & ~PSL_I; /* ints disabled */ + /* + * If we didn't copy the pcb, we'd need to do the following registers: + * pcb2->pcb_savefpu: cloned above. + * pcb2->pcb_rflags: cloned above. + * pcb2->pcb_onfault: cloned above (always NULL here?). + * pcb2->pcb_[fg]sbase: cloned above + */ } /* @@ -231,6 +276,29 @@ cpu_set_upcall(struct thread *td, struct thread *td0) void cpu_set_upcall_kse(struct thread *td, struct kse_upcall *ku) { + + /* + * Do any extra cleaning that needs to be done. + * The thread may have optional components + * that are not present in a fresh thread. + * This may be a recycled thread so make it look + * as though it's newly allocated. + */ + cpu_thread_clean(td); + + /* + * Set the trap frame to point at the beginning of the uts + * function. + */ + td->td_frame->tf_rsp = + ((register_t)ku->ku_stack.ss_sp + ku->ku_stack.ss_size) & ~0x0f; + td->td_frame->tf_rip = (register_t)ku->ku_func; + + /* + * Pass the address of the mailbox for this kse to the uts + * function as a parameter on the stack. + */ + td->td_frame->tf_rdi = (register_t)ku->ku_mailbox; } |