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
20struct virtual_address_restrictions;
21
22
23struct VMAddressSpace {
24public:
25			class AreaIterator;
26			class AreaRangeIterator;
27
28public:
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
136protected:
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
142protected:
143			struct HashDefinition;
144
145protected:
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
162void
163VMAddressSpace::Put()
164{
165	team_id id = fID;
166	if (atomic_add(&fRefCount, -1) == 1)
167		_DeleteIfUnreferenced(id);
168}
169
170
171class VMAddressSpace::AreaIterator {
172public:
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
202private:
203	VMAddressSpace*	fAddressSpace;
204	VMArea*			fNext;
205};
206
207
208class VMAddressSpace::AreaRangeIterator : public VMAddressSpace::AreaIterator {
209public:
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
248private:
249	VMAddressSpace*	fAddressSpace;
250	VMArea*			fNext;
251	addr_t			fAddress;
252	addr_t			fEndAddress;
253};
254
255
256inline VMAddressSpace::AreaIterator
257VMAddressSpace::GetAreaIterator()
258{
259	return AreaIterator(this);
260}
261
262
263inline VMAddressSpace::AreaRangeIterator
264VMAddressSpace::GetAreaRangeIterator(addr_t address, addr_t size)
265{
266	return AreaRangeIterator(this, address, size);
267}
268
269
270#ifdef __cplusplus
271extern "C" {
272#endif
273
274void 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