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
IDVMAddressSpace35 team_id ID() const { return fID; }
BaseVMAddressSpace36 addr_t Base() const { return fBase; }
EndAddressVMAddressSpace37 addr_t EndAddress() const { return fEndAddress; }
SizeVMAddressSpace38 size_t Size() const { return fEndAddress - fBase + 1; }
FreeSpaceVMAddressSpace39 size_t FreeSpace() const { return fFreeSpace; }
IsBeingDeletedVMAddressSpace40 bool IsBeingDeleted() const { return fDeleting; }
41
TranslationMapVMAddressSpace42 VMTranslationMap* TranslationMap() { return fTranslationMap; }
43
ReadLockVMAddressSpace44 status_t ReadLock()
45 { return rw_lock_read_lock(&fLock); }
ReadUnlockVMAddressSpace46 void ReadUnlock()
47 { rw_lock_read_unlock(&fLock); }
WriteLockVMAddressSpace48 status_t WriteLock()
49 { return rw_lock_write_lock(&fLock); }
WriteUnlockVMAddressSpace50 void WriteUnlock()
51 { rw_lock_write_unlock(&fLock); }
52
RefCountVMAddressSpace53 int32 RefCount() const
54 { return fRefCount; }
55
GetVMAddressSpace56 inline void Get() { atomic_add(&fRefCount, 1); }
57 inline void Put();
58 void RemoveAndPut();
59
IncrementFaultCountVMAddressSpace60 void IncrementFaultCount()
61 { atomic_add(&fFaultCount, 1); }
IncrementChangeCountVMAddressSpace62 void IncrementChangeCount()
63 { fChangeCount++; }
64
IsRandomizingEnabledVMAddressSpace65 inline bool IsRandomizingEnabled() const
66 { return fRandomizingEnabled; }
SetRandomizingEnabledVMAddressSpace67 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
HashTableLinkVMAddressSpace74 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
KernelIDVMAddressSpace121 static team_id KernelID()
122 { return sKernelAddressSpace->ID(); }
KernelVMAddressSpace123 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
Put()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:
AreaIterator()173 AreaIterator()
174 {
175 }
176
AreaIterator(VMAddressSpace * addressSpace)177 AreaIterator(VMAddressSpace* addressSpace)
178 :
179 fAddressSpace(addressSpace),
180 fNext(addressSpace->FirstArea())
181 {
182 }
183
HasNext()184 bool HasNext() const
185 {
186 return fNext != NULL;
187 }
188
Next()189 VMArea* Next()
190 {
191 VMArea* result = fNext;
192 if (fNext != NULL)
193 fNext = fAddressSpace->NextArea(fNext);
194 return result;
195 }
196
Rewind()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:
AreaRangeIterator()210 AreaRangeIterator()
211 {
212 }
213
AreaRangeIterator(VMAddressSpace * addressSpace,addr_t address,addr_t size)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
HasNext()224 bool HasNext() const
225 {
226 return fNext != NULL;
227 }
228
Next()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
Rewind()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
GetAreaIterator()257 VMAddressSpace::GetAreaIterator()
258 {
259 return AreaIterator(this);
260 }
261
262
263 inline VMAddressSpace::AreaRangeIterator
GetAreaRangeIterator(addr_t address,addr_t size)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