Adding mmap for code cache and exposing cache properties.
This commit is contained in:
parent
c34db170f5
commit
5f33087a12
|
@ -299,6 +299,7 @@
|
||||||
<ClInclude Include="src\xenia\base\vec128.h" />
|
<ClInclude Include="src\xenia\base\vec128.h" />
|
||||||
<ClInclude Include="src\xenia\cpu\backend\assembler.h" />
|
<ClInclude Include="src\xenia\cpu\backend\assembler.h" />
|
||||||
<ClInclude Include="src\xenia\cpu\backend\backend.h" />
|
<ClInclude Include="src\xenia\cpu\backend\backend.h" />
|
||||||
|
<ClInclude Include="src\xenia\cpu\backend\code_cache.h" />
|
||||||
<ClInclude Include="src\xenia\cpu\backend\machine_info.h" />
|
<ClInclude Include="src\xenia\cpu\backend\machine_info.h" />
|
||||||
<ClInclude Include="src\xenia\cpu\backend\x64\x64_assembler.h" />
|
<ClInclude Include="src\xenia\cpu\backend\x64\x64_assembler.h" />
|
||||||
<ClInclude Include="src\xenia\cpu\backend\x64\x64_backend.h" />
|
<ClInclude Include="src\xenia\cpu\backend\x64\x64_backend.h" />
|
||||||
|
|
|
@ -1497,6 +1497,9 @@
|
||||||
<ClInclude Include="src\xenia\cpu\compiler\passes\memory_sequence_combination_pass.h">
|
<ClInclude Include="src\xenia\cpu\compiler\passes\memory_sequence_combination_pass.h">
|
||||||
<Filter>src\xenia\cpu\compiler\passes</Filter>
|
<Filter>src\xenia\cpu\compiler\passes</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\xenia\cpu\backend\code_cache.h">
|
||||||
|
<Filter>src\xenia\cpu\backend</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="src\xenia\cpu\backend\x64\x64_sequence.inl">
|
<None Include="src\xenia\cpu\backend\x64\x64_sequence.inl">
|
||||||
|
|
|
@ -13,7 +13,8 @@ namespace xe {
|
||||||
namespace cpu {
|
namespace cpu {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
|
|
||||||
Backend::Backend(Processor* processor) : processor_(processor) {
|
Backend::Backend(Processor* processor)
|
||||||
|
: processor_(processor), code_cache_(nullptr) {
|
||||||
std::memset(&machine_info_, 0, sizeof(machine_info_));
|
std::memset(&machine_info_, 0, sizeof(machine_info_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace cpu {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
|
|
||||||
class Assembler;
|
class Assembler;
|
||||||
|
class CodeCache;
|
||||||
|
|
||||||
class Backend {
|
class Backend {
|
||||||
public:
|
public:
|
||||||
|
@ -33,6 +34,7 @@ class Backend {
|
||||||
|
|
||||||
Processor* processor() const { return processor_; }
|
Processor* processor() const { return processor_; }
|
||||||
const MachineInfo* machine_info() const { return &machine_info_; }
|
const MachineInfo* machine_info() const { return &machine_info_; }
|
||||||
|
CodeCache* code_cache() const { return code_cache_; }
|
||||||
|
|
||||||
virtual bool Initialize();
|
virtual bool Initialize();
|
||||||
|
|
||||||
|
@ -47,6 +49,7 @@ class Backend {
|
||||||
protected:
|
protected:
|
||||||
Processor* processor_;
|
Processor* processor_;
|
||||||
MachineInfo machine_info_;
|
MachineInfo machine_info_;
|
||||||
|
CodeCache* code_cache_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_BACKEND_CODE_CACHE_H_
|
||||||
|
#define XENIA_BACKEND_CODE_CACHE_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace cpu {
|
||||||
|
namespace backend {
|
||||||
|
|
||||||
|
class CodeCache {
|
||||||
|
public:
|
||||||
|
CodeCache() = default;
|
||||||
|
virtual ~CodeCache() = default;
|
||||||
|
|
||||||
|
virtual std::wstring file_name() const = 0;
|
||||||
|
virtual uint32_t base_address() const = 0;
|
||||||
|
virtual uint32_t total_size() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace backend
|
||||||
|
} // namespace cpu
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
#endif // XENIA_BACKEND_CODE_CACHE_H_
|
|
@ -62,6 +62,7 @@ bool X64Backend::Initialize() {
|
||||||
};
|
};
|
||||||
|
|
||||||
code_cache_ = new X64CodeCache();
|
code_cache_ = new X64CodeCache();
|
||||||
|
Backend::code_cache_ = code_cache_;
|
||||||
if (!code_cache_->Initialize()) {
|
if (!code_cache_->Initialize()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "xenia/cpu/backend/x64/x64_code_cache.h"
|
#include "xenia/cpu/backend/x64/x64_code_cache.h"
|
||||||
|
|
||||||
#include "xenia/base/assert.h"
|
#include "xenia/base/assert.h"
|
||||||
|
#include "xenia/base/clock.h"
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
#include "xenia/base/math.h"
|
#include "xenia/base/math.h"
|
||||||
#include "xenia/base/memory.h"
|
#include "xenia/base/memory.h"
|
||||||
|
@ -24,7 +25,8 @@ namespace x64 {
|
||||||
const static uint32_t kUnwindInfoSize = 4 + (2 * 1 + 2 + 2);
|
const static uint32_t kUnwindInfoSize = 4 + (2 * 1 + 2 + 2);
|
||||||
|
|
||||||
X64CodeCache::X64CodeCache()
|
X64CodeCache::X64CodeCache()
|
||||||
: indirection_default_value_(0xFEEDF00D),
|
: mapping_(nullptr),
|
||||||
|
indirection_default_value_(0xFEEDF00D),
|
||||||
indirection_table_base_(nullptr),
|
indirection_table_base_(nullptr),
|
||||||
generated_code_base_(nullptr),
|
generated_code_base_(nullptr),
|
||||||
generated_code_offset_(0),
|
generated_code_offset_(0),
|
||||||
|
@ -39,8 +41,11 @@ X64CodeCache::~X64CodeCache() {
|
||||||
if (indirection_table_base_) {
|
if (indirection_table_base_) {
|
||||||
VirtualFree(indirection_table_base_, 0, MEM_RELEASE);
|
VirtualFree(indirection_table_base_, 0, MEM_RELEASE);
|
||||||
}
|
}
|
||||||
if (generated_code_base_) {
|
// Unmap all views and close mapping.
|
||||||
VirtualFree(generated_code_base_, 0, MEM_RELEASE);
|
if (mapping_) {
|
||||||
|
UnmapViewOfFile(generated_code_base_);
|
||||||
|
CloseHandle(mapping_);
|
||||||
|
mapping_ = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,9 +62,22 @@ bool X64CodeCache::Initialize() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
generated_code_base_ = reinterpret_cast<uint8_t*>(
|
// Create mmap file. This allows us to share the code cache with the debugger.
|
||||||
VirtualAlloc(reinterpret_cast<void*>(kGeneratedCodeBase),
|
wchar_t file_name[256];
|
||||||
kGeneratedCodeSize, MEM_RESERVE, PAGE_EXECUTE_READWRITE));
|
wsprintf(file_name, L"Local\\xenia_code_cache_%p", Clock::QueryHostTickCount());
|
||||||
|
file_name_ = file_name;
|
||||||
|
mapping_ = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
|
||||||
|
PAGE_EXECUTE_READWRITE | SEC_RESERVE, 0,
|
||||||
|
kGeneratedCodeSize, file_name_.c_str());
|
||||||
|
if (!mapping_) {
|
||||||
|
XELOGE("Unable to create code cache mmap");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mapp generated code region into the file. Pages are committed as required.
|
||||||
|
generated_code_base_ = reinterpret_cast<uint8_t*>(MapViewOfFileEx(
|
||||||
|
mapping_, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0,
|
||||||
|
kGeneratedCodeSize, reinterpret_cast<void*>(kGeneratedCodeBase)));
|
||||||
if (!generated_code_base_) {
|
if (!generated_code_base_) {
|
||||||
XELOGE("Unable to allocate code cache generated code storage");
|
XELOGE("Unable to allocate code cache generated code storage");
|
||||||
XELOGE(
|
XELOGE(
|
||||||
|
@ -103,7 +121,7 @@ void X64CodeCache::CommitExecutableRange(uint32_t guest_low,
|
||||||
uint32_t guest_high) {
|
uint32_t guest_high) {
|
||||||
// Commit the memory.
|
// Commit the memory.
|
||||||
VirtualAlloc(indirection_table_base_ + (guest_low - kIndirectionTableBase),
|
VirtualAlloc(indirection_table_base_ + (guest_low - kIndirectionTableBase),
|
||||||
guest_high - guest_low, MEM_COMMIT, PAGE_READWRITE);
|
guest_high - guest_low, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||||
|
|
||||||
// Fill memory with the default value.
|
// Fill memory with the default value.
|
||||||
uint32_t* p = reinterpret_cast<uint32_t*>(indirection_table_base_);
|
uint32_t* p = reinterpret_cast<uint32_t*>(indirection_table_base_);
|
||||||
|
|
|
@ -10,27 +10,31 @@
|
||||||
#ifndef XENIA_BACKEND_X64_X64_CODE_CACHE_H_
|
#ifndef XENIA_BACKEND_X64_X64_CODE_CACHE_H_
|
||||||
#define XENIA_BACKEND_X64_X64_CODE_CACHE_H_
|
#define XENIA_BACKEND_X64_X64_CODE_CACHE_H_
|
||||||
|
|
||||||
// For RUNTIME_FUNCTION:
|
|
||||||
#include "xenia/base/platform.h"
|
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "xenia/base/mutex.h"
|
#include "xenia/base/mutex.h"
|
||||||
|
#include "xenia/base/platform.h"
|
||||||
|
#include "xenia/cpu/backend/code_cache.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace cpu {
|
namespace cpu {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
|
|
||||||
class X64CodeCache {
|
class X64CodeCache : public CodeCache {
|
||||||
public:
|
public:
|
||||||
X64CodeCache();
|
X64CodeCache();
|
||||||
virtual ~X64CodeCache();
|
~X64CodeCache() override;
|
||||||
|
|
||||||
bool Initialize();
|
bool Initialize();
|
||||||
|
|
||||||
|
std::wstring file_name() const override { return file_name_; }
|
||||||
|
uint32_t base_address() const override { return kGeneratedCodeBase; }
|
||||||
|
uint32_t total_size() const override { return kGeneratedCodeSize; }
|
||||||
|
|
||||||
// TODO(benvanik): ELF serialization/etc
|
// TODO(benvanik): ELF serialization/etc
|
||||||
// TODO(benvanik): keep track of code blocks
|
// TODO(benvanik): keep track of code blocks
|
||||||
// TODO(benvanik): padding/guards/etc
|
// TODO(benvanik): padding/guards/etc
|
||||||
|
@ -55,6 +59,9 @@ class X64CodeCache {
|
||||||
size_t unwind_table_slot, uint8_t* code_address,
|
size_t unwind_table_slot, uint8_t* code_address,
|
||||||
size_t code_size, size_t stack_size);
|
size_t code_size, size_t stack_size);
|
||||||
|
|
||||||
|
std::wstring file_name_;
|
||||||
|
HANDLE mapping_;
|
||||||
|
|
||||||
// Must be held when manipulating the offsets or counts of anything, to keep
|
// Must be held when manipulating the offsets or counts of anything, to keep
|
||||||
// the tables consistent and ordered.
|
// the tables consistent and ordered.
|
||||||
xe::mutex allocation_mutex_;
|
xe::mutex allocation_mutex_;
|
||||||
|
|
Loading…
Reference in New Issue