OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libcpu/] [i386/] [page.c] - Blame information for rev 851

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
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: /home/marcus/revision_ctrl_test/oc_cvs/cvs/or1k/rtems/c/src/lib/libcpu/i386/page.c,v 1.2 2001-09-27 12:01:22 chris Exp $
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
 
30
static int directoryEntry=0;
31
static int tableEntry=0;
32
static page_directory *pageDirectory;
33
 
34
extern rtems_unsigned32 rtemsFreeMemStart;
35
 
36
 
37
/*************************************************************************/
38
/************** IT IS A ONE-TO-ONE TRANSLATION ***************************/
39
/*************************************************************************/
40
 
41
 
42
/*
43
 * Disable the paging
44
 */
45
void _CPU_disable_paging() {
46
  cr0 regCr0;
47
 
48
  flush_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
 */
57
void _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
  flush_cache();
64
}
65
 
66
 
67
/*
68
 * Initialize the paging with 1-to-1 mapping
69
 */
70
 
71
int 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
 * Disable the entire cache
158
 */
159
void _CPU_disable_cache() {
160
  cr0 regCr0;
161
 
162
  regCr0.i = i386_get_cr0();
163
  regCr0.cr0.page_level_cache_disable = 1;
164
  regCr0.cr0.no_write_through = 1;
165
  i386_set_cr0( regCr0.i );
166
  flush_cache();
167
}
168
 
169
/*
170
 * Disable the entire cache
171
 */
172
void _CPU_enable_cache() {
173
  cr0 regCr0;
174
 
175
  regCr0.i = i386_get_cr0();
176
  regCr0.cr0.page_level_cache_disable = 0;
177
  regCr0.cr0.no_write_through = 0;
178
  i386_set_cr0( regCr0.i );
179
  /*flush_cache();*/
180
}
181
 
182
/*
183
 * Is cache enable
184
 */
185
int  _CPU_is_cache_enabled() {
186
  cr0 regCr0;
187
 
188
  regCr0.i = i386_get_cr0();
189
  return( ~(regCr0.cr0.page_level_cache_disable) );
190
}
191
 
192
/*
193
 * Is paging enable
194
 */
195
int  _CPU_is_paging_enabled() {
196
  cr0 regCr0;
197
 
198
  regCr0.i = i386_get_cr0();
199
  return(regCr0.cr0.paging);
200
}
201
 
202
 
203
/*
204
 * Translate the physical address in the virtual space and return
205
 * the translated address in mappedAddress
206
 */
207
 
