⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usercontext.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 1998, 1999, 2001, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <kerninc/kernel.hxx>#include <kerninc/Node.hxx>#include <arch-kerninc/KernTune.hxx>#include <kerninc/Depend.hxx>#include <kerninc/Thread.hxx>#include <kerninc/CpuReserve.hxx>#include <kerninc/util.h>#include <kerninc/ObjectCache.hxx>#include <kerninc/Machine.hxx>#include <kerninc/IRQ.hxx>#include <kerninc/Invocation.hxx>#include <kerninc/Check.hxx>#include <eros/Key.h>#include <kerninc/Process.hxx>#include <arch-kerninc/Process.hxx>#include <arch-kerninc/PTE.hxx>#include "TSS.hxx"#include <eros/Invoke.h>#include <eros/ProcessState.h>#include <eros/SegKeeperInfo.h>#include <eros/Registers.h>#include <eros/i486/Registers.h>#include <kerninc/PhysMem.hxx>#include <eros/ProcessKey.h>#include <eros/SysTraceKey.h>#include <kerninc/Invocation.hxx>#if 0#include <machine/RegLayout.hxx>#endif#include <disk/DiskLSS.hxx>#include "gen.REGMOVE.hxx"/* #define MSGDEBUG * #define RESUMEDEBUG * #define XLATEDEBUG */Process *Process::ContextCache;#ifdef EROS_HAVE_FPUProcess *Process::fpuOwner;#endif#ifdef OPTION_SMALL_SPACESPTE *Process::smallSpaces = 0;#endifboolProcess::HasDevicePriveleges(){  bool hasPrivs = false;    assert((hazards & hz::DomRoot) == 0);  assert((hazards & hz::KeyRegs) == 0);  if (procRoot->slot[ProcIoSpace].IsType(KT_DevicePrivs))    hasPrivs = true;  return hasPrivs;}voidProcess::AllocUserContexts(){  Process::ContextCache = new (0) Process[KTUNE_NCONTEXT];  assert (KTUNE_NCONTEXT < 1000);  for (int i = 0; i < KTUNE_NCONTEXT; i++) {    int ndx = i;    Process::ContextCache[i].name[0] = 'u';    Process::ContextCache[i].name[1] = 's';    Process::ContextCache[i].name[2] = 'e';    Process::ContextCache[i].name[3] = 'r';    Process::ContextCache[i].name[4] = '0' + (ndx / 100);    ndx %= 100;    Process::ContextCache[i].name[5] = '0' + (ndx / 10);    ndx %= 10;    Process::ContextCache[i].name[6] = '0' + (ndx % 10);    Process::ContextCache[i].name[7] = 0;  }  printf("Allocated User Contexts: 0x%x at 0x%08x\n",		 sizeof(Process[KTUNE_NCONTEXT]),		 Process::ContextCache);}/* FIX: It is unfortunate that some of these checks require !NDEBUG. * Should they? */boolCheck::Contexts(const char *){  bool result = true;    IRQ::DISABLE();  /* It is possible for this to get called from interrupt handlers   * before the context cache has been allocated.   */  if (Process::ContextCache) {    for (int i = 0; i < KTUNE_NCONTEXT; i++) {      Process *p = &Process::ContextCache[i];    #ifndef NDEBUG      if (p->kr.IsValid(p) == false) {	result = false;	break;      }#endif    #ifndef NDEBUG      for (unsigned k = 0; k < EROS_PROCESS_KEYREGS; k++) {	if (p->keyReg[0].IsValid() == false) {	  result = false;	  break;	}      }#endif      if (p->procRoot && p->procRoot->IsFree()) {	dprintf(true, "Context 0x%08x has free process root 0x%08x\n",			p, p->procRoot);	result = false;      }      if (p->keysNode && p->keysNode->IsFree()) {	dprintf(true, "Context 0x%08x has free keys node 0x%08x\n",			p, p->keysNode);	result = false;      }      if (result == false)	break;    }  }  IRQ::ENABLE();  return result;}#ifndef NDEBUGboolValidCtxtPtr(const Process *ctxt){  if ( ((uint32_t) ctxt < (uint32_t) Process::ContextCache ) ||        ((uint32_t) ctxt >= (uint32_t)	&Process::ContextCache[KTUNE_NCONTEXT]) )    return false;  uint32_t offset = ((uint32_t) ctxt) - ((uint32_t) Process::ContextCache);  offset %= sizeof(Process);  if (offset == 0)    return true;  return false;}boolProcess::ValidKeyReg(const Key *pKey){  if ( ((uint32_t) pKey < (uint32_t) Process::ContextCache ) ||        ((uint32_t) pKey >= (uint32_t)	&Process::ContextCache[KTUNE_NCONTEXT]) )    return false;  /* Find the containing context: */  uint32_t ctxt = ((uint32_t) pKey) - ((uint32_t) Process::ContextCache);  ctxt /= sizeof(Process);  Process *p = &Process::ContextCache[ctxt];    if ( ((uint32_t) pKey < (uint32_t) &p->keyReg[0] ) ||        ((uint32_t) pKey >= (uint32_t) &p->keyReg[EROS_PROCESS_KEYREGS]) )    return false;  uint32_t offset = ((uint32_t) pKey) - ((uint32_t) &p->keyReg[0]);  offset %= sizeof(Key);  if (offset == 0)    return true;    return false;}#endif#ifndef NDEBUGboolValidCtxtKeyRingPtr(const KeyRing* kr){  for (uint32_t c = 0; c < KTUNE_NCONTEXT; c++) {    Process *ctxt = &Process::ContextCache[c];    if (kr == &ctxt->kr)      return true;  }  return false;}#endifvoidProcess::FlushAll(){  for (uint32_t c = 0; c < KTUNE_NCONTEXT; c++) {    Process *ctxt = &Process::ContextCache[c];    /* Unload the context structure, as we are going to COW the process     * root anyway.     */        ctxt->Unload();  }}extern "C" {  void resume_from_kernel_interrupt(fixregs_t *);  void resume_process(Process *);  void resume_v86_process(Process *);};voidProcess::DumpFixRegs(){  if (saveArea == 0)    printf("Note: context is NOT runnable\n");  ::DumpFixRegs(&fixRegs);}#ifdef EROS_HAVE_FPUvoidProcess::DumpFloatRegs(){  printf("fctrl: 0x%04x fstatus: 0x%04x ftag: 0x%04x fopcode 0x%04x\n",		 fpuRegs.f_ctrl, 		 fpuRegs.f_status, 		 fpuRegs.f_tag, 		 fpuRegs.f_opcode);  printf("fcs: 0x%04x fip: 0x%08x fds: 0x%04x fdp: 0x%08x\n",		 fpuRegs.f_cs, 		 fpuRegs.f_ip,		 fpuRegs.f_ds,		 fpuRegs.f_dp);}#endif	      voidDumpFixRegs(const fixregs_t * fx){#if 0  uint32_t cip;  __asm__("movl 4(%%ebp),%0"		: "=g" (cip)	        : /* no inputs */);#endif#if 0  if ( sa_IsProcess(fx) )    printf("Process Savearea 0x%08x (cip 0x%08x)\n", fx, cip);  else    printf("Kernel Savearea 0x%08x (cip 0x%08x)\n", fx, cip);#else  if ( sa_IsProcess(fx) )    printf("Process Savearea 0x%08x\n", fx);  else    printf("Kernel Savearea 0x%08x\n", fx);#endif    printf(       "Units  = 0x%08x  ASID  = 0x%08x  EFLAGS = 0x%08x\n"       "EAX    = 0x%08x  EBX   = 0x%08x  ECX    = 0x%08x\n"       "EDX    = 0x%08x  EDI   = 0x%08x  ESI    = 0x%08x\n"       "EBP    = 0x%08x  CS    = 0x%08x  EIP    = 0x%08x\n"       "ExNo   = 0x%08x  ExAdr = 0x%08x  Error  = 0x%08x\n",       fx->ReloadUnits, fx->MappingTable, fx->EFLAGS,       fx->EAX, fx->EBX, fx->ECX,       fx->EDX, fx->EDI, fx->ESI,       fx->EBP, fx->CS, fx->EIP,       fx->ExceptNo, fx->ExceptAddr, fx->Error);  if ( sa_IsProcess(fx) ) {    /* user save area: */    const fixregs_t* sa = fx;        printf(		   "invTy = %d invKey = 0x%x sndPtr = 0x%08x sndLen= %5d sndKeys=0x%08x rcvKeys=0x%08x\n",		   sa->invType, sa->invKey, sa->sndPtr, sa->sndLen,		   sa->sndKeys, sa->rcvKeys);    printf(		   "SS     = 0x%08x  ESP   = 0x%08x\n"		   "DS   = 0x%04x  ES   = 0x%04x  FS   = 0x%04x"		   "  GS   = 0x%04x\n",		   sa->SS, sa->ESP,		   sa->DS, sa->ES, sa->FS, sa->GS);  }  else {    uint16_t ss;    uint16_t ds;    uint16_t es;    uint16_t fs;    uint16_t gs;        __asm__ __volatile__ ("mov %%ss, %0"			  : "=r" (ss)			  : /* no input */);    __asm__ __volatile__ ("mov %%ds, %0"			  : "=r" (ds)			  : /* no input */);    __asm__ __volatile__ ("mov %%es, %0"			  : "=r" (es)			  : /* no input */);    __asm__ __volatile__ ("mov %%fs, %0"			  : "=r" (fs)			  : /* no input */);    __asm__ __volatile__ ("mov %%gs, %0"			  : "=r" (gs)			  : /* no input */);    printf(	 "SS     = 0x%08x  ESP   = 0x%08x\n"	 "DS   = 0x%04x  ES   = 0x%04x  FS   = 0x%04x  GS   = 0x%04x\n",	 ss, ((uint32_t) fx) + 60,	 ds, es, fs, gs);  }}/* NEW POLICY FOR USER CONTEXT MANAGEMENT: *  *   A context goes through several stages before being allowed to *   run: *  *   HAZARD    ACTION *  *   DomRoot     Load the process root registers. *  *   Annex0      Reprepare the process general registers annex and load *               it's registers  *  *   KeyRegs     Reprepare the process key registers annex and load *               it's registers *  *   Validate    Verify that all register values are suitable. *  *   AddrSpace   Reload the master address space pointer. *  *   FloatUnit   Floating point unit needs to be loaded. *  * Note that the Annex0 hazard implies that the associated capability * in the process root is NOT validated.  If any of 'DomRoot' 'Annex0' * or 'KeyRegs' cannot be cleared the process is malformed. *  * Since it has been getting me in trouble, I am no longer trying to * micro-optimize slot reload. *//* Simple round-robin policy for now:  */voidProcess::Load(Node* procRoot){  assert(procRoot);  static uint32_t nextClobber = 0;  Process* pContext = 0;  #if 0  printf("Begin Process::Load\n");#endif    do {    pContext = &Process::ContextCache[nextClobber++];    if (nextClobber >= KTUNE_NCONTEXT)      nextClobber = 0;    if (pContext == Thread::Current()->context) {      pContext = 0;      continue;    }    if (inv.IsActive() && pContext == inv.invokee) {      pContext = 0;      continue;    }    #if 0    if (pContext->pinCount)      pContext = 0;#endif        if (pContext->curThread &&	pContext->curThread->state == Thread::Running)      pContext = 0;  } while (pContext == 0);  Process& cc = (*pContext);    /* wipe out current contents, if any */#if 0  printf("  Unload old context\n");#endif  cc.Unload();#if 0  printf("  unloaded\n");#endif    assert(procRoot->obType == ObType::NtProcessRoot);    cc.procRoot = procRoot;    cc.saveArea = 0;		/* make sure not runnable! */  cc.faultCode = FC_NoFault;  cc.faultInfo = 0;  cc.processFlags = 0;  /* FIX: what to do about runState? */#ifdef OPTION_SMALL_SPACES  uint32_t ndx = &cc - Process::ContextCache;  cc.limit = SMALL_SPACE_PAGES * EROS_PAGE_SIZE;  cc.bias = UMSGTOP + (ndx * SMALL_SPACE_PAGES * EROS_PAGE_SIZE);  cc.smallPTE = &smallSpaces[SMALL_SPACE_PAGES * ndx];#if 0  dprintf(true, "Loading small space process 0x%X bias 0x%x "		  "limit 0x%x\n",		  procRoot->oid, cc.bias, cc.limit);#endif    for (uint32_t pg = 0; pg < SMALL_SPACE_PAGES; pg++)    cc.smallPTE[pg].Invalidate();#endif  cc.fixRegs.MappingTable = KERNPAGEDIR;    cc.hazards =    hz::DomRoot | hz::KeyRegs | hz::Schedule | hz::AddrSpace;#ifdef EROS_HAVE_FPU  /* Must be hazarded by float regs so that we can correctly re-issue   * floating point exceptions on restart:   */  cc.hazards |= hz::FloatRegs;#endif  cc.curThread = 0;    procRoot->context = &cc;  procRoot->obType = ObType::NtProcessRoot;#if 0  printf("End Process::Load\n");#endif}/* ValidateRegValues() -- runs last to validate that the loaded context * will not violate protection rules if it is run.  This routine must * be careful not to overwrite an existing fault condition. To avoid * this, it must only alter the fault code value if there isn't * already a fault code.  Basically, think of this as meaning that bad * register values are the lowest priority fault that will be reported * to the user. */void

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -