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

4.104.114.84.95
Last change on this file since 8ef3818 was 8ef3818, checked in by Joel Sherrill <joel.sherrill@…>, on Jun 12, 2000 at 7:57:02 PM

Patch from John Cotton <john.cotton@…>, Charles-Antoine Gauthier
<charles.gauthier@…>, and Darlene A. Stewart
<Darlene.Stewart@…> to add support for a number of very
significant things:

+ BSPs for many variations on the Motorola MBX8xx board series
+ Cache Manager including initial support for m68040

and PowerPC

+ Rework of mpc8xx libcpu code so all mpc8xx CPUs now use

same code base.

+ Rework of eth_comm BSP to utiltize above.

John reports this works on the 821 and 860

  • Property mode set to 100644
File size: 13.6 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_flush_entire_data_cache();
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_flush_entire_data_cache();
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/* hack to avoid dependency on bsp.h */
443void printk(char *fmt, ...);             /* from 'printk.c' */
444
445int  _CPU_display_memory_attribute(){ 
446  unsigned int dirCount, pageCount;
447  cr0 regCr0;
448  page_table *localPageTable;
449  unsigned int prevCache;
450  unsigned int prevPresent;
451  unsigned int maxPage;
452  unsigned char pagingWasEnabled;
453 
454  regCr0.i = i386_get_cr0();
455 
456  printk("\n\n >>>>>>>>>  MEMORY CACHE CONFIGURATION <<<<<<<<<<\n\n");
457
458  printk("CR0 -> paging           : %s\n",(regCr0.cr0.paging ? "ENABLE ":"DISABLE"));
459  printk("       page-level cache : %s\n\n",(regCr0.cr0.page_level_cache_disable ? "DISABLE":"ENABLE"));
460
461  if (regCr0.cr0.paging == 0)
462    return 0;
463 
464  prevPresent = 0;
465  prevCache   = 1;
466 
467  pagingWasEnabled = 0;
468
469  if (_CPU_is_paging_enabled()){
470    pagingWasEnabled = 1;
471    _CPU_disable_paging();
472  }
473
474  for (dirCount = 0; dirCount < directoryEntry+1; dirCount++) {
475
476    localPageTable = (page_table *)(pageDirectory->
477                                    pageDirEntry[dirCount].bits.
478                                    page_frame_address << 12);
479
480    maxPage = MAX_ENTRY;
481    /*if ( dirCount == (directoryEntry-1))
482      maxPage = tableEntry;*/
483    for (pageCount = 0; pageCount < maxPage; pageCount++) {
484
485      if (localPageTable->pageTableEntry[pageCount].bits.present != 0){
486        if (prevPresent == 0){
487          prevPresent = 1;
488          printk ("present page from address %x \n", ((dirCount << 22)|(pageCount << 12)));
489        }
490        if (prevCache != localPageTable->pageTableEntry[pageCount].bits.cache_disable ) {
491          prevCache = localPageTable->pageTableEntry[pageCount].
492            bits.cache_disable;
493          printk ("    cache %s from %x <phy %x>\n",
494                  (prevCache ? "DISABLE" : "ENABLE "),
495                  ((dirCount << 22)|(pageCount << 12)),
496                  localPageTable->pageTableEntry[pageCount].bits.page_frame_address << 12);
497        }
498      }
499      else {
500        if (prevPresent == 1){
501          prevPresent = 0;
502          printk ("Absent from %x \n", ((dirCount << 22)|(pageCount << 12)));
503        }
504      }
505    }
506  }
507  if (pagingWasEnabled)
508    _CPU_enable_paging();
509  return 0;
510
511}
512
513
514
515
516
Note: See TracBrowser for help on using the repository browser.