[Memory] Add HostToGuestVirtual and use it in a couple of places
This commit is contained in:
@@ -25,6 +25,8 @@ MMIOHandler* MMIOHandler::global_handler_ = nullptr;
|
||||
|
||||
std::unique_ptr<MMIOHandler> MMIOHandler::Install(
|
||||
uint8_t* virtual_membase, uint8_t* physical_membase, uint8_t* membase_end,
|
||||
HostToGuestVirtual host_to_guest_virtual,
|
||||
const void* host_to_guest_virtual_context,
|
||||
AccessViolationCallback access_violation_callback,
|
||||
void* access_violation_callback_context) {
|
||||
// There can be only one handler at a time.
|
||||
@@ -34,7 +36,8 @@ std::unique_ptr<MMIOHandler> MMIOHandler::Install(
|
||||
}
|
||||
|
||||
auto handler = std::unique_ptr<MMIOHandler>(new MMIOHandler(
|
||||
virtual_membase, physical_membase, membase_end, access_violation_callback,
|
||||
virtual_membase, physical_membase, membase_end, host_to_guest_virtual,
|
||||
host_to_guest_virtual_context, access_violation_callback,
|
||||
access_violation_callback_context));
|
||||
|
||||
// Install the exception handler directed at the MMIOHandler.
|
||||
@@ -46,11 +49,15 @@ std::unique_ptr<MMIOHandler> MMIOHandler::Install(
|
||||
|
||||
MMIOHandler::MMIOHandler(uint8_t* virtual_membase, uint8_t* physical_membase,
|
||||
uint8_t* membase_end,
|
||||
HostToGuestVirtual host_to_guest_virtual,
|
||||
const void* host_to_guest_virtual_context,
|
||||
AccessViolationCallback access_violation_callback,
|
||||
void* access_violation_callback_context)
|
||||
: virtual_membase_(virtual_membase),
|
||||
physical_membase_(physical_membase),
|
||||
memory_end_(membase_end),
|
||||
host_to_guest_virtual_(host_to_guest_virtual),
|
||||
host_to_guest_virtual_context_(host_to_guest_virtual_context),
|
||||
access_violation_callback_(access_violation_callback),
|
||||
access_violation_callback_context_(access_violation_callback_context) {}
|
||||
|
||||
@@ -279,14 +286,16 @@ bool MMIOHandler::ExceptionCallback(Exception* ex) {
|
||||
// Quick kill anything outside our mapping.
|
||||
return false;
|
||||
}
|
||||
void* fault_host_address = reinterpret_cast<void*>(ex->fault_address());
|
||||
|
||||
// Access violations are pretty rare, so we can do a linear search here.
|
||||
// Only check if in the virtual range, as we only support virtual ranges.
|
||||
const MMIORange* range = nullptr;
|
||||
if (ex->fault_address() < uint64_t(physical_membase_)) {
|
||||
uint32_t fault_virtual_address = host_to_guest_virtual_(
|
||||
host_to_guest_virtual_context_, fault_host_address);
|
||||
for (const auto& test_range : mapped_ranges_) {
|
||||
if ((static_cast<uint32_t>(ex->fault_address()) & test_range.mask) ==
|
||||
test_range.address) {
|
||||
if ((fault_virtual_address & test_range.mask) == test_range.address) {
|
||||
// Address is within the range of this mapping.
|
||||
range = &test_range;
|
||||
break;
|
||||
@@ -300,8 +309,7 @@ bool MMIOHandler::ExceptionCallback(Exception* ex) {
|
||||
auto lock = global_critical_region_.Acquire();
|
||||
memory::PageAccess cur_access;
|
||||
size_t page_length = memory::page_size();
|
||||
memory::QueryProtect(reinterpret_cast<void*>(ex->fault_address()),
|
||||
page_length, cur_access);
|
||||
memory::QueryProtect(fault_host_address, page_length, cur_access);
|
||||
if (cur_access != memory::PageAccess::kReadOnly &&
|
||||
cur_access != memory::PageAccess::kNoAccess) {
|
||||
// Another thread has cleared this write watch. Abort.
|
||||
@@ -314,10 +322,10 @@ bool MMIOHandler::ExceptionCallback(Exception* ex) {
|
||||
switch (ex->access_violation_operation()) {
|
||||
case Exception::AccessViolationOperation::kRead:
|
||||
return access_violation_callback_(access_violation_callback_context_,
|
||||
size_t(ex->fault_address()), false);
|
||||
fault_host_address, false);
|
||||
case Exception::AccessViolationOperation::kWrite:
|
||||
return access_violation_callback_(access_violation_callback_context_,
|
||||
size_t(ex->fault_address()), true);
|
||||
fault_host_address, true);
|
||||
default:
|
||||
// Data Execution Prevention or something else uninteresting.
|
||||
break;
|
||||
|
||||
@@ -27,8 +27,6 @@ typedef uint32_t (*MMIOReadCallback)(void* ppc_context, void* callback_context,
|
||||
uint32_t addr);
|
||||
typedef void (*MMIOWriteCallback)(void* ppc_context, void* callback_context,
|
||||
uint32_t addr, uint32_t value);
|
||||
typedef void (*AccessWatchCallback)(void* context_ptr, void* data_ptr,
|
||||
uint32_t address);
|
||||
|
||||
struct MMIORange {
|
||||
uint32_t address;
|
||||
@@ -44,7 +42,9 @@ class MMIOHandler {
|
||||
public:
|
||||
virtual ~MMIOHandler();
|
||||
|
||||
typedef bool (*AccessViolationCallback)(void* context, size_t host_address,
|
||||
typedef uint32_t (*HostToGuestVirtual)(const void* context,
|
||||
const void* host_address);
|
||||
typedef bool (*AccessViolationCallback)(void* context, void* host_address,
|
||||
bool is_write);
|
||||
|
||||
// access_violation_callback is called in global_critical_region, so if
|
||||
@@ -52,6 +52,8 @@ class MMIOHandler {
|
||||
// will be called only once.
|
||||
static std::unique_ptr<MMIOHandler> Install(
|
||||
uint8_t* virtual_membase, uint8_t* physical_membase, uint8_t* membase_end,
|
||||
HostToGuestVirtual host_to_guest_virtual,
|
||||
const void* host_to_guest_virtual_context,
|
||||
AccessViolationCallback access_violation_callback,
|
||||
void* access_violation_callback_context);
|
||||
static MMIOHandler* global_handler() { return global_handler_; }
|
||||
@@ -66,7 +68,8 @@ class MMIOHandler {
|
||||
|
||||
protected:
|
||||
MMIOHandler(uint8_t* virtual_membase, uint8_t* physical_membase,
|
||||
uint8_t* membase_end,
|
||||
uint8_t* membase_end, HostToGuestVirtual host_to_guest_virtual,
|
||||
const void* host_to_guest_virtual_context,
|
||||
AccessViolationCallback access_violation_callback,
|
||||
void* access_violation_callback_context);
|
||||
|
||||
@@ -79,6 +82,9 @@ class MMIOHandler {
|
||||
|
||||
std::vector<MMIORange> mapped_ranges_;
|
||||
|
||||
HostToGuestVirtual host_to_guest_virtual_;
|
||||
const void* host_to_guest_virtual_context_;
|
||||
|
||||
AccessViolationCallback access_violation_callback_;
|
||||
void* access_violation_callback_context_;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user