source: rtems/c/src/lib/libcpu/i386/page.c @ f43d7f7

4.104.114.84.9
Last change on this file since f43d7f7 was f43d7f7, checked in by Joel Sherrill <joel.sherrill@…>, on Oct 18, 2000 at 1:10:38 PM

2000-10-18 Joel Sherrill <joel@…>

  • page.c: Replaced prototype of printk() with include of <bspIo.h>.
  • Property mode set to 100644
File size: 13.4 KB
Line 
1 *           Instanciate paging. More detailled information
2 *           can be found on Intel site and more precisely in
3 *           the following book :
4 *
5 *              Pentium Processor familly
6 *              Developper's Manual
7 *
8 *              Volume 3 : Architecture and Programming Manual
9 *
10 * Copyright (C) 1999  Emmanuel Raguet (raguet@crf.canon.fr)
11 *                     Canon Centre Recherche France.
12 *
13 *  The license and distribution terms for this file may be
14 *  found in found in the file LICENSE in this distribution or at
15 *  http://www.OARcorp.com/rtems/license.html.
16 *
17 * $Header$
18 */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <rtems.h>
24#include <libcpu/cpu.h>
25
26#define MEMORY_SIZE 0x4000000           /* 64Mo */
27
28static int directoryEntry=0;
29static int tableEntry=0;
30static page_directory *pageDirectory;
31
32extern rtems_unsigned32 rtemsFreeMemStart;
33
34
35/*************************************************************************/
36/************** IT IS A ONE-TO-ONE TRANSLATION ***************************/
37/*************************************************************************/
38
39
40/*
41 * Disable the paging
42 */
43void _CPU_disable_paging() {
44  cr0 regCr0;
45
46  rtems_cache_flush_entire_data();
47  regCr0.i = i386_get_cr0();
48  regCr0.cr0.paging = 0;
49  i386_set_cr0( regCr0.i );
50}
51
52/*
53 * Enable the paging
54 */
55void _CPU_enable_paging() {
56  cr0 regCr0;
57
58  regCr0.i = i386_get_cr0();
59  regCr0.cr0.paging = 1;
60  i386_set_cr0( regCr0.i );
61  rtems_cache_flush_entire_data();
62}
63
64
65/*
66 * Initialize the paging with 1-to-1 mapping
67 */
68
69int init_paging() {
70
71  int memorySize;
72  int nbPages;
73  int nbInitPages;
74  char *Tables;
75  cr3 regCr3;
76  page_table *pageTable;
77  unsigned int physPage;
78  int nbTables=0;
79 
80  /*
81   * rtemsFreeMemStart is the last valid 32-bits address
82   * so the size is rtemsFreeMemStart + 4
83   */
84  memorySize = rtemsFreeMemStart + 4;
85 
86  nbPages = ( (memorySize - 1) / PG_SIZE ) + 1;
87  nbTables = ( (memorySize - 1) / FOUR_MB ) + 2;
88
89  /* allocate 1 page more to page alignement */
90  Tables = (char *)malloc( (nbTables + 1)*sizeof(page_table) ); 
91  if ( Tables == NULL ){
92    return -1; /*unable to allocate memory */
93  }
94 
95  /* 4K-page alignement */
96  Tables += (PG_SIZE - (int)Tables) & 0xFFF;
97
98  /* Reset Tables */
99  memset( Tables, 0, nbTables*sizeof(page_table) );
100  pageDirectory = (page_directory *) Tables;
101  pageTable     = (page_table *)((int)Tables + PG_SIZE);
102
103  nbInitPages = 0;
104  directoryEntry = 0;
105  tableEntry = 0;
106  physPage = 0;
107
108  while ( nbInitPages != nbPages ){
109    if ( tableEntry == 0 ){
110      pageDirectory->pageDirEntry[directoryEntry].bits.page_frame_address = (unsigned int)pageTable >> 12;
111      pageDirectory->pageDirEntry[directoryEntry].bits.available      = 0;
112      pageDirectory->pageDirEntry[directoryEntry].bits.page_size      = 0;
113      pageDirectory->pageDirEntry[directoryEntry].bits.accessed       = 0;
114      pageDirectory->pageDirEntry[directoryEntry].bits.cache_disable  = 0;
115      pageDirectory->pageDirEntry[directoryEntry].bits.write_through  = 0;
116      pageDirectory->pageDirEntry[directoryEntry].bits.user           = 1;
117      pageDirectory->pageDirEntry[directoryEntry].bits.writable       = 1;
118      pageDirectory->pageDirEntry[directoryEntry].bits.present        = 1;
119    }
120    pageTable->pageTableEntry[tableEntry].bits.page_frame_address = physPage;
121    pageTable->pageTableEntry[tableEntry].bits.available      = 0;
122    pageTable->pageTableEntry[tableEntry].bits.dirty          = 0;
123    pageTable->pageTableEntry[tableEntry].bits.accessed       = 0;
124    pageTable->pageTableEntry[tableEntry].bits.cache_disable  = 0;
125    pageTable->pageTableEntry[tableEntry].bits.write_through  = 0;
126    pageTable->pageTableEntry[tableEntry].bits.user           = 1;
127    pageTable->pageTableEntry[tableEntry].bits.writable       = 1;
128    pageTable->pageTableEntry[tableEntry].bits.present        = 1;
129
130    physPage ++;
131    tableEntry ++;
132
133    if (tableEntry >= MAX_ENTRY){
134      tableEntry = 0;
135      directoryEntry ++;
136      pageTable ++;
137    }
138     
139    nbInitPages++;
140  }
141
142  regCr3.cr3.page_write_transparent = 0;
143  regCr3.cr3.page_cache_disable     = 0;
144  regCr3.cr3.page_directory_base    = (unsigned int)pageDirectory >> 12;
145
146  i386_set_cr3( regCr3.i );
147
148  _CPU_enable_cache(); 
149  _CPU_enable_paging(); 
150
151  return 0;
152}
153
154/*
155 * Is cache enable
156 */
157int  _CPU_is_cache_enabled() {
158  cr0 regCr0;
159
160  regCr0.i = i386_get_cr0();
161  return( ~(regCr0.cr0.page_level_cache_disable) );
162}
163
164/*
165 * Is paging enable
166 */
167int  _CPU_is_paging_enabled() {
168  cr0 regCr0;
169
170  regCr0.i = i386_get_cr0();
171  return(regCr0.cr0.paging);
172}
173
174
175/*
176 * Translate the physical address in the virtual space and return
177 * the translated address in mappedAddress
178 */
179
180int _CPU_map_phys_address
181        (void **mappedAddress, void *physAddress, int size, int flag){ 
182
183  page_table *localPageTable;
184  unsigned int lastAddress, countAddress;
185  char *Tables;
186  linear_address virtualAddress;
187  unsigned char pagingWasEnabled;
188 
189  pagingWasEnabled = 0;
190
191  if (_CPU_is_paging_enabled()){
192    pagingWasEnabled = 1;
193    _CPU_disable_paging();
194  }
195
196  countAddress = (unsigned int)physAddress;
197  lastAddress = (unsigned int)physAddress + (size - 1);
198  virtualAddress.address = 0;
199
200  while (1){
201
202    if ((countAddress & ~MASK_OFFSET) > (lastAddress & ~MASK_OFFSET))
203      break;
204
205    /* Need to allocate a new page table */
206    if (pageDirectory->pageDirEntry[directoryEntry].bits.page_frame_address == 0){
207      /* We allocate 2 pages to perform 4k-page alignement */
208      Tables = (char *)malloc(2*sizeof(page_table)); 
209      if ( Tables == NULL ){
210        if (pagingWasEnabled)
211          _CPU_enable_paging();
212        return -1; /* unable to allocate memory */
213      }
214      /* 4K-page alignement */
215      Tables += (PG_SIZE - (int)Tables) & 0xFFF;
216
217      /* Reset Table */
218      memset( Tables, 0, sizeof(page_table) );     
219      pageDirectory->pageDirEntry[directoryEntry].bits.page_frame_address =
220        (unsigned int)Tables >> 12;
221      pageDirectory->pageDirEntry[directoryEntry].bits.available      = 0;
222      pageDirectory->pageDirEntry[directoryEntry].bits.page_size      = 0;
223      pageDirectory->pageDirEntry[directoryEntry].bits.accessed       = 0;
224      pageDirectory->pageDirEntry[directoryEntry].bits.cache_disable  = 0;
225      pageDirectory->pageDirEntry[directoryEntry].bits.write_through  = 0;
226      pageDirectory->pageDirEntry[directoryEntry].bits.user           = 1;
227      pageDirectory->pageDirEntry[directoryEntry].bits.writable       = 1;
228      pageDirectory->pageDirEntry[directoryEntry].bits.present        = 1;
229    }
230     
231
232    localPageTable = (page_table *)(pageDirectory->
233                                    pageDirEntry[directoryEntry].bits.
234                                    page_frame_address << 12);
235
236    if (virtualAddress.address == 0){
237      virtualAddress.bits.directory = directoryEntry;
238      virtualAddress.bits.page      = tableEntry;
239      virtualAddress.bits.offset    = (unsigned int)physAddress & MASK_OFFSET;
240    }
241
242    localPageTable->pageTableEntry[tableEntry].bits.page_frame_address =
243      ((unsigned int)countAddress & ~MASK_OFFSET) >> 12;
244    localPageTable->pageTableEntry[tableEntry].bits.available      = 0;
245    localPageTable->pageTableEntry[tableEntry].bits.dirty          = 0;
246    localPageTable->pageTableEntry[tableEntry].bits.accessed       = 0;
247    localPageTable->pageTableEntry[tableEntry].bits.cache_disable  = 0;
248    localPageTable->pageTableEntry[tableEntry].bits.write_through  = 0;
249    localPageTable->pageTableEntry[tableEntry].bits.user           = 1;
250    localPageTable->pageTableEntry[tableEntry].bits.writable       = 0;
251    localPageTable->pageTableEntry[tableEntry].bits.present        = 1;
252
253    localPageTable->pageTableEntry[tableEntry].table_entry |= flag ;
254
255    countAddress += PG_SIZE;
256    tableEntry++;
257    if (tableEntry >= MAX_ENTRY){     
258      tableEntry = 0;
259      directoryEntry++;
260    }
261  }
262
263  if (mappedAddress != 0)
264    *mappedAddress = (void *)(virtualAddress.address);
265  if (pagingWasEnabled)
266    _CPU_enable_paging();
267  return 0;
268}
269
270/*
271 * "Compress" the Directory and Page tables to avoid
272 * important loss of address range
273 */
274static void Paging_Table_Compress() {
275  unsigned int dirCount, pageCount;
276  page_table *localPageTable;
277 
278  if (tableEntry == 0){
279    dirCount  = directoryEntry - 1;
280    pageCount = MAX_ENTRY - 1;
281  }
282  else {
283    dirCount  = directoryEntry;
284    pageCount = tableEntry - 1;
285  }
286   
287  while (1){
288
289    localPageTable = (page_table *)(pageDirectory->
290                                    pageDirEntry[dirCount].bits.
291                                    page_frame_address << 12);
292
293    if (localPageTable->pageTableEntry[pageCount].bits.present == 1){
294      pageCount++;
295      if (pageCount >= MAX_ENTRY){     
296        pageCount = 0;
297        dirCount++;
298      }
299      break;
300    }
301
302
303    if (pageCount == 0) {
304      if (dirCount == 0){       
305        break;
306      }
307      else {
308        pageCount = MAX_ENTRY - 1;
309        dirCount-- ;
310      } 
311    }
312    else
313      pageCount-- ;
314  }
315
316  directoryEntry = dirCount;
317  tableEntry = pageCount;
318}
319     
320 
321/*
322 * Unmap the virtual address from the tables
323 * (we do not deallocate the table already allocated)
324 */
325
326int _CPU_unmap_virt_address(void *mappedAddress, int size){ 
327
328  linear_address linearAddr;
329  page_table *localPageTable;
330  unsigned int lastAddr ;
331  unsigned int dirCount ;
332  unsigned char pagingWasEnabled;
333 
334  pagingWasEnabled = 0;
335
336  if (_CPU_is_paging_enabled()){
337    pagingWasEnabled = 1;
338    _CPU_disable_paging();
339  }
340
341  linearAddr.address = (unsigned int)mappedAddress;
342  lastAddr = (unsigned int)mappedAddress + (size - 1);
343  dirCount = linearAddr.bits.directory;
344
345  while (1){
346
347    if ((linearAddr.address & ~MASK_OFFSET) > (lastAddr & ~MASK_OFFSET))
348      break;
349
350    if (pageDirectory->pageDirEntry[linearAddr.bits.directory].bits.present == 0){
351      if (pagingWasEnabled)
352        _CPU_enable_paging();
353      return -1;
354    }
355
356    localPageTable = (page_table *)(pageDirectory->
357                                    pageDirEntry[linearAddr.bits.directory].bits.
358                                    page_frame_address << 12);
359   
360    if (localPageTable->pageTableEntry[linearAddr.bits.page].bits.present == 0){
361      if (pagingWasEnabled)
362        _CPU_enable_paging();
363      return -1;
364    }
365 
366    localPageTable->pageTableEntry[linearAddr.bits.page].bits.present = 0;   
367   
368    linearAddr.address += PG_SIZE ;
369  }
370  Paging_Table_Compress();
371  if (pagingWasEnabled)
372    _CPU_enable_paging();
373
374  return 0;
375}
376
377/*
378 * Modify the flags PRESENT, WRITABLE, USER, WRITE_TROUGH, CACHE_DISABLE
379 * of the page's descriptor.
380 */
381
382int _CPU_change_memory_mapping_attribute
383    (void **newAddress, void *mappedAddress, unsigned int size, unsigned int flag){ 
384
385  linear_address linearAddr;
386  page_table *localPageTable;
387  unsigned int lastAddr ;
388  unsigned char pagingWasEnabled;
389 
390  pagingWasEnabled = 0;
391
392  if (_CPU_is_paging_enabled()){
393    pagingWasEnabled = 1;
394    _CPU_disable_paging();
395  }
396 
397  linearAddr.address  = (unsigned int)mappedAddress;
398  lastAddr = (unsigned int)mappedAddress + (size - 1);
399
400  while (1){
401
402    if ((linearAddr.address & ~MASK_OFFSET) > (lastAddr & ~MASK_OFFSET))
403      break;
404
405    if (pageDirectory->pageDirEntry[linearAddr.bits.directory].bits.present == 0){
406      if (pagingWasEnabled)
407        _CPU_enable_paging();
408      return -1;
409    }
410    localPageTable = (page_table *)(pageDirectory->
411                                    pageDirEntry[linearAddr.bits.directory].bits.
412                                    page_frame_address << 12);
413   
414    if (localPageTable->pageTableEntry[linearAddr.bits.page].bits.present == 0){
415      if (pagingWasEnabled)
416        _CPU_enable_paging();
417      return -1;
418    }
419 
420    localPageTable->pageTableEntry[linearAddr.bits.page].table_entry &= ~MASK_FLAGS ;
421    localPageTable->pageTableEntry[linearAddr.bits.page].table_entry |= flag ;
422   
423    linearAddr.address += PG_SIZE ;
424  } 
425
426  if (newAddress != NULL)
427    *newAddress = mappedAddress ;
428
429  if (pagingWasEnabled)
430    _CPU_enable_paging();
431
432  return 0;
433}
434
435/*
436 * Display the page descriptor flags
437 * CACHE_DISABLE of the whole memory
438 */
439
440#include <bspIo.h>
441
442int  _CPU_display_memory_attribute(){ 
443  unsigned int dirCount, pageCount;
444  cr0 regCr0;
445  page_table *localPageTable;
446  unsigned int prevCache;
447  unsigned int prevPresent;
448  unsigned int maxPage;
449  unsigned char pagingWasEnabled;
450 
451  regCr0.i = i386_get_cr0();
452 
453  printk("\n\n >>>>>>>>>  MEMORY CACHE CONFIGURATION <<<<<<<<<<\n\n");
454
455  printk("CR0 -> paging           : %s\n",(regCr0.cr0.paging ? "ENABLE ":"DISABLE"));
456  printk("       page-level cache : %s\n\n",(regCr0.cr0.page_level_cache_disable ? "DISABLE":"ENABLE"));
457
458  if (regCr0.cr0.paging == 0)
459    return 0;
460 
461  prevPresent = 0;
462  prevCache   = 1;
463 
464  pagingWasEnabled = 0;
465
466  if (_CPU_is_paging_enabled()){
467    pagingWasEnabled = 1;
468    _CPU_disable_paging();
469  }
470
471  for (dirCount = 0; dirCount < directoryEntry+1; dirCount++) {
472
473    localPageTable = (page_table *)(pageDirectory->
474                                    pageDirEntry[dirCount].bits.
475                                    page_frame_address << 12);
476
477    maxPage = MAX_ENTRY;
478    /*if ( dirCount == (directoryEntry-1))
479      maxPage = tableEntry;*/
480    for (pageCount = 0; pageCount < maxPage; pageCount++) {
481
482      if (localPageTable->pageTableEntry[pageCount].bits.present != 0){
483        if (prevPresent == 0){
484          prevPresent = 1;
485          printk ("present page from address %x \n", ((dirCount << 22)|(pageCount << 12)));
486        }
487        if (prevCache != localPageTable->pageTableEntry[pageCount].bits.cache_disable ) {
488          prevCache = localPageTable->pageTableEntry[pageCount].
489            bits.cache_disable;
490          printk ("    cache %s from %x <phy %x>\n",
491                  (prevCache ? "DISABLE" : "ENABLE "),
492                  ((dirCount << 22)|(pageCount << 12)),
493                  localPageTable->pageTableEntry[pageCount].bits.page_frame_address << 12);
494        }
495      }
496      else {
497        if (prevPresent == 1){
498          prevPresent = 0;
499          printk ("Absent from %x \n", ((dirCount << 22)|(pageCount << 12)));
500        }
501      }
502    }
503  }
504  if (pagingWasEnabled)
505    _CPU_enable_paging();
506  return 0;
507
508}
509
510
511
512
513
Note: See TracBrowser for help on using the repository browser.