1 /* 2 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>, 3 * Alexander Warg <warg@os.inf.tu-dresden.de> 4 * economic rights: Technische Universität Dresden (Germany) 5 * 6 * This file is part of TUD:OS and distributed under the terms of the 7 * GNU General Public License 2. 8 * Please see the COPYING-GPL-2 file for details. 9 */ 10 #pragma once 11 12 #include "dataspace.h" 13 14 namespace Moe { 15 16 /** 17 * Dataspace with dynamic backing of physical memory. 18 * 19 * The dataspace is created in an empty state. Memory pages are allocated 20 * and freed dynamically as they are requested by the client. 21 */ 22 class Dataspace_noncont : public Dataspace 23 { 24 public: 25 enum 26 { 27 Page_addr_mask = ~((1UL << 12)-1), 28 Page_cow = 0x04UL, 29 }; 30 31 class Page 32 { 33 private: 34 unsigned long p; 35 36 public: Page()37 Page() throw() : p(0) {} throw()38 void *operator * () const throw() { return (void*)(p & Page_addr_mask); } valid()39 bool valid() const throw() { return p & Page_addr_mask;} flags()40 unsigned long flags() const throw() { return p & ~Page_addr_mask; } 41 set(void * addr,unsigned long flags)42 void set(void *addr, unsigned long flags) throw() 43 { p = ((unsigned long)addr & Page_addr_mask) | (flags & ~Page_addr_mask); } 44 throw()45 void flags(unsigned long add, unsigned long del = 0) throw() 46 { 47 p = (p & Page_addr_mask & ~(del & ~Page_addr_mask)) 48 | ((unsigned long)add & ~Page_addr_mask); 49 } 50 addr(void * a)51 void addr(void *a) throw() 52 { p = (p & ~Page_addr_mask) | ((unsigned long)a & Page_addr_mask); } 53 }; 54 is_static()55 bool is_static() const throw() override { return false; } 56 57 Dataspace_noncont(unsigned long size, throw()58 Flags flags = L4Re::Dataspace::F::RWX) throw() 59 : Dataspace(size, flags | Flags(Cow_enabled), L4_LOG2_PAGESIZE), _pages(0) 60 {} 61 ~Dataspace_noncont()62 virtual ~Dataspace_noncont() {} 63 64 Address address(l4_addr_t offset, 65 Flags flags = L4Re::Dataspace::F::RWX, l4_addr_t hot_spot = 0, 66 l4_addr_t min = 0, l4_addr_t max = ~0) const override; 67 int copy_address(l4_addr_t offset, Flags flags, l4_addr_t *copy_addr, 68 unsigned long *copy_size) const override; 69 70 int pre_allocate(l4_addr_t offset, l4_size_t size, unsigned rights) override; 71 72 virtual Page &page(unsigned long offs) const throw() = 0; 73 virtual Page &alloc_page(unsigned long offs) const = 0; 74 num_pages()75 unsigned long num_pages() const throw() 76 { return (size()+page_size()-1) / page_size(); } 77 78 #if 0 79 private: 80 unsigned idx_of(unsigned long offset) const { return offset >> 12; } 81 82 void *page(unsigned idx) const 83 { return (void*)(pages[idx] & Page_addr_mask); } 84 unsigned flags(unsigned idx) const { return pages[idx] & ~Page_addr_mask; } 85 void page(unsigned idx, void *page, unsigned flags = 0) const 86 { 87 pages[idx] = (unsigned long)page & Page_addr_mask | flags 88 & ~Page_addr_mask; 89 } 90 #endif 91 92 void free_page(Page &p) const throw(); 93 void unmap_page(Page const &p, bool ro = false) const throw(); 94 95 public: 96 long clear(unsigned long offs, unsigned long size) const throw() override; 97 98 static Dataspace_noncont *create(Q_alloc *q, unsigned long size, 99 Flags flags = L4Re::Dataspace::F::RWX); 100 101 protected: 102 union 103 { 104 Page *_pages; 105 Page _page; 106 }; 107 108 private: 109 Address map_address(l4_addr_t offset, Flags flags) const; 110 }; 111 }; 112