📄 usercontext.cxx
字号:
Process::ValidateRegValues(){ if (processFlags & PF_Faulted) return; uint32_t code = 0; uint32_t info = 0; fixreg_t iopl = (fixRegs.EFLAGS & MASK_EFLAGS_IOPL) >> SHIFT_EFLAGS_IOPL; /* FIX: This is no longer correct, as a valid user-mode application * can now carry PrivDomainCode and PrivDomainData in some cases. */ uint32_t wantCode = isUserContext ? Selector::DomainCode : Selector::KProcCode; uint32_t wantData = isUserContext ? Selector::DomainData : Selector::KProcData; /* FIX: The whole segment register check needs to be MUCH more * specific. There are only a few allowable values, and they should * be explicitly tested here. */#define validate(seg, want) \ do { \ if ( ((seg) != Selector::Null) && ((seg) != (want)) ) { \ code = FC_RegValue; \ info = (seg); \ goto fault; \ } \ } while (0) validate(fixRegs.CS, wantCode); /* Strictly speaking, it's okay for a user program to place the code * segment value in a data segment register, so long as read-only * access is sufficient. Fix this when somebody complains someday. */ validate(fixRegs.DS, wantData); validate(fixRegs.ES, wantData); validate(fixRegs.FS, wantData); validate(fixRegs.GS, wantData); validate(fixRegs.SS, wantData); #undef validate if ( (fixRegs.EFLAGS & MASK_EFLAGS_Interrupt) == 0 ) { /* interrupts must be enabled, various others not: */ code = FC_RegValue; } else if ( fixRegs.EFLAGS & MASK_EFLAGS_Nested ) { code = FC_RegValue; } else if ( iopl != 0 && !HasDevicePriveleges() ) { code = FC_RegValue; }#ifdef EROS_HAVE_FPU /* Check for pending floating point exceptions too. If an unmasked exception is pending, invoke the process keeper. The bits in the control words are 'mask if set', while the bits in the status words are 'raise if set'. The and-not logic is therefore what we want: */ else if (fpuRegs.f_status & ~(fpuRegs.f_ctrl & FPSTATUS_EXCEPTIONS)) { code = FC_FloatingPointError; info = fpuRegs.f_cs; } /* The floating point %f_cs, %f_ip, %f_ds, and %f_dp registers record the location of the last operation. They are output only, and need not be checked. */#endif fault: if (code) SetFault(code, info, true); #if 0 if (faultCode) printf("Bad register values\n");#endif return;}/* Both loads the register values and validates that the process root * is well-formed. */voidProcess::LoadFixRegs(){ assert(hazards & hz::DomRoot); assert(procRoot); procRoot->MakeObjectDirty();#ifdef ProcAltMsgBuf#error "Type checks need revision"#endif /* Ensure slots containing fixed regs are number keys. */ for (uint32_t k = ProcFirstRootRegSlot; k <= ProcLastRootRegSlot; k++) { if ( (*procRoot)[k].IsType(KT_Number) == false ) { SetMalformed(); return; } assert ( (*procRoot)[k].IsHazard() == false ); } stats.pfCount = 0;#if 1 uint8_t *rootkey0 = (uint8_t *) & ((*procRoot)[0]); LOAD_FIX_REGS;#else DomRegLayout* pDomRegs = (DomRegLayout*) & ((*procRoot)[0]); faultCode = pDomRegs->faultCode; faultInfo = pDomRegs->faultInfo; runState = pDomRegs->runState; processFlags = pDomRegs->flags; if (faultCode) printf("Fault code already set\n"); fixRegs.EDX = pDomRegs->edx; fixRegs.EDI = pDomRegs->edi; fixRegs.DS = pDomRegs->ds; fixRegs.ECX = pDomRegs->ecx; fixRegs.ESI = pDomRegs->esi; fixRegs.ES = pDomRegs->es; fixRegs.EAX = pDomRegs->eax; fixRegs.EBX = pDomRegs->ebx; fixRegs.SS = pDomRegs->ss; fixRegs.EIP = pDomRegs->eip; fixRegs.ESP = pDomRegs->esp; fixRegs.CS = pDomRegs->cs; fixRegs.EFLAGS = pDomRegs->eflags; fixRegs.EBP = pDomRegs->ebp; fixRegs.FS = pDomRegs->fs; fixRegs.GS = pDomRegs->gs; fixRegs.sndPtr = pDomRegs->sndPtr; fixRegs.sndLen = pDomRegs->sndLen; fixRegs.rcvPtr = pDomRegs->rcvPtr; fixRegs.invType = pDomRegs->invType; stats.evtCounter0 = pDomRegs->hiEvtCount; stats.evtCounter0 <<= 32; stats.evtCounter0 |= pDomRegs->loEvtCount; stats.evtCounter1 = 0;#endif fixRegs.ReloadUnits = 0; for (uint32_t k = ProcFirstRootRegSlot; k <= ProcLastRootRegSlot; k++) (*procRoot)[k].SetRwHazard(); hazards &= ~hz::DomRoot;#if 0 dprintf(true, "Process root oid=0x%x to ctxt 0x%08x, eip 0x%08x hz 0x%08x\n", (uint32_t) procRoot->oid, this, fixRegs.EIP, hazards);#endif}#ifdef EROS_HAVE_FPU/* This version requires no annex node. */voidProcess::LoadFloatRegs(){ assert (hazards & hz::FloatRegs); assert (procRoot); assert (procRoot->IsDirty()); uint8_t *rootkey0 = (uint8_t *) & ((*procRoot)[0]); LOAD_FLOAT_REGS; hazards &= ~hz::FloatRegs;}#endifvoidProcess::LoadKeyRegs(){ assert (hazards & hz::KeyRegs); assert (procRoot->slot[ProcGenKeys].IsHazard() == false); if (procRoot->slot[ProcGenKeys].IsType(KT_Node) == false) { SetMalformed(); return; } #if 0 { Key& k = procRoot->slot[ProcGenKeys]; printf("Preparing nd oid 0x%08x%08x\n", (uint32_t) (k.GetKeyOid() >> 32), (uint32_t) (k.GetKeyOid())); }#endif procRoot->slot[ProcGenKeys].Prepare(); Node *kn = (Node *) procRoot->slot[ProcGenKeys].GetObjectPtr(); assertex(kn,kn->IsUserPinned()); assert ( kn->Validate() ); kn->Unprepare(false); if (kn->obType != ObType::NtUnprepared || kn == procRoot) { SetMalformed(); return; } kn->MakeObjectDirty(); for (uint32_t k = 0; k < EROS_NODE_SIZE; k++) { if ( (*kn)[k].IsHazard() ) dprintf(true, "Key register slot %d is hazarded in node 0x%08x%08x\n", k, (uint32_t) (kn->ob.oid >> 32), (uint32_t) kn->ob.oid);#ifndef NDEBUG /* We know that the context structure key registers are unhazarded * and unprepared by virtue of the fact that they are unloaded, * but check here just in case: */ if ( keyReg[k].IsHazard() ) dprintf(true, "Key register %d is hazarded in Process 0x%08x\n", k, this); if ( keyReg[k].IsUnprepared() == false ) dprintf(true, "Key register %d is prepared in Process 0x%08x\n", k, this);#endif if (k == 0) keyReg[0].NH_VoidKey(); /* key register 0 is always void */ else keyReg[k].NH_Set(kn->slot[k]); (*kn)[k].SetRwHazard(); } /* Node is now known to be valid... */ kn->context = this; kn->obType = ObType::NtKeyRegs; keysNode = kn; procRoot->slot[ProcGenKeys].SetWrHazard(); assert(keysNode); hazards &= ~hz::KeyRegs;}voidProcess::FlushFixRegs(){ assert((hazards & hz::DomRoot) == 0); assert(procRoot); assert(procRoot->IsDirty()); assert(isUserContext);#ifdef ProcAltMsgBuf#error "Type checks need revision"#endif for (uint32_t k = ProcFirstRootRegSlot; k <= ProcLastRootRegSlot; k++) { assert ( (*procRoot)[k].IsRdHazard() ); assert ( (*procRoot)[k].IsWrHazard() ); (*procRoot)[k].UnHazard(); }#if 1 uint8_t *rootkey0 = (uint8_t *) & ((*procRoot)[0]); UNLOAD_FIX_REGS; /* ISSUE: If this process has IOPL privileges, it is not clear that * we should ever be recording them back to the domain root, as this * makes them fairly well permanent. */ #else DomRegLayout* pDomRegs = (DomRegLayout*) & ((*procRoot)[0]); pDomRegs->faultCode = faultCode; pDomRegs->faultInfo = faultInfo; pDomRegs->runState = runState; pDomRegs->flags = processFlags; pDomRegs->edx = fixRegs.EDX; pDomRegs->edi = fixRegs.EDI; pDomRegs->ds = fixRegs.DS; pDomRegs->ecx = fixRegs.ECX; pDomRegs->esi = fixRegs.ESI; pDomRegs->es = fixRegs.ES; pDomRegs->eax = fixRegs.EAX; pDomRegs->ebx = fixRegs.EBX; pDomRegs->ss = fixRegs.SS; pDomRegs->eip = fixRegs.EIP; pDomRegs->esp = fixRegs.ESP; pDomRegs->cs = fixRegs.CS; pDomRegs->eflags = fixRegs.EFLAGS; pDomRegs->ebp = fixRegs.EBP; pDomRegs->fs = fixRegs.FS; pDomRegs->gs = fixRegs.GS; pDomRegs->sndPtr = fixRegs.sndPtr; pDomRegs->sndLen = fixRegs.sndLen; pDomRegs->rcvPtr = fixRegs.rcvPtr; pDomRegs->invType = fixRegs.invType; pDomRegs->loEvtCount = stats.evtCounter0; pDomRegs->hiEvtCount = stats.evtCounter0 >> 32;#endif (*procRoot)[ProcSched].UnHazard(); hazards |= (hz::DomRoot | hz::Schedule); saveArea = 0;}#ifdef EROS_HAVE_FPUvoidProcess::SaveFPU(){ assert(fpuOwner == this); Machine::EnableFPU(); __asm__ __volatile__("fnsave %0\n\t" : "=m" (fpuRegs)); fpuOwner = 0; Machine::DisableFPU();}#ifdef EROS_HAVE_FPUvoidProcess::LoadFPU(){ /* FPU is unloaded, or is owned by some other process. Unload * that, and load the current process's FPU state in it's place. */ if (fpuOwner) Process::fpuOwner->SaveFPU(); assert(fpuOwner == 0); Machine::EnableFPU(); __asm__ __volatile__("frstor %0\n\t" : /* no outputs */ : "m" (fpuRegs)); fpuOwner = this; Machine::DisableFPU(); hazards &= ~hz::NumericsUnit;}#endif/* This version requires no annex node. */voidProcess::FlushFloatRegs(){ assert ((hazards & hz::FloatRegs) == 0); assert (procRoot); assert (procRoot->IsDirty()); uint8_t *rootkey0 = (uint8_t *) & ((*procRoot)[0]); UNLOAD_FLOAT_REGS; hazards |= hz::FloatRegs; saveArea = 0;}#endifvoidProcess::FlushKeyRegs(){ assert (keysNode); assert ((hazards & hz::KeyRegs) == 0); assert(procRoot); assert (keysNode->IsDirty()); assert ( keysNode->Validate() );#if 0 printf("Flushing key regs on ctxt=0x%08x\n", this); if (inv.IsActive() && inv.invokee == this) dprintf(true,"THAT WAS INVOKEE!\n");#endif for (uint32_t k = 0; k < EROS_NODE_SIZE; k++) { keysNode->slot[k].UnHazard(); keysNode->slot[k].NH_Set(keyReg[k]); /* Not hazarded because key register */ keyReg[k].NH_VoidKey(); /* We know that the context structure key registers are unhazarded * and unlinked by virtue of the fact that they are unloaded. */ } keysNode->context = 0; keysNode->obType = ObType::NtUnprepared; keysNode = 0; hazards |= hz::KeyRegs; procRoot->slot[ProcGenKeys].UnHazard(); saveArea = 0;}/* Rewrite the process key back to our current thread. Note that * the thread's process key is not reliable unless this unload has * been performed. */voidProcess::SyncThread(){ assert(curThread); assert(procRoot); assert (curThread->context == this); Key& procKey = curThread->processKey; assert (procKey.IsHazard() == false); /* Not hazarded because thread key */ if (procKey.IsPrepared()) procKey.NH_Unprepare(); procKey.InitType(KT_Process); procKey.unprep.oid = procRoot->ob.oid; procKey.unprep.count = procRoot->ob.allocCount; }voidProcess::Unload(){ /* It might already be unloaded: */ if (procRoot == 0) return; #if 0 { const char *descrip = "other"; bool shouldStop = false; if (this == Thread::Current()->context) descrip = "current"; if (inv.IsActive() && this == inv.invokee) { descrip = "invokee"; shouldStop = true; } dprintf(shouldStop, "Unloading %s ctxt 0x%08x\n", descrip, this); }#endif #if 0 if (hazards & hz::DomRoot) dprintf(false, "Calling Context::Unload() on 0x%08x, eip=???\n", this); else dprintf(false, "Calling Context::Unload() on 0x%08x, eip=0x%08x\n", this, fixRegs.EIP);#endif#if defined(DBG_WILD_PTR)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -