1 /* 2 * Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 * 6 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. 7 * Distributed under the terms of the NewOS License. 8 */ 9 #ifndef _KERNEL_VM_VM_AREA_H 10 #define _KERNEL_VM_VM_AREA_H 11 12 13 #include <vm_defs.h> 14 15 #include <lock.h> 16 #include <util/DoublyLinkedList.h> 17 #include <util/SinglyLinkedList.h> 18 #include <util/OpenHashTable.h> 19 #include <vm/vm_types.h> 20 21 22 struct VMAddressSpace; 23 struct VMCache; 24 struct VMKernelAddressSpace; 25 struct VMUserAddressSpace; 26 27 28 struct VMAreaUnwiredWaiter 29 : public DoublyLinkedListLinkImpl<VMAreaUnwiredWaiter> { 30 VMArea* area; 31 addr_t base; 32 size_t size; 33 ConditionVariable condition; 34 ConditionVariableEntry waitEntry; 35 }; 36 37 typedef DoublyLinkedList<VMAreaUnwiredWaiter> VMAreaUnwiredWaiterList; 38 39 40 struct VMAreaWiredRange : SinglyLinkedListLinkImpl<VMAreaWiredRange> { 41 VMArea* area; 42 addr_t base; 43 size_t size; 44 bool writable; 45 bool implicit; // range created automatically 46 VMAreaUnwiredWaiterList waiters; 47 48 VMAreaWiredRange() 49 { 50 } 51 52 VMAreaWiredRange(addr_t base, size_t size, bool writable, bool implicit) 53 : 54 area(NULL), 55 base(base), 56 size(size), 57 writable(writable), 58 implicit(implicit) 59 { 60 } 61 62 void SetTo(addr_t base, size_t size, bool writable, bool implicit) 63 { 64 this->area = NULL; 65 this->base = base; 66 this->size = size; 67 this->writable = writable; 68 this->implicit = implicit; 69 } 70 71 bool IntersectsWith(addr_t base, size_t size) const 72 { 73 return this->base + this->size - 1 >= base 74 && base + size - 1 >= this->base; 75 } 76 }; 77 78 typedef SinglyLinkedList<VMAreaWiredRange> VMAreaWiredRangeList; 79 80 81 struct VMPageWiringInfo { 82 VMAreaWiredRange range; 83 phys_addr_t physicalAddress; 84 // the actual physical address corresponding to 85 // the virtual address passed to vm_wire_page() 86 // (i.e. with in-page offset) 87 vm_page* page; 88 }; 89 90 91 struct VMArea { 92 public: 93 enum { 94 // AddWaiterIfWired() flags 95 IGNORE_WRITE_WIRED_RANGES = 0x01, // ignore existing ranges that 96 // wire for writing 97 }; 98 99 public: 100 char* name; 101 area_id id; 102 uint32 protection; 103 uint16 wiring; 104 105 private: 106 uint16 memory_type; // >> shifted by MEMORY_TYPE_SHIFT 107 108 public: 109 VMCache* cache; 110 vint32 no_cache_change; 111 off_t cache_offset; 112 uint32 cache_type; 113 VMAreaMappings mappings; 114 uint8* page_protections; 115 116 struct VMAddressSpace* address_space; 117 struct VMArea* cache_next; 118 struct VMArea* cache_prev; 119 struct VMArea* hash_next; 120 121 addr_t Base() const { return fBase; } 122 size_t Size() const { return fSize; } 123 124 inline uint32 MemoryType() const; 125 inline void SetMemoryType(uint32 memoryType); 126 127 bool ContainsAddress(addr_t address) const 128 { return address >= fBase 129 && address <= fBase + (fSize - 1); } 130 131 bool IsWired() const 132 { return !fWiredRanges.IsEmpty(); } 133 bool IsWired(addr_t base, size_t size) const; 134 135 void Wire(VMAreaWiredRange* range); 136 void Unwire(VMAreaWiredRange* range); 137 VMAreaWiredRange* Unwire(addr_t base, size_t size, bool writable); 138 139 bool AddWaiterIfWired(VMAreaUnwiredWaiter* waiter); 140 bool AddWaiterIfWired(VMAreaUnwiredWaiter* waiter, 141 addr_t base, size_t size, uint32 flags = 0); 142 143 protected: 144 VMArea(VMAddressSpace* addressSpace, 145 uint32 wiring, uint32 protection); 146 ~VMArea(); 147 148 status_t Init(const char* name, uint32 allocationFlags); 149 150 protected: 151 friend class VMAddressSpace; 152 friend class VMKernelAddressSpace; 153 friend class VMUserAddressSpace; 154 155 protected: 156 void SetBase(addr_t base) { fBase = base; } 157 void SetSize(size_t size) { fSize = size; } 158 159 protected: 160 addr_t fBase; 161 size_t fSize; 162 VMAreaWiredRangeList fWiredRanges; 163 }; 164 165 166 struct VMAreaHashDefinition { 167 typedef area_id KeyType; 168 typedef VMArea ValueType; 169 170 size_t HashKey(area_id key) const 171 { 172 return key; 173 } 174 175 size_t Hash(const VMArea* value) const 176 { 177 return HashKey(value->id); 178 } 179 180 bool Compare(area_id key, const VMArea* value) const 181 { 182 return value->id == key; 183 } 184 185 VMArea*& GetLink(VMArea* value) const 186 { 187 return value->hash_next; 188 } 189 }; 190 191 typedef BOpenHashTable<VMAreaHashDefinition> VMAreaHashTable; 192 193 194 struct VMAreaHash { 195 static status_t Init(); 196 197 static status_t ReadLock() 198 { return rw_lock_read_lock(&sLock); } 199 static void ReadUnlock() 200 { rw_lock_read_unlock(&sLock); } 201 static status_t WriteLock() 202 { return rw_lock_write_lock(&sLock); } 203 static void WriteUnlock() 204 { rw_lock_write_unlock(&sLock); } 205 206 static VMArea* LookupLocked(area_id id) 207 { return sTable.Lookup(id); } 208 static VMArea* Lookup(area_id id); 209 static area_id Find(const char* name); 210 static void Insert(VMArea* area); 211 static void Remove(VMArea* area); 212 213 static VMAreaHashTable::Iterator GetIterator() 214 { return sTable.GetIterator(); } 215 216 private: 217 static rw_lock sLock; 218 static VMAreaHashTable sTable; 219 }; 220 221 222 uint32 223 VMArea::MemoryType() const 224 { 225 return (uint32)memory_type << MEMORY_TYPE_SHIFT; 226 } 227 228 229 void 230 VMArea::SetMemoryType(uint32 memoryType) 231 { 232 memory_type = memoryType >> MEMORY_TYPE_SHIFT; 233 } 234 235 236 #endif // _KERNEL_VM_VM_AREA_H 237