Fixing MMIO build on Windows.
This commit is contained in:
parent
12f734d7a0
commit
4ad7662ef7
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
#include <poly/debugging.h>
|
#include <poly/debugging.h>
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
namespace poly {
|
namespace poly {
|
||||||
namespace debugging {
|
namespace debugging {
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue