📄 address_space.c
字号:
/** address_space.c ** ** Original Author: Guido de Jong ** Date: 11/16/99 ** ** Description: ** Address space management functions ** ** 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 of the License, 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 or 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, Inc., 59 Temple Place, Suite 330, ** Boston, MA 02111-1307 USA ** *********************************************************Apostle OS**/#include <address_space.h>#include <mapping.h>#include <paging.h>#include <types.h>#include <mem.h>#include <string.h>#ifdef DEBUG#include <debug/conio.h>#endif/* map * * Share page control with another address space. * If necessary page tables and node tables are created and initialized. */void map(dword *srcAddrSp, void *src, dword *destAddrSp, void *dest, size_t n, int flags){ uint i; dword *srcPT, *destPT; MappingNode **srcNT, **destNT; dword srcPage = ((dword) src) >> 12, destPage = ((dword) dest) >> 12; for (i = 0; i < n; i++) { /* Initializing page and node tables */ if (srcAddrSp[srcPage >> 10] & PAGE_PRESENT) { srcPT = (dword *)(srcAddrSp[srcPage >> 10] & 0xfffff000); srcNT = (MappingNode **)((dword)srcPT + PAGE_SIZE); } else { srcPT = NULL; srcNT = NULL; } if (destAddrSp[destPage >> 10] & PAGE_PRESENT) { destPT = (dword *)(destAddrSp[destPage >> 10] & 0xfffff000); destNT = (MappingNode **)((dword)destPT + PAGE_SIZE); } else { destPT = p2malloc(); destAddrSp[destPage >> 10 ] = (dword) destPT \ | PAGE_USER | PAGE_WRITABLE | PAGE_PRESENT; destNT = (MappingNode **)((dword)destPT + PAGE_SIZE); memset(destNT, 0, PAGE_SIZE); } /* create source node if necessarry (1st time map) */ if (srcNT[srcPage & 0x3ff] == NULL) srcNT[srcPage & 0x3ff] = NewMappingNode(srcAddrSp, src); /* destination mapping node should not exist ... */ if (destNT[destPage & 0x3ff] != NULL) flush(destNT[destPage & 0x3ff]->addrSpace, destNT[destPage & 0x3ff]->address, PAGE_SIZE, TRUE, TRUE); destNT[destPage & 0x3ff] = NewMappingNode(destAddrSp, dest); AddNode(srcNT[srcPage & 0x3ff], destNT[destPage & 0x3ff]); /* do the actual mapping */ if (srcPT == NULL) destPT[destPage & 0x3ff] = 0; else destPT[destPage & 0x3ff] = (srcPT[srcPage & 0x3ff] & 0xfffff000) \ | (flags & 0x0fff); srcPage++; destPage++; }}/* grant * * Grant exclusive page control to another address space. * If necessary page tables and node tables are created and initialized. */void grant(dword *srcAddrSp, void *src, dword *destAddrSp, void *dest, size_t n, int flags){ uint i; dword *srcPT, *destPT; MappingNode **srcNT, **destNT; dword srcPage = ((dword) src) >> 12, destPage = ((dword) dest) >> 12; for (i = 0; i < n; i++) { /* Initializing page and node tables */ if (srcAddrSp[srcPage >> 10] & PAGE_PRESENT) { srcPT = (dword *)(srcAddrSp[srcPage >> 10] & 0xfffff000); srcNT = (MappingNode **)((dword)srcPT + PAGE_SIZE); } else { srcPT = NULL; srcNT = NULL; } if (destAddrSp[destPage >> 10] & PAGE_PRESENT) { destPT = (dword *)(destAddrSp[destPage >> 10] & 0xfffff000); destNT = (MappingNode **)((dword)destPT + PAGE_SIZE); } else { destPT = p2malloc(); destAddrSp[destPage >> 10 ] = (dword) destPT \ | PAGE_USER | PAGE_WRITABLE | PAGE_PRESENT; destNT = (MappingNode **)((dword)destPT + PAGE_SIZE); memset(destNT, 0, PAGE_SIZE); } /* destination mapping node should not exist ... */ if (destNT[destPage & 0x3ff] != NULL) flush(destNT[destPage & 0x3ff]->addrSpace, destNT[destPage & 0x3ff]->address, PAGE_SIZE, TRUE, TRUE); /* Source node will never be created here. If it does not exist, * there's no need for a destination node either. If it does exist, * just swap pointers and update node attributes. */ if (srcNT[srcPage & 0x3ff] == NULL) destNT[destPage & 0x3ff] = NULL; else { destNT[destPage & 0x3ff] = srcNT[srcPage & 0x3ff]; destNT[destPage & 0x3ff]->addrSpace = destAddrSp; destNT[destPage & 0x3ff]->address = dest; srcNT[srcPage & 0x3ff] = NULL; } /* do the actual granting */ if (srcPT == NULL) destPT[destPage & 0x3ff] = 0; else destPT[destPage & 0x3ff] = srcPT[srcPage & 0x3ff] & \ (0xfffff000 | (flags & 0x0fff)); srcPage++; destPage++; }}/* flush * * Return mapped/granted of pages back to parent. * Any possible mappings to other processes are unmapped. */void flush(dword *addressSpace, void *addr, size_t n, bool me_too, bool partial){ int i; dword *PT, page = (dword)addr >> 12; MappingNode **NT, *node; for (i = 0; i < n; i++) { if (addressSpace[page >> 10] & PAGE_PRESENT) { PT = (dword *)(addressSpace[page >> 10] & 0xfffff000); NT = (MappingNode **)((dword)PT + PAGE_SIZE); } else { PT = NULL; NT = NULL; } if (NT) { if (NT[page & 0x3ff]) /* we don't want to crash on NULL pointers */ { node = NT[page & 0x3ff]; /* flush any children */ while (node->child) flush(node->child->addrSpace, node->child->address, n, TRUE, partial); if (me_too) /* return this page to parent */ { if (partial) PT[page & 0x3ff] &= ~PAGE_WRITABLE; else { PT[page & 0x3ff] = 0; /* delete the node */ DeleteNode(node); NT[page & 0x3ff] = NULL; } } } } addr++; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -