Changeset View
Changeset View
Standalone View
Standalone View
head/sys/arm/arm/vm_machdep.c
Show First 20 Lines • Show All 220 Lines • ▼ Show 20 Lines | #endif | ||||
default: | default: | ||||
frame->tf_r0 = error; | frame->tf_r0 = error; | ||||
frame->tf_spsr |= PSR_C; /* carry bit */ | frame->tf_spsr |= PSR_C; /* carry bit */ | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Initialize machine state (pcb and trap frame) for a new thread about to | * Initialize machine state, mostly pcb and trap frame for a new | ||||
* upcall. Put enough state in the new thread's PCB to get it to go back | * thread, about to return to userspace. Put enough state in the new | ||||
* userret(), where we can intercept it again to set the return (upcall) | * thread's PCB to get it to go back to the fork_return(), which | ||||
* Address and stack, along with those from upcals that are from other sources | * finalizes the thread state and handles peculiarities of the first | ||||
* such as those generated in thread_userret() itself. | * return to userspace for the new thread. | ||||
*/ | */ | ||||
void | void | ||||
cpu_set_upcall(struct thread *td, struct thread *td0) | cpu_copy_thread(struct thread *td, struct thread *td0) | ||||
{ | { | ||||
bcopy(td0->td_frame, td->td_frame, sizeof(struct trapframe)); | bcopy(td0->td_frame, td->td_frame, sizeof(struct trapframe)); | ||||
bcopy(td0->td_pcb, td->td_pcb, sizeof(struct pcb)); | bcopy(td0->td_pcb, td->td_pcb, sizeof(struct pcb)); | ||||
td->td_pcb->pcb_regs.sf_r4 = (register_t)fork_return; | td->td_pcb->pcb_regs.sf_r4 = (register_t)fork_return; | ||||
td->td_pcb->pcb_regs.sf_r5 = (register_t)td; | td->td_pcb->pcb_regs.sf_r5 = (register_t)td; | ||||
td->td_pcb->pcb_regs.sf_lr = (register_t)fork_trampoline; | td->td_pcb->pcb_regs.sf_lr = (register_t)fork_trampoline; | ||||
td->td_pcb->pcb_regs.sf_sp = STACKALIGN(td->td_frame); | td->td_pcb->pcb_regs.sf_sp = STACKALIGN(td->td_frame); | ||||
td->td_frame->tf_spsr &= ~PSR_C; | td->td_frame->tf_spsr &= ~PSR_C; | ||||
td->td_frame->tf_r0 = 0; | td->td_frame->tf_r0 = 0; | ||||
/* Setup to release spin count in fork_exit(). */ | /* Setup to release spin count in fork_exit(). */ | ||||
td->td_md.md_spinlock_count = 1; | td->td_md.md_spinlock_count = 1; | ||||
td->td_md.md_saved_cspr = PSR_SVC32_MODE; | td->td_md.md_saved_cspr = PSR_SVC32_MODE; | ||||
} | } | ||||
/* | /* | ||||
* Set that machine state for performing an upcall that has to | * Set that machine state for performing an upcall that starts | ||||
* be done in thread_userret() so that those upcalls generated | * the entry function with the given argument. | ||||
* in thread_userret() itself can be done as well. | |||||
*/ | */ | ||||
void | void | ||||
cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg, | cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg, | ||||
stack_t *stack) | stack_t *stack) | ||||
{ | { | ||||
struct trapframe *tf = td->td_frame; | struct trapframe *tf = td->td_frame; | ||||
tf->tf_usr_sp = STACKALIGN((int)stack->ss_sp + stack->ss_size); | tf->tf_usr_sp = STACKALIGN((int)stack->ss_sp + stack->ss_size); | ||||
tf->tf_pc = (int)entry; | tf->tf_pc = (int)entry; | ||||
tf->tf_r0 = (int)arg; | tf->tf_r0 = (int)arg; | ||||
tf->tf_spsr = PSR_USR32_MODE; | tf->tf_spsr = PSR_USR32_MODE; | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Intercept the return address from a freshly forked process that has NOT | * Intercept the return address from a freshly forked process that has NOT | ||||
* been scheduled yet. | * been scheduled yet. | ||||
* | * | ||||
* This is needed to make kernel threads stay in kernel mode. | * This is needed to make kernel threads stay in kernel mode. | ||||
*/ | */ | ||||
void | void | ||||
cpu_set_fork_handler(struct thread *td, void (*func)(void *), void *arg) | cpu_fork_kthread_handler(struct thread *td, void (*func)(void *), void *arg) | ||||
{ | { | ||||
td->td_pcb->pcb_regs.sf_r4 = (register_t)func; /* function */ | td->td_pcb->pcb_regs.sf_r4 = (register_t)func; /* function */ | ||||
td->td_pcb->pcb_regs.sf_r5 = (register_t)arg; /* first arg */ | td->td_pcb->pcb_regs.sf_r5 = (register_t)arg; /* first arg */ | ||||
} | } | ||||
/* | /* | ||||
* Software interrupt handler for queued VM system processing. | * Software interrupt handler for queued VM system processing. | ||||
*/ | */ | ||||
Show All 13 Lines |