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