rpcsx/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp

276 lines
6.2 KiB
C++
Raw Normal View History

#include "stdafx.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/SysCalls.h"
2014-08-23 16:51:51 +02:00
#include "sys_memory.h"
2014-08-23 16:51:51 +02:00
#include "sys_vm.h"
2014-08-23 16:51:51 +02:00
SysCallBase sys_vm("vm");
MemoryContainerInfo* current_ct;
s32 sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 addr)
{
2014-09-03 18:33:30 +02:00
sys_vm.Todo("sys_vm_memory_map(vsize=0x%x,psize=0x%x,cidr=0x%x,flags=0x%llx,policy=0x%llx,addr=0x%x)",
vsize, psize, cid, flag, policy, addr);
// Check virtual size.
if((vsize < (0x100000 * 32)) || (vsize > (0x100000 * 256)))
{
return CELL_EINVAL;
}
// Check physical size.
if(psize > (0x100000 * 256))
{
return CELL_ENOMEM;
}
// If container ID is SYS_MEMORY_CONTAINER_ID_INVALID, allocate directly.
if(cid == SYS_MEMORY_CONTAINER_ID_INVALID)
{
u32 new_addr;
switch(flag)
{
case SYS_MEMORY_PAGE_SIZE_1M:
2014-08-30 20:35:18 +02:00
new_addr = (u32)Memory.Alloc(psize, 0x100000);
break;
case SYS_MEMORY_PAGE_SIZE_64K:
2014-08-30 20:35:18 +02:00
new_addr = (u32)Memory.Alloc(psize, 0x10000);
break;
default: return CELL_EINVAL;
}
if(!new_addr) return CELL_ENOMEM;
// Create a new MemoryContainerInfo to act as default container with vsize.
current_ct = new MemoryContainerInfo(new_addr, vsize);
}
else
{
// Check memory container.
MemoryContainerInfo* ct;
2014-08-23 16:51:51 +02:00
if(!sys_vm.CheckId(cid, ct)) return CELL_ESRCH;
current_ct = ct;
}
// Write a pointer for the allocated memory.
2014-09-06 15:33:01 +02:00
vm::write32(addr, current_ct->addr);
return CELL_OK;
}
s32 sys_vm_unmap(u32 addr)
{
2014-09-03 18:33:30 +02:00
sys_vm.Todo("sys_vm_unmap(addr=0x%x)", addr);
// Simply free the memory to unmap.
if(!Memory.Free(addr)) return CELL_EINVAL;
return CELL_OK;
}
s32 sys_vm_append_memory(u32 addr, u32 size)
{
2014-09-03 18:33:30 +02:00
sys_vm.Todo("sys_vm_append_memory(addr=0x%x,size=0x%x)", addr, size);
// Check address and size.
if((current_ct->addr != addr) || (size <= 0))
{
return CELL_EINVAL;
}
// Total memory size must not be superior to 256MB.
if((current_ct->size + size) > (0x100000 * 256))
{
return CELL_ENOMEM;
}
// The size is added to the virtual size, which should be inferior to the physical size allocated.
current_ct->size += size;
return CELL_OK;
}
s32 sys_vm_return_memory(u32 addr, u32 size)
{
2014-09-03 18:33:30 +02:00
sys_vm.Todo("sys_vm_return_memory(addr=0x%x,size=0x%x)", addr, size);
// Check address and size.
if((current_ct->addr != addr) || (size <= 0))
{
return CELL_EINVAL;
}
// The memory size to return should not be superior to the virtual size in use minus 1MB.
if(current_ct->size < (size + 0x100000))
{
return CELL_EBUSY;
}
// The size is returned to physical memory and is subtracted to the virtual size.
current_ct->size -= size;
return CELL_OK;
}
s32 sys_vm_lock(u32 addr, u32 size)
{
2014-09-03 18:33:30 +02:00
sys_vm.Todo("sys_vm_lock(addr=0x%x,size=0x%x)", addr, size);
// Check address and size.
if((current_ct->addr != addr) || (current_ct->size < size) || (size <= 0))
{
return CELL_EINVAL;
}
// The memory size to return should not be superior to the virtual size to lock minus 1MB.
if(current_ct->size < (size + 0x100000))
{
return CELL_EBUSY;
}
2014-09-03 18:33:30 +02:00
// TODO: The locked memory area keeps allocated and unchanged until sys_vm_unlocked is called.
return CELL_OK;
}
s32 sys_vm_unlock(u32 addr, u32 size)
{
2014-09-03 18:33:30 +02:00
sys_vm.Todo("sys_vm_unlock(addr=0x%x,size=0x%x)", addr, size);
// Check address and size.
if((current_ct->addr != addr) || (current_ct->size < size) || (size <= 0))
{
return CELL_EINVAL;
}
2014-09-03 18:33:30 +02:00
// TODO: Unlock
return CELL_OK;
}
s32 sys_vm_touch(u32 addr, u32 size)
{
2014-08-23 16:51:51 +02:00
sys_vm.Todo("sys_vm_touch(addr=0x%x,size=0x%x)", addr, size);
// Check address and size.
if((current_ct->addr != addr) || (current_ct->size < size) || (size <= 0))
{
return CELL_EINVAL;
}
// TODO
// sys_vm_touch allocates physical memory for a virtual memory address.
// This function is asynchronous, so it may not complete immediately.
return CELL_OK;
}
s32 sys_vm_flush(u32 addr, u32 size)
{
2014-08-23 16:51:51 +02:00
sys_vm.Todo("sys_vm_flush(addr=0x%x,size=0x%x)", addr, size);
// Check address and size.
if((current_ct->addr != addr) || (current_ct->size < size) || (size <= 0))
{
return CELL_EINVAL;
}
// TODO
// sys_vm_flush frees physical memory for a virtual memory address and creates a backup if the memory area is dirty.
// This function is asynchronous, so it may not complete immediately.
return CELL_OK;
}
s32 sys_vm_invalidate(u32 addr, u32 size)
{
2014-08-23 16:51:51 +02:00
sys_vm.Todo("sys_vm_invalidate(addr=0x%x,size=0x%x)", addr, size);
// Check address and size.
if((current_ct->addr != addr) || (current_ct->size < size) || (size <= 0))
{
return CELL_EINVAL;
}
// TODO
// sys_vm_invalidate frees physical memory for a virtual memory address.
// This function is asynchronous, so it may not complete immediately.
return CELL_OK;
}
s32 sys_vm_store(u32 addr, u32 size)
{
2014-08-23 16:51:51 +02:00
sys_vm.Todo("sys_vm_store(addr=0x%x,size=0x%x)", addr, size);
// Check address and size.
if((current_ct->addr != addr) || (current_ct->size < size) || (size <= 0))
{
return CELL_EINVAL;
}
// TODO
// sys_vm_store creates a backup for a dirty virtual memory area and marks it as clean.
// This function is asynchronous, so it may not complete immediately.
return CELL_OK;
}
s32 sys_vm_sync(u32 addr, u32 size)
{
2014-08-23 16:51:51 +02:00
sys_vm.Todo("sys_vm_sync(addr=0x%x,size=0x%x)", addr, size);
// Check address and size.
if((current_ct->addr != addr) || (current_ct->size < size) || (size <= 0))
{
return CELL_EINVAL;
}
// TODO
// sys_vm_sync stalls execution until all asynchronous vm calls finish.
return CELL_OK;
}
2014-09-03 18:33:30 +02:00
s32 sys_vm_test(u32 addr, u32 size, vm::ptr<u64> result)
{
2014-09-03 18:33:30 +02:00
sys_vm.Todo("sys_vm_test(addr=0x%x, size=0x%x, result_addr=0x%x)", addr, size, result.addr());
// Check address and size.
if((current_ct->addr != addr) || (current_ct->size < size) || (size <= 0))
{
return CELL_EINVAL;
}
// TODO
// sys_vm_test checks the state of a portion of the virtual memory area.
// Faking.
2014-09-03 18:33:30 +02:00
*result = SYS_VM_TEST_ALLOCATED;
return CELL_OK;
}
2014-09-03 18:33:30 +02:00
s32 sys_vm_get_statistics(u32 addr, vm::ptr<sys_vm_statistics> stat)
{
2014-09-03 18:33:30 +02:00
sys_vm.Todo("sys_vm_get_statistics(addr=0x%x, stat_addr=0x%x)", addr, stat.addr());
// Check address.
if(current_ct->addr != addr)
{
return CELL_EINVAL;
}
// TODO
2014-09-03 18:33:30 +02:00
stat->page_fault_ppu = 0;
stat->page_fault_spu = 0;
stat->page_in = 0;
stat->page_out = 0;
stat->pmem_total = current_ct->size;
stat->pmem_used = 0;
stat->timestamp = 0;
return CELL_OK;
}