forked from SirMangler/pcsx2
-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
HostSys.h
201 lines (160 loc) · 5.54 KB
/
HostSys.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
// SPDX-License-Identifier: GPL-3.0+
#pragma once
#include "common/Pcsx2Defs.h"
#include <atomic>
#include <map>
#include <memory>
#include <string>
class Error;
// --------------------------------------------------------------------------------------
// PageProtectionMode
// --------------------------------------------------------------------------------------
class PageProtectionMode
{
protected:
bool m_read = false;
bool m_write = false;
bool m_exec = false;
public:
__fi constexpr PageProtectionMode() = default;
__fi constexpr PageProtectionMode& Read(bool allow = true)
{
m_read = allow;
return *this;
}
__fi constexpr PageProtectionMode& Write(bool allow = true)
{
m_write = allow;
return *this;
}
__fi constexpr PageProtectionMode& Execute(bool allow = true)
{
m_exec = allow;
return *this;
}
__fi constexpr PageProtectionMode& All(bool allow = true)
{
m_read = m_write = m_exec = allow;
return *this;
}
__fi constexpr bool CanRead() const { return m_read; }
__fi constexpr bool CanWrite() const { return m_write; }
__fi constexpr bool CanExecute() const { return m_exec && m_read; }
__fi constexpr bool IsNone() const { return !m_read && !m_write; }
};
static __fi PageProtectionMode PageAccess_None()
{
return PageProtectionMode();
}
static __fi PageProtectionMode PageAccess_ReadOnly()
{
return PageProtectionMode().Read();
}
static __fi PageProtectionMode PageAccess_WriteOnly()
{
return PageProtectionMode().Write();
}
static __fi PageProtectionMode PageAccess_ReadWrite()
{
return PageAccess_ReadOnly().Write();
}
static __fi PageProtectionMode PageAccess_ExecOnly()
{
return PageAccess_ReadOnly().Execute();
}
static __fi PageProtectionMode PageAccess_Any()
{
return PageProtectionMode().All();
}
// --------------------------------------------------------------------------------------
// HostSys
// --------------------------------------------------------------------------------------
namespace HostSys
{
// Maps a block of memory for use as a recompiled code buffer.
// Returns NULL on allocation failure.
extern void* Mmap(void* base, size_t size, const PageProtectionMode& mode);
// Unmaps a block allocated by SysMmap
extern void Munmap(void* base, size_t size);
extern void MemProtect(void* baseaddr, size_t size, const PageProtectionMode& mode);
extern std::string GetFileMappingName(const char* prefix);
extern void* CreateSharedMemory(const char* name, size_t size);
extern void DestroySharedMemory(void* ptr);
extern void* MapSharedMemory(void* handle, size_t offset, void* baseaddr, size_t size, const PageProtectionMode& mode);
extern void UnmapSharedMemory(void* baseaddr, size_t size);
/// JIT write protect for Apple Silicon. Needs to be called prior to writing to any RWX pages.
#if !defined(__APPLE__) || !defined(_M_ARM64)
// clang-format -off
[[maybe_unused]] __fi static void BeginCodeWrite() {}
[[maybe_unused]] __fi static void EndCodeWrite() {}
// clang-format on
#else
void BeginCodeWrite();
void EndCodeWrite();
#endif
/// Flushes the instruction cache on the host for the specified range.
/// Only needed on ARM64, X86 has coherent D/I cache.
#ifdef _M_X86
[[maybe_unused]] __fi static void FlushInstructionCache(void* address, u32 size) {}
#else
void FlushInstructionCache(void* address, u32 size);
#endif
/// Returns the size of pages for the current host.
size_t GetRuntimePageSize();
/// Returns the size of a cache line for the current host.
size_t GetRuntimeCacheLineSize();
} // namespace HostSys
namespace PageFaultHandler
{
enum class HandlerResult
{
ContinueExecution,
ExecuteNextHandler,
};
HandlerResult HandlePageFault(void* exception_pc, void* fault_address, bool is_write);
bool Install(Error* error = nullptr);
} // namespace PageFaultHandler
class SharedMemoryMappingArea
{
public:
static std::unique_ptr<SharedMemoryMappingArea> Create(size_t size);
~SharedMemoryMappingArea();
__fi size_t GetSize() const { return m_size; }
__fi size_t GetNumPages() const { return m_num_pages; }
__fi u8* BasePointer() const { return m_base_ptr; }
__fi u8* OffsetPointer(size_t offset) const { return m_base_ptr + offset; }
__fi u8* PagePointer(size_t page) const { return m_base_ptr + __pagesize * page; }
u8* Map(void* file_handle, size_t file_offset, void* map_base, size_t map_size, const PageProtectionMode& mode);
bool Unmap(void* map_base, size_t map_size);
private:
SharedMemoryMappingArea(u8* base_ptr, size_t size, size_t num_pages);
u8* m_base_ptr;
size_t m_size;
size_t m_num_pages;
size_t m_num_mappings = 0;
#ifdef _WIN32
using PlaceholderMap = std::map<size_t, size_t>;
PlaceholderMap::iterator FindPlaceholder(size_t page);
PlaceholderMap m_placeholder_ranges;
#endif
};
extern u64 GetTickFrequency();
extern u64 GetCPUTicks();
extern u64 GetPhysicalMemory();
/// Spin for a short period of time (call while spinning waiting for a lock)
/// Returns the approximate number of ns that passed
extern u32 ShortSpin();
/// Number of ns to spin for before sleeping a thread
extern const u32 SPIN_TIME_NS;
/// Like C abort() but adds the given message to the crashlog
[[noreturn]] void AbortWithMessage(const char* msg);
extern std::string GetOSVersionString();
namespace Common
{
/// Enables or disables the screen saver from starting.
bool InhibitScreensaver(bool inhibit);
/// Abstracts platform-specific code for asynchronously playing a sound.
/// On Windows, this will use PlaySound(). On Linux, it will shell out to aplay. On MacOS, it uses NSSound.
bool PlaySoundAsync(const char* path);
} // namespace Common