208
int _CPU_map_phys_address
209
        (void **mappedAddress, void *physAddress, int size, int flag){
210
 
211
  page_table *localPageTable;
212
  unsigned int lastAddress, countAddress;
213
  char *Tables;
214
  linear_address virtualAddress;
215
  unsigned char pagingWasEnabled;
216
 
217
  pagingWasEnabled = 0;
218
 
219
  if (_CPU_is_paging_enabled()){
220
    pagingWasEnabled = 1;
221
    _CPU_disable_paging();
222
  }
223
 
224
  countAddress = (unsigned int)physAddress;
225
  lastAddress = (unsigned int)physAddress + (size - 1);
226
  virtualAddress.address = 0;
227
 
228
  while (1){
229
 
230
    if ((countAddress & ~MASK_OFFSET) > (lastAddress & ~MASK_OFFSET))
231
      break;
232
 
233
    /* Need to allocate a new page table */
234
    if (pageDirectory->pageDirEntry[directoryEntry].bits.page_frame_address == 0){
235
      /* We allocate 2 pages to perform 4k-page alignement */
236
      Tables = (char *)malloc(2*sizeof(page_table));
237
      if ( Tables == NULL ){
238
        if (pagingWasEnabled)
239
          _CPU_enable_paging();
240
        return -1; /* unable to allocate memory */
241
      }
242
      /* 4K-page alignement */
243
      Tables += (PG_SIZE - (int)Tables) & 0xFFF;
244
 
245
      /* Reset Table */
246
      memset( Tables, 0, sizeof(page_table) );
247
      pageDirectory->pageDirEntry[directoryEntry].bits.page_frame_address =
248
        (unsigned int)Tables >> 12;
249
      pageDirectory->pageDirEntry[directoryEntry].bits.available      = 0;
250
      pageDirectory->pageDirEntry[directoryEntry].bits.page_size      = 0;
251
      pageDirectory->pageDirEntry[directoryEntry].bits.accessed       = 0;
252
      pageDirectory->pageDirEntry[directoryEntry].bits.cache_disable  = 0;
253
      pageDirectory->pageDirEntry[directoryEntry].bits.write_through  = 0;
254
      pageDirectory->pageDirEntry[directoryEntry].bits.user           = 1;
255
      pageDirectory->pageDirEntry[directoryEntry].bits.writable       = 1;
256
      pageDirectory->pageDirEntry[directoryEntry].bits.present        = 1;
257
    }
258
 
259
 
260
    localPageTable = (page_table *)(pageDirectory->
261
                                    pageDirEntry[directoryEntry].bits.
262
                                    page_frame_address << 12);
263
 
264
    if (virtualAddress.address == 0){
265
      virtualAddress.bits.directory = directoryEntry;
266
      virtualAddress.bits.page      = tableEntry;
267
      virtualAddress.bits.offset    = (unsigned int)physAddress & MASK_OFFSET;
268
    }
269
 
270
    localPageTable->pageTableEntry[tableEntry].bits.page_frame_address =
271
      ((unsigned int)countAddress & ~MASK_OFFSET) >> 12;
272
    localPageTable->pageTableEntry[tableEntry].bits.available      = 0;
273
    localPageTable->pageTableEntry[tableEntry].bits.dirty          = 0;
274
    localPageTable->pageTableEntry[tableEntry].bits.accessed       = 0;
275
    localPageTable->pageTableEntry[tableEntry].bits.cache_disable  = 0;
276
    localPageTable->pageTableEntry[tableEntry].bits.write_through  = 0;
277
    localPageTable->pageTableEntry[tableEntry].bits.user           = 1;
278
    localPageTable->pageTableEntry[tableEntry].bits.writable       = 0;
279
    localPageTable->pageTableEntry[tableEntry].bits.present        = 1;
280
 
281
    localPageTable->pageTableEntry[tableEntry].table_entry |= flag ;
282
 
283
    countAddress += PG_SIZE;
284
    tableEntry++;
285
    if (tableEntry >= MAX_ENTRY){
286
      tableEntry = 0;
287
      directoryEntry++;
288
    }
289
  }
290
 
291
  if (mappedAddress != 0)
292
    *mappedAddress = (void *)(virtualAddress.address);
293
  if (pagingWasEnabled)
294
    _CPU_enable_paging();
295
  return 0;
296
}
297
 
298
/*
299
 * "Compress" the Directory and Page tables to avoid
300
 * important loss of address range
301
 */
302
static void Paging_Table_Compress() {
303
  unsigned int dirCount, pageCount;
304
  page_table *localPageTable;
305
 
306
  if (tableEntry == 0){
307
    dirCount  = directoryEntry - 1;
308
    pageCount = MAX_ENTRY - 1;
309
  }
310
  else {
311
    dirCount  = directoryEntry;
312
    pageCount = tableEntry - 1;
313
  }
314
 
315
  while (1){
316
 
317
    localPageTable = (page_table *)(pageDirectory->
318
                                    pageDirEntry[dirCount].bits.
319
                                    page_frame_address << 12);
320
 
321
    if (localPageTable->pageTableEntry[pageCount].bits.present == 1){
322
      pageCount++;
323
      if (pageCount >= MAX_ENTRY){
324
        pageCount = 0;
325
        dirCount++;
326
      }
327
      break;
328
    }
329
 
330
 
331
    if (pageCount == 0) {
332
      if (dirCount == 0){
333
        break;
334
      }
335
      else {
336
        pageCount = MAX_ENTRY - 1;
337
        dirCount-- ;
338
      }
339
    }
340
    else
341
      pageCount-- ;
342
  }
343
 
344
  directoryEntry = dirCount;
345
  tableEntry = pageCount;
346
}
347
 
