1 /* 2 * Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 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_ADDRESS_SPACE_H 10 #define _KERNEL_VM_VM_ADDRESS_SPACE_H 11 12 13 #include <OS.h> 14 15 #include <vm/vm_priv.h> 16 #include <vm/VMArea.h> 17 #include <vm/VMTranslationMap.h> 18 19 20 struct virtual_address_restrictions; 21 22 23 struct VMAddressSpace { 24 public: 25 class AreaIterator; 26 class AreaRangeIterator; 27 28 public: 29 VMAddressSpace(team_id id, addr_t base, 30 size_t size, const char* name); 31 virtual ~VMAddressSpace(); 32 33 static status_t Init(); 34 35 team_id ID() const { return fID; } 36 addr_t Base() const { return fBase; } 37 addr_t EndAddress() const { return fEndAddress; } 38 size_t Size() const { return fEndAddress - fBase + 1; } 39 size_t FreeSpace() const { return fFreeSpace; } 40 bool IsBeingDeleted() const { return fDeleting; } 41 42 VMTranslationMap* TranslationMap() { return fTranslationMap; } 43 44 status_t ReadLock() 45 { return rw_lock_read_lock(&fLock); } 46 void ReadUnlock() 47 { rw_lock_read_unlock(&fLock); } 48 status_t WriteLock() 49 { return rw_lock_write_lock(&fLock); } 50 void WriteUnlock() 51 { rw_lock_write_unlock(&fLock); } 52 53 int32 RefCount() const 54 { return fRefCount; } 55 56 inline void Get() { atomic_add(&fRefCount, 1); } 57 inline void Put(); 58 void RemoveAndPut(); 59 60 void IncrementFaultCount() 61 { atomic_add(&fFaultCount, 1); } 62 void IncrementChangeCount() 63 { fChangeCount++; } 64 65 inline bool IsRandomizingEnabled() const 66 { return fRandomizingEnabled; } 67 inline void SetRandomizingEnabled(bool enabled) 68 { fRandomizingEnabled = enabled; } 69 70 inline AreaIterator GetAreaIterator(); 71 inline AreaRangeIterator GetAreaRangeIterator(addr_t address, 72 addr_t size); 73 74 VMAddressSpace*& HashTableLink() { return fHashTableLink; } 75 76 virtual status_t InitObject(); 77 78 virtual VMArea* FirstArea() const = 0; 79 virtual VMArea* NextArea(VMArea* area) const = 0; 80 81 virtual VMArea* LookupArea(addr_t address) const = 0; 82 virtual VMArea* FindClosestArea(addr_t address, bool less) const 83 = 0; 84 virtual VMArea* CreateArea(const char* name, uint32 wiring, 85 uint32 protection, 86 uint32 allocationFlags) = 0; 87 virtual void DeleteArea(VMArea* area, 88 uint32 allocationFlags) = 0; 89 virtual status_t InsertArea(VMArea* area, size_t size, 90 const virtual_address_restrictions* 91 addressRestrictions, 92 uint32 allocationFlags, void** _address) 93 = 0; 94 virtual void RemoveArea(VMArea* area, 95 uint32 allocationFlags) = 0; 96 97 virtual bool CanResizeArea(VMArea* area, size_t newSize) = 0; 98 virtual status_t ResizeArea(VMArea* area, size_t newSize, 99 uint32 allocationFlags) = 0; 100 virtual status_t ShrinkAreaHead(VMArea* area, size_t newSize, 101 uint32 allocationFlags) = 0; 102 virtual status_t ShrinkAreaTail(VMArea* area, size_t newSize, 103 uint32 allocationFlags) = 0; 104 105 virtual status_t ReserveAddressRange(size_t size, 106 const virtual_address_restrictions* 107 addressRestrictions, 108 uint32 flags, uint32 allocationFlags, 109 void** _address) = 0; 110 virtual status_t UnreserveAddressRange(addr_t address, 111 size_t size, uint32 allocationFlags) = 0; 112 virtual void UnreserveAllAddressRanges( 113 uint32 allocationFlags) = 0; 114 115 virtual void Dump() const; 116 117 static status_t Create(team_id teamID, addr_t base, size_t size, 118 bool kernel, 119 VMAddressSpace** _addressSpace); 120 121 static team_id KernelID() 122 { return sKernelAddressSpace->ID(); } 123 static VMAddressSpace* Kernel() 124 { return sKernelAddressSpace; } 125 static VMAddressSpace* GetKernel(); 126 127 static team_id CurrentID(); 128 static VMAddressSpace* GetCurrent(); 129 130 static VMAddressSpace* Get(team_id teamID); 131 132 static VMAddressSpace* DebugFirst(); 133 static VMAddressSpace* DebugNext(VMAddressSpace* addressSpace); 134 static VMAddressSpace* DebugGet(team_id teamID); 135 136 protected: 137 static void _DeleteIfUnreferenced(team_id id); 138 139 static int _DumpCommand(int argc, char** argv); 140 static int _DumpListCommand(int argc, char** argv); 141 142 protected: 143 struct HashDefinition; 144 145 protected: 146 VMAddressSpace* fHashTableLink; 147 addr_t fBase; 148 addr_t fEndAddress; // base + (size - 1) 149 size_t fFreeSpace; 150 rw_lock fLock; 151 team_id fID; 152 int32 fRefCount; 153 int32 fFaultCount; 154 int32 fChangeCount; 155 VMTranslationMap* fTranslationMap; 156 bool fRandomizingEnabled; 157 bool fDeleting; 158 static VMAddressSpace* sKernelAddressSpace; 159 }; 160 161 162 void 163 VMAddressSpace::Put() 164 { 165 team_id id = fID; 166 if (atomic_add(&fRefCount, -1) == 1) 167 _DeleteIfUnreferenced(id); 168 } 169 170 171 class VMAddressSpace::AreaIterator { 172 public: 173 AreaIterator() 174 { 175 } 176 177 AreaIterator(VMAddressSpace* addressSpace) 178 : 179 fAddressSpace(addressSpace), 180 fNext(addressSpace->FirstArea()) 181 { 182 } 183 184 bool HasNext() const 185 { 186 return fNext != NULL; 187 } 188 189 VMArea* Next() 190 { 191 VMArea* result = fNext; 192 if (fNext != NULL) 193 fNext = fAddressSpace->NextArea(fNext); 194 return result; 195 } 196 197 void Rewind() 198 { 199 fNext = fAddressSpace->FirstArea(); 200 } 201 202 private: 203 VMAddressSpace* fAddressSpace; 204 VMArea* fNext; 205 }; 206 207 208 class VMAddressSpace::AreaRangeIterator : public VMAddressSpace::AreaIterator { 209 public: 210 AreaRangeIterator() 211 { 212 } 213 214 AreaRangeIterator(VMAddressSpace* addressSpace, addr_t address, addr_t size) 215 : 216 fAddressSpace(addressSpace), 217 fNext(NULL), 218 fAddress(address), 219 fEndAddress(address + size - 1) 220 { 221 Rewind(); 222 } 223 224 bool HasNext() const 225 { 226 return fNext != NULL; 227 } 228 229 VMArea* Next() 230 { 231 VMArea* result = fNext; 232 if (fNext != NULL) { 233 fNext = fAddressSpace->NextArea(fNext); 234 if (fNext != NULL && fNext->Base() > fEndAddress) 235 fNext = NULL; 236 } 237 238 return result; 239 } 240 241 void Rewind() 242 { 243 fNext = fAddressSpace->FindClosestArea(fAddress, true); 244 if (fNext != NULL && !fNext->ContainsAddress(fAddress)) 245 Next(); 246 } 247 248 private: 249 VMAddressSpace* fAddressSpace; 250 VMArea* fNext; 251 addr_t fAddress; 252 addr_t fEndAddress; 253 }; 254 255 256 inline VMAddressSpace::AreaIterator 257 VMAddressSpace::GetAreaIterator() 258 { 259 return AreaIterator(this); 260 } 261 262 263 inline VMAddressSpace::AreaRangeIterator 264 VMAddressSpace::GetAreaRangeIterator(addr_t address, addr_t size) 265 { 266 return AreaRangeIterator(this, address, size); 267 } 268 269 270 #ifdef __cplusplus 271 extern "C" { 272 #endif 273 274 void vm_delete_areas(struct VMAddressSpace *aspace, bool deletingAddressSpace); 275 #define vm_swap_address_space(from, to) arch_vm_aspace_swap(from, to) 276 277 #ifdef __cplusplus 278 } 279 #endif 280 281 282 #endif /* _KERNEL_VM_VM_ADDRESS_SPACE_H */ 283