Skip to content

Commit

Permalink
Implement sys_vm_append/return_memory
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 committed Mar 27, 2019
1 parent 63a9472 commit 9b82596
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 15 deletions.
178 changes: 174 additions & 4 deletions rpcs3/Emu/Cell/lv2/sys_vm.cpp
@@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "sys_vm.h"
#include "sys_memory.h"

Expand All @@ -15,13 +15,22 @@ error_code sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy
return CELL_EINVAL;
}

if (cid != SYS_MEMORY_CONTAINER_ID_INVALID && !idm::check<lv2_memory_container>(cid))
auto ct = cid == SYS_MEMORY_CONTAINER_ID_INVALID ? fxm::get<lv2_memory_container>() : idm::get<lv2_memory_container>(cid);

if (!ct)
{
return CELL_ESRCH;
}

if (!ct->take(psize))
{
return CELL_ENOMEM;
}

auto info = new sys_vm_block_t(ct.get(), psize);

// Look for unmapped space
if (const auto area = vm::find_map(0x10000000, 0x10000000, 2 | (flag & SYS_MEMORY_PAGE_SIZE_MASK)))
if (auto area = vm::find_map(0x10000000, 0x10000000, 2 | (flag & SYS_MEMORY_PAGE_SIZE_MASK), info))
{
// Alloc all memory (shall not fail)
verify(HERE), area->alloc(vsize);
Expand All @@ -31,6 +40,8 @@ error_code sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy
return CELL_OK;
}

ct->used -= psize;
delete info;
return CELL_ENOMEM;
}

Expand Down Expand Up @@ -58,48 +69,156 @@ error_code sys_vm_append_memory(u32 addr, u32 size)
{
sys_vm.warning("sys_vm_append_memory(addr=0x%x, size=0x%x)", addr, size);

if (!size || size % 0x100000)
{
return CELL_EINVAL;
}

const auto block = vm::get(vm::any, addr);

if (!block || !block->sup)
{
return CELL_EINVAL;
}

auto info = static_cast<sys_vm_block_t*>(block->sup);

std::lock_guard lock(info->mutex);

if (!info->ct->take(size))
{
return CELL_ENOMEM;
}

info->psize += size;

return CELL_OK;
}

error_code sys_vm_return_memory(u32 addr, u32 size)
{
sys_vm.warning("sys_vm_return_memory(addr=0x%x, size=0x%x)", addr, size);

if (!size || size % 0x100000)
{
return CELL_EINVAL;
}

const auto block = vm::get(vm::any, addr);

if (!block || !block->sup)
{
return CELL_EINVAL;
}

auto info = static_cast<sys_vm_block_t*>(block->sup);

std::lock_guard lock(info->mutex);

if (info->psize < 0x100000 + size)
{
return CELL_EBUSY;
}

info->psize -= size;

info->ct->used -= size;

return CELL_OK;
}

error_code sys_vm_lock(u32 addr, u32 size)
{
sys_vm.warning("sys_vm_lock(addr=0x%x, size=0x%x)", addr, size);

if (!size)
{
return CELL_EINVAL;
}

const auto block = vm::get(vm::any, addr);

if (!block || !block->sup)
{
return CELL_EINVAL;
}

return CELL_OK;
}

error_code sys_vm_unlock(u32 addr, u32 size)
{
sys_vm.warning("sys_vm_unlock(addr=0x%x, size=0x%x)", addr, size);

if (!size)
{
return CELL_EINVAL;
}

const auto block = vm::get(vm::any, addr);

if (!block || !block->sup)
{
return CELL_EINVAL;
}

return CELL_OK;
}

error_code sys_vm_touch(u32 addr, u32 size)
{
sys_vm.warning("sys_vm_touch(addr=0x%x, size=0x%x)", addr, size);

if (!size)
{
return CELL_EINVAL;
}

const auto block = vm::get(vm::any, addr);

if (!block || !block->sup)
{
return CELL_EINVAL;
}

return CELL_OK;
}

error_code sys_vm_flush(u32 addr, u32 size)
{
sys_vm.warning("sys_vm_flush(addr=0x%x, size=0x%x)", addr, size);

if (!size)
{
return CELL_EINVAL;
}

const auto block = vm::get(vm::any, addr);

if (!block || !block->sup)
{
return CELL_EINVAL;
}

return CELL_OK;
}

error_code sys_vm_invalidate(u32 addr, u32 size)
{
sys_vm.warning("sys_vm_invalidate(addr=0x%x, size=0x%x)", addr, size);

if (!size)
{
return CELL_EINVAL;
}

const auto block = vm::get(vm::any, addr);

if (!block || !block->sup)
{
return CELL_EINVAL;
}

std::memset(vm::base(addr), 0, size);
return CELL_OK;
}
Expand All @@ -108,20 +227,51 @@ error_code sys_vm_store(u32 addr, u32 size)
{
sys_vm.warning("sys_vm_store(addr=0x%x, size=0x%x)", addr, size);

if (!size)
{
return CELL_EINVAL;
}

const auto block = vm::get(vm::any, addr);

if (!block || !block->sup)
{
return CELL_EINVAL;
}

return CELL_OK;
}

