vm: implement vm::try_access, vm::ptr::try_read/write

This commit is contained in:
Nekotekina 2019-11-26 00:01:05 +03:00
parent 1b9a3e6077
commit 2290c389d6
4 changed files with 56 additions and 4 deletions

View File

@ -15,14 +15,12 @@ error_code sys_gpio_get(u64 device_id, vm::ptr<u64> value)
return CELL_ESRCH;
}
if (!vm::check_addr(value.addr(), value.size(), vm::page_writable))
// Retail consoles dont have LEDs or DIPs switches, hence always sets 0 in paramenter
if (!value.try_write(0))
{
return CELL_EFAULT;
}
// Retail consoles dont have LEDs or DIPs switches, hence always sets 0 in paramenter
*value = 0;
return CELL_OK;
}

View File

@ -1078,6 +1078,47 @@ namespace vm
return _map(addr, area_size, flags);
}
bool try_access(u32 addr, void* ptr, u32 size, bool is_write)
{
vm::reader_lock lock;
if (size == 0)
{
return true;
}
if (vm::check_addr(addr, size, is_write ? page_writable : page_readable))
{
void* src = vm::g_sudo_addr + addr;
void* dst = ptr;
if (is_write)
std::swap(src, dst);
if (size <= 16 && utils::popcnt32(size) == 1 && (addr & (size - 1)) == 0)
{
if (is_write)
{
switch (size)
{
case 1: atomic_storage<u8>::release(*static_cast<u8*>(dst), *static_cast<u8*>(src)); break;
case 2: atomic_storage<u16>::release(*static_cast<u16*>(dst), *static_cast<u16*>(src)); break;
case 4: atomic_storage<u32>::release(*static_cast<u32*>(dst), *static_cast<u32*>(src)); break;
case 8: atomic_storage<u64>::release(*static_cast<u64*>(dst), *static_cast<u64*>(src)); break;
case 16: _mm_store_si128(static_cast<__m128i*>(dst), _mm_loadu_si128(static_cast<__m128i*>(src))); break;
}
return true;
}
}
std::memcpy(dst, src, size);
return true;
}
return false;
}
inline namespace ps3_
{
void init()

View File

@ -216,6 +216,9 @@ namespace vm
g_base_addr[addr] = value;
}
// Read or write virtual memory in a safe manner, returns false on failure
bool try_access(u32 addr, void* ptr, u32 size, bool is_write);
inline namespace ps3_
{
// Convert specified PS3 address to a pointer of specified (possibly converted to BE) type

View File

@ -199,6 +199,16 @@ namespace vm
m_addr = vm::cast(m_addr, HERE) - count * size();
return *this;
}
bool try_read(std::conditional_t<std::is_void_v<T>, char&, std::add_lvalue_reference_t<std::remove_const_t<T>>> out) const
{
return vm::try_access(vm::cast(m_addr, HERE), &out, sizeof(T), false);
}
bool try_write(std::conditional_t<std::is_void_v<T>, const char&, std::add_lvalue_reference_t<const T>> _in) const
{
return vm::try_access(vm::cast(m_addr, HERE), const_cast<T*>(&_in), sizeof(T), true);
}
};
template<typename AT, typename RT, typename... T>