00001
00002
00003 #ifndef paging_h
00004 #define paging_h
00005
00006 #include "types.h"
00007
00008 #include "types.h"
00009 #include "config.h"
00010 #include "assert.h"
00011
00012
00013
00014
00015
00016
00017 class Ptab;
00018 class Pdir;
00019
00020 namespace Page {
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 };
00043
00044 class PF {
00045 public:
00046 static Mword is_translation_error( Mword error );
00047 static Mword is_usermode_error( Mword error );
00048 static Mword is_read_error( Mword error );
00049 static Mword addr_to_msgword0( Address pfa, Mword error );
00050 static Mword pc_to_msgword1( Address pc, Mword error );
00051 };
00052
00053 class Pd_entry
00054 {
00055 public:
00056 enum
00057 {
00058 Shift = Config::SUPERPAGE_SHIFT,
00059 Mask = (Config::SUPERPAGE_SIZE/4-1),
00060 };
00061
00062 enum
00063 {
00064 Valid = 0x00000001,
00065 Writable = 0x00000002,
00066 User = 0x00000004,
00067 Write_through = 0x00000008,
00068 Cacheable = 0x00000000,
00069 Noncacheable = 0x00000010,
00070 Referenced = 0x00000020,
00071 Dirty = 0x00000040,
00072 Superpage = 0x00000080,
00073 Cpu_global = 0x00000100,
00074 L4_global = 0x00000200,
00075 Ptabfn = 0xfffff000,
00076 Superfn = 0xffc00000,
00077 };
00078
00079 private:
00080 Unsigned32 _raw;
00081 static Unsigned32 _cpu_global;
00082
00083 public:
00084 inline int valid() const;
00085
00086 inline int user() const;
00087
00088 inline int writable() const;
00089
00090 inline int superpage() const;
00091
00092 inline Address ptabfn() const;
00093
00094 inline Address superfn() const;
00095
00096 inline Ptab* ptab() const;
00097
00098 inline Unsigned32 raw() const;
00099
00100 inline Unsigned32 raw() const volatile;
00101
00102 inline Unsigned32& raw();
00103
00104 inline void add_attr(Unsigned32 attr);
00105
00106 inline void del_attr(Unsigned32 attr);
00107
00108 inline Pd_entry const& operator = (Pd_entry const& other);
00109
00110 inline Pd_entry const& operator = (Unsigned32 raw);
00111
00112 static inline void enable_global();
00113
00120 static inline Unsigned32 global();
00121 };
00122
00123 class Pt_entry
00124 {
00125 public:
00126 enum
00127 {
00128 Shift = Config::PAGE_SHIFT,
00129 Mask = (Config::PAGE_SIZE/4-1),
00130 };
00131
00132 enum
00133 {
00134 Valid = 0x00000001,
00135 Writable = 0x00000002,
00136 User = 0x00000004,
00137 Write_through = 0x00000008,
00138 Cacheable = 0x00000000,
00139 Noncacheable = 0x00000010,
00140 Referenced = 0x00000020,
00141 Dirty = 0x00000040,
00142 Pat_index = 0x00000080,
00143 Cpu_global = 0x00000100,
00144 L4_global = 0x00000200,
00145 Pfn = 0xfffff000,
00146 };
00147
00148 private:
00149 Unsigned32 _raw;
00150
00151 public:
00152
00153 inline Pt_entry const& operator = (Pt_entry const &other);
00154
00155 inline Pt_entry const& operator = (Unsigned32 raw);
00156
00157 inline Unsigned32 raw() const;
00158
00159 inline Unsigned32& raw();
00160
00161 inline void add_attr(Unsigned32 attr);
00162
00163 inline void del_attr(Unsigned32 attr);
00164
00165 inline int valid() const;
00166
00167 inline int writable() const;
00168
00169 inline Address pfn() const;
00170
00171 static inline Unsigned32 global();
00172 };
00173
00174 class Pdir
00175 {
00176 protected:
00177 Pd_entry _entries[1024];
00178
00179 private:
00180 static bool _have_superpages;
00181
00182 public:
00183 Address virt_to_phys(Address virt) const;
00184
00185 static inline unsigned virt_to_idx(Address virt);
00186
00187 inline Pd_entry* lookup(Address virt);
00188
00189 inline Pd_entry entry(Address virt) const;
00190
00191 inline const Pd_entry* index(unsigned idx) const;
00192
00193 inline Pd_entry* index(unsigned idx);
00194
00195 inline Unsigned32& operator[](unsigned idx);
00196
00197 inline Unsigned32 operator[](unsigned idx) const;
00198
00199 inline void clear();
00200
00201 void map_superpage(Address phys, Address virt, Address (*ptab_alloc)(), Unsigned32 attr);
00202
00203 static inline void have_superpages(bool yes);
00204 };
00205
00206 class Ptab
00207 {
00208 protected:
00209 Pt_entry _entries[1024];
00210
00211 public:
00212
00213 static inline unsigned virt_to_idx(Address virt);
00214
00215 inline Pt_entry* lookup(Address virt);
00216
00217 inline Pt_entry entry(Address virt) const;
00218
00219 inline Pt_entry* index(unsigned idx);
00220
00221 inline Unsigned32& operator[](unsigned idx);
00222
00223 inline Unsigned32 operator[](unsigned idx) const;
00224
00225 inline void clear();
00226 };
00227
00228 namespace Page
00229 {
00230 typedef Unsigned32 Attribs;
00231
00232 enum Attribs_enum
00233 {
00234 USER_NO = 0x00000002,
00235 USER_RO = 0x00000004,
00236 USER_RW = 0x00000006,
00237 USER_RX = 0x00000004,
00238 USER_XO = 0x00000004,
00239 USER_RWX = 0x00000006,
00240 MAX_ATTRIBS = 0x00000006,
00241 };
00242 };
00243
00244
00245
00246
00247
00248
00249 #include <cstring>
00250 #include "mem_layout.h"
00251 #include "regdefs.h"
00252
00253
00254
00255
00256
00257
00258
00259
00260 inline Mword PF::is_translation_error(Mword error)
00261 {
00262 return !(error & PF_ERR_PRESENT);
00263 }
00264
00265
00266
00267 inline Mword PF::is_usermode_error(Mword error)
00268 {
00269 return (error & PF_ERR_USERMODE);
00270 }
00271
00272
00273
00274 inline Mword PF::is_read_error(Mword error)
00275 {
00276 return !(error & PF_ERR_WRITE);
00277 }
00278
00279
00280
00281 inline Mword PF::addr_to_msgword0(Address pfa, Mword error)
00282 {
00283 return (pfa & ~(PF_ERR_PRESENT | PF_ERR_WRITE))
00284 | (error & (PF_ERR_PRESENT | PF_ERR_WRITE));
00285 }
00286
00287
00288
00289 inline Mword PF::pc_to_msgword1(Address pc, Mword error)
00290 {
00291 return is_usermode_error(error) ? pc : (Mword)-1;
00292 }
00293
00294
00295
00296 inline int
00297 Pd_entry::valid() const
00298 {
00299 return _raw & Valid;
00300 }
00301
00302
00303
00304 inline int
00305 Pd_entry::user() const
00306 {
00307 return _raw & User;
00308 }
00309
00310
00311
00312 inline int
00313 Pd_entry::writable() const
00314 {
00315 return _raw & Writable;
00316 }
00317
00318
00319
00320 inline int
00321 Pd_entry::superpage() const
00322 {
00323 return _raw & Superpage;
00324 }
00325
00326
00327
00328 inline Address
00329 Pd_entry::ptabfn() const
00330 {
00331 return _raw & Ptabfn;
00332 }
00333
00334
00335
00336 inline Address
00337 Pd_entry::superfn() const
00338 {
00339 return _raw & Superfn;
00340 }
00341
00342
00343
00344 inline Ptab*
00345 Pd_entry::ptab() const
00346 {
00347 return reinterpret_cast<Ptab*>(Mem_layout::phys_to_pmem(ptabfn()));
00348 }
00349
00350
00351
00352 inline Unsigned32
00353 Pd_entry::raw() const
00354 {
00355 return _raw;
00356 }
00357
00358
00359
00360 inline Unsigned32
00361 Pd_entry::raw() const volatile
00362 {
00363 return _raw;
00364 }
00365
00366
00367
00368 inline Unsigned32&
00369 Pd_entry::raw()
00370 {
00371 return _raw;
00372 }
00373
00374
00375
00376 inline void
00377 Pd_entry::add_attr(Unsigned32 attr)
00378 {
00379 _raw |= attr;
00380 }
00381
00382
00383
00384 inline void
00385 Pd_entry::del_attr(Unsigned32 attr)
00386 {
00387 _raw &= ~attr;
00388 }
00389
00390
00391
00392 inline Pd_entry const&
00393 Pd_entry::operator = (Pd_entry const& other)
00394 {
00395 _raw = other.raw();
00396 return *this;
00397 }
00398
00399
00400
00401 inline Pd_entry const&
00402 Pd_entry::operator = (Unsigned32 raw)
00403 {
00404 _raw = raw;
00405 return *this;
00406 }
00407
00408
00409
00410 inline void
00411 Pd_entry::enable_global()
00412 {
00413 _cpu_global |= Pd_entry::Cpu_global;
00414 }
00415
00416
00424 inline Unsigned32
00425 Pd_entry::global()
00426 {
00427 return _cpu_global;
00428 }
00429
00430
00431
00432
00433
00434 inline Pt_entry const&
00435 Pt_entry::operator = (Pt_entry const &other)
00436 {
00437 _raw = other.raw();
00438 return *this;
00439 }
00440
00441
00442
00443 inline Pt_entry const&
00444 Pt_entry::operator = (Unsigned32 raw)
00445 {
00446 _raw = raw;
00447 return *this;
00448 }
00449
00450
00451
00452 inline Unsigned32
00453 Pt_entry::raw() const
00454 {
00455 return _raw;
00456 }
00457
00458
00459
00460 inline Unsigned32&
00461 Pt_entry::raw()
00462 {
00463 return _raw;
00464 }
00465
00466
00467
00468 inline void
00469 Pt_entry::add_attr(Unsigned32 attr)
00470 {
00471 _raw |= attr;
00472 }
00473
00474
00475
00476 inline void
00477 Pt_entry::del_attr(Unsigned32 attr)
00478 {
00479 _raw &= ~attr;
00480 }
00481
00482
00483
00484 inline int
00485 Pt_entry::valid() const
00486 {
00487 return _raw & Valid;
00488 }
00489
00490
00491
00492 inline int
00493 Pt_entry::writable() const
00494 {
00495 return _raw & Writable;
00496 }
00497
00498
00499
00500 inline Address
00501 Pt_entry::pfn() const
00502 {
00503 return _raw & Pfn;
00504 }
00505
00506
00507
00508 inline Unsigned32
00509 Pt_entry::global()
00510 {
00511 return Pd_entry::global();
00512 }
00513
00514
00515
00516 inline unsigned
00517 Pdir::virt_to_idx(Address virt)
00518 {
00519 return (virt >> Pd_entry::Shift) & Pd_entry::Mask;
00520 }
00521
00522
00523
00524 inline Pd_entry*
00525 Pdir::lookup(Address virt)
00526 {
00527 return _entries + virt_to_idx(virt);
00528 }
00529
00530
00531
00532 inline Pd_entry
00533 Pdir::entry(Address virt) const
00534 {
00535 return _entries[virt_to_idx(virt)];
00536 }
00537
00538
00539
00540 inline const Pd_entry*
00541 Pdir::index(unsigned idx) const
00542 {
00543 assert(idx < 1024);
00544 return _entries + idx;
00545 }
00546
00547
00548
00549 inline Pd_entry*
00550 Pdir::index(unsigned idx)
00551 {
00552 assert(idx < 1024);
00553 return _entries + idx;
00554 }
00555
00556
00557
00558 inline Unsigned32&
00559 Pdir::operator[](unsigned idx)
00560 {
00561 assert(idx < 1024);
00562 return _entries[idx].raw();
00563 }
00564
00565
00566
00567 inline Unsigned32
00568 Pdir::operator[](unsigned idx) const
00569 {
00570 assert(idx < 1024);
00571 return _entries[idx].raw();
00572 }
00573
00574
00575
00576 inline void
00577 Pdir::clear()
00578 {
00579 memset(_entries, 0, Config::PAGE_SIZE);
00580 }
00581
00582
00583
00584 inline void
00585 Pdir::have_superpages(bool yes)
00586 {
00587 _have_superpages = yes;
00588 }
00589
00590
00591
00592
00593
00594 inline unsigned
00595 Ptab::virt_to_idx(Address virt)
00596 {
00597 return (virt >> Pt_entry::Shift) & Pt_entry::Mask;
00598 }
00599
00600
00601
00602 inline Pt_entry*
00603 Ptab::lookup(Address virt)
00604 {
00605 return _entries + virt_to_idx(virt);
00606 }
00607
00608
00609
00610 inline Pt_entry
00611 Ptab::entry(Address virt) const
00612 {
00613 return _entries[virt_to_idx(virt)];
00614 }
00615
00616
00617
00618 inline Pt_entry*
00619 Ptab::index(unsigned idx)
00620 {
00621 assert(idx < 1024);
00622 return _entries + idx;
00623 }
00624
00625
00626
00627 inline Unsigned32&
00628 Ptab::operator[](unsigned idx)
00629 {
00630 assert(idx < 1024);
00631 return _entries[idx].raw();
00632 }
00633
00634
00635
00636 inline Unsigned32
00637 Ptab::operator[](unsigned idx) const
00638 {
00639 assert(idx < 1024);
00640 return _entries[idx].raw();
00641 }
00642
00643
00644
00645 inline void
00646 Ptab::clear()
00647 {
00648 memset(_entries, 0, Config::PAGE_SIZE);
00649 }
00650
00651 #endif // paging_h