mirror of
https://github.com/xenia-project/xenia.git
synced 2024-12-04 01:22:38 +00:00
Fixing MMIO build on Windows.
This commit is contained in:
parent
12f734d7a0
commit
4ad7662ef7
@ -9,6 +9,8 @@
|
||||
|
||||
#include <poly/debugging.h>
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
namespace poly {
|
||||
namespace debugging {
|
||||
|
||||
|
@ -21,9 +21,9 @@ namespace cpu {
|
||||
MMIOHandler* MMIOHandler::global_handler_ = nullptr;
|
||||
|
||||
// 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.
|
||||
assert_null(global_handler_);
|
||||
if (global_handler_) {
|
||||
@ -31,7 +31,7 @@ std::unique_ptr<MMIOHandler> MMIOHandler::Install() {
|
||||
}
|
||||
|
||||
// Create the platform-specific handler.
|
||||
auto handler = CreateMMIOHandler();
|
||||
auto handler = CreateMMIOHandler(mapping_base);
|
||||
|
||||
// Platform-specific initialization for the handler.
|
||||
if (!handler->Initialize()) {
|
||||
@ -45,19 +45,17 @@ std::unique_ptr<MMIOHandler> MMIOHandler::Install() {
|
||||
MMIOHandler::~MMIOHandler() {
|
||||
assert_true(global_handler_ == this);
|
||||
global_handler_ = nullptr;
|
||||
|
||||
// Platform-specific handler uninstall.
|
||||
Uninstall();
|
||||
}
|
||||
|
||||
bool MMIOHandler::RegisterRange(uint64_t address, uint64_t mask, uint64_t size,
|
||||
void* context, MMIOReadCallback read_callback,
|
||||
MMIOWriteCallback write_callback) {
|
||||
mapped_ranges_.emplace_back({
|
||||
mapped_ranges_.push_back({
|
||||
reinterpret_cast<uint64_t>(mapping_base_) | address,
|
||||
0xFFFFFFFF00000000ull | mask, size, context, read_callback,
|
||||
write_callback,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
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)) {
|
||||
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;
|
||||
} else if ((arg2_type & BE::CONSTANT_TYPE) == BE::CONSTANT_TYPE) {
|
||||
value = disasm.Instruction.Immediat;
|
||||
|
@ -24,7 +24,7 @@ class MMIOHandler {
|
||||
public:
|
||||
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_; }
|
||||
|
||||
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);
|
||||
|
||||
protected:
|
||||
MMIOHandler() = default;
|
||||
MMIOHandler(uint8_t* mapping_base) : mapping_base_(mapping_base) {}
|
||||
|
||||
virtual bool Initialize() = 0;
|
||||
virtual void Uninstall() = 0;
|
||||
|
||||
virtual uint64_t GetThreadStateRip(void* thread_state_ptr) = 0;
|
||||
virtual void SetThreadStateRip(void* thread_state_ptr, uint64_t rip) = 0;
|
||||
virtual uint64_t* GetThreadStateRegPtr(void* thread_state_ptr,
|
||||
int32_t be_reg_index) = 0;
|
||||
|
||||
uint8_t* mapping_base_;
|
||||
|
||||
struct MMIORange {
|
||||
uint64_t address;
|
||||
uint64_t mask;
|
||||
|
@ -34,11 +34,11 @@ namespace cpu {
|
||||
|
||||
class MachMMIOHandler : public MMIOHandler {
|
||||
public:
|
||||
MachMMIOHandler();
|
||||
MachMMIOHandler(uint8_t* mapping_base);
|
||||
~MachMMIOHandler() override;
|
||||
|
||||
protected:
|
||||
bool Initialize() override;
|
||||
void Uninstall() override;
|
||||
|
||||
uint64_t GetThreadStateRip(void* thread_state_ptr) override;
|
||||
void SetThreadStateRip(void* thread_state_ptr, uint64_t rip) override;
|
||||
@ -54,11 +54,12 @@ class MachMMIOHandler : public MMIOHandler {
|
||||
mach_port_t listen_port_;
|
||||
};
|
||||
|
||||
std::unique_ptr<MMIOHandler> CreateMMIOHandler() {
|
||||
return std::make_unique<MachMMIOHandler>();
|
||||
std::unique_ptr<MMIOHandler> CreateMMIOHandler(uint8_t* mapping_base) {
|
||||
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() {
|
||||
// Allocates the port that listens for exceptions.
|
||||
@ -93,7 +94,7 @@ bool MachMMIOHandler::Initialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void MachMMIOHandler::Uninstall() {
|
||||
MachMMIOHandler::~MachMMIOHandler() {
|
||||
task_set_exception_ports(mach_task_self(), EXC_MASK_BAD_ACCESS, 0,
|
||||
EXCEPTION_DEFAULT, 0);
|
||||
mach_port_deallocate(mach_task_self(), listen_port_);
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
#include <xenia/cpu/mmio_handler.h>
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
|
||||
@ -16,11 +18,11 @@ LONG CALLBACK MMIOExceptionHandler(PEXCEPTION_POINTERS ex_info);
|
||||
|
||||
class WinMMIOHandler : public MMIOHandler {
|
||||
public:
|
||||
WinMMIOHandler() = default;
|
||||
WinMMIOHandler(uint8_t* mapping_base) : MMIOHandler(mapping_base) {}
|
||||
~WinMMIOHandler() override;
|
||||
|
||||
protected:
|
||||
bool Initialize() override;
|
||||
void Uninstall() override;
|
||||
|
||||
uint64_t GetThreadStateRip(void* thread_state_ptr) 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;
|
||||
};
|
||||
|
||||
std::unique_ptr<MMIOHandler> CreateMMIOHandler() {
|
||||
return std::make_unique<WinMMIOHandler>();
|
||||
std::unique_ptr<MMIOHandler> CreateMMIOHandler(uint8_t* mapping_base) {
|
||||
return std::make_unique<WinMMIOHandler>(mapping_base);
|
||||
}
|
||||
|
||||
bool WinMMIOHandler::Initialize() {
|
||||
@ -43,7 +45,7 @@ bool WinMMIOHandler::Initialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void WinMMIOHandler::Uninstall() {
|
||||
WinMMIOHandler::~WinMMIOHandler() {
|
||||
// Remove exception handlers.
|
||||
RemoveVectoredExceptionHandler(MMIOExceptionHandler);
|
||||
RemoveVectoredContinueHandler(MMIOExceptionHandler);
|
||||
@ -58,7 +60,8 @@ LONG CALLBACK MMIOExceptionHandler(PEXCEPTION_POINTERS ex_info) {
|
||||
auto code = ex_info->ExceptionRecord->ExceptionCode;
|
||||
if (code == STATUS_ACCESS_VIOLATION) {
|
||||
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.
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
} else {
|
||||
|
@ -130,13 +130,6 @@ XenonMemory::~XenonMemory() {
|
||||
// requests.
|
||||
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_) {
|
||||
// GPU writeback.
|
||||
VirtualFree(
|
||||
@ -208,7 +201,7 @@ int XenonMemory::Initialize() {
|
||||
MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
// Add handlers for MMIO.
|
||||
mmio_handler_ = MMIOHandler::Install();
|
||||
mmio_handler_ = MMIOHandler::Install(mapping_base_);
|
||||
if (!mmio_handler_) {
|
||||
XELOGE("Unable to install MMIO handlers");
|
||||
assert_always();
|
||||
|
Loading…
Reference in New Issue
Block a user