vm: memory locking rewritten

Added vm::lock_sudo method (wrapper for utils::memory_lock).
Put locking outside of vm::g_mutex scope.
Prelock sudo memory for RSX, vm::stack, vm::main.
Prelock sudo memory for shared memory objects.
Don't check for TSX path.
This commit is contained in:
Nekotekina 2020-11-15 03:26:43 +03:00
parent eaf0bbc108
commit ea5f5aea5f
6 changed files with 52 additions and 35 deletions

View file

@ -763,18 +763,6 @@ namespace vm
// Unlock
g_range_lock.release(0);
perf_meter<"PAGE_LCK"_u64> perf1;
if (!g_use_rtm)
{
perf1.reset();
}
else if (!utils::memory_lock(g_sudo_addr + addr, size))
{
vm_log.error("Failed to lock memory. Consider increasing your system limits.\n"
"addr=0x%x, size=0x%x, shm=%d, shm:[f=%d,l=%u]", addr, size, +!!shm, shm ? shm->flags() : 0, shm ? shm->info : 0);
}
}
bool page_protect(u32 addr, u32 size, u8 flags_test, u8 flags_set, u8 flags_clear)
@ -1009,7 +997,7 @@ namespace vm
fmt::throw_exception("Invalid memory location (%u)" HERE, +location);
}
return block->alloc(size, align);
return block->alloc(size, nullptr, align);
}
u32 falloc(u32 addr, u32 size, memory_location_t location)
@ -1053,6 +1041,19 @@ namespace vm
}
}
void lock_sudo(u32 addr, u32 size)
{
perf_meter<"PAGE_LCK"_u64> perf;
verify("lock_sudo" HERE), addr % 4096 == 0;
verify("lock_sudo" HERE), size % 4096 == 0;
if (!utils::memory_lock(g_sudo_addr + addr, size))
{
vm_log.error("Failed to lock sudo memory (addr=0x%x, size=0x%x). Consider increasing your system limits.", addr, size);
}
}
bool block_t::try_alloc(u32 addr, u8 flags, u32 size, std::shared_ptr<utils::shm>&& shm)
{
// Check if memory area is already mapped
@ -1108,12 +1109,13 @@ namespace vm
, size(size)
, flags(flags)
{
if (flags & 0x100)
if (flags & 0x100 || flags & 0x20)
{
// Special path for 4k-aligned pages
// Special path for whole-allocated areas allowing 4k granularity
m_common = std::make_shared<utils::shm>(size);
verify(HERE), m_common->map_critical(vm::base(addr), utils::protection::no) == vm::base(addr);
verify(HERE), m_common->map_critical(vm::get_super_ptr(addr)) == vm::get_super_ptr(addr);
m_common->map_critical(vm::base(addr), utils::protection::no);
m_common->map_critical(vm::get_super_ptr(addr));
lock_sudo(addr, size);
}
}
@ -1131,7 +1133,6 @@ namespace vm
it = next;
}
// Special path for 4k-aligned pages
if (m_common)
{
m_common->unmap_critical(vm::base(addr));
@ -1140,7 +1141,7 @@ namespace vm
}
}
u32 block_t::alloc(const u32 orig_size, u32 align, const std::shared_ptr<utils::shm>* src, u64 flags)
u32 block_t::alloc(const u32 orig_size, const std::shared_ptr<utils::shm>* src, u32 align, u64 flags)
{
if (!src)
{
@ -1148,8 +1149,6 @@ namespace vm
flags = this->flags;
}
vm::writer_lock lock(0);
// Determine minimal alignment
const u32 min_page_size = flags & 0x100 ? 0x1000 : 0x10000;
@ -1187,7 +1186,11 @@ namespace vm
else if (src)
shm = *src;
else
{
shm = std::make_shared<utils::shm>(size);
}
vm::writer_lock lock(0);
// Search for an appropriate place (unoptimized)
for (u32 addr = ::align(this->addr, align); u64{addr} + size <= u64{this->addr} + this->size; addr += align)
@ -1209,8 +1212,6 @@ namespace vm
flags = this->flags;
}
vm::writer_lock lock(0);
// Determine minimal alignment
const u32 min_page_size = flags & 0x100 ? 0x1000 : 0x10000;
@ -1242,7 +1243,11 @@ namespace vm
else if (src)
shm = *src;
else
{
shm = std::make_shared<utils::shm>(size);
}
vm::writer_lock lock(0);
if (!try_alloc(addr, pflags, size, std::move(shm)))
{
@ -1289,7 +1294,7 @@ namespace vm
}
}
std::pair<u32, std::shared_ptr<utils::shm>> block_t::get(u32 addr, u32 size)
std::pair<u32, std::shared_ptr<utils::shm>> block_t::peek(u32 addr, u32 size)
{
if (addr < this->addr || addr + u64{size} > this->addr + u64{this->size})
{
@ -1602,12 +1607,12 @@ namespace vm
g_locations =
{
std::make_shared<block_t>(0x00010000, 0x1FFF0000, 0x200), // main
std::make_shared<block_t>(0x00010000, 0x1FFF0000, 0x220), // main
std::make_shared<block_t>(0x20000000, 0x10000000, 0x201), // user 64k pages
nullptr, // user 1m pages
nullptr, // rsx context
std::make_shared<block_t>(0xC0000000, 0x10000000), // video
std::make_shared<block_t>(0xD0000000, 0x10000000, 0x111), // stack
std::make_shared<block_t>(0xC0000000, 0x10000000, 0x220), // video
std::make_shared<block_t>(0xD0000000, 0x10000000, 0x131), // stack
std::make_shared<block_t>(0xE0000000, 0x20000000), // SPU reserved
};