mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-22 10:49:05 +02:00
commit
c9a2f87edc
20 files changed
+30
-75
No files matched your search
+5
-7
@@ -51,12 +51,9 @@ public:
|
||||
// Call this before you generate any code.
|
||||
void AllocCodeSpace(int size) {
|
||||
region_size = size;
|
||||
// The protection will be set to RW if PlatformIsWXExclusive.
|
||||
region = (u8*)AllocateExecutableMemory(region_size);
|
||||
T::SetCodePointer(region);
|
||||
// On W^X platforms, we start with writable but not executable pages.
|
||||
if (PlatformIsWXExclusive()) {
|
||||
ProtectMemoryPages(region, region_size, MEM_PROT_READ | MEM_PROT_WRITE);
|
||||
}
|
||||
}
|
||||
|
||||
// Always clear code space with breakpoints, so that if someone accidentally executes
|
||||
@@ -71,7 +68,8 @@ public:
|
||||
ResetCodePtr();
|
||||
}
|
||||
|
||||
// BeginWrite/EndWrite assume that we keep appending. If you don't specify a size and we encounter later executable block, we're screwed.
|
||||
// BeginWrite/EndWrite assume that we keep appending.
|
||||
// If you don't specify a size and we later encounter an executable non-writable block, we're screwed.
|
||||
// These CANNOT be nested. We rely on the memory protection starting at READ|WRITE after start and reset.
|
||||
void BeginWrite(size_t sizeEstimate = 1) {
|
||||
#ifdef _DEBUG
|
||||
@@ -88,9 +86,9 @@ public:
|
||||
|
||||
void EndWrite() {
|
||||
// OK, we're done. Re-protect the memory we touched.
|
||||
if (PlatformIsWXExclusive()) {
|
||||
if (PlatformIsWXExclusive() && writeStart_ != nullptr) {
|
||||
const uint8_t *end = GetCodePtr();
|
||||
ProtectMemoryPages(writeStart_, end, MEM_PROT_READ | MEM_PROT_EXEC);
|
||||
ProtectMemoryPages(writeStart_, end - writeStart_, MEM_PROT_READ | MEM_PROT_EXEC);
|
||||
writeStart_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,21 +67,6 @@ error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ashmem_set_prot_region(int fd, int prot) {
|
||||
return ioctl(fd, ASHMEM_SET_PROT_MASK, prot);
|
||||
}
|
||||
|
||||
static int ashmem_pin_region(int fd, size_t offset, size_t len) {
|
||||
// Even on 64-bit, it seems these arguments are 32-bit and thus need a cast to avoid warnings.
|
||||
struct ashmem_pin pin = { (uint32_t)offset, (uint32_t)len };
|
||||
return ioctl(fd, ASHMEM_PIN, &pin);
|
||||
}
|
||||
|
||||
static int ashmem_unpin_region(int fd, size_t offset, size_t len) {
|
||||
struct ashmem_pin pin = { (uint32_t)offset, (uint32_t)len };
|
||||
return ioctl(fd, ASHMEM_UNPIN, &pin);
|
||||
}
|
||||
|
||||
// Windows mappings need to be on 64K boundaries, due to Alpha legacy.
|
||||
size_t MemArena::roundup(size_t x) {
|
||||
return x;
|
||||
|
||||
+15
-8
@@ -50,7 +50,7 @@ static SYSTEM_INFO sys_info;
|
||||
|
||||
#ifdef _WIN32
|
||||
// Win32 flags are odd...
|
||||
uint32_t ConvertProtFlagsWin32(uint32_t flags) {
|
||||
static uint32_t ConvertProtFlagsWin32(uint32_t flags) {
|
||||
uint32_t protect = 0;
|
||||
switch (flags) {
|
||||
case 0: protect = PAGE_NOACCESS; break;
|
||||
@@ -67,7 +67,7 @@ uint32_t ConvertProtFlagsWin32(uint32_t flags) {
|
||||
|
||||
#else
|
||||
|
||||
uint32_t ConvertProtFlagsUnix(uint32_t flags) {
|
||||
static uint32_t ConvertProtFlagsUnix(uint32_t flags) {
|
||||
uint32_t protect = 0;
|
||||
if (flags & MEM_PROT_READ)
|
||||
protect |= PROT_READ;
|
||||
@@ -117,6 +117,9 @@ static void *SearchForFreeMem(size_t size) {
|
||||
void *AllocateExecutableMemory(size_t size) {
|
||||
#if defined(_WIN32)
|
||||
void *ptr;
|
||||
DWORD prot = PAGE_EXECUTE_READWRITE;
|
||||
if (PlatformIsWXExclusive())
|
||||
prot = PAGE_READWRITE;
|
||||
#if defined(_M_X64)
|
||||
if ((uintptr_t)&hint_location > 0xFFFFFFFFULL) {
|
||||
if (sys_info.dwPageSize == 0)
|
||||
@@ -131,14 +134,16 @@ void *AllocateExecutableMemory(size_t size) {
|
||||
ptr = SearchForFreeMem(aligned_size);
|
||||
}
|
||||
if (ptr) {
|
||||
ptr = VirtualAlloc(ptr, aligned_size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
ptr = VirtualAlloc(ptr, aligned_size, MEM_RESERVE | MEM_COMMIT, prot);
|
||||
} else {
|
||||
ERROR_LOG(COMMON, "Unable to find nearby executable memory for jit");
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
ptr = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
{
|
||||
ptr = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, prot);
|
||||
}
|
||||
#else
|
||||
static char *map_hint = 0;
|
||||
#if defined(_M_X64)
|
||||
@@ -192,7 +197,6 @@ void *AllocateExecutableMemory(size_t size) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -205,7 +209,7 @@ void *AllocateMemoryPages(size_t size, uint32_t memProtFlags) {
|
||||
PanicAlert("Failed to allocate raw memory");
|
||||
#else
|
||||
uint32_t protect = ConvertProtFlagsUnix(memProtFlags);
|
||||
void* ptr = mmap(0, size, protect, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
void *ptr = mmap(0, size, protect, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
if (ptr == MAP_FAILED) {
|
||||
ERROR_LOG(MEMMAP, "Failed to allocate memory pages: errno=%d", errno);
|
||||
return nullptr;
|
||||
@@ -274,11 +278,14 @@ bool PlatformIsWXExclusive() {
|
||||
}
|
||||
|
||||
bool ProtectMemoryPages(const void* ptr, size_t size, uint32_t memProtFlags) {
|
||||
VERBOSE_LOG(JIT, "ProtectMemoryPages: %p (%d) : r%d w%d x%d", ptr, (int)size, (memProtFlags & MEM_PROT_READ) != 0, (memProtFlags & MEM_PROT_WRITE) != 0, (memProtFlags & MEM_PROT_EXEC) != 0);
|
||||
VERBOSE_LOG(JIT, "ProtectMemoryPages: %p (%d) : r%d w%d x%d", ptr, (int)size,
|
||||
(memProtFlags & MEM_PROT_READ) != 0, (memProtFlags & MEM_PROT_WRITE) != 0, (memProtFlags & MEM_PROT_EXEC) != 0);
|
||||
|
||||
if (PlatformIsWXExclusive()) {
|
||||
if ((memProtFlags & (MEM_PROT_WRITE | MEM_PROT_EXEC)) == (MEM_PROT_WRITE | MEM_PROT_EXEC))
|
||||
if ((memProtFlags & (MEM_PROT_WRITE | MEM_PROT_EXEC)) == (MEM_PROT_WRITE | MEM_PROT_EXEC)) {
|
||||
ERROR_LOG(MEMMAP, "Bad memory protection %d!", memProtFlags);
|
||||
PanicAlert("Bad memory protect : W^X is in effect, can't both write and exec");
|
||||
}
|
||||
}
|
||||
// Note - VirtualProtect will affect the full pages containing the requested range.
|
||||
// mprotect does not seem to, at least not on Android unless I made a mistake somewhere, so we manually round.
|
||||
|
||||
@@ -37,9 +37,6 @@ void* AllocateExecutableMemory(size_t size);
|
||||
void* AllocateMemoryPages(size_t size, uint32_t memProtFlags);
|
||||
// Note that on platforms returning PlatformIsWXExclusive, you cannot set a page to be both readable and writable at the same time.
|
||||
bool ProtectMemoryPages(const void* ptr, size_t size, uint32_t memProtFlags);
|
||||
inline void ProtectMemoryPages(const void *start, const void *end, uint32_t memProtFlags) {
|
||||
ProtectMemoryPages((void *)start, (const uint8_t *)end - (const uint8_t *)start, memProtFlags);
|
||||
}
|
||||
void FreeMemoryPages(void* ptr, size_t size);
|
||||
|
||||
// Regular aligned memory. Don't try to apply memory protection willy-nilly to memory allocated this way as in-page alignment is unknown (though could be checked).
|
||||
|
||||
@@ -540,7 +540,7 @@ void CBreakPoints::Update(u32 addr)
|
||||
if (addr != 0)
|
||||
MIPSComp::jit->InvalidateCacheAt(addr - 4, 8);
|
||||
else
|
||||
MIPSComp::jit->InvalidateCache();
|
||||
MIPSComp::jit->ClearCache();
|
||||
|
||||
if (resume)
|
||||
Core_EnableStepping(false);
|
||||
|
||||
@@ -154,11 +154,6 @@ void ArmJit::ClearCache()
|
||||
GenerateFixedCode();
|
||||
}
|
||||
|
||||
void ArmJit::InvalidateCache()
|
||||
{
|
||||
blocks.Clear();
|
||||
}
|
||||
|
||||
void ArmJit::InvalidateCacheAt(u32 em_address, int length)
|
||||
{
|
||||
blocks.InvalidateICache(em_address, length);
|
||||
|
||||
@@ -174,7 +174,6 @@ public:
|
||||
void RestoreSavedEmuHackOps(std::vector<u32> saved) override { blocks.RestoreSavedEmuHackOps(saved); }
|
||||
|
||||
void ClearCache() override;
|
||||
void InvalidateCache() override;
|
||||
void InvalidateCacheAt(u32 em_address, int length = 4) override;
|
||||
|
||||
void EatPrefix() override { js.EatPrefix(); }
|
||||
|
||||
@@ -146,10 +146,6 @@ void Arm64Jit::ClearCache() {
|
||||
GenerateFixedCode(jo);
|
||||
}
|
||||
|
||||
void Arm64Jit::InvalidateCache() {
|
||||
blocks.Clear();
|
||||
}
|
||||
|
||||
void Arm64Jit::InvalidateCacheAt(u32 em_address, int length) {
|
||||
blocks.InvalidateICache(em_address, length);
|
||||
}
|
||||
@@ -194,7 +190,7 @@ void Arm64Jit::Compile(u32 em_address) {
|
||||
ClearCache();
|
||||
}
|
||||
|
||||
BeginWrite();
|
||||
BeginWrite(4);
|
||||
|
||||
int block_num = blocks.AllocateBlock(em_address);
|
||||
JitBlock *b = blocks.GetBlock(block_num);
|
||||
@@ -203,6 +199,9 @@ void Arm64Jit::Compile(u32 em_address) {
|
||||
|
||||
EndWrite();
|
||||
|
||||
// Don't forget to zap the newly written instructions in the instruction cache!
|
||||
FlushIcache();
|
||||
|
||||
bool cleanSlate = false;
|
||||
|
||||
if (js.hasSetRounding && !js.lastSetRounding) {
|
||||
@@ -336,9 +335,6 @@ const u8 *Arm64Jit::DoJit(u32 em_address, JitBlock *b) {
|
||||
if (dontLogBlocks > 0)
|
||||
dontLogBlocks--;
|
||||
|
||||
// Don't forget to zap the newly written instructions in the instruction cache!
|
||||
FlushIcache();
|
||||
|
||||
if (js.lastContinuedPC == 0) {
|
||||
b->originalSize = js.numInstructions;
|
||||
} else {
|
||||
@@ -406,7 +402,7 @@ void Arm64Jit::LinkBlock(u8 *exitPoint, const u8 *checkedEntry) {
|
||||
}
|
||||
ARM64XEmitter emit(exitPoint);
|
||||
emit.B(checkedEntry);
|
||||
// TODO: Write stuff after.
|
||||
// TODO: Write stuff after, convering up the now-unused instructions.
|
||||
emit.FlushIcache();
|
||||
if (PlatformIsWXExclusive()) {
|
||||
ProtectMemoryPages(exitPoint, 32, MEM_PROT_READ | MEM_PROT_EXEC);
|
||||
|
||||
@@ -175,7 +175,6 @@ public:
|
||||
void RestoreSavedEmuHackOps(std::vector<u32> saved) override { blocks.RestoreSavedEmuHackOps(saved); }
|
||||
|
||||
void ClearCache() override;
|
||||
void InvalidateCache() override;
|
||||
void InvalidateCacheAt(u32 em_address, int length = 4) override;
|
||||
|
||||
void EatPrefix() override { js.EatPrefix(); }
|
||||
|
||||
@@ -69,10 +69,6 @@ void IRJit::ClearCache() {
|
||||
blocks_.Clear();
|
||||
}
|
||||
|
||||
void IRJit::InvalidateCache() {
|
||||
blocks_.Clear();
|
||||
}
|
||||
|
||||
void IRJit::InvalidateCacheAt(u32 em_address, int length) {
|
||||
blocks_.InvalidateICache(em_address, length);
|
||||
}
|
||||
|
||||
@@ -144,7 +144,6 @@ public:
|
||||
void RestoreSavedEmuHackOps(std::vector<u32> saved) override { blocks_.RestoreSavedEmuHackOps(saved); }
|
||||
|
||||
void ClearCache() override;
|
||||
void InvalidateCache() override;
|
||||
void InvalidateCacheAt(u32 em_address, int length = 4) override;
|
||||
|
||||
const u8 *GetDispatcher() const override { return nullptr; }
|
||||
|
||||
@@ -60,7 +60,7 @@ op_agent_t agent;
|
||||
const u32 INVALID_EXIT = 0xFFFFFFFF;
|
||||
|
||||
JitBlockCache::JitBlockCache(MIPSState *mips, CodeBlockCommon *codeBlock) :
|
||||
codeBlock_(codeBlock), blocks_(0), num_blocks_(0) {
|
||||
codeBlock_(codeBlock), blocks_(nullptr), num_blocks_(0) {
|
||||
}
|
||||
|
||||
JitBlockCache::~JitBlockCache() {
|
||||
|
||||
@@ -123,7 +123,6 @@ namespace MIPSComp {
|
||||
virtual bool DescribeCodePtr(const u8 *ptr, std::string &name) = 0;
|
||||
virtual const u8 *GetDispatcher() const = 0;
|
||||
virtual JitBlockCache *GetBlockCache() = 0;
|
||||
virtual void InvalidateCache() = 0;
|
||||
virtual void InvalidateCacheAt(u32 em_address, int length = 4) = 0;
|
||||
virtual void DoState(PointerWrap &p) = 0;
|
||||
virtual void DoDummyState(PointerWrap &p) = 0;
|
||||
|
||||
@@ -99,11 +99,6 @@ void MipsJit::ClearCache()
|
||||
//GenerateFixedCode();
|
||||
}
|
||||
|
||||
void MipsJit::InvalidateCache()
|
||||
{
|
||||
blocks.Clear();
|
||||
}
|
||||
|
||||
void MipsJit::InvalidateCacheAt(u32 em_address, int length)
|
||||
{
|
||||
blocks.InvalidateICache(em_address, length);
|
||||
|
||||
@@ -135,7 +135,6 @@ public:
|
||||
void RestoreSavedEmuHackOps(std::vector<u32> saved) override { blocks.RestoreSavedEmuHackOps(saved); }
|
||||
|
||||
void ClearCache() override;
|
||||
void InvalidateCache() override;
|
||||
void InvalidateCacheAt(u32 em_address, int length = 4) override;
|
||||
|
||||
void EatPrefix() override { js.EatPrefix(); }
|
||||
|
||||
@@ -94,11 +94,6 @@ void FakeJit::ClearCache()
|
||||
//GenerateFixedCode();
|
||||
}
|
||||
|
||||
void FakeJit::InvalidateCache()
|
||||
{
|
||||
blocks.Clear();
|
||||
}
|
||||
|
||||
void FakeJit::InvalidateCacheAt(u32 em_address, int length)
|
||||
{
|
||||
blocks.InvalidateICache(em_address, length);
|
||||
|
||||
@@ -128,7 +128,6 @@ public:
|
||||
JitBlockCache *GetBlockCache() { return &blocks; }
|
||||
|
||||
void ClearCache();
|
||||
void InvalidateCache();
|
||||
void InvalidateCacheAt(u32 em_address, int length = 4);
|
||||
|
||||
void EatPrefix() { js.EatPrefix(); }
|
||||
|
||||
@@ -245,11 +245,6 @@ void Jit::ClearCache()
|
||||
GenerateFixedCode(jo);
|
||||
}
|
||||
|
||||
void Jit::InvalidateCache()
|
||||
{
|
||||
blocks.Clear();
|
||||
}
|
||||
|
||||
void Jit::CompileDelaySlot(int flags, RegCacheState *state)
|
||||
{
|
||||
// Need to offset the downcount which was already incremented for the branch + delay slot.
|
||||
|
||||
@@ -163,7 +163,6 @@ public:
|
||||
void RestoreSavedEmuHackOps(std::vector<u32> saved) override { blocks.RestoreSavedEmuHackOps(saved); }
|
||||
|
||||
void ClearCache() override;
|
||||
void InvalidateCache() override;
|
||||
void InvalidateCacheAt(u32 em_address, int length = 4) override {
|
||||
if (blocks.RangeMayHaveEmuHacks(em_address, em_address + length)) {
|
||||
blocks.InvalidateICache(em_address, length);
|
||||
|
||||
@@ -363,6 +363,9 @@ void SystemInfoScreen::CreateViews() {
|
||||
deviceSpecs->Add(new InfoItem("D3DX Version", StringFromFormat("%d", GetD3DXVersion())));
|
||||
}
|
||||
#endif
|
||||
deviceSpecs->Add(new ItemHeader("OS Information"));
|
||||
deviceSpecs->Add(new InfoItem("Memory Page Size", StringFromFormat("%d bytes", GetMemoryProtectPageSize())));
|
||||
deviceSpecs->Add(new InfoItem("RW/RX exclusive: ", PlatformIsWXExclusive() ? "Yes" : "No"));
|
||||
|
||||
#ifdef __ANDROID__
|
||||
deviceSpecs->Add(new ItemHeader("Audio Information"));
|
||||
|
||||
Reference in new issue
Block a user