void switch_if_needed(uint32_t ticks) { task_t *current = current_task(); current->rem_quantum--; current->ticks++; if (!current->rem_quantum) { restart_quantum(current); switch_tasks(); } }
int emu_iret(unsigned char *lina) { trace("iret\n"); if (! opa.pe) { Bit32u tmp; int width = opa.opb; if (REG(esp) > 0x10000 - 3*width) { set_guest_exc(12, 0); goto exc; } if (get_memory(LWORD(ss), LWORD(esp), ®(eip), width)) goto exc; if (width == 2) REG(eip) &= 0xffff; LWORD(esp) += width; if (get_memory(LWORD(ss), LWORD(esp), &tmp, 2)) /* always only use 16 bits */ goto exc; REG(cs) = tmp; LWORD(esp) += width; if (get_memory(LWORD(ss), LWORD(esp), &tmp, width)) goto exc; LWORD(eflags) = tmp; LWORD(esp) += width; if (width == 4) { /* 32 bit -- VM, IOPL, VIP, and VIF are unmodified */ REG(eflags) = ((tmp & ~(VM_MASK | IOPL_MASK | VIP_MASK | VIF_MASK)) | (REG(eflags) & (VM_MASK | IOPL_MASK | VIP_MASK | VIF_MASK))); } else { /* 16 bit -- IOPL is unmodified */ REG(eflags) = ((tmp & ~(0xffff000 | IOPL_MASK)) | (REG(eflags) & (0xffff000 | IOPL_MASK))); } trace("%d byte iret; eip=%x cs=%x, eflags=%x; new lina=%x\n", opa.opb, REG(eip), REG(cs), REG(eflags), (u_int)lina); } else { /* PROTECTED-MODE */ if (REG(eflags) & NT_MASK) { /* TASK-RETURN */ Bit16u old_sel = vmstate.tr_sel; struct seg_descr *old_tss; struct Ts *ts = (struct Ts*)vmstate.tr_base; struct seg_descr tss; Bit16u selector = ts->ts_link; int err; if (get_tss_descriptor(selector, &tss, 1) || switch_tasks(selector, &tss)) goto exc; ts->ts_t = 0; /* We probably got here because this was set, to let us emulate it. */ /* mark the descriptor of the abandoned task as "not busy" */ ASSERT((old_sel & ~7) == 0); ASSERT((old_sel & ~7) >= vmstate.g_gdt_limit); err = set_get_any(&vmstate.g_gdt_base, (u_int*)&old_tss); ASSERT(!err); old_tss += (old_sel >> 3); old_tss->type &= ~2; } else {