2
1
Fork 0
mirror of https://github.com/yuzu-emu/yuzu.git synced 2024-07-04 23:31:19 +01:00

core/memory: Migrate over address checking functions to the new Memory class

A fairly straightforward migration. These member functions can just be
mostly moved verbatim with minor changes. We already have the necessary
plumbing in places that they're used.

IsKernelVirtualAddress() can remain a non-member function, since it
doesn't rely on class state in any form.
This commit is contained in:
Lioncash 2019-11-26 13:46:41 -05:00
parent 323680e5ad
commit e58748fd80
6 changed files with 70 additions and 39 deletions

View file

@ -969,7 +969,8 @@ static void ReadMemory() {
SendReply("E01"); SendReply("E01");
} }
if (!Memory::IsValidVirtualAddress(addr)) { const auto& memory = Core::System::GetInstance().Memory();
if (!memory.IsValidVirtualAddress(addr)) {
return SendReply("E00"); return SendReply("E00");
} }
@ -984,22 +985,23 @@ static void ReadMemory() {
/// Modify location in memory with data received from the gdb client. /// Modify location in memory with data received from the gdb client.
static void WriteMemory() { static void WriteMemory() {
auto start_offset = command_buffer + 1; auto start_offset = command_buffer + 1;
auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); const auto addr_pos = std::find(start_offset, command_buffer + command_length, ',');
VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset)); const VAddr addr = HexToLong(start_offset, static_cast<u64>(addr_pos - start_offset));
start_offset = addr_pos + 1; start_offset = addr_pos + 1;
auto len_pos = std::find(start_offset, command_buffer + command_length, ':'); const auto len_pos = std::find(start_offset, command_buffer + command_length, ':');
u64 len = HexToLong(start_offset, static_cast<u64>(len_pos - start_offset)); const u64 len = HexToLong(start_offset, static_cast<u64>(len_pos - start_offset));
if (!Memory::IsValidVirtualAddress(addr)) { auto& system = Core::System::GetInstance();
const auto& memory = system.Memory();
if (!memory.IsValidVirtualAddress(addr)) {
return SendReply("E00"); return SendReply("E00");
} }
std::vector<u8> data(len); std::vector<u8> data(len);
GdbHexToMem(data.data(), len_pos + 1, len); GdbHexToMem(data.data(), len_pos + 1, len);
Memory::WriteBlock(addr, data.data(), len); Memory::WriteBlock(addr, data.data(), len);
Core::System::GetInstance().InvalidateCpuInstructionCaches(); system.InvalidateCpuInstructionCaches();
SendReply("OK"); SendReply("OK");
} }

View file

