mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 04:02:42 +01:00
Implement sys_vm_append/return_memory
This commit is contained in:
parent
3c0564c9b7
commit
182054b8af
@ -1,8 +1,27 @@
|
||||
#include "stdafx.h"
|
||||
#include "stdafx.h"
|
||||
#include "sys_vm.h"
|
||||
#include "sys_memory.h"
|
||||
|
||||
sys_vm_t::sys_vm_t(const std::shared_ptr<vm::block_t>& area, const std::shared_ptr<lv2_memory_container>& ct, u32 psize)
|
||||
: ct(ct)
|
||||
, psize(psize)
|
||||
, addr(area->addr)
|
||||
, size(area->size)
|
||||
{
|
||||
// Write ID
|
||||
g_ids[addr >> 28].release(idm::last_id());
|
||||
}
|
||||
|
||||
sys_vm_t::~sys_vm_t()
|
||||
{
|
||||
// Free ID
|
||||
g_ids[addr >> 28].release(0);
|
||||
|
||||
// Free block
|
||||
verify(HERE), vm::unmap(addr);
|
||||
|
||||
// Return memory
|
||||
ct->used -= psize;
|
||||
}
|
||||
|
||||
LOG_CHANNEL(sys_vm);
|
||||
|
||||
@ -15,22 +34,32 @@ 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;
|
||||
}
|
||||
|
||||
// Look for unmapped space
|
||||
if (const auto area = vm::find_map(0x10000000, 0x10000000, 2 | (flag & SYS_MEMORY_PAGE_SIZE_MASK)))
|
||||
{
|
||||
// Alloc all memory (shall not fail)
|
||||
verify(HERE), area->alloc(vsize);
|
||||
|
||||
idm::make<sys_vm_t>(area, ct, psize);
|
||||
|
||||
// Write a pointer for the allocated memory
|
||||
*addr = area->addr;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
ct->used -= psize;
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
@ -46,9 +75,16 @@ error_code sys_vm_unmap(u32 addr)
|
||||
{
|
||||
sys_vm.warning("sys_vm_unmap(addr=0x%x)", addr);
|
||||
|
||||
if (!vm::unmap(addr))
|
||||
// Special case, check if its a start address by alignment
|
||||
if (addr % 0x10000000)
|
||||
{
|
||||
return {CELL_EINVAL, addr};
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
// Free block and info
|
||||
if (!idm::remove<sys_vm_t>(sys_vm_t::find_id(addr)))
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
@ -58,6 +94,26 @@ 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 = idm::get<sys_vm_t>(sys_vm_t::find_id(addr));
|
||||
|
||||
if (!block || block->addr != addr)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
std::lock_guard lock(block->mutex);
|
||||
|
||||
if (!block->ct->take(size))
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
block->psize += size;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -65,6 +121,27 @@ 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 = idm::get<sys_vm_t>(sys_vm_t::find_id(addr));
|
||||
|
||||
if (!block || block->addr != addr)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
std::lock_guard lock(block->mutex);
|
||||
|
||||
if (block->psize < 0x100000 + size)
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
block->psize -= size;
|
||||
block->ct->used -= size;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -72,6 +149,18 @@ 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 = idm::get<sys_vm_t>(sys_vm_t::find_id(addr));
|
||||
|
||||
if (!block || addr + size > block->addr + block->size)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -79,6 +168,18 @@ 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 = idm::get<sys_vm_t>(sys_vm_t::find_id(addr));
|
||||
|
||||
if (!block || addr + size > block->addr + block->size)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -86,6 +187,18 @@ 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 = idm::get<sys_vm_t>(sys_vm_t::find_id(addr));
|
||||
|
||||
if (!block || addr + size > block->addr + block->size)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -93,6 +206,18 @@ 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 = idm::get<sys_vm_t>(sys_vm_t::find_id(addr));
|
||||
|
||||
if (!block || addr + size > block->addr + block->size)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -100,6 +225,18 @@ 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 = idm::get<sys_vm_t>(sys_vm_t::find_id(addr));
|
||||
|
||||
if (!block || addr + size > block->addr + block->size)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
std::memset(vm::base(addr), 0, size);
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -108,6 +245,18 @@ 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 = idm::get<sys_vm_t>(sys_vm_t::find_id(addr));
|
||||
|
||||
if (!block || addr + size > block->addr + block->size)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -115,6 +264,18 @@ 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 = idm::get<sys_vm_t>(sys_vm_t::find_id(addr));
|
||||
|
||||
if (!block || addr + size > block->addr + block->size)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -122,6 +283,13 @@ 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 = idm::get<sys_vm_t>(sys_vm_t::find_id(addr));
|
||||
|
||||
if (!block || addr + size > block->addr + block->size)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
*result = SYS_VM_STATE_ON_MEMORY;
|
||||
|
||||
return CELL_OK;
|
||||
@ -131,13 +299,22 @@ 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 = idm::get<sys_vm_t>(sys_vm_t::find_id(addr));
|
||||
|
||||
if (!block || block->addr != addr)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
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 = block->psize;
|
||||
stat->pmem_used = 0;
|
||||
stat->timestamp = 0;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
DECLARE(sys_vm_t::g_ids){};
|
||||
|
@ -1,8 +1,11 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "Emu/Memory/vm.h"
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "sys_memory.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
enum : u64
|
||||
{
|
||||
@ -25,6 +28,30 @@ struct sys_vm_statistics_t
|
||||
be_t<u64> timestamp;
|
||||
};
|
||||
|
||||
// Block info
|
||||
struct sys_vm_t
|
||||
{
|
||||
static const u32 id_base = 0x1;
|
||||
static const u32 id_step = 0x1;
|
||||
static const u32 id_count = 16;
|
||||
|
||||
const std::shared_ptr<lv2_memory_container> ct;
|
||||
const u32 addr;
|
||||
const u32 size;
|
||||
u32 psize;
|
||||
shared_mutex mutex;
|
||||
|
||||
sys_vm_t(const std::shared_ptr<vm::block_t>& area, const std::shared_ptr<lv2_memory_container>& ct, u32 psize);
|
||||
~sys_vm_t();
|
||||
|
||||
static std::array<atomic_t<u32>, id_count> g_ids;
|
||||
|
||||
static u32 find_id(u32 addr)
|
||||
{
|
||||
return g_ids[addr >> 28].load();
|
||||
}
|
||||
};
|
||||
|
||||
// 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);
|
||||
|
@ -958,7 +958,7 @@ namespace vm
|
||||
|
||||
auto block = _find_map(size, align, flags);
|
||||
|
||||
g_locations.emplace_back(block);
|
||||
if (block) g_locations.emplace_back(block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user