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 area_id id; 101 char name[B_OS_NAME_LENGTH]; 102 uint32 protection; 103 uint32 protection_max; 104 uint16 wiring; 105 106 private: 107 uint16 memory_type; // >> shifted by MEMORY_TYPE_SHIFT 108 109 public: 110 VMCache* cache; 111 vint32 no_cache_change; 112 off_t cache_offset; 113 uint32 cache_type; 114 VMAreaMappings mappings; 115 uint8* page_protections; 116 117 struct VMAddressSpace* address_space; 118 struct VMArea* cache_next; 119 struct VMArea* cache_prev; 120 struct VMArea* hash_next; 121 122 addr_t Base() const { return fBase; } 123 size_t Size() const { return fSize; } 124 125 inline uint32 MemoryType() const; 126 inline void SetMemoryType(uint32 memoryType); 127 128 bool ContainsAddress(addr_t address) const 129 { return address >= fBase 130 && address <= fBase + (fSize - 1); } 131 132 bool IsWired() const 133 { return !fWiredRanges.IsEmpty(); } 134 bool IsWired(addr_t base, size_t size) const; 135 136 void Wire(VMAreaWiredRange* range); 137 void Unwire(VMAreaWiredRange* range); 138 VMAreaWiredRange* Unwire(addr_t base, size_t size, bool writable); 139 140 bool AddWaiterIfWired(VMAreaUnwiredWaiter* waiter); 141 bool AddWaiterIfWired(VMAreaUnwiredWaiter* waiter, 142 addr_t base, size_t size, uint32 flags = 0); 143 144 protected: 145 VMArea(VMAddressSpace* addressSpace, 146 uint32 wiring, uint32 protection); 147 ~VMArea(); 148 149 status_t Init(const char* name, uint32 allocationFlags); 150 151 protected: 152 friend struct VMAddressSpace; 153 friend struct VMKernelAddressSpace; 154 friend struct VMUserAddressSpace; 155 156 protected: 157 void SetBase(addr_t base) { fBase = base; } 158 void SetSize(size_t size) { fSize = size; } 159 160 protected: 161 addr_t fBase; 162 size_t fSize; 163 VMAreaWiredRangeList fWiredRanges; 164 }; 165 166 167 struct VMAreaHashDefinition { 168 typedef area_id KeyType; 169 typedef VMArea ValueType; 170 171 size_t HashKey(area_id key) const 172 { 173 return key; 174 } 175 176 size_t Hash(const VMArea* value) const 177 { 178 return HashKey(value->id); 179 } 180 181 bool Compare(area_id key, const VMArea* value) const 182 { 183 return value->id == key; 184 } 185 186 VMArea*& GetLink(VMArea* value) const 187 { 188 return value->hash_next; 189 } 190 }; 191 192 typedef BOpenHashTable<VMAreaHashDefinition> VMAreaHashTable; 193 194 195 struct VMAreaHash { 196 static status_t Init(); 197 198 static status_t ReadLock() 199 { return rw_lock_read_lock(&sLock); } 200 static void ReadUnlock() 201 { rw_lock_read_unlock(&sLock); } 202 static status_t WriteLock() 203 { return rw_lock_write_lock(&sLock); } 204 static void WriteUnlock() 205 { rw_lock_write_unlock(&sLock); } 206 207 static VMArea* LookupLocked(area_id id) 208 { return sTable.Lookup(id); } 209 static VMArea* Lookup(area_id id); 210 static area_id Find(const char* name); 211 static void Insert(VMArea* area); 212 static void Remove(VMArea* area); 213 214 static VMAreaHashTable::Iterator GetIterator() 215 { return sTable.GetIterator(); } 216 217 private: 218 static rw_lock sLock; 219 static VMAreaHashTable sTable; 220 }; 221 222 223 uint32 224 VMArea::MemoryType() const 225 { 226 return (uint32)memory_type << MEMORY_TYPE_SHIFT; 227 } 228 229 230 void 231 VMArea::SetMemoryType(uint32 memoryType) 232 { 233 memory_type = memoryType >> MEMORY_TYPE_SHIFT; 234 } 235 236 237 #endif // _KERNEL_VM_VM_AREA_H 238