@ -68,7 +68,7 @@ ResultCode AddressArbiter::SignalToAddressOnly(VAddr address, s32 num_to_wake) {
ResultCode AddressArbiter::IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, ResultCode AddressArbiter::IncrementAndSignalToAddressIfEqual(VAddr address, s32 value,
s32 num_to_wake) { s32 num_to_wake) {
// Ensure that we can write to the address. // Ensure that we can write to the address.
if (!Memory::IsValidVirtualAddress(address)) { if (!system.Memory().IsValidVirtualAddress(address)) {
return ERR_INVALID_ADDRESS_STATE; return ERR_INVALID_ADDRESS_STATE;
} }
@ -83,7 +83,7 @@ ResultCode AddressArbiter::IncrementAndSignalToAddressIfEqual(VAddr address, s32
ResultCode AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value, ResultCode AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value,
s32 num_to_wake) { s32 num_to_wake) {
// Ensure that we can write to the address. // Ensure that we can write to the address.
if (!Memory::IsValidVirtualAddress(address)) { if (!system.Memory().IsValidVirtualAddress(address)) {
return ERR_INVALID_ADDRESS_STATE; return ERR_INVALID_ADDRESS_STATE;
} }
@ -135,7 +135,7 @@ ResultCode AddressArbiter::WaitForAddress(VAddr address, ArbitrationType type, s
ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout,
bool should_decrement) { bool should_decrement) {
// Ensure that we can read the address. // Ensure that we can read the address.
if (!Memory::IsValidVirtualAddress(address)) { if (!system.Memory().IsValidVirtualAddress(address)) {
return ERR_INVALID_ADDRESS_STATE; return ERR_INVALID_ADDRESS_STATE;
} }
@ -158,7 +158,7 @@ ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s6
ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) { ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) {
// Ensure that we can read the address. // Ensure that we can read the address.
if (!Memory::IsValidVirtualAddress(address)) { if (!system.Memory().IsValidVirtualAddress(address)) {
return ERR_INVALID_ADDRESS_STATE; return ERR_INVALID_ADDRESS_STATE;
} }
// Only wait for the address if equal. // Only wait for the address if equal.

View file

@ -332,7 +332,7 @@ static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_ad
/// Connect to an OS service given the port name, returns the handle to the port to out /// Connect to an OS service given the port name, returns the handle to the port to out
static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle, static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
VAddr port_name_address) { VAddr port_name_address) {
if (!Memory::IsValidVirtualAddress(port_name_address)) { if (!system.Memory().IsValidVirtualAddress(port_name_address)) {
LOG_ERROR(Kernel_SVC, LOG_ERROR(Kernel_SVC,
"Port Name Address is not a valid virtual address, port_name_address=0x{:016X}", "Port Name Address is not a valid virtual address, port_name_address=0x{:016X}",
port_name_address); port_name_address);
@ -452,7 +452,7 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr
LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, handle_count={}, nano_seconds={}", LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, handle_count={}, nano_seconds={}",
handles_address, handle_count, nano_seconds); handles_address, handle_count, nano_seconds);
if (!Memory::IsValidVirtualAddress(handles_address)) { if (!system.Memory().IsValidVirtualAddress(handles_address)) {
LOG_ERROR(Kernel_SVC, LOG_ERROR(Kernel_SVC,
"Handle address is not a valid virtual address, handle_address=0x{:016X}", "Handle address is not a valid virtual address, handle_address=0x{:016X}",
handles_address); handles_address);

View file

@ -162,13 +162,13 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(KernelCore& kernel, std::strin
return ERR_INVALID_PROCESSOR_ID; return ERR_INVALID_PROCESSOR_ID;
} }
if (!Memory::IsValidVirtualAddress(owner_process, entry_point)) { auto& system = Core::System::GetInstance();
if (!system.Memory().IsValidVirtualAddress(owner_process, entry_point)) {
LOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:016X}", name, entry_point); LOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:016X}", name, entry_point);
// TODO (bunnei): Find the correct error code to use here // TODO (bunnei): Find the correct error code to use here
return RESULT_UNKNOWN; return RESULT_UNKNOWN;
} }
auto& system = Core::System::GetInstance();
std::shared_ptr<Thread> thread = std::make_shared<Thread>(kernel); std::shared_ptr<Thread> thread = std::make_shared<Thread>(kernel);
thread->thread_id = kernel.CreateNewThreadID(); thread->thread_id = kernel.CreateNewThreadID();

View file

@ -75,6 +75,29 @@ struct Memory::Impl {
std::make_pair(interval, std::set<Common::SpecialRegion>{region})); std::make_pair(interval, std::set<Common::SpecialRegion>{region}));
} }
bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) const {
const auto& page_table = process.VMManager().page_table;
const u8* const page_pointer = page_table.pointers[vaddr >> PAGE_BITS];
if (page_pointer != nullptr) {
return true;
}
if (page_table.attributes[vaddr >> PAGE_BITS] == Common::PageType::RasterizerCachedMemory) {
return true;
}
if (page_table.attributes[vaddr >> PAGE_BITS] != Common::PageType::Special) {
return false;
}
return false;
}
bool IsValidVirtualAddress(VAddr vaddr) const {
return IsValidVirtualAddress(*system.CurrentProcess(), vaddr);
}
/** /**
* Maps a region of pages as a specific type. * Maps a region of pages as a specific type.
* *
@ -148,6 +171,14 @@ void Memory::RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size
impl->RemoveDebugHook(page_table, base, size, std::move(hook)); impl->RemoveDebugHook(page_table, base, size, std::move(hook));
} }
bool Memory::IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) const {
return impl->IsValidVirtualAddress(process, vaddr);
}
bool Memory::IsValidVirtualAddress(const VAddr vaddr) const {
return impl->IsValidVirtualAddress(vaddr);
}
void SetCurrentPageTable(Kernel::Process& process) { void SetCurrentPageTable(Kernel::Process& process) {
current_page_table = &process.VMManager().page_table; current_page_table = &process.VMManager().page_table;
@ -256,26 +287,6 @@ void Write(const VAddr vaddr, const T data) {
} }
} }
bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) {
const auto& page_table = process.VMManager().page_table;
const u8* page_pointer = page_table.pointers[vaddr >> PAGE_BITS];
if (page_pointer)
return true;
if (page_table.attributes[vaddr >> PAGE_BITS] == Common::PageType::RasterizerCachedMemory)
return true;
if (page_table.attributes[vaddr >> PAGE_BITS] != Common::PageType::Special)
return false;
return false;
}
bool IsValidVirtualAddress(const VAddr vaddr) {
return IsValidVirtualAddress(*Core::System::GetInstance().CurrentProcess(), vaddr);
}
bool IsKernelVirtualAddress(const VAddr vaddr) { bool IsKernelVirtualAddress(const VAddr vaddr) {
return KERNEL_REGION_VADDR <= vaddr && vaddr < KERNEL_REGION_END; return KERNEL_REGION_VADDR <= vaddr && vaddr < KERNEL_REGION_END;
} }

View file

@ -111,6 +111,27 @@ public:
void RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size, void RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size,
Common::MemoryHookPointer hook); Common::MemoryHookPointer hook);
/**
* Checks whether or not the supplied address is a valid virtual
* address for the given process.
*
* @param process The emulated process to check the address against.
* @param vaddr The virtual address to check the validity of.
*
* @returns True if the given virtual address is valid, false otherwise.
*/
bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr) const;
/**
* Checks whether or not the supplied address is a valid virtual
* address for the current process.
*
* @param vaddr The virtual address to check the validity of.
*
* @returns True if the given virtual address is valid, false otherwise.
*/
bool IsValidVirtualAddress(VAddr vaddr) const;
private: private:
struct Impl; struct Impl;
std::unique_ptr<Impl> impl; std::unique_ptr<Impl> impl;
@ -120,9 +141,6 @@ private:
/// the given process instance. /// the given process instance.
void SetCurrentPageTable(Kernel::Process& process); void SetCurrentPageTable(Kernel::Process& process);
/// Determines if the given VAddr is valid for the specified process.
bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr);
bool IsValidVirtualAddress(VAddr vaddr);
/// Determines if the given VAddr is a kernel address /// Determines if the given VAddr is a kernel address
bool IsKernelVirtualAddress(VAddr vaddr); bool IsKernelVirtualAddress(VAddr vaddr);