PRIVATE void Thread::ipc_send_msg(Receiver *recv) { Syscall_frame *regs = _snd_regs; bool success = transfer_msg(regs->tag(), nonull_static_cast<Thread*>(recv), regs, _ipc_send_rights); sender_dequeue(recv->sender_list()); recv->vcpu_update_state(); //printf(" done\n"); regs->tag(L4_msg_tag(regs->tag(), success ? 0 : L4_msg_tag::Error)); Mword state_del = Thread_ipc_mask | Thread_ipc_transfer; Mword state_add = Thread_ready; if (Receiver::prepared()) // same as in Receiver::prepare_receive_dirty_2 state_add |= Thread_receive_wait; if (cpu() == current_cpu()) { state_change_dirty(~state_del, state_add); if (current_sched()->deblock(cpu(), current_sched(), true)) recv->switch_to_locked(this); } else { drq_state_change(~state_del, state_add); current()->schedule_if(current()->handle_drq()); } }
L4_msg_tag Icu::op_icu_get_info(Mword *features, Mword *num_irqs, Mword *num_msis) { *num_irqs = Irq_mgr::mgr->nr_irqs(); *num_msis = Irq_mgr::mgr->nr_msis(); *features = *num_msis ? (unsigned)Msi_bit : 0; return L4_msg_tag(0); }
PUBLIC inline Syscall_frame * Irq_sender::transfer_msg(Receiver *recv) { Syscall_frame* dst_regs = recv->rcv_regs(); // set ipc return value: OK dst_regs->tag(L4_msg_tag(0)); // set ipc source thread id dst_regs->from(_irq_id); return dst_regs; }
static L4_msg_tag no_reply() { return L4_msg_tag(L4_msg_tag::Schedule); }
PRIVATE inline L4_msg_tag Thread_object::sys_vcpu_resume(L4_msg_tag const &tag, Utcb *utcb) { if (this != current() || !(state() & Thread_vcpu_enabled)) return commit_result(-L4_err::EInval); Space *s = space(); Vcpu_state *vcpu = vcpu_state().access(true); L4_obj_ref user_task = vcpu->user_task; if (user_task.valid()) { L4_fpage::Rights task_rights = L4_fpage::Rights(0); Task *task = Kobject::dcast<Task*>(s->lookup_local(user_task.cap(), &task_rights)); if (EXPECT_FALSE(task && !(task_rights & L4_fpage::Rights::W()))) return commit_result(-L4_err::EPerm); if (task != vcpu_user_space()) vcpu_set_user_space(task); vcpu->user_task = L4_obj_ref(); } else if (user_task.op() == L4_obj_ref::Ipc_reply) vcpu_set_user_space(0); L4_snd_item_iter snd_items(utcb, tag.words()); int items = tag.items(); if (vcpu_user_space()) for (; items && snd_items.more(); --items) { if (EXPECT_FALSE(!snd_items.next())) break; Lock_guard<Lock> guard; if (!guard.check_and_lock(&static_cast<Task *>(vcpu_user_space())->existence_lock)) return commit_result(-L4_err::ENoent); cpu_lock.clear(); L4_snd_item_iter::Item const *const item = snd_items.get(); L4_fpage sfp(item->d); Reap_list rl; L4_error err = fpage_map(space(), sfp, vcpu_user_space(), L4_fpage::all_spaces(), item->b, &rl); rl.del(); cpu_lock.lock(); if (EXPECT_FALSE(!err.ok())) return commit_error(utcb, err); } if ((vcpu->_saved_state & Vcpu_state::F_irqs) && (vcpu->sticky_flags & Vcpu_state::Sf_irq_pending)) { assert_kdb(cpu_lock.test()); do_ipc(L4_msg_tag(), 0, 0, true, 0, L4_timeout_pair(L4_timeout::Zero, L4_timeout::Zero), &vcpu->_ipc_regs, L4_fpage::Rights::FULL()); vcpu = vcpu_state().access(true); if (EXPECT_TRUE(!vcpu->_ipc_regs.tag().has_error() || this->utcb().access(true)->error.error() == L4_error::R_timeout)) { vcpu->_ts.set_ipc_upcall(); Address sp; // tried to resume to user mode, so an IRQ enters from user mode if (vcpu->_saved_state & Vcpu_state::F_user_mode) sp = vcpu->_entry_sp; else sp = vcpu->_ts.sp(); arch_load_vcpu_kern_state(vcpu, true); LOG_TRACE("VCPU events", "vcpu", this, Vcpu_log, l->type = 4; l->state = vcpu->state; l->ip = vcpu->_entry_ip; l->sp = sp; l->space = static_cast<Task*>(_space.vcpu_aware())->dbg_id(); );