00001
00002
00003 #ifndef space_h
00004 #define space_h
00005
00006 #include "space_index.h"
00007
00008 #include "paging.h"
00009
00010
00011
00012
00013
00014
00020 class Space
00021 {
00022 public:
00024 enum Status {
00025 Insert_ok = 0,
00026 Insert_warn_exists,
00027 Insert_warn_attrib_upgrade,
00028 Insert_err_nomem,
00029 Insert_err_exists
00030 };
00031
00033 enum Page_attrib
00034 {
00035 Page_no_attribs = 0,
00037 Page_writable = Pt_entry::Writable,
00039 Page_noncacheable = Pt_entry::Noncacheable | Pt_entry::Write_through,
00041 Page_user_accessible = Pt_entry::User,
00043 Page_all_attribs = Page_writable | Page_noncacheable |
00044 Page_user_accessible,
00045 };
00046
00048 bool is_privileged (void);
00049
00050 static Space *id_lookup(Task_num id);
00051
00052 public:
00053 static Space *current();
00054 void make_current();
00055 void switchin_context();
00056
00057 protected:
00058 void switchin_lipc_kip_pointer();
00059
00060
00061 Pdir _dir;
00062 private:
00063
00064 private:
00065 Space();
00066 Space(const Space&);
00067 private:
00068
00069 public:
00076 template < typename T >
00077 T peek (T const *addr, bool user_space);
00078
00084 template < typename T >
00085 T peek_user (T const *addr);
00086
00092 template < typename T >
00093 void poke_user (T *addr, T value);
00094
00101 template < typename T >
00102 void copy_from_user (T *kdst, T const *usrc, size_t n);
00103
00110 template < typename T >
00111 void copy_to_user (T *udst, T const *ksrc, size_t n);
00112 private:
00113
00114 public:
00115
00116 void page_map (Address phys, Address virt,
00117 Address size, unsigned page_attribs);
00118
00119 void page_unmap (Address virt, Address size);
00120
00121 void page_protect (Address virt, Address size,
00122 unsigned page_attribs);
00123
00128 Address kip_address() const;
00129
00138 void kmem_update (void *addr);
00139
00150 void remote_update (const Address, const Space *,
00151 const Address, size_t);
00152
00157 void update_small (Address virt, bool flush);
00158
00164 bool is_mappable (Address addr, size_t size);
00165
00166 private:
00168 void remove_from_space_index();
00169 private:
00170
00171 private:
00172 void switch_ldt();
00173
00174 public:
00175
00176 inline int mapped(Address addr, int need_writable) const;
00177
00184 inline Address virt_to_phys(Address virt) const;
00185
00186 inline const Pdir* dir() const;
00187
00192 inline Space_index id() const;
00193
00198 inline Space_index chief() const;
00199
00200
00201 void * operator new (size_t size);
00202
00203 void operator delete (void *block);
00204
00205
00206
00220 inline Address virt_to_phys_s0(void *a) const;
00221
00226 inline bool is_sigma0(void) const;
00227
00228 inline unsigned get_io_counter(void);
00229
00230 inline bool io_lookup(Address);
00231
00236 ~Space();
00237
00256 Space::Status v_insert(Address phys, Address virt, size_t size, unsigned page_attribs);
00257
00273 bool v_lookup(Address virt, Address *phys = 0, Address *size = 0, unsigned *page_attribs = 0);
00274
00284 bool v_delete(Address virt, Address size, unsigned page_attribs = 0);
00285
00286 inline void ldt_addr(void *addr);
00287
00288 inline Address ldt_addr() const;
00289
00290 inline void ldt_size(Mword size);
00291
00292 inline Mword ldt_size() const;
00293
00294 protected:
00305 Space(unsigned number);
00306
00307 private:
00308 inline void free_ldt_memory();
00309 };
00310
00316 inline Space * current_space();
00317
00318
00319
00320
00321
00322 #include "globals.h"
00323
00324 #include <cassert>
00325 #include "l4_types.h"
00326 #include "mem_unit.h"
00327 #include "paging.h"
00328 #include "config.h"
00329
00330 #include "cpu.h"
00331 #include "kmem.h"
00332 #include "logdefs.h"
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 inline int
00343 Space::mapped(Address addr, int need_writable) const
00344 {
00345 Pd_entry p = _dir.entry(addr);
00346
00347 if (!p.valid())
00348 return 0;
00349
00350 if (p.superpage())
00351 return !need_writable || p.writable();
00352
00353 Pt_entry e = *(p.ptab()->lookup(addr));
00354
00355 return e.valid() && (!need_writable || e.writable());
00356 }
00357
00358
00366 inline Address
00367 Space::virt_to_phys(Address virt) const
00368 {
00369 return dir()->virt_to_phys(virt);
00370 }
00371
00372
00373
00374 inline const Pdir*
00375 Space::dir() const
00376 {
00377 return &_dir;
00378 }
00379
00380
00386 inline Space_index
00387 Space::id() const
00388 {
00389 return Space_index (_dir.entry(Mem_layout::Space_index).raw() >> 8);
00390 }
00391
00392
00398 inline Space_index
00399 Space::chief() const
00400 {
00401 return Space_index (_dir.entry(Mem_layout::Chief_index).raw() >> 8);
00402 }
00403
00404
00405
00406
00421 inline Address
00422 Space::virt_to_phys_s0(void *a) const
00423 {
00424 if (is_sigma0())
00425 return (Address)a;
00426
00427 return dir()->virt_to_phys((Address)a);
00428 }
00429
00430
00436 inline bool Space::is_sigma0(void) const
00437 {
00438 return this == sigma0_space;
00439 }
00440
00441
00442
00443 inline unsigned
00444 Space::get_io_counter(void)
00445 { return 0; }
00446
00447
00448
00449 inline bool
00450 Space::io_lookup(Address)
00451 { return false; }
00452
00453
00454
00455 inline void
00456 Space::ldt_addr(void *addr)
00457 {
00458 Pd_entry *p = _dir.lookup(Mem_layout::Ldt_addr);
00459 assert(!p->valid());
00460 assert(!((Address)addr & 1));
00461
00462 *p = (Address)addr & ~1;
00463 }
00464
00465
00466
00467 inline Address
00468 Space::ldt_addr() const
00469 {
00470 Pd_entry p = _dir.entry(Mem_layout::Ldt_addr);
00471 assert(!p.valid());
00472
00473 return p.raw();
00474 }
00475
00476
00477
00478 inline void
00479 Space::ldt_size(Mword size)
00480 {
00481 Pd_entry *p = _dir.lookup(Mem_layout::Ldt_size);
00482 assert(!p->valid());
00483 assert(!(size & 1));
00484
00485 *p = size & ~1;
00486 }
00487
00488
00489
00490 inline Mword
00491 Space::ldt_size() const
00492 {
00493 Pd_entry p = _dir.entry(Mem_layout::Ldt_size);
00494 assert(!p.valid());
00495
00496 return p.raw();
00497 }
00498
00499
00500
00501 inline void
00502 Space::switchin_lipc_kip_pointer()
00503 {}
00504
00505
00507
00508 inline Space *
00509 Space::id_lookup(Task_num id)
00510 {
00511 return Space_index (id).lookup();
00512 }
00513
00514
00515
00516 inline bool Space::is_privileged(void)
00517 {
00518
00519 return (!Config::enable_io_protection
00520 || (get_io_counter() == L4_fpage::Io_port_max));
00521 }
00522
00523
00524
00525 template < typename T > inline T
00526 Space::peek(T const *addr, bool user_space)
00527 {
00528
00529 return user_space ? peek_user (addr) : *addr;
00530 }
00531
00532
00533
00534 template < typename T > inline T
00535 Space::peek_user(T const *addr)
00536 {
00537 assert (this == current_space());
00538 return *addr;
00539 }
00540
00541
00542
00543 template < typename T > inline void
00544 Space::poke_user(T *addr, T value)
00545 {
00546 assert (this == current_space());
00547 *addr = value;
00548 }
00549
00550
00551
00552 template < typename T > inline void
00553 Space::copy_from_user(T *kdst, T const *usrc, size_t n)
00554 {
00555 assert (this == current_space());
00556 Cpu::memcpy_bytes (kdst, usrc, n * sizeof (T));
00557 }
00558
00559
00560
00561 template <> inline void
00562 Space::copy_from_user <Mword>(Mword *kdst, Mword const *usrc, size_t n)
00563 {
00564 assert (this == current_space());
00565 Cpu::memcpy_mwords (kdst, usrc, n);
00566 }
00567
00568
00569
00570 template < typename T > inline void
00571 Space::copy_to_user(T *udst, T const *ksrc, size_t n)
00572 {
00573 assert (this == current_space());
00574 Cpu::memcpy_bytes (udst, ksrc, n * sizeof (T));
00575 }
00576
00577
00578
00579 template <> inline void
00580 Space::copy_to_user <Mword>(Mword *udst, Mword const *ksrc, size_t n)
00581 {
00582 assert (this == current_space());
00583 Cpu::memcpy_mwords (udst, ksrc, n);
00584 }
00585
00586
00587
00588 inline Address
00589 Space::kip_address() const
00590 {
00591 return (is_sigma0()
00592 ? Kmem::virt_to_phys (Kip::k())
00593 : (Address)Mem_layout::Kip_auto_map);
00594 }
00595
00596
00597
00598 inline void
00599 Space::remove_from_space_index()
00600 {
00601 Space_index::del (id(), chief());
00602 }
00603
00604
00605
00606 inline bool
00607 Space::is_mappable(Address, size_t)
00608 {
00609 return true;
00610 }
00611
00612
00613
00614 inline Space *
00615 Space::current()
00616 {
00617 return reinterpret_cast<Space*>(Kmem::phys_to_virt(Cpu::get_pdbr()));
00618 }
00619
00620
00621
00622 inline void
00623 Space::make_current()
00624 {
00625 Cpu::set_pdbr((Mem_layout::pmem_to_phys(this)));
00626 }
00627
00628
00629
00630 inline void
00631 Space::switchin_context()
00632 {
00633
00634 if (this == (Space*)Kmem::dir())
00635 return;
00636
00637 bool need_flush_tlb = false;
00638 unsigned index = Pdir::virt_to_idx(Kmem::ipc_window(0));
00639
00640 if (_dir[index] || _dir[index + 1])
00641 {
00642 _dir[index] = 0;
00643 _dir[index + 1] = 0;
00644 need_flush_tlb = true;
00645 }
00646
00647 index = Pdir::virt_to_idx(Kmem::ipc_window(1));
00648
00649 if (_dir[index] || _dir[index + 1])
00650 {
00651 _dir[index] = 0;
00652 _dir[index + 1] = 0;
00653 need_flush_tlb = true;
00654 }
00655
00656 if (need_flush_tlb || this != Space::current())
00657 {
00658 switchin_lipc_kip_pointer();
00659 CNT_ADDR_SPACE_SWITCH;
00660 make_current();
00661 switch_ldt();
00662 }
00663 }
00664
00665
00666
00667 inline void
00668 Space::switch_ldt()
00669 {
00670 }
00671
00672
00673
00674
00675
00676
00677
00678
00679 inline void
00680 Space::page_map(Address, Address, Address, unsigned)
00681 {}
00682
00683
00684
00685 inline void
00686 Space::page_protect(Address, Address, unsigned)
00687 {}
00688
00689
00690
00691 inline void
00692 Space::page_unmap(Address, Address)
00693 {}
00694
00695
00696
00697 inline void Space::kmem_update(void *addr)
00698 {
00699 unsigned i = Pdir::virt_to_idx((Address)addr);
00700
00701 _dir[i] = (*Kmem::dir())[i];
00702 }
00703
00704
00712 inline void
00713 Space::remote_update(const Address loc_addr, const Space *rem,
00714 const Address rem_addr, size_t n)
00715 {
00716 bool tlb_flush = false;
00717 unsigned loc_slot = Pdir::virt_to_idx(loc_addr),
00718 rem_slot = Pdir::virt_to_idx(rem_addr);
00719
00720
00721 assert (loc_slot + n <= 1024);
00722 assert (rem_slot + n <= 1024);
00723
00724 while (n--)
00725 {
00726 if (_dir[loc_slot])
00727 tlb_flush = true;
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749 for(;;) {
00750
00751 const volatile Pd_entry *val = rem->dir()->index(rem_slot);
00752 _dir[loc_slot] = val->raw();
00753
00754 if(EXPECT_TRUE(_dir[loc_slot] == val->raw()))
00755 break;
00756 }
00757
00758 loc_slot++;
00759 rem_slot++;
00760
00761 }
00762
00763 if (tlb_flush)
00764 Mem_unit::tlb_flush();
00765 }
00766
00767
00768
00769 inline void
00770 Space::update_small(Address, bool)
00771 {}
00772
00773
00774
00775 inline Space *
00776 current_space()
00777 {
00778 return Space::current();
00779 }
00780
00781 #endif // space_h