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

Last change on this file since 948a069 was 86d23e2, checked in by Joel Sherrill <joel.sherrill@…>, on 01/04/02 at 18:17:04

2002-01-03 Ralf Corsepius <corsepiu@…>

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