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

📄 usercontextinvoke.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
字号:
/* * Copyright (C) 1998, 1999, 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/Thread.hxx>#include <kerninc/Process.hxx>#include <kerninc/Node.hxx>#include <kerninc/Invocation.hxx>#include <kerninc/Machine.hxx>#include <kerninc/ObjectCache.hxx>#include <arch-kerninc/Process.hxx>#ifndef OPTION_SMALL_SPACESconst uint32_t bias = 0;#endif#ifndef ASM_VALIDATE_STRINGSvoidProcess::SetupEntryString(Invocation& inv){#ifndef OPTION_PURE_ENTRY_STRINGS  if (inv.entry.len == 0)    return;#endif  /* Make sure the string gets mapped if there is one: */  ula_t ula = fixRegs.sndPtr + bias;  ula_t ulaTop = ula + inv.entry.len;  ula &= ~EROS_PAGE_MASK;  while (ula < ulaTop) {    PTE *pte0 = proc_TranslatePage(this, ula, PTE_V|PTE_USER, false);    if (pte0 == 0)      pte0 = proc_BuildMapping(this, ula, false, false);    ula += EROS_PAGE_SIZE;  }  uint32_t addr = (uint32_t) fixRegs.sndPtr + bias + KUVA;    inv.entry.data = (uint8_t *) addr;}#endif /* ASM_VALIDATE_STRINGS */voidProcess::SetupExitString(Invocation& inv, uint32_t bound){#ifndef OPTION_PURE_EXIT_STRINGS  if (inv.validLen == 0)    return;#endif  if (inv.validLen > bound)    inv.validLen = bound;  /* In the case where we are going cross-space, we need to do some   * fairly hairy crud here, but for device drivers it is important to   * get the invoker == invokee case right.  In that special case, we   * can simply use the invokee address directly and run the test in a   * fashion similar to that of the EntryBlock case.   */  assert( IsRunnable() );  if (      /* It is okay for recipient space to point to the kernel page	 directory; if it gets bumped up to a large space we will	 yield due to PTE zap. */#ifdef OPTION_SMALL_SPACES      smallPTE ||#endif      (Thread::CurContext()->fixRegs.MappingTable == fixRegs.MappingTable)      ) {#ifdef OPTION_SMALL_SPACES    ula_t ula = fixRegs.EDI + bias;#else    ula_t ula = fixRegs.EDI;#endif    ula_t ulaTop = ula + inv.validLen;    ula &= ~EROS_PAGE_MASK;    while (ula < ulaTop) {      PTE *pte0 = proc_TranslatePage(this, ula, PTE_V|PTE_USER, true);      if (pte0 == 0)	pte0 = proc_BuildMapping(this, ula, true, true);      if (pte0 == 0) {	uint32_t lenHere = ula - fixRegs.EDI;	if (lenHere < inv.validLen)	  inv.validLen = lenHere;	break;      }            ula += EROS_PAGE_SIZE;    }#ifdef OPTION_SMALL_SPACES    ula_t addr = fixRegs.EDI + bias + KUVA;#else    ula_t addr = fixRegs.EDI + KUVA;#endif    inv.exit.data = (uint8_t *) addr;  }  else {#ifdef OPTION_SMALL_SPACES    ula_t addr = fixRegs.EDI + bias;#else    ula_t addr = fixRegs.EDI;#endif    addr &= EROS_PAGE_MASK;    addr |= KVA_PTEBUF;      inv.exit.data = (uint8_t *) addr;    /* Make sure the string gets mapped if there is one: */    PTE *rcvPTE = PTE::kern_ptebuf;    kva_t kernAddr = KVA_PTEBUF;#ifdef OPTION_SMALL_SPACES    ula_t ula = fixRegs.EDI + bias;#else    ula_t ula = fixRegs.EDI;#endif    ula_t ulaTop = ula + inv.validLen;    ula &= ~EROS_PAGE_MASK;    while (ula < ulaTop) {      PTE *pte0 = proc_TranslatePage(this, ula, PTE_V|PTE_USER, true);      if (pte0 == 0)	pte0 = proc_BuildMapping(this, ula, true, false);      if (pte0 == 0) {	uint32_t lenHere = ula - fixRegs.EDI;	if (lenHere < inv.validLen)	  inv.validLen = lenHere;	break;      }          *rcvPTE = *pte0;      /* FIX: flush logic here is really stupid! */      Machine::FlushTLB(kernAddr);      kernAddr += EROS_PAGE_SIZE;      ula += EROS_PAGE_SIZE;      rcvPTE++;    }  }  /* The segment walking logic may have set a fault code.  Clear it   * here, since no segment keeper invocation should happen as a   * result of the above.  We know this was the prior state, as the   * domain would not otherwise have been runnable.   */  SetFault(FC_NoFault, 0, false);}voidProcess::DeliverResult(Invocation& inv){  /* No need to call Prepare() here -- it has already been  called in   * the invocation path.   */  assert(IsRunnable());    assert (inv.keyType > KT_Resume);    /* copy return code and words */  fixRegs.EAX = inv.exit.code;  fixRegs.EBX = inv.exit.w1;  fixRegs.ECX = inv.exit.w2;  fixRegs.EDX = inv.exit.w3;  uint32_t rcvPtr = fixRegs.EDI;    fixRegs.EDI = 0;		/* key info field */  /* Data has already been copied out, so don't need to copy here.  DO   * need to deliver the data length, however:   */  fixRegs.ESI = inv.exit.len;  /* If the recipient specified an invalid receive area, though, they   * are gonna get FC_ParmLack:   */  if (inv.validLen < inv.exit.len)    SetFault(FC_ParmLack, rcvPtr + inv.validLen, false);}

⌨️ 快捷键说明

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