348
 
349
/*
350
 * Unmap the virtual address from the tables
351
 * (we do not deallocate the table already allocated)
352
 */
353
 
354
int _CPU_unmap_virt_address(void *mappedAddress, int size){
355
 
356
  linear_address linearAddr;
357
  page_table *localPageTable;
358
  unsigned int lastAddr ;
359
  unsigned int dirCount ;
360
  unsigned char pagingWasEnabled;
361
 
362
  pagingWasEnabled = 0;
363
 
364
  if (_CPU_is_paging_enabled()){
365
    pagingWasEnabled = 1;
366
    _CPU_disable_paging();
367
  }
368
 
369
  linearAddr.address = (unsigned int)mappedAddress;
370
  lastAddr = (unsigned int)mappedAddress + (size - 1);
371
  dirCount = linearAddr.bits.directory;
372
 
373
  while (1){
374
 
375
    if ((linearAddr.address & ~MASK_OFFSET) > (lastAddr & ~MASK_OFFSET))
376
      break;
377
 
378
    if (pageDirectory->pageDirEntry[linearAddr.bits.directory].bits.present == 0){
379
      if (pagingWasEnabled)
380
        _CPU_enable_paging();
381
      return -1;
382
    }
383
 
384
    localPageTable = (page_table *)(pageDirectory->
385
                                    pageDirEntry[linearAddr.bits.directory].bits.
386
                                    page_frame_address << 12);
387
 
388
    if (localPageTable->pageTableEntry[linearAddr.bits.page].bits.present == 0){
389
      if (pagingWasEnabled)
390
        _CPU_enable_paging();
391
      return -1;
392
    }
393
 
394
    localPageTable->pageTableEntry[linearAddr.bits.page].bits.present = 0;
395
 
396
    linearAddr.address += PG_SIZE ;
397
  }
398
  Paging_Table_Compress();
399
  if (pagingWasEnabled)
400
    _CPU_enable_paging();
401
 
402
  return 0;
403
}
404
 
405
/*
406
 * Modify the flags PRESENT, WRITABLE, USER, WRITE_TROUGH, CACHE_DISABLE
407
 * of the page's descriptor.
408
 */
409
 
410
int _CPU_change_memory_mapping_attribute
411
    (void **newAddress, void *mappedAddress, unsigned int size, unsigned int flag){
412
 
413
  linear_address linearAddr;
414
  page_table *localPageTable;
415
  unsigned int lastAddr ;
416
  unsigned char pagingWasEnabled;
417
 
418
  pagingWasEnabled = 0;
419
 
420
  if (_CPU_is_paging_enabled()){
421
    pagingWasEnabled = 1;
422
    _CPU_disable_paging();
423
  }
424
 
425
  linearAddr.address  = (unsigned int)mappedAddress;
426
  lastAddr = (unsigned int)mappedAddress + (size - 1);
427
 
428
  while (1){
429
 
430
    if ((linearAddr.address & ~MASK_OFFSET) > (lastAddr & ~MASK_OFFSET))
431
      break;
432
 
433
    if (pageDirectory->pageDirEntry[linearAddr.bits.directory].bits.present == 0){
434
      if (pagingWasEnabled)
435
        _CPU_enable_paging();
436
      return -1;
437
    }
438
    localPageTable = (page_table *)(pageDirectory->
439
                                    pageDirEntry[linearAddr.bits.directory].bits.
440
                                    page_frame_address << 12);
441
 
442
    if (localPageTable->pageTableEntry[linearAddr.bits.page].bits.present == 0){
443
      if (pagingWasEnabled)
444
        _CPU_enable_paging();
445
      return -1;
446
    }
447
 
448
    localPageTable->pageTableEntry[linearAddr.bits.page].table_entry &= ~MASK_FLAGS ;
449
    localPageTable->pageTableEntry[linearAddr.bits.page].table_entry |= flag ;
450
 
451
    linearAddr.address += PG_SIZE ;
452
  }
453
 
454
  if (newAddress != NULL)
455
    *newAddress = mappedAddress ;
456
 
457
  if (pagingWasEnabled)
458
    _CPU_enable_paging();
459
 
460
  return 0;
461
}
462
 
