The Pedigree Project 0.1
kernel/core/processor/x64/VirtualAddressSpace.h
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#ifndef KERNEL_PROCESSOR_X64_VIRTUALADDRESSSPACE_H
21#define KERNEL_PROCESSOR_X64_VIRTUALADDRESSSPACE_H
22#include "pedigree/kernel/Atomic.h"
23#include "pedigree/kernel/Spinlock.h"
24#include "pedigree/kernel/compiler.h"
25#include "pedigree/kernel/processor/VirtualAddressSpace.h"
26#include "pedigree/kernel/processor/types.h"
27#include "pedigree/kernel/utilities/Vector.h"
28#include "pedigree/kernel/utilities/utility.h"
29
30#include <config.h>
31
34
43#define USERSPACE_DYNAMIC_LINKER_LOCATION reinterpret_cast<void*>(0x4FA00000)
44
45#define USERSPACE_VIRTUAL_START reinterpret_cast<void*>(0x400000)
46#define USERSPACE_VIRTUAL_HEAP reinterpret_cast<void*>(0x50000000)
47#define USERSPACE_RESERVED_START USERSPACE_DYNAMIC_LINKER_LOCATION
48#define USERSPACE_VIRTUAL_STACK_SIZE 0x100000
49#define USERSPACE_VIRTUAL_MAX_STACK_SIZE 0x100000
50#define USERSPACE_DYNAMIC_START reinterpret_cast<void*>(0x100000000)
51#define USERSPACE_DYNAMIC_END reinterpret_cast<void*>(0x00000FFFFFFFFFFF)
52#define USERSPACE_VIRTUAL_LOWEST_STACK \
53 reinterpret_cast<void*>(USERSPACE_DYNAMIC_END + USERSPACE_VIRTUAL_MAX_STACK_SIZE)
54#define USERSPACE_VIRTUAL_STACK \
55 reinterpret_cast<void*>(0x00007FFFEFFFF000) // right below the Event base
56#define KERNEL_VIRTUAL_EVENT_BASE \
57 reinterpret_cast<void*>(0x00007FFFF0000000) // right above the stacks
58
59#define KERNEL_SPACE_START reinterpret_cast<void*>(0xFFFF800000000000)
60#define KERNEL_VIRTUAL_PAGESTACK_ABV4GB1 reinterpret_cast<void*>(0xFFFF800100000000)
61#define KERNEL_VIRTUAL_PAGESTACK_ABV4GB2 reinterpret_cast<void*>(0xFFFF801000000000)
62#define KERNEL_VIRTUAL_HEAP reinterpret_cast<void*>(0xFFFF900000000000)
63#define KERNEL_VIRTUAL_CACHE reinterpret_cast<void*>(0xFFFFB00000000000)
64#define KERNEL_VIRTUAL_MEMORYREGION_ADDRESS reinterpret_cast<void*>(0xFFFFF00000000000)
65#define KERNEL_VIRTUAL_PAGESTACK_4GB reinterpret_cast<void*>(0xFFFFFFFF7FC00000)
66#define KERNEL_VIRTUAL_ADDRESS reinterpret_cast<void*>(0xFFFFFFFF7FF00000)
67#define KERNEL_VIRTUAL_INFO_BLOCK reinterpret_cast<void*>(0xFFFFFFFF8FFF0000)
68#define KERNEL_VIRTUAL_MODULE_BASE reinterpret_cast<void*>(0xFFFFFFFF90000000)
69#define KERNEL_VIRTUAL_LOWEST_STACK reinterpret_cast<void*>(0xFFFFFFFFE0000000)
70#define KERNEL_VIRTUAL_STACK reinterpret_cast<void*>(0xFFFFFFFFFFFF7000)
71
72#define KERNEL_VIRTUAL_MODULE_SIZE \
73 pointer_diff_const(KERNEL_VIRTUAL_MODULE_BASE, KERNEL_VIRTUAL_LOWEST_STACK)
74#define KERNEL_VIRTUAL_HEAP_SIZE pointer_diff_const(KERNEL_VIRTUAL_HEAP, KERNEL_VIRTUAL_CACHE)
75#define KERNEL_VIRTUAL_CACHE_SIZE \
76 pointer_diff_const(KERNEL_VIRTUAL_CACHE, KERNEL_VIRTUAL_MEMORYREGION_ADDRESS)
77#define KERNEL_VIRTUAL_MEMORYREGION_SIZE \
78 pointer_diff_const(KERNEL_VIRTUAL_MEMORYREGION_ADDRESS, KERNEL_VIRTUAL_PAGESTACK_4GB)
79#define KERNEL_STACK_SIZE 0x8000
80
89 friend class ProcessorBase;
91 friend class Multiprocessor;
97
98 public:
99 //
100 // VirtualAddressSpace Interface
101 //
102 virtual bool isAddressValid(void* virtualAddress);
103 virtual bool isMapped(void* virtualAddress);
104 virtual size_t runtimeMappingPages(uintptr_t base, size_t length);
105
106 virtual bool map(physical_uintptr_t physAddress, void* virtualAddress, size_t flags);
107 bool tryMapUserPage(physical_uintptr_t physical, void* address, size_t flags,
108 size_t* committedTablePages = nullptr) override;
109 bool tryDetachUserPage(void* address, physical_uintptr_t expected) override;
110 virtual bool mapHuge(physical_uintptr_t physAddress, void* virtualAddress, size_t count,
111 size_t flags);
112 virtual bool getMapping(void* virtualAddress, physical_uintptr_t& physAddress, size_t& flags);
113 virtual bool handleCopyOnWriteFault(void* virtualAddress, bool userMode);
114 ResidentCopyStatus copyResidentUserPage(uintptr_t userAddress, void* kernelBuffer, size_t bytes,
115 bool write) override;
116 virtual bool tryWriteUser32(uintptr_t address, uint32_t value);
117 virtual bool tryReadUser32(uintptr_t address, uint32_t& value);
118 virtual bool tryReadUserPointer(uintptr_t address, uintptr_t& value);
119 virtual bool tryCompareExchangeUser32(uintptr_t address, uint32_t& expected, uint32_t desired,
120 bool& exchanged);
121 virtual void setFlags(void* virtualAddress, size_t newFlags);
122 MUST_USE_RESULT bool trySetFlags(void* virtualAddress, size_t newFlags) override;
123 virtual void unmap(void* virtualAddress);
124 virtual bool detachMapping(void* virtualAddress, physical_uintptr_t& physical, size_t& flags,
125 size_t requiredFlags = 0);
126 RemapStatus prepareRemap(const PageRemapRequest& request,
127 UniquePointer<PreparedPageRemap>& plan) override;
128 void setRemapPreparationFailureForTest(ssize_t allocations) override {
129 __atomic_store_n(&m_RemapPreparationFailure, allocations, __ATOMIC_RELEASE);
130 }
131 virtual Stack* allocateStack();
132 virtual Stack* allocateStack(size_t stackSz);
133 virtual void freeStack(Stack* pStack);
134
135 virtual bool memIsInKernelHeap(void* pMem);
136 virtual bool memIsInHeap(void* pMem);
137 virtual void* getEndOfHeap();
138
139 virtual VirtualAddressSpace* clone(bool copyOnWrite = true);
140 virtual void revertToKernelAddressSpace();
141
142 //
143 // Needed for the PhysicalMemoryManager
144 //
155 bool mapPageStructures(physical_uintptr_t physAddress, void* virtualAddress, size_t flags);
156 bool mapPageStructuresAbove4GB(physical_uintptr_t physAddress, void* virtualAddress,
157 size_t flags);
158
160 virtual ~X64VirtualAddressSpace();
161
163 virtual uintptr_t getKernelStart() const {
164 return reinterpret_cast<uintptr_t>(KERNEL_SPACE_START);
165 }
166
168 virtual uintptr_t getUserStart() const {
169 return reinterpret_cast<uintptr_t>(USERSPACE_VIRTUAL_START);
170 }
171
173 virtual uintptr_t getUserReservedStart() const {
174 return reinterpret_cast<uintptr_t>(USERSPACE_RESERVED_START);
175 }
176
178 virtual uintptr_t getDynamicLinkerAddress() const {
179 return reinterpret_cast<uintptr_t>(USERSPACE_DYNAMIC_LINKER_LOCATION);
180 }
181
183 virtual uintptr_t getKernelHeapStart() const {
184 return reinterpret_cast<uintptr_t>(KERNEL_VIRTUAL_HEAP);
185 }
186
188 virtual uintptr_t getKernelHeapEnd() const {
189 return reinterpret_cast<uintptr_t>(KERNEL_VIRTUAL_HEAP) + KERNEL_VIRTUAL_HEAP_SIZE;
190 }
191
193 virtual uintptr_t getDynamicStart() const {
194 return reinterpret_cast<uintptr_t>(USERSPACE_DYNAMIC_START);
195 }
196
198 virtual uintptr_t getDynamicEnd() const {
199 return reinterpret_cast<uintptr_t>(USERSPACE_DYNAMIC_END);
200 }
201
203 virtual uintptr_t getGlobalInfoBlock() const {
204 return reinterpret_cast<uintptr_t>(KERNEL_VIRTUAL_INFO_BLOCK);
205 }
206
208 virtual uintptr_t getKernelCacheStart() const {
209 return reinterpret_cast<uintptr_t>(KERNEL_VIRTUAL_CACHE);
210 }
211
213 virtual uintptr_t getKernelCacheEnd() const {
214 return reinterpret_cast<uintptr_t>(KERNEL_VIRTUAL_CACHE) + KERNEL_VIRTUAL_CACHE_SIZE;
215 }
216
218 virtual uintptr_t getKernelEventBlockStart() const {
219 return reinterpret_cast<uintptr_t>(KERNEL_VIRTUAL_EVENT_BASE);
220 }
221
223 virtual uintptr_t getKernelModulesStart() const {
224 return reinterpret_cast<uintptr_t>(KERNEL_VIRTUAL_MODULE_BASE);
225 }
226
228 virtual uintptr_t getKernelModulesEnd() const {
229 return reinterpret_cast<uintptr_t>(KERNEL_VIRTUAL_MODULE_BASE) + KERNEL_VIRTUAL_MODULE_SIZE;
230 }
231
233 virtual uintptr_t getKernelVirtualPagestack() const {
234 return reinterpret_cast<uintptr_t>(KERNEL_VIRTUAL_PAGESTACK_4GB);
235 }
236
238 virtual uintptr_t getKernelVirtualPagestackAdd1() const {
239 return reinterpret_cast<uintptr_t>(KERNEL_VIRTUAL_PAGESTACK_ABV4GB1);
240 }
241
243 virtual uintptr_t getKernelVirtualPagestackAdd2() const {
244 return reinterpret_cast<uintptr_t>(KERNEL_VIRTUAL_PAGESTACK_ABV4GB2);
245 }
246
247 private:
248 friend class X64PreparedPageRemap;
249 bool tryAccessUserWord(uintptr_t address, size_t width, uintptr_t& value,
250 const uintptr_t* replacement);
259 X64VirtualAddressSpace(void* Heap, physical_uintptr_t PhysicalPML4, void* VirtualStack);
260
267
273 bool getPageTableEntry(void* virtualAddress, uint64_t*& pageTableEntry) const;
282 size_t detachEmptyTables(void* virtualAddress, physical_uintptr_t* detachedTables);
286 bool invalidateMapping(void* virtualAddress, X64MappingMutationScope& mutation);
292 uint64_t toFlags(size_t flags, void* virtualAddress, bool bFinal = false) const PURE;
298 size_t fromFlags(uint64_t Flags, bool bFinal = false) const PURE;
303 bool conditionalTableEntryAllocation(uint64_t* tableEntry, uint64_t flags);
309 bool conditionalTableEntryMapping(uint64_t* tableEntry, uint64_t physAddress, uint64_t flags);
310
315 bool mapUnlocked(physical_uintptr_t physAddress, void* virtualAddress, size_t flags,
316 X64MappingMutationScope& mutation, bool locked = false);
317
321 bool unmapUnlocked(void* virtualAddress, X64MappingMutationScope& mutation,
322 bool requireMapped = true);
323
325 Stack* doAllocateStack(size_t sSize);
326 Stack* allocateTrackedUserStack(size_t size);
327
329 physical_uintptr_t m_PhysicalPML4;
332 ssize_t m_RemapPreparationFailure = -1;
343
346};
347
350#endif
A vector / dynamic array.
Definition Vector.h:33
static VirtualAddressSpace * create()
static EXPORTED_PUBLIC VirtualAddressSpace & getKernelAddressSpace()
MUST_USE_RESULT bool trySetFlags(void *virtualAddress, size_t newFlags) override
X64VirtualAddressSpace & operator=(const X64VirtualAddressSpace &)
bool unmapUnlocked(void *virtualAddress, X64MappingMutationScope &mutation, bool requireMapped=true)
size_t fromFlags(uint64_t Flags, bool bFinal=false) const PURE
virtual bool tryReadUser32(uintptr_t address, uint32_t &value)
virtual bool handleCopyOnWriteFault(void *virtualAddress, bool userMode)
virtual void freeStack(Stack *pStack)
uint64_t toFlags(size_t flags, void *virtualAddress, bool bFinal=false) const PURE
virtual bool mapHuge(physical_uintptr_t physAddress, void *virtualAddress, size_t count, size_t flags)
X64VirtualAddressSpace(const X64VirtualAddressSpace &)
virtual void unmap(void *virtualAddress)
virtual bool isAddressValid(void *virtualAddress)
virtual bool detachMapping(void *virtualAddress, physical_uintptr_t &physical, size_t &flags, size_t requiredFlags=0)
virtual bool memIsInKernelHeap(void *pMem)
virtual bool map(physical_uintptr_t physAddress, void *virtualAddress, size_t flags)
bool invalidateMapping(void *virtualAddress, X64MappingMutationScope &mutation)
bool conditionalTableEntryAllocation(uint64_t *tableEntry, uint64_t flags)
ResidentCopyStatus copyResidentUserPage(uintptr_t userAddress, void *kernelBuffer, size_t bytes, bool write) override
virtual VirtualAddressSpace * clone(bool copyOnWrite=true)
bool conditionalTableEntryMapping(uint64_t *tableEntry, uint64_t physAddress, uint64_t flags)
virtual bool tryCompareExchangeUser32(uintptr_t address, uint32_t &expected, uint32_t desired, bool &exchanged)
size_t detachEmptyTables(void *virtualAddress, physical_uintptr_t *detachedTables)
virtual bool memIsInHeap(void *pMem)
virtual bool tryWriteUser32(uintptr_t address, uint32_t value)
Stack * doAllocateStack(size_t sSize)
RemapStatus prepareRemap(const PageRemapRequest &request, UniquePointer< PreparedPageRemap > &plan) override
virtual bool getMapping(void *virtualAddress, physical_uintptr_t &physAddress, size_t &flags)
bool mapPageStructures(physical_uintptr_t physAddress, void *virtualAddress, size_t flags)
virtual void setFlags(void *virtualAddress, size_t newFlags)
void setRemapPreparationFailureForTest(ssize_t allocations) override
virtual bool isMapped(void *virtualAddress)
bool getPageTableEntry(void *virtualAddress, uint64_t *&pageTableEntry) const
bool mapUnlocked(physical_uintptr_t physAddress, void *virtualAddress, size_t flags, X64MappingMutationScope &mutation, bool locked=false)