/* callback, runs in vcore context. this sets up our initial context. once we * become runnable again, we'll run the first bits of the vm ctx. after that, * our context will be stopped and started and will just run whatever the guest * VM wants. we'll never come back to this code or to run_vm(). */ static void __build_vm_ctx_cb(struct uthread *uth, void *arg) { struct pthread_tcb *pthread = (struct pthread_tcb*)uth; struct vmctl *vmctl = (struct vmctl*)arg; struct vm_trapframe *vm_tf; __pthread_generic_yield(pthread); pthread->state = PTH_BLK_YIELDING; memset(&uth->u_ctx, 0, sizeof(struct user_context)); uth->u_ctx.type = ROS_VM_CTX; vm_tf = &uth->u_ctx.tf.vm_tf; vm_tf->tf_guest_pcoreid = 0; /* assuming only 1 guest core */ copy_vmctl_to_vmtf(vmctl, vm_tf); /* other HW/GP regs are 0, which should be fine. the FP state is still * whatever we were running before, though this is pretty much unnecessary. * we mostly don't want crazy crap in the uth->as, and a non-current_uthread * VM ctx is supposed to have something in their FP state (like HW ctxs). */ save_fp_state(&uth->as); uth->flags |= UTHREAD_FPSAVED | UTHREAD_SAVED; uthread_runnable(uth); }
/* Prep a pthread to run a signal handler. The original context of the pthread * is saved, and a new context with a new stack is set up to run the signal * handler the next time the pthread is run. */ static void __pthread_prep_sighandler(struct pthread_tcb *pthread, void (*entry)(void), struct siginfo *info) { struct user_context *ctx; pthread->sigdata = alloc_sigdata(); if (info != NULL) pthread->sigdata->info = *info; init_user_ctx(&pthread->sigdata->u_ctx, (uintptr_t)entry, (uintptr_t)pthread->sigdata->stack); if (pthread->uthread.flags & UTHREAD_SAVED) { ctx = &pthread->uthread.u_ctx; if (pthread->uthread.flags & UTHREAD_FPSAVED) { pthread->sigdata->as = pthread->uthread.as; pthread->uthread.flags &= ~UTHREAD_FPSAVED; } } else { assert(current_uthread == &pthread->uthread); ctx = &vcpd_of(vcore_id())->uthread_ctx; save_fp_state(&pthread->sigdata->as); } swap_user_contexts(ctx, &pthread->sigdata->u_ctx); }
static long setup_sigcontext(struct rt_sigframe __user *frame, struct pt_regs *regs) { struct sigcontext __user *sc = &frame->uc.uc_mcontext; long err; /* sc_regs is structured the same as the start of pt_regs */ err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs)); /* Save the floating-point state. */ if (has_fpu) err |= save_fp_state(regs, &sc->sc_fpregs); return err; }