error_code sys_vm_sync(u32 addr, u32 size)
{
sys_vm.warning("sys_vm_sync(addr=0x%x, size=0x%x)", addr, size);

if (!size)
{
return CELL_EINVAL;
}

const auto block = vm::get(vm::any, addr);

if (!block || !block->sup)
{
return CELL_EINVAL;
}

return CELL_OK;
}

error_code sys_vm_test(u32 addr, u32 size, vm::ptr<u64> result)
{
sys_vm.warning("sys_vm_test(addr=0x%x, size=0x%x, result=*0x%x)", addr, size, result);

const auto block = vm::get(vm::any, addr);

if (!block || !block->sup || !block->addr != addr)
{
return CELL_EINVAL;
}

*result = SYS_VM_STATE_ON_MEMORY;

return CELL_OK;
Expand All @@ -131,13 +281,33 @@ error_code sys_vm_get_statistics(u32 addr, vm::ptr<sys_vm_statistics_t> stat)
{
sys_vm.warning("sys_vm_get_statistics(addr=0x%x, stat=*0x%x)", addr, stat);

const auto block = vm::get(vm::any, addr);

if (!block || !block->sup || block->addr != addr)
{
return CELL_EINVAL;
}

auto info = static_cast<sys_vm_block_t*>(block->sup);

stat->page_fault_ppu = 0;
stat->page_fault_spu = 0;
stat->page_in = 0;
stat->page_out = 0;
stat->pmem_total = 0;
stat->pmem_total = info->psize;
stat->pmem_used = 0;
stat->timestamp = 0;

return CELL_OK;
}

sys_vm_block_t::sys_vm_block_t(lv2_memory_container* ct, u32 psize)
: ct(ct)
, psize(psize)
{
}

sys_vm_block_t::~sys_vm_block_t()
{
ct->used -= psize;
}
11 changes: 11 additions & 0 deletions rpcs3/Emu/Cell/lv2/sys_vm.h
Expand Up @@ -3,6 +3,7 @@
#include "Emu/Memory/vm.h"
#include "Emu/Cell/ErrorCodes.h"
#include "Emu/IdManager.h"
#include "sys_memory.h"

enum : u64
{
Expand All @@ -25,6 +26,16 @@ struct sys_vm_statistics_t
be_t<u64> timestamp;
};

struct sys_vm_block_t
{
lv2_memory_container* ct;
u32 psize;
shared_mutex mutex;

sys_vm_block_t(lv2_memory_container* ct, u32 psize);
~sys_vm_block_t();
};

// SysCalls
error_code sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, vm::ptr<u32> addr);
error_code sys_vm_memory_map_different(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, vm::ptr<u32> addr);
Expand Down
19 changes: 11 additions & 8 deletions rpcs3/Emu/Memory/vm.cpp
Expand Up @@ -601,10 +601,11 @@ namespace vm
return true;
}

block_t::block_t(u32 addr, u32 size, u64 flags)
block_t::block_t(u32 addr, u32 size, u64 flags, void* sup)
: addr(addr)
, size(size)
, flags(flags)
, sup(sup)
{
// Allocate compressed reservation info area (avoid SPU MMIO area)
if (addr != 0xe0000000)
Expand Down Expand Up @@ -663,6 +664,8 @@ namespace vm
m_common->unmap_critical(vm::get_super_ptr(addr));
}
}

delete sup;
}

u32 block_t::alloc(const u32 orig_size, u32 align, const std::shared_ptr<utils::shm>* src, u64 flags)
Expand Down Expand Up @@ -890,20 +893,20 @@ namespace vm
return true;
}

static std::shared_ptr<block_t> _find_map(u32 size, u32 align, u64 flags)
static std::shared_ptr<block_t> _find_map(u32 size, u32 align, u64 flags, void* sup = nullptr)
{
for (u32 addr = ::align<u32>(0x20000000, align); addr < 0xC0000000; addr += align)
{
if (_test_map(addr, size))
{
return std::make_shared<block_t>(addr, size, flags);
return std::make_shared<block_t>(addr, size, flags, sup);
}
}

return nullptr;
}

std::shared_ptr<block_t> map(u32 addr, u32 size, u64 flags)
std::shared_ptr<block_t> map(u32 addr, u32 size, u64 flags, void* sup)
{
vm::writer_lock lock(0);

Expand All @@ -925,14 +928,14 @@ namespace vm
}
}

auto block = std::make_shared<block_t>(addr, size, flags);
auto block = std::make_shared<block_t>(addr, size, flags, sup);

g_locations.emplace_back(block);

return block;
}

std::shared_ptr<block_t> find_map(u32 orig_size, u32 align, u64 flags)
std::shared_ptr<block_t> find_map(u32 orig_size, u32 align, u64 flags, void* sup)
{
vm::writer_lock lock(0);

Expand All @@ -951,9 +954,9 @@ namespace vm
return nullptr;
}

auto block = _find_map(size, align, flags);
auto block = _find_map(size, align, flags, sup);

g_locations.emplace_back(block);
if (block) g_locations.emplace_back(block);

return block;
}
Expand Down

0 comments on commit 9b82596

Please sign in to comment.