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

📄 kernelpage.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 4 页
字号:
  int status = 0;  // Make it occupy the first spot.  kernelPageDir = pageDirList[numberPageDirectories++];  // Get some physical memory for the page directory.  The physical  // address we use for this is static, and is defined in kernelParameters.h   if ((kernelPagingData % MEMORY_PAGE_SIZE) != 0)    return (status = ERR_ALIGN);  kernelPageDir->physical = (kernelPageDirPhysicalMem *) kernelPagingData;  // Make the virtual address be physical for now  kernelPageDir->virtual = kernelPageDir->physical;  // Clear the physical memory  kernelMemClear((void *) kernelPageDir->physical,		 sizeof(kernelPageDirPhysicalMem));  kernelPageDir->processId = KERNELPROCID;  kernelPageDir->numberShares = 0;  kernelPageDir->parent = 0;  kernelPageDir->privilege = PRIVILEGE_SUPERVISOR;  return (status = 0);}static int firstPageTable(void){  // This will create the first page table, specifically for the  // kernel.  Just as like the first page directory, we don't want to map  // it into the current, temporary page directory set up by the loader.  // We have to do this one manually.  Returns a pointer to the first table  // on success, NULL on failure.  int status = 0;  int tableNumber = 0;  kernelPageTable *table = NULL;  // Assign the page table to a slot  table = pageTableList[numberPageTables++];  // Get some physical memory for the page table.  The base physical  // address we use for this is static, and is defined in   // kernelParameters.h   if ((kernelPagingData % MEMORY_PAGE_SIZE) != 0)    return (status = ERR_ALIGN);  tableNumber = getTableNumber(KERNEL_VIRTUAL_ADDRESS);  table->directory = kernelPageDir;  table->tableNumber = tableNumber;  table->freePages = PAGE_PAGES_PER_TABLE;  table->physical = (kernelPageTablePhysicalMem *)     (kernelPagingData + sizeof(kernelPageDirPhysicalMem));  // Make the virtual address be physical, for now  table->virtual = table->physical;  // Clear the physical memory  kernelMemClear((void *) table->physical,		 sizeof(kernelPageTablePhysicalMem));  // Now we actually go into the page directory memory and add the  // real page table to the requested slot number.  // Write the page table entry into the kernel's page directory.  // Enable read/write and page-present  kernelPageDir->physical->table[tableNumber] = (unsigned) table->physical;  kernelPageDir->physical->table[tableNumber] |=    (PAGEFLAG_WRITABLE | PAGEFLAG_PRESENT);  return (status = 0);}static int kernelPaging(unsigned kernelMemory){  // This function will reinitialize the paging environment at kernel  // startup.  This needs to be handled differently than when regular  // processes are created.    int status = 0;  kernelPageDirPhysicalMem *oldPageDirectory = NULL;  kernelPageTablePhysicalMem *oldPageTable = NULL;  kernelPageTable *newPageTable = NULL;  int tableNumber = 0;  int pageNumber = 0;  void *kernelAddress;  // Interrupts should currently be disabled at this point.  kernelProcessorSuspendInts(status);  // The kernel is currently located at kernelVirtualAddress (virtually).  // We need to locate the current, temporary page directory, then the page  // table that corresponds to kernelVirtualAddress.  From there, we need  // to copy the contents of the page table(s) until all of the kernel's  // current memory set has been remapped.  // Get the address of the old page directory.  In this special instance,  // the physical address we get back from this call can be used like   // a virtual address, since the lower part of memory should presently  // be identity-mapped.  kernelProcessorGetCR3(oldPageDirectory);  oldPageDirectory = (kernelPageDirPhysicalMem *)     ((unsigned) oldPageDirectory & 0xFFFFF800);  // The index of the page table can be determined from the virtual  // address of the kernel.  This will be the same value we use in our  // new page directory.  tableNumber = getTableNumber(KERNEL_VIRTUAL_ADDRESS);  // Get the old page table address.  The number of the old page table  // can be used as an index into the old page directory.  We mask out  // the lower 12 bits of the value we find at that index, and voila, we  // have a pointer to the old page table.  Again, we could normally  // not use this for much since it's a physical address, but again,  // this time it's also a virtual address.  oldPageTable = (kernelPageTablePhysicalMem *)     (oldPageDirectory->table[tableNumber] & 0xFFFFF000);  if (oldPageTable == NULL)    return (status = ERR_NOTINITIALIZED);  // Create a new page directory for the kernel.  We have to do this  // differently, as opposed to calling createPageDirectory(), since this  // should not be "mapped" into the current, temporary page directory.  status = firstPageDirectory();  if (status < 0)    return (status = ERR_NOTINITIALIZED);  // Create a new, initial page table for the kernel.  Again, we have to  // do this manually, as opposed to calling createPageTable(), since  // this should also not be mapped into the current, temporary page  // directory.  status = firstPageTable();  if (status < 0)    return (status = ERR_NOTINITIALIZED);  // The index of the first page in the page table can also be determined  // from the virtual address of the kernel.  This will be the same value  // we use to start our new page tables.  pageNumber = getPageNumber(KERNEL_VIRTUAL_ADDRESS);  // Copy the RELEVANT contents of the old page table into the new  // page table.  This suggests that some of the data in the old page  // table might be irrelevant.  That would be correct.  You see, the   // loader might (presently DOES) map pages gratuitously, irrespective  // of how many pages the kernel actually uses.  We will only copy the  // pages that the kernel uses, based on the kernelSize.  The following  // code needs to assume that the kernel does not cross a 4-Mb boundary.    newPageTable = findPageTable(kernelPageDir, tableNumber);  if (newPageTable == NULL)    return (status = ERR_NOTINITIALIZED);  // Map the kernel memory into the existing page directory and page  // table  kernelAddress = (void *) KERNEL_VIRTUAL_ADDRESS;  // Map the kernel itself at the prescribed virtual address  status = map(kernelPageDir, (void *) KERNEL_LOAD_ADDRESS, &kernelAddress,	       kernelMemory, PAGE_MAP_EXACT, 1); // last by Davide Airaghi  if (status < 0)    return (status);  status = map(kernelPageDir, (void *) kernelPageDir->physical,	       (void **) &(kernelPageDir->virtual),	       sizeof(kernelPageDirPhysicalMem), PAGE_MAP_ANY, 1); // last by Davide Airaghi  if (status < 0)    return (status);  status = map(kernelPageDir, (void *) newPageTable->physical,	       (void **) &(newPageTable->virtual),	       sizeof(kernelPageTablePhysicalMem), PAGE_MAP_ANY, 1 ); // last by Davide Airaghi  if (status < 0)    return (status);  // Now we should be able to switch the processor to our new page   // directory and table(s).  kernelProcessorSetCR3((unsigned) kernelPageDir->physical);  // Return success  return (status = 0);}static void shareKernelPages(kernelPageDirectory *directory){  // This routine will put pointers to the kernel's page tables into the  // supplied page directory.  This effectively puts the kernel "into  // the virtual address space" of the process that owns the directory.  int kernelStartingTable = 0;  int count;  // Determine the starting page table of the kernel's address space  kernelStartingTable = getTableNumber(KERNEL_VIRTUAL_ADDRESS);  // We will do a loop, copying the table entries from the kernel's  // page directory to the target page directory.  for (count = kernelStartingTable; count < PAGE_TABLES_PER_DIR; count ++)    directory->virtual->table[count] = kernelPageDir->virtual->table[count];  // Return  return;}static int setPageAttrs(kernelPageDirectory *directory, int set,			unsigned char flags, void *virtualAddress, int pages){  // This allows the setting/clearing of page attributes  int status = 0;  kernelPageTable *pageTable = NULL;  int pageNumber = 0;  while (pages > 0)    {      pageTable = findPageTable(directory, getTableNumber(virtualAddress));      if (pageTable == NULL)	return (status = ERR_NOSUCHENTRY);      pageNumber = getPageNumber(virtualAddress);      for ( ; (pages > 0) && (pageNumber < PAGE_PAGES_PER_TABLE);	    pageNumber ++)	{	  if (!pageTable->virtual->page[pageNumber])	    {	      kernelError(kernel_error, "Virtual address %08x is not mapped",			  virtualAddress);	      return (status = ERR_NODATA);	    }	  if (set)	    pageTable->virtual->page[pageNumber] |= (flags & 0x0FFF);	  else	    pageTable->virtual->page[pageNumber] &= ~(flags & 0x0FFF);	  virtualAddress += MEMORY_PAGE_SIZE;	  pages -= 1;	}    }  return (status = 0);}//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////  Below here, the functions are exported for external use////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////int kernelPageInitialize(unsigned kernelMemory){  // This function will initialize the page manager and call the kernelPaging  // routine to create a set of new page tables for the kernel environment.  // (This is based on the assumptions that paging has been enabled prior  // to the kernel starting, and that there must be an existing set of  // basic page tables created by the loader).  Returns 0 on success,   // negative on error.  int status = 0;  int count;  // Clear out the memory we'll use to keep track of all the page   // directories and page tables, and set both counters to zero.  kernelMemClear((void *) pageDirMemory, 			(sizeof(kernelPageDirectory) * MAX_PROCESSES));  kernelMemClear((void *) pageTableMemory, 			(sizeof(kernelPageTable) * MAX_PROCESSES));  // Loop through both of the dynamic lists that we'll use to keep   // pointers to the memory space we just reserved  for (count = 0; count < MAX_PROCESSES; count ++)    {      pageDirList[count] = &pageDirMemory[count];      pageTableList[count] = &pageTableMemory[count];    }  numberPageDirectories = 0;  numberPageTables = 0;  // Calculate the physical memory location where we'll store the kernel's  // paging data.  kernelPagingData = (KERNEL_LOAD_ADDRESS + kernelMemory);  // Initialize the kernel's paging environment, which is done differently  // than for a normal process.  status = kernelPaging(kernelMemory);  if (status < 0)    return (status);  // Make note that we're initialized  initialized = 1;  // Return success  return (status = 0);}void *kernelPageGetDirectory(int processId){  // This is an accessor function, which just returns the physical address of  // the requested page directory (suitable for putting in the CR3 register).  // Returns NULL on failure  int status = 0;  kernelPageDirectory *directory = NULL;  void *physicalAddress = NULL;  // Have we been initialized?  if (!initialized)    return (NULL);  // Find the appropriate page directory  directory = findPageDirectory(processId);  if (directory == NULL)    return (NULL);  status = kernelLockGet(&(directory->dirLock));  if (status < 0)    return (physicalAddress = NULL);    physicalAddress = (void *) directory->physical;  kernelLockRelease(&(directory->dirLock));  return (physicalAddress);}void *kernelPageNewDirectory(int processId, int privilege){  // This function will create a new page directory and one page table for  // a new process.  int status = 0;  kernelPageDirectory *directory = NULL;  kernelPageTable *table = NULL;  void *physicalAddress = NULL;  // next by Davide Airaghi  int kernel = 0;    // Have we been initialized?  if (!initialized)    return (physicalAddress = NULL);  // Make sure privilege is legal  if ((privilege != PRIVILEGE_USER) && (privilege != PRIVILEGE_SUPERVISOR))     return (physicalAddress = NULL);    // by Davide Airaghi  if (privilege != PRIVILEGE_SUPERVISOR && kernel)    return (physicalAddress = NULL); // normal user can't be at ring0!      // next 5 lines by Davide Airaghi  kernel = kernelMultitaskerIsLowLevelProcess(processId);  if (kernel < 0)    kernel = 0;  else    kernel = 1;      // Create a page directory for the process  directory = createPageDirectory(processId, privilege, kernel); // last by Davide Airaghi  if (directory == NULL)    return (physicalAddress = NULL);  status = kernelLockGet(&(directory->dirLock));  if (status < 0)    return (physicalAddress = NULL);    // Create an initial page table in the page directory, in the first spot  table = createPageTable(directory, 0, kernel ); // slot 0, last by Davide Airaghi  if (table == NULL)    {      // Deallocate the page directory we created.  Don't unlock it since      // it's going away      deletePageDirectory(directory);      return (physicalAddress = NULL);    }    // Finally, we need to map the kernel's address space into that of this  // new process.  The process will not receive copies of the kernel's  // page tables.  It will only get mappings in its page directory.  shareKernelPages(directory);  physicalAddress = (void *) directory->physical;  kernelLockRelease(&(directory->dirLock));  // Return the physical address of the new page directory.  return (physicalAddress);}void *kernelPageShareDirectory(int parentId, int childId){  // This function will allow a new process thread to share the page  // directory of its parent.  int status = 0;  kernelPageDirectory *parentDirectory = NULL;  kernelPageDirectory *childDirectory = NULL;  void *physicalAddress = NULL;  // Have we been initialized?  if (!initialized)    return (physicalAddress = NULL);  // Find the page directory belonging to the parent process  parentDirectory = findPageDirectory(parentId);

⌨️ 快捷键说明

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