📄 usercontextinvoke.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 + -