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

📄 page.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
字号:
/* * page.c :- This file contains implementation of C function to *           Instanciate paging. More detailled information *	     can be found on Intel site and more precisely in *           the following book : * *		Pentium Processor familly *		Developper's Manual * *		Volume 3 : Architecture and Programming Manual * * Copyright (C) 1999  Emmanuel Raguet (raguet@crf.canon.fr) *                     Canon Centre Recherche France. * *  The license and distribution terms for this file may be *  found in found in the file LICENSE in this distribution or at *  http://www.rtems.com/license/LICENSE. * * $Header: /usr1/CVS/rtems/c/src/lib/libcpu/i386/page.c,v 1.8.4.1 2003/09/04 18:45:43 joel Exp $ */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <rtems.h>#include <libcpu/cpu.h>#define MEMORY_SIZE 0x4000000 		/* 64Mo */static int directoryEntry=0;static int tableEntry=0;static page_directory *pageDirectory;extern rtems_unsigned32 rtemsFreeMemStart;/*************************************************************************//************** IT IS A ONE-TO-ONE TRANSLATION ***************************//*************************************************************************//* * Disable the paging */void _CPU_disable_paging() {  cr0 regCr0;  rtems_cache_flush_entire_data();  regCr0.i = i386_get_cr0();  regCr0.cr0.paging = 0;  i386_set_cr0( regCr0.i );}/* * Enable the paging */void _CPU_enable_paging() {  cr0 regCr0;  regCr0.i = i386_get_cr0();  regCr0.cr0.paging = 1;  i386_set_cr0( regCr0.i );  rtems_cache_flush_entire_data();}/* * Initialize the paging with 1-to-1 mapping */int init_paging() {  int memorySize;  int nbPages;  int nbInitPages;  char *Tables;  cr3 regCr3;  page_table *pageTable;  unsigned int physPage;  int nbTables=0;    /*   * rtemsFreeMemStart is the last valid 32-bits address   * so the size is rtemsFreeMemStart + 4   */  memorySize = rtemsFreeMemStart + 4;    nbPages = ( (memorySize - 1) / PG_SIZE ) + 1;  nbTables = ( (memorySize - 1) / FOUR_MB ) + 2;  /* allocate 1 page more to page alignement */  Tables = (char *)malloc( (nbTables + 1)*sizeof(page_table) );   if ( Tables == NULL ){    return -1; /*unable to allocate memory */  }    /* 4K-page alignement */  Tables += (PG_SIZE - (int)Tables) & 0xFFF;  /* Reset Tables */  memset( Tables, 0, nbTables*sizeof(page_table) );  pageDirectory = (page_directory *) Tables;  pageTable     = (page_table *)((int)Tables + PG_SIZE);  nbInitPages = 0;  directoryEntry = 0;  tableEntry = 0;  physPage = 0;  while ( nbInitPages != nbPages ){    if ( tableEntry == 0 ){      pageDirectory->pageDirEntry[directoryEntry].bits.page_frame_address = (unsigned int)pageTable >> 12;      pageDirectory->pageDirEntry[directoryEntry].bits.available      = 0;      pageDirectory->pageDirEntry[directoryEntry].bits.page_size      = 0;      pageDirectory->pageDirEntry[directoryEntry].bits.accessed       = 0;      pageDirectory->pageDirEntry[directoryEntry].bits.cache_disable  = 0;      pageDirectory->pageDirEntry[directoryEntry].bits.write_through  = 0;      pageDirectory->pageDirEntry[directoryEntry].bits.user           = 1;      pageDirectory->pageDirEntry[directoryEntry].bits.writable       = 1;      pageDirectory->pageDirEntry[directoryEntry].bits.present        = 1;    }    pageTable->pageTableEntry[tableEntry].bits.page_frame_address = physPage;    pageTable->pageTableEntry[tableEntry].bits.available      = 0;    pageTable->pageTableEntry[tableEntry].bits.dirty          = 0;    pageTable->pageTableEntry[tableEntry].bits.accessed       = 0;    pageTable->pageTableEntry[tableEntry].bits.cache_disable  = 0;    pageTable->pageTableEntry[tableEntry].bits.write_through  = 0;    pageTable->pageTableEntry[tableEntry].bits.user           = 1;    pageTable->pageTableEntry[tableEntry].bits.writable       = 1;    pageTable->pageTableEntry[tableEntry].bits.present        = 1;    physPage ++;    tableEntry ++;    if (tableEntry >= MAX_ENTRY){      tableEntry = 0;      directoryEntry ++;      pageTable ++;    }          nbInitPages++;  }  regCr3.cr3.page_write_transparent = 0;  regCr3.cr3.page_cache_disable     = 0;  regCr3.cr3.page_directory_base    = (unsigned int)pageDirectory >> 12;  i386_set_cr3( regCr3.i );  _CPU_enable_cache();    _CPU_enable_paging();    return 0;}/* * Is cache enable */int  _CPU_is_cache_enabled() {  cr0 regCr0;  regCr0.i = i386_get_cr0();  return( ~(regCr0.cr0.page_level_cache_disable) );}/* * Is paging enable */int  _CPU_is_paging_enabled() {  cr0 regCr0;  regCr0.i = i386_get_cr0();  return(regCr0.cr0.paging);}/* * Translate the physical address in the virtual space and return * the translated address in mappedAddress */int _CPU_map_phys_address        (void **mappedAddress, void *physAddress, int size, int flag){   page_table *localPageTable;  unsigned int lastAddress, countAddress;  char *Tables;  linear_address virtualAddress;  unsigned char pagingWasEnabled;    pagingWasEnabled = 0;  if (_CPU_is_paging_enabled()){    pagingWasEnabled = 1;    _CPU_disable_paging();  }  countAddress = (unsigned int)physAddress;  lastAddress = (unsigned int)physAddress + (size - 1);  virtualAddress.address = 0;  while (1){    if ((countAddress & ~MASK_OFFSET) > (lastAddress & ~MASK_OFFSET))      break;    /* Need to allocate a new page table */    if (pageDirectory->pageDirEntry[directoryEntry].bits.page_frame_address == 0){      /* We allocate 2 pages to perform 4k-page alignement */      Tables = (char *)malloc(2*sizeof(page_table));       if ( Tables == NULL ){	if (pagingWasEnabled)	  _CPU_enable_paging();	return -1; /* unable to allocate memory */      }      /* 4K-page alignement */      Tables += (PG_SIZE - (int)Tables) & 0xFFF;      /* Reset Table */      memset( Tables, 0, sizeof(page_table) );            pageDirectory->pageDirEntry[directoryEntry].bits.page_frame_address =	(unsigned int)Tables >> 12;      pageDirectory->pageDirEntry[directoryEntry].bits.available      = 0;      pageDirectory->pageDirEntry[directoryEntry].bits.page_size      = 0;      pageDirectory->pageDirEntry[directoryEntry].bits.accessed       = 0;      pageDirectory->pageDirEntry[directoryEntry].bits.cache_disable  = 0;      pageDirectory->pageDirEntry[directoryEntry].bits.write_through  = 0;      pageDirectory->pageDirEntry[directoryEntry].bits.user           = 1;      pageDirectory->pageDirEntry[directoryEntry].bits.writable       = 1;      pageDirectory->pageDirEntry[directoryEntry].bits.present        = 1;    }          localPageTable = (page_table *)(pageDirectory->				    pageDirEntry[directoryEntry].bits.				    page_frame_address << 12);    if (virtualAddress.address == 0){      virtualAddress.bits.directory = directoryEntry;      virtualAddress.bits.page      = tableEntry;      virtualAddress.bits.offset    = (unsigned int)physAddress & MASK_OFFSET;    }    localPageTable->pageTableEntry[tableEntry].bits.page_frame_address =      ((unsigned int)countAddress & ~MASK_OFFSET) >> 12;    localPageTable->pageTableEntry[tableEntry].bits.available      = 0;    localPageTable->pageTableEntry[tableEntry].bits.dirty          = 0;    localPageTable->pageTableEntry[tableEntry].bits.accessed       = 0;    localPageTable->pageTableEntry[tableEntry].bits.cache_disable  = 0;    localPageTable->pageTableEntry[tableEntry].bits.write_through  = 0;    localPageTable->pageTableEntry[tableEntry].bits.user           = 1;    localPageTable->pageTableEntry[tableEntry].bits.writable       = 0;    localPageTable->pageTableEntry[tableEntry].bits.present        = 1;    localPageTable->pageTableEntry[tableEntry].table_entry |= flag ;    countAddress += PG_SIZE;    tableEntry++;    if (tableEntry >= MAX_ENTRY){            tableEntry = 0;      directoryEntry++;    }  }  if (mappedAddress != 0)    *mappedAddress = (void *)(virtualAddress.address);  if (pagingWasEnabled)    _CPU_enable_paging();  return 0;}/* * "Compress" the Directory and Page tables to avoid * important loss of address range */static void Paging_Table_Compress() {  unsigned int dirCount, pageCount;  page_table *localPageTable;    if (tableEntry == 0){    dirCount  = directoryEntry - 1;    pageCount = MAX_ENTRY - 1;  }  else {    dirCount  = directoryEntry;    pageCount = tableEntry - 1;  }      while (1){    localPageTable = (page_table *)(pageDirectory->				    pageDirEntry[dirCount].bits.				    page_frame_address << 12);    if (localPageTable->pageTableEntry[pageCount].bits.present == 1){      pageCount++;      if (pageCount >= MAX_ENTRY){      	pageCount = 0;	dirCount++;      }      break;    }    if (pageCount == 0) {      if (dirCount == 0){		break;      }      else {	pageCount = MAX_ENTRY - 1;	dirCount-- ;      }	    }    else      pageCount-- ;  }  directoryEntry = dirCount;  tableEntry = pageCount;}        /* * Unmap the virtual address from the tables * (we do not deallocate the table already allocated) */int _CPU_unmap_virt_address(void *mappedAddress, int size){   linear_address linearAddr;  page_table *localPageTable;  unsigned int lastAddr ;  unsigned int dirCount ;  unsigned char pagingWasEnabled;    pagingWasEnabled = 0;  if (_CPU_is_paging_enabled()){    pagingWasEnabled = 1;    _CPU_disable_paging();  }  linearAddr.address = (unsigned int)mappedAddress;  lastAddr = (unsigned int)mappedAddress + (size - 1);  dirCount = linearAddr.bits.directory;  while (1){    if ((linearAddr.address & ~MASK_OFFSET) > (lastAddr & ~MASK_OFFSET))      break;    if (pageDirectory->pageDirEntry[linearAddr.bits.directory].bits.present == 0){      if (pagingWasEnabled)	_CPU_enable_paging();      return -1;    }    localPageTable = (page_table *)(pageDirectory->				    pageDirEntry[linearAddr.bits.directory].bits.				    page_frame_address << 12);        if (localPageTable->pageTableEntry[linearAddr.bits.page].bits.present == 0){      if (pagingWasEnabled)	_CPU_enable_paging();      return -1;    }      localPageTable->pageTableEntry[linearAddr.bits.page].bits.present = 0;            linearAddr.address += PG_SIZE ;  }  Paging_Table_Compress();  if (pagingWasEnabled)    _CPU_enable_paging();  return 0;}/* * Modify the flags PRESENT, WRITABLE, USER, WRITE_TROUGH, CACHE_DISABLE  * of the page's descriptor. */int _CPU_change_memory_mapping_attribute    (void **newAddress, void *mappedAddress, unsigned int size, unsigned int flag){   linear_address linearAddr;  page_table *localPageTable;  unsigned int lastAddr ;  unsigned char pagingWasEnabled;    pagingWasEnabled = 0;  if (_CPU_is_paging_enabled()){    pagingWasEnabled = 1;    _CPU_disable_paging();  }    linearAddr.address  = (unsigned int)mappedAddress;  lastAddr = (unsigned int)mappedAddress + (size - 1);  while (1){    if ((linearAddr.address & ~MASK_OFFSET) > (lastAddr & ~MASK_OFFSET))      break;    if (pageDirectory->pageDirEntry[linearAddr.bits.directory].bits.present == 0){      if (pagingWasEnabled)	_CPU_enable_paging();      return -1;    }    localPageTable = (page_table *)(pageDirectory->				    pageDirEntry[linearAddr.bits.directory].bits.				    page_frame_address << 12);        if (localPageTable->pageTableEntry[linearAddr.bits.page].bits.present == 0){      if (pagingWasEnabled)	_CPU_enable_paging();      return -1;    }      localPageTable->pageTableEntry[linearAddr.bits.page].table_entry &= ~MASK_FLAGS ;    localPageTable->pageTableEntry[linearAddr.bits.page].table_entry |= flag ;        linearAddr.address += PG_SIZE ;  }    if (newAddress != NULL)    *newAddress = mappedAddress ;  if (pagingWasEnabled)    _CPU_enable_paging();  return 0;}/* * Display the page descriptor flags * CACHE_DISABLE of the whole memory */#include <rtems/bspIo.h>int  _CPU_display_memory_attribute(){   unsigned int dirCount, pageCount;  cr0 regCr0;  page_table *localPageTable;  unsigned int prevCache;  unsigned int prevPresent;  unsigned int maxPage;  unsigned char pagingWasEnabled;    regCr0.i = i386_get_cr0();    printk("\n\n >>>>>>>>>  MEMORY CACHE CONFIGURATION <<<<<<<<<<\n\n");  printk("CR0 -> paging           : %s\n",(regCr0.cr0.paging ? "ENABLE ":"DISABLE"));  printk("       page-level cache : %s\n\n",(regCr0.cr0.page_level_cache_disable ? "DISABLE":"ENABLE"));  if (regCr0.cr0.paging == 0)    return 0;    prevPresent = 0;  prevCache   = 1;    pagingWasEnabled = 0;  if (_CPU_is_paging_enabled()){    pagingWasEnabled = 1;    _CPU_disable_paging();  }  for (dirCount = 0; dirCount < directoryEntry+1; dirCount++) {    localPageTable = (page_table *)(pageDirectory->				    pageDirEntry[dirCount].bits.				    page_frame_address << 12);    maxPage = MAX_ENTRY;    /*if ( dirCount == (directoryEntry-1))      maxPage = tableEntry;*/    for (pageCount = 0; pageCount < maxPage; pageCount++) {      if (localPageTable->pageTableEntry[pageCount].bits.present != 0){	if (prevPresent == 0){	  prevPresent = 1;	  printk ("present page from address %x \n", ((dirCount << 22)|(pageCount << 12)));	}	if (prevCache != localPageTable->pageTableEntry[pageCount].bits.cache_disable ) {	  prevCache = localPageTable->pageTableEntry[pageCount].	    bits.cache_disable;	  printk ("    cache %s from %x <phy %x>\n",		  (prevCache ? "DISABLE" : "ENABLE "),		  ((dirCount << 22)|(pageCount << 12)),		  localPageTable->pageTableEntry[pageCount].bits.page_frame_address << 12);	}      }      else {	if (prevPresent == 1){	  prevPresent = 0;	  printk ("Absent from %x \n", ((dirCount << 22)|(pageCount << 12)));	}      }    }  }  if (pagingWasEnabled)    _CPU_enable_paging();  return 0;}

⌨️ 快捷键说明

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