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 <cstddef> 13 #include <l4/sys/types.h> 14 #include <l4/cxx/iostream> 15 #include <l4/cxx/list> 16 #include <l4/sys/cxx/ipc_epiface> 17 #include <l4/re/dataspace> 18 19 #include "dma_space.h" 20 #include "server_obj.h" 21 #include "globals.h" 22 #include "quota.h" 23 24 namespace Moe { 25 26 /** 27 * Base class for all dataspace types. 28 * 29 * Provides common implementations of the Dataspace interface functions. 30 * The behaviour may be adapted by overwriting the provided virtual 31 * functions. 32 */ 33 class Dataspace : 34 public L4::Epiface_t<Dataspace, L4Re::Dataspace, Server_object>, 35 public Q_object 36 { 37 public: 38 using Flags = L4Re::Dataspace::Flags; 39 enum { Cow_enabled = 0x100 }; 40 41 struct Address 42 { 43 l4_fpage_t fpage; 44 l4_addr_t offs; 45 throwAddress46 Address(long error) throw() : offs(-1UL) { fpage.raw = error; } 47 48 Address(l4_addr_t base, l4_addr_t size, 49 Flags flags, throwAddress50 l4_addr_t offs = 0) throw() 51 : fpage(l4_fpage(base, size, flags.fpage_rights())), 52 offs(offs) {} 53 bsAddress54 unsigned long bs() const throw() { return fpage.raw & L4_FPAGE_ADDR_MASK; } szAddress55 unsigned long sz() const throw() { return 1 << l4_fpage_size(fpage); } ofAddress56 unsigned long of() const throw() { return offs; } fpAddress57 l4_fpage_t fp() const throw() { return fpage; } 58 59 template< typename T > adrAddress60 T adr() const throw() { return (T)(bs() + offs); } 61 adrAddress62 void *adr() const throw() { return (void*)(bs() + offs); } 63 is_nilAddress64 bool is_nil() const throw() { return offs == -1UL; } 65 /** 66 * \brief Get the error code that led to the invalid address. 67 * \pre is_nil() must return true. 68 */ errorAddress69 long error() const throw() { return fpage.raw; } 70 71 }; 72 Dataspace(unsigned long size,Flags flags,unsigned char page_shift)73 Dataspace(unsigned long size, Flags flags, 74 unsigned char page_shift) throw() 75 : _size(size), _flags(flags), _page_shift(page_shift) 76 {} 77 78 size()79 unsigned long size() const throw() { return _size; } 80 virtual Address address(l4_addr_t ds_offset, 81 Flags flags = L4Re::Dataspace::F::RWX, 82 l4_addr_t hot_spot = 0, 83 l4_addr_t min = 0, l4_addr_t max = ~0) const = 0; 84 virtual int copy_address(l4_addr_t ds_offset, Flags flags, 85 l4_addr_t *copy_addr, unsigned long *copy_size) const = 0; 86 87 virtual int pre_allocate(l4_addr_t offset, l4_size_t size, unsigned rights) = 0; 88 can_cow()89 bool can_cow() const noexcept { return (bool)(_flags & Flags(Cow_enabled)); } flags()90 Flags flags() const noexcept { return _flags; } 91 92 Flags map_flags(L4Re::Dataspace::Rights rights = L4_CAP_FPAGE_W) const noexcept 93 { 94 auto f = (_flags & Flags(L4Re::Dataspace::F::Rights_mask)) 95 | L4Re::Dataspace::F::Caching_mask; 96 if (!(rights & L4_CAP_FPAGE_W)) 97 f &= ~L4Re::Dataspace::F::W; 98 99 return f; 100 } 101 ~Dataspace()102 virtual ~Dataspace() {} 103 page_shift()104 unsigned long page_shift() const throw() { return _page_shift; } page_size()105 unsigned long page_size() const throw() { return 1UL << _page_shift; } 106 107 virtual bool is_static() const throw() = 0; 108 virtual long clear(unsigned long offs, unsigned long size) const throw(); 109 110 protected: size(unsigned long size)111 void size(unsigned long size) throw() { _size = size; } 112 113 public: round_size()114 unsigned long round_size() const throw() 115 { return l4_round_size(size(), page_shift()); } check_limit(l4_addr_t offset)116 bool check_limit(l4_addr_t offset) const throw() 117 { return offset < round_size(); } check_range(l4_addr_t offset,unsigned long sz)118 bool check_range(l4_addr_t offset, unsigned long sz) const throw() 119 { return offset < round_size() && size() - offset >= sz; } 120 121 public: 122 int map(l4_addr_t offs, l4_addr_t spot, Flags flags, 123 l4_addr_t min, l4_addr_t max, L4::Ipc::Snd_fpage &memory); 124 125 typedef Dma_space::Attributes Dma_attribs; 126 virtual int dma_map(Dma_space *dma, l4_addr_t offset, l4_size_t *size, 127 Dma_attribs dma_attrs, Dma_space::Direction dir, 128 Dma_space::Dma_addr *dma_addr); 129 130 long op_map(L4Re::Dataspace::Rights rights, 131 L4Re::Dataspace::Offset offset, 132 L4Re::Dataspace::Map_addr spot, 133 L4Re::Dataspace::Flags flags, L4::Ipc::Snd_fpage &fp); 134 op_allocate(L4Re::Dataspace::Rights rights,L4Re::Dataspace::Offset offset,L4Re::Dataspace::Size size)135 long op_allocate(L4Re::Dataspace::Rights rights, 136 L4Re::Dataspace::Offset offset, 137 L4Re::Dataspace::Size size) 138 { return pre_allocate(offset, size, rights & 3); } 139 140 long op_copy_in(L4Re::Dataspace::Rights rights, 141 L4Re::Dataspace::Offset dst_offs, 142 L4::Ipc::Snd_fpage const &src_cap, 143 L4Re::Dataspace::Offset src_offs, 144 L4Re::Dataspace::Size sz); 145 op_info(L4Re::Dataspace::Rights rights,L4Re::Dataspace::Stats & s)146 long op_info(L4Re::Dataspace::Rights rights, L4Re::Dataspace::Stats &s) 147 { 148 s.size = size(); 149 s.flags = flags(); 150 // only return writable if really writable 151 if (!(rights & L4_CAP_FPAGE_W)) 152 s.flags &= ~L4Re::Dataspace::F::W; 153 154 return L4_EOK; 155 } 156 op_clear(L4Re::Dataspace::Rights rights,L4Re::Dataspace::Offset offset,L4Re::Dataspace::Size size)157 long op_clear(L4Re::Dataspace::Rights rights, 158 L4Re::Dataspace::Offset offset, 159 L4Re::Dataspace::Size size) 160 { 161 if (!map_flags(rights).w()) 162 return -L4_EACCESS; 163 164 return clear(offset, size); 165 } 166 167 168 private: 169 unsigned long _size; 170 Flags _flags; 171 unsigned char _page_shift; 172 }; 173 174 } 175 176 177 178