Fixing MMIO build on Windows.

This commit is contained in:
Ben Vanik 2014-08-01 20:29:57 -07:00
parent 12f734d7a0
commit 4ad7662ef7
6 changed files with 29 additions and 31 deletions

View File

@ -9,6 +9,8 @@
#include <poly/debugging.h> #include <poly/debugging.h>
#include <Windows.h>
namespace poly { namespace poly {
namespace debugging { namespace debugging {

View File

@ -21,9 +21,9 @@ namespace cpu {
MMIOHandler* MMIOHandler::global_handler_ = nullptr; MMIOHandler* MMIOHandler::global_handler_ = nullptr;
// Implemented in the platform cc file. // Implemented in the platform cc file.
std::unique_ptr<MMIOHandler> CreateMMIOHandler(); std::unique_ptr<MMIOHandler> CreateMMIOHandler(uint8_t* mapping_base);
std::unique_ptr<MMIOHandler> MMIOHandler::Install() { std::unique_ptr<MMIOHandler> MMIOHandler::Install(uint8_t* mapping_base) {
// There can be only one handler at a time. // There can be only one handler at a time.
assert_null(global_handler_); assert_null(global_handler_);
if (global_handler_) { if (global_handler_) {
@ -31,7 +31,7 @@ std::unique_ptr<MMIOHandler> MMIOHandler::Install() {
} }
// Create the platform-specific handler. // Create the platform-specific handler.
auto handler = CreateMMIOHandler(); auto handler = CreateMMIOHandler(mapping_base);
// Platform-specific initialization for the handler. // Platform-specific initialization for the handler.
if (!handler->Initialize()) { if (!handler->Initialize()) {
@ -45,19 +45,17 @@ std::unique_ptr<MMIOHandler> MMIOHandler::Install() {
MMIOHandler::~MMIOHandler() { MMIOHandler::~MMIOHandler() {
assert_true(global_handler_ == this); assert_true(global_handler_ == this);
global_handler_ = nullptr; global_handler_ = nullptr;
// Platform-specific handler uninstall.
Uninstall();
} }
bool MMIOHandler::RegisterRange(uint64_t address, uint64_t mask, uint64_t size, bool MMIOHandler::RegisterRange(uint64_t address, uint64_t mask, uint64_t size,
void* context, MMIOReadCallback read_callback, void* context, MMIOReadCallback read_callback,
MMIOWriteCallback write_callback) { MMIOWriteCallback write_callback) {
mapped_ranges_.emplace_back({ mapped_ranges_.push_back({
reinterpret_cast<uint64_t>(mapping_base_) | address, reinterpret_cast<uint64_t>(mapping_base_) | address,
0xFFFFFFFF00000000ull | mask, size, context, read_callback, 0xFFFFFFFF00000000ull | mask, size, context, read_callback,
write_callback, write_callback,
}); });
return true;
} }
bool MMIOHandler::CheckLoad(uint64_t address, uint64_t* out_value) { bool MMIOHandler::CheckLoad(uint64_t address, uint64_t* out_value) {
@ -153,7 +151,7 @@ bool MMIOHandler::HandleAccessFault(void* thread_state,
if (!poly::bit_scan_forward(arg2_type & 0xFFFF, &be_reg_index)) { if (!poly::bit_scan_forward(arg2_type & 0xFFFF, &be_reg_index)) {
be_reg_index = 0; be_reg_index = 0;
} }
uint64_t* reg_ptr = GetThreadStateRegPtr(thread_state, arg2_type); uint64_t* reg_ptr = GetThreadStateRegPtr(thread_state, be_reg_index);
value = *reg_ptr; value = *reg_ptr;
} else if ((arg2_type & BE::CONSTANT_TYPE) == BE::CONSTANT_TYPE) { } else if ((arg2_type & BE::CONSTANT_TYPE) == BE::CONSTANT_TYPE) {
value = disasm.Instruction.Immediat; value = disasm.Instruction.Immediat;

View File

@ -24,7 +24,7 @@ class MMIOHandler {
public: public:
virtual ~MMIOHandler(); virtual ~MMIOHandler();
static std::unique_ptr<MMIOHandler> Install(); static std::unique_ptr<MMIOHandler> Install(uint8_t* mapping_base);
static MMIOHandler* global_handler() { return global_handler_; } static MMIOHandler* global_handler() { return global_handler_; }
bool RegisterRange(uint64_t address, uint64_t mask, uint64_t size, bool RegisterRange(uint64_t address, uint64_t mask, uint64_t size,
@ -38,16 +38,17 @@ class MMIOHandler {
bool HandleAccessFault(void* thread_state, uint64_t fault_address); bool HandleAccessFault(void* thread_state, uint64_t fault_address);
protected: protected:
MMIOHandler() = default; MMIOHandler(uint8_t* mapping_base) : mapping_base_(mapping_base) {}
virtual bool Initialize() = 0; virtual bool Initialize() = 0;
virtual void Uninstall() = 0;
virtual uint64_t GetThreadStateRip(void* thread_state_ptr) = 0; virtual uint64_t GetThreadStateRip(void* thread_state_ptr) = 0;
virtual void SetThreadStateRip(void* thread_state_ptr, uint64_t rip) = 0; virtual void SetThreadStateRip(void* thread_state_ptr, uint64_t rip) = 0;
virtual uint64_t* GetThreadStateRegPtr(void* thread_state_ptr, virtual uint64_t* GetThreadStateRegPtr(void* thread_state_ptr,
int32_t be_reg_index) = 0; int32_t be_reg_index) = 0;
uint8_t* mapping_base_;
struct MMIORange { struct MMIORange {
uint64_t address; uint64_t address;
uint64_t mask; uint64_t mask;

View File

@ -34,11 +34,11 @@ namespace cpu {
class MachMMIOHandler : public MMIOHandler { class MachMMIOHandler : public MMIOHandler {
public: public:
MachMMIOHandler(); MachMMIOHandler(uint8_t* mapping_base);
~MachMMIOHandler() override;
protected: protected:
bool Initialize() override; bool Initialize() override;
void Uninstall() override;
uint64_t GetThreadStateRip(void* thread_state_ptr) override; uint64_t GetThreadStateRip(void* thread_state_ptr) override;
void SetThreadStateRip(void* thread_state_ptr, uint64_t rip) override; void SetThreadStateRip(void* thread_state_ptr, uint64_t rip) override;
@ -54,11 +54,12 @@ class MachMMIOHandler : public MMIOHandler {
mach_port_t listen_port_; mach_port_t listen_port_;
}; };
std::unique_ptr<MMIOHandler> CreateMMIOHandler() { std::unique_ptr<MMIOHandler> CreateMMIOHandler(uint8_t* mapping_base) {
return std::make_unique<MachMMIOHandler>(); return std::make_unique<MachMMIOHandler>(mapping_base);
} }
MachMMIOHandler::MachMMIOHandler() : listen_port_(0) {} MachMMIOHandler::MachMMIOHandler(uint8_t* mapping_base)
: MMIOHandler(mapping_base), listen_port_(0) {}
bool MachMMIOHandler::Initialize() { bool MachMMIOHandler::Initialize() {
// Allocates the port that listens for exceptions. // Allocates the port that listens for exceptions.
@ -93,7 +94,7 @@ bool MachMMIOHandler::Initialize() {
return true; return true;
} }
void MachMMIOHandler::Uninstall() { MachMMIOHandler::~MachMMIOHandler() {
task_set_exception_ports(mach_task_self(), EXC_MASK_BAD_ACCESS, 0, task_set_exception_ports(mach_task_self(), EXC_MASK_BAD_ACCESS, 0,
EXCEPTION_DEFAULT, 0); EXCEPTION_DEFAULT, 0);
mach_port_deallocate(mach_task_self(), listen_port_); mach_port_deallocate(mach_task_self(), listen_port_);

View File

@ -9,6 +9,8 @@
#include <xenia/cpu/mmio_handler.h> #include <xenia/cpu/mmio_handler.h>
#include <Windows.h>
namespace xe { namespace xe {
namespace cpu { namespace cpu {
@ -16,11 +18,11 @@ LONG CALLBACK MMIOExceptionHandler(PEXCEPTION_POINTERS ex_info);
class WinMMIOHandler : public MMIOHandler { class WinMMIOHandler : public MMIOHandler {
public: public:
WinMMIOHandler() = default; WinMMIOHandler(uint8_t* mapping_base) : MMIOHandler(mapping_base) {}
~WinMMIOHandler() override;
protected: protected:
bool Initialize() override; bool Initialize() override;
void Uninstall() override;
uint64_t GetThreadStateRip(void* thread_state_ptr) override; uint64_t GetThreadStateRip(void* thread_state_ptr) override;
void SetThreadStateRip(void* thread_state_ptr, uint64_t rip) override; void SetThreadStateRip(void* thread_state_ptr, uint64_t rip) override;
@ -28,8 +30,8 @@ class WinMMIOHandler : public MMIOHandler {
int32_t be_reg_index) override; int32_t be_reg_index) override;
}; };
std::unique_ptr<MMIOHandler> CreateMMIOHandler() { std::unique_ptr<MMIOHandler> CreateMMIOHandler(uint8_t* mapping_base) {
return std::make_unique<WinMMIOHandler>(); return std::make_unique<WinMMIOHandler>(mapping_base);
} }
bool WinMMIOHandler::Initialize() { bool WinMMIOHandler::Initialize() {
@ -43,7 +45,7 @@ bool WinMMIOHandler::Initialize() {
return true; return true;
} }
void WinMMIOHandler::Uninstall() { WinMMIOHandler::~WinMMIOHandler() {
// Remove exception handlers. // Remove exception handlers.
RemoveVectoredExceptionHandler(MMIOExceptionHandler); RemoveVectoredExceptionHandler(MMIOExceptionHandler);
RemoveVectoredContinueHandler(MMIOExceptionHandler); RemoveVectoredContinueHandler(MMIOExceptionHandler);
@ -58,7 +60,8 @@ LONG CALLBACK MMIOExceptionHandler(PEXCEPTION_POINTERS ex_info) {
auto code = ex_info->ExceptionRecord->ExceptionCode; auto code = ex_info->ExceptionRecord->ExceptionCode;
if (code == STATUS_ACCESS_VIOLATION) { if (code == STATUS_ACCESS_VIOLATION) {
auto fault_address = ex_info->ExceptionRecord->ExceptionInformation[1]; auto fault_address = ex_info->ExceptionRecord->ExceptionInformation[1];
if (HandleAccessFault(ex_info->ContextRecord, fault_address)) { if (MMIOHandler::global_handler()->HandleAccessFault(ex_info->ContextRecord,
fault_address)) {
// Handled successfully - RIP has been updated and we can continue. // Handled successfully - RIP has been updated and we can continue.
return EXCEPTION_CONTINUE_EXECUTION; return EXCEPTION_CONTINUE_EXECUTION;
} else { } else {

View File

@ -130,13 +130,6 @@ XenonMemory::~XenonMemory() {
// requests. // requests.
mmio_handler_.reset(); mmio_handler_.reset();
// Unallocate mapped ranges.
for (int i = 0; i < g_mapped_range_count_; ++i) {
const auto& range = g_mapped_ranges_[i];
VirtualFree(reinterpret_cast<LPVOID>(range.address), range.size,
MEM_DECOMMIT);
}
if (mapping_base_) { if (mapping_base_) {
// GPU writeback. // GPU writeback.
VirtualFree( VirtualFree(
@ -208,7 +201,7 @@ int XenonMemory::Initialize() {
MEM_COMMIT, PAGE_READWRITE); MEM_COMMIT, PAGE_READWRITE);
// Add handlers for MMIO. // Add handlers for MMIO.
mmio_handler_ = MMIOHandler::Install(); mmio_handler_ = MMIOHandler::Install(mapping_base_);
if (!mmio_handler_) { if (!mmio_handler_) {
XELOGE("Unable to install MMIO handlers"); XELOGE("Unable to install MMIO handlers");
assert_always(); assert_always();