00001 // See the end of this file for license information. 00002 00003 #ifndef TORSION_PAGE_H 00004 #define TORSION_PAGE_H 00005 00006 #include "irq.h" 00007 #include "hash.h" 00008 #include "array.h" 00009 #include "types.h" 00010 #include "addrmap.h" 00011 #include "critical.h" 00012 #include "slaballoc.h" 00013 00014 class Page_map; 00015 extern Page_map page_map; 00016 00017 const unsigned VIRTUAL_MEMORY_END = ~0; 00018 00020 00021 class Mapping_cache_info { 00022 public: 00023 unsigned ref_count; 00024 unsigned last_mapped_time; 00025 void* virtual_page; 00026 void* physical_page; 00027 00029 inline void 00030 init(void* virtual_page = NULL, void* physical_page = NULL) { 00031 ref_count = 0; 00032 last_mapped_time = 0; 00033 this->virtual_page = virtual_page; 00034 this->physical_page = physical_page; 00035 } 00036 }; 00037 00039 00040 class Page_map : public Address_map { 00041 protected: 00042 void* direct_mapped_end; 00043 unsigned* temp_mapping_cache; 00044 unsigned* first_free_temp_mapping; 00045 static const Size MAPPING_CACHE_PAGE_COUNT = 1024; 00047 Mapping_cache_info mapping_cache_usage[MAPPING_CACHE_PAGE_COUNT]; 00049 Hash_table<void*, Mapping_cache_info*> mapping_cache_mappings; 00051 Hash_node<void*, Mapping_cache_info*> mapping_nodes[MAPPING_CACHE_PAGE_COUNT]; 00052 Int_handler handler; 00053 00059 Hash_table<void*, void*> dirty_pages[2]; 00060 int dirty_pages_index; 00061 00064 Slab_allocator dirty_pages_nodes[2]; 00065 00066 public: 00067 static const unsigned PTE_USER = 0x4; 00068 static const unsigned PTE_ACCESSED = 0x20; 00069 static const unsigned PTE_PAGE_FRAME_ADDRESS = 0xfffff000; 00071 static const unsigned DIRTY_PAGE_COPIED = 1; 00072 static const unsigned CR0_PAGING = (1 << 31); 00074 static const unsigned CR0_RESPECT_READONLY = (1 << 16); 00075 00077 void 00078 init(unsigned& last_available_address); 00079 00085 void map_page(void* virtual_page, void* physical_page); 00086 00094 unsigned* 00095 map_temp_page(unsigned* physical_page); 00096 00101 void 00102 unmap_temp_page(unsigned* virtual_page); 00103 00105 void 00106 unmap_page(void* virtual_page); 00107 00110 static inline unsigned* 00111 table_entry_to_phys(unsigned page_entry) { 00112 return (unsigned*)(page_entry & PTE_PAGE_FRAME_ADDRESS); 00113 } 00114 00118 inline Hash_table<void*, void*>& 00119 get_dirty_pages() { 00120 return dirty_pages[dirty_pages_index]; 00121 } 00122 00126 inline Hash_table<void*, void*>& 00127 get_dirty_pages_next() { 00128 // 1 - dirty_pages_index, so as to get whichever of the two indices 00129 // (0 and 1) that dirty_pages_index isn't 00130 return dirty_pages[1 - dirty_pages_index]; 00131 } 00132 00138 inline void 00139 switch_dirty_pages_hashes() { 00140 // each time this function is called, dirty_pages_index switches between 00141 // 0 and 1 00142 dirty_pages_index = 1 - dirty_pages_index; 00143 } 00144 00146 void 00147 free_dirty_pages_next(); 00148 00150 bool 00151 handle_page_fault(); 00152 00154 inline void* 00155 virtual_to_physical_page(void* virtual_addr) { 00156 return table_entry_to_phys(get_table_entry(virtual_addr)); 00157 } 00158 00160 inline bool 00161 is_dirty(void* virtual_addr) { 00162 if (dirty_pages_index == -1) 00163 return false; 00164 00165 return dirty_pages[dirty_pages_index].has_key(virtual_addr); 00166 } 00167 00176 void 00177 add_dirty_page(void* dirty_page, void* physical_page = NULL, int index = -1); 00178 00180 void 00181 print(); 00182 }; 00183 00185 inline bool 00186 page_fault_handler(); 00187 00188 // TODO: 00189 // upon evicting a page to disk (swapping): 00190 // log the page to disk 00191 // (note that if the page to swap is copy-on-write, maybe log the original 00192 // instead of the copy so as to ensure snapshot consistency?) 00193 // unset dirty bit in pte 00194 // add the page to the block map (in memory) 00195 00196 // Page table entry for virtual page in memory: 00197 // 00198 // 31 12 9 8 7 6 5 4 3 2 1 0 00199 // +---------------------------------------------------------------+ 00200 // | | U R | 00201 // | page frame address 31..12 |0 0 0 X X D A X X / / P| 00202 // | | S W | 00203 // +---------------------------------------------------------------+ 00204 // 00205 // P : present = 1 00206 // R/W : read/write 00207 // U/S : user/supervisor = 0 00208 // D : dirty 00209 // X : Intel reserved 00210 // 0 : unused 00211 // 00212 // Page table entry for unused virtual page: 00213 // 00214 // 31 0 00215 // +---------------------------------------------------------------+ 00216 // | | 00217 // |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0| 00218 // | | 00219 // +---------------------------------------------------------------+ 00220 00221 #endif 00222 00223 /* Torsion Operating System, Copyright (C) 2000-2004 Dan Helfman 00224 * 00225 * This program is free software; you can redistribute it and/or modify it 00226 * under the terms of the GNU General Public License as published by the 00227 * Free Software Foundation; either version 2 of the License, or (at your 00228 * option) any later version. 00229 * 00230 * This program is distributed in the hope that it will be useful, but 00231 * WITHOUT ANY WARRANTY; without even the implied warranty of 00232 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00233 * General Public License for more details (in the COPYING file). 00234 * 00235 * You should have received a copy of the GNU General Public License along 00236 * with this program; if not, write to the Free Software Foundation, Inc., 00237 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00238 */
Torsion Operating System, Copyright (C) 2000-2004 Dan Helfman