Adding mmap for code cache and exposing cache properties.

This commit is contained in:
Ben Vanik 2015-06-16 20:13:39 -07:00
parent c34db170f5
commit 5f33087a12
8 changed files with 80 additions and 13 deletions

View File

@ -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" />

View File

@ -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">

View File

@ -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_));
} }

View File

@ -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

View File

@ -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_

View File

@ -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;
} }

View File

@ -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_);

View File

@ -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_;