463
/*
464
 * Display the page descriptor flags
465
 * CACHE_DISABLE of the whole memory
466
 */
467
 
468
/* hack to avoid dependency on bsp.h */
469
void printk(char *fmt, ...);             /* from 'printk.c' */
470
 
471
int  _CPU_display_memory_attribute(){
472
  unsigned int dirCount, pageCount;
473
  cr0 regCr0;
474
  page_table *localPageTable;
475
  unsigned int prevCache;
476
  unsigned int prevPresent;
477
  unsigned int maxPage;
478
  unsigned char pagingWasEnabled;
479
 
480
  regCr0.i = i386_get_cr0();
481
 
482
  printk("\n\n >>>>>>>>>  MEMORY CACHE CONFIGURATION <<<<<<<<<<\n\n");
483
 
484
  printk("CR0 -> paging           : %s\n",(regCr0.cr0.paging ? "ENABLE ":"DISABLE"));
485
  printk("       page-level cache : %s\n\n",(regCr0.cr0.page_level_cache_disable ? "DISABLE":"ENABLE"));
486
 
487
  if (regCr0.cr0.paging == 0)
488
    return 0;
489
 
490
  prevPresent = 0;
491
  prevCache   = 1;
492
 
493
  pagingWasEnabled = 0;
494
 
495
  if (_CPU_is_paging_enabled()){
496
    pagingWasEnabled = 1;
497
    _CPU_disable_paging();
498
  }
499
 
500
  for (dirCount = 0; dirCount < directoryEntry+1; dirCount++) {
501
 
502
    localPageTable = (page_table *)(pageDirectory->
503
                                    pageDirEntry[dirCount].bits.
504
                                    page_frame_address << 12);
505
 
506
    maxPage = MAX_ENTRY;
507
    /*if ( dirCount == (directoryEntry-1))
508
      maxPage = tableEntry;*/
509
    for (pageCount = 0; pageCount < maxPage; pageCount++) {
510
 
511
      if (localPageTable->pageTableEntry[pageCount].bits.present != 0){
512
        if (prevPresent == 0){
513
          prevPresent = 1;
514
          printk ("present page from address %x \n", ((dirCount << 22)|(pageCount << 12)));
515
        }
516
        if (prevCache != localPageTable->pageTableEntry[pageCount].bits.cache_disable ) {
517
          prevCache = localPageTable->pageTableEntry[pageCount].
518
            bits.cache_disable;
519
          printk ("    cache %s from %x <phy %x>\n",
520
                  (prevCache ? "DISABLE" : "ENABLE "),
521
                  ((dirCount << 22)|(pageCount << 12)),
522
                  localPageTable->pageTableEntry[pageCount].bits.page_frame_address << 12);
523
        }
524
      }
525
      else {
526
        if (prevPresent == 1){
527
          prevPresent = 0;
528
          printk ("Absent from %x \n", ((dirCount << 22)|(pageCount << 12)));
529
        }
530
      }
531
    }
532
  }
533
  if (pagingWasEnabled)
534
    _CPU_enable_paging();
535
  return 0;
536
 
537
}
538
 
539
 
540
 
541
 
542
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.