mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 20:15:27 +00:00
sys_memory, sys_mmapper rewritten
LogBase::Fatal() removed
This commit is contained in:
parent
39629c5c7a
commit
2d37c6b5e2
20 changed files with 598 additions and 456 deletions
|
@ -3292,10 +3292,10 @@ void Compiler::MFSPR(u32 rd, u32 spr) {
|
|||
rd_i64 = GetVrsave();
|
||||
break;
|
||||
case 0x10C:
|
||||
rd_i64 = Call<u64>("get_timebased_time", get_timebased_time);
|
||||
rd_i64 = Call<u64>("get_timebased_time", get_timebased_time);
|
||||
break;
|
||||
case 0x10D:
|
||||
rd_i64 = Call<u64>("get_timebased_time", get_timebased_time);
|
||||
rd_i64 = Call<u64>("get_timebased_time", get_timebased_time);
|
||||
rd_i64 = m_ir_builder->CreateLShr(rd_i64, 32);
|
||||
break;
|
||||
default:
|
||||
|
@ -3340,7 +3340,7 @@ void Compiler::LVXL(u32 vd, u32 ra, u32 rb) {
|
|||
}
|
||||
|
||||
void Compiler::MFTB(u32 rd, u32 spr) {
|
||||
auto tb_i64 = Call<u64>("get_timebased_time", get_timebased_time);
|
||||
auto tb_i64 = Call<u64>("get_timebased_time", get_timebased_time);
|
||||
|
||||
u32 n = (spr >> 5) | ((spr & 0x1f) << 5);
|
||||
if (n == 0x10D) {
|
||||
|
|
|
@ -9,16 +9,16 @@
|
|||
thread_local spu_mfc_arg_t raw_spu_mfc[8] = {};
|
||||
|
||||
RawSPUThread::RawSPUThread(const std::string& name, u32 index)
|
||||
: SPUThread(CPU_THREAD_RAW_SPU, name, WRAP_EXPR(fmt::format("RawSPU[0x%x] Thread (%s)[0x%08x]", GetId(), GetName(), PC)), index, RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index)
|
||||
: SPUThread(CPU_THREAD_RAW_SPU, name, COPY_EXPR(fmt::format("RawSPU_%d[0x%x] Thread (%s)[0x%08x]", index, GetId(), GetName(), PC)), index, RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index)
|
||||
{
|
||||
Memory.Map(offset, 0x40000);
|
||||
vm::page_map(offset, 0x40000, vm::page_readable | vm::page_writable);
|
||||
}
|
||||
|
||||
RawSPUThread::~RawSPUThread()
|
||||
{
|
||||
join();
|
||||
|
||||
Memory.Unmap(offset);
|
||||
vm::page_unmap(offset, 0x40000);
|
||||
}
|
||||
|
||||
void RawSPUThread::start()
|
||||
|
|
|
@ -66,10 +66,26 @@ void MemoryBase::Close()
|
|||
|
||||
bool MemoryBase::Map(const u32 addr, const u32 size)
|
||||
{
|
||||
assert(size && (size | addr) % 4096 == 0);
|
||||
if (!size || (size | addr) % 4096)
|
||||
{
|
||||
throw EXCEPTION("Invalid arguments (addr=0x%x, size=0x%x)", addr, size);
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(Memory.mutex);
|
||||
|
||||
for (auto& block : MemoryBlocks)
|
||||
{
|
||||
if (block->GetStartAddr() >= addr && block->GetStartAddr() <= addr + size - 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (addr >= block->GetStartAddr() && addr <= block->GetEndAddr())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++)
|
||||
{
|
||||
if (vm::check_addr(i * 4096, 4096))
|
||||
|
@ -78,9 +94,8 @@ bool MemoryBase::Map(const u32 addr, const u32 size)
|
|||
}
|
||||
}
|
||||
|
||||
MemoryBlocks.push_back((new MemoryBlock())->SetRange(addr, size));
|
||||
MemoryBlocks.push_back((new DynamicMemoryBlock())->SetRange(addr, size));
|
||||
|
||||
LOG_WARNING(MEMORY, "Memory mapped at 0x%x: size=0x%x", addr, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -97,9 +112,25 @@ bool MemoryBase::Unmap(const u32 addr)
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
MemoryBlock* MemoryBase::Get(const u32 addr)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(Memory.mutex);
|
||||
|
||||
for (auto& block : MemoryBlocks)
|
||||
{
|
||||
if (block->GetStartAddr() == addr)
|
||||
{
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MemBlockInfo::MemBlockInfo(u32 addr, u32 size)
|
||||
: MemInfo(addr, size)
|
||||
{
|
||||
|
|
|
@ -28,7 +28,8 @@ public:
|
|||
{
|
||||
DynamicMemoryBlock RAM;
|
||||
DynamicMemoryBlock Userspace;
|
||||
} PSV;
|
||||
}
|
||||
PSV;
|
||||
|
||||
struct
|
||||
{
|
||||
|
@ -37,7 +38,8 @@ public:
|
|||
DynamicMemoryBlock RAM;
|
||||
DynamicMemoryBlock Kernel;
|
||||
DynamicMemoryBlock Userspace;
|
||||
} PSP;
|
||||
}
|
||||
PSP;
|
||||
|
||||
bool m_inited;
|
||||
|
||||
|
@ -51,10 +53,6 @@ public:
|
|||
Close();
|
||||
}
|
||||
|
||||
void RegisterPages(u32 addr, u32 size);
|
||||
|
||||
void UnregisterPages(u32 addr, u32 size);
|
||||
|
||||
void Init(MemoryType type);
|
||||
|
||||
void Close();
|
||||
|
@ -82,6 +80,8 @@ public:
|
|||
bool Map(const u32 addr, const u32 size);
|
||||
|
||||
bool Unmap(const u32 addr);
|
||||
|
||||
MemoryBlock* Get(const u32 addr);
|
||||
};
|
||||
|
||||
extern MemoryBase Memory;
|
||||
|
|
|
@ -16,8 +16,7 @@ void LogBase::LogOutput(LogType type, const std::string& text) const
|
|||
case LogNotice: LOG_NOTICE(HLE, GetName() + ": " + text); break;
|
||||
case LogSuccess: LOG_SUCCESS(HLE, GetName() + ": " + text); break;
|
||||
case LogWarning: LOG_WARNING(HLE, GetName() + ": " + text); break;
|
||||
case LogError: LOG_ERROR(HLE, GetName() + " error: " + text); break;
|
||||
case LogError: LOG_ERROR(HLE, GetName() + ": " + text); break;
|
||||
case LogTodo: LOG_ERROR(HLE, GetName() + " TODO: " + text); break;
|
||||
case LogFatal: throw EXCEPTION("%s error: %s", GetName().c_str(), text.c_str());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ class LogBase
|
|||
LogSuccess,
|
||||
LogWarning,
|
||||
LogError,
|
||||
LogFatal,
|
||||
LogTodo,
|
||||
};
|
||||
|
||||
|
@ -63,11 +62,6 @@ public:
|
|||
LogPrepare(LogError, fmt, fmt::do_unveil(args)...);
|
||||
}
|
||||
|
||||
template<typename... Args> force_inline void Fatal(const char* fmt, Args... args) const
|
||||
{
|
||||
LogPrepare(LogFatal, fmt, fmt::do_unveil(args)...);
|
||||
}
|
||||
|
||||
template<typename... Args> force_inline void Todo(const char* fmt, Args... args) const
|
||||
{
|
||||
LogPrepare(LogTodo, fmt, fmt::do_unveil(args)...);
|
||||
|
|
|
@ -777,7 +777,7 @@ s32 cellAdecGetPcm(u32 handle, vm::ptr<float> outBuffer)
|
|||
}
|
||||
else
|
||||
{
|
||||
cellAdec.Fatal("cellAdecGetPcm(): unsupported frame format (channels=%d, format=%d)", frame->channels, frame->format);
|
||||
throw EXCEPTION("Unsupported frame format (channels=%d, format=%d)", frame->channels, frame->format);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -645,7 +645,7 @@ s32 cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, vm::cptr<CellVdecAuInf
|
|||
|
||||
if (mode != CELL_VDEC_DEC_MODE_NORMAL)
|
||||
{
|
||||
cellVdec.Fatal("cellVdecDecodeAu(): unsupported decoding mode (%d)", mode);
|
||||
throw EXCEPTION("Unsupported decoding mode (%d)", mode);
|
||||
}
|
||||
|
||||
// TODO: check info
|
||||
|
@ -711,13 +711,13 @@ s32 cellVdecGetPicture(u32 handle, vm::cptr<CellVdecPicFormat> format, vm::ptr<u
|
|||
|
||||
default:
|
||||
{
|
||||
cellVdec.Fatal("cellVdecGetPicture: unknown formatType(%d)", type);
|
||||
throw EXCEPTION("Unknown formatType(%d)", type);
|
||||
}
|
||||
}
|
||||
|
||||
if (format->colorMatrixType != CELL_VDEC_COLOR_MATRIX_TYPE_BT709)
|
||||
{
|
||||
cellVdec.Fatal("cellVdecGetPicture: unknown colorMatrixType(%d)", format->colorMatrixType);
|
||||
throw EXCEPTION("Unknown colorMatrixType(%d)", format->colorMatrixType);
|
||||
}
|
||||
|
||||
if (alpha_plane)
|
||||
|
@ -733,7 +733,7 @@ s32 cellVdecGetPicture(u32 handle, vm::cptr<CellVdecPicFormat> format, vm::ptr<u
|
|||
|
||||
default:
|
||||
{
|
||||
cellVdec.Fatal("cellVdecGetPicture: unknown pix_fmt(%d)", f);
|
||||
throw EXCEPTION("Unknown pix_fmt(%d)", f);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -775,7 +775,7 @@ s32 _nid_a21aa896(PPUThread& CPU, u32 handle, vm::cptr<CellVdecPicFormat2> forma
|
|||
|
||||
if (arg4 || format2->unk0 || format2->unk1)
|
||||
{
|
||||
cellVdec.Fatal("_nid_a21aa896(): unknown arguments (arg4=*0x%x, unk0=0x%x, unk1=0x%x)", arg4, format2->unk0, format2->unk1);
|
||||
throw EXCEPTION("Unknown arguments (arg4=*0x%x, unk0=0x%x, unk1=0x%x)", arg4, format2->unk0, format2->unk1);
|
||||
}
|
||||
|
||||
vm::stackvar<CellVdecPicFormat> format(CPU);
|
||||
|
@ -924,7 +924,7 @@ s32 cellVdecGetPicItem(u32 handle, vm::pptr<CellVdecPicItem> picItem)
|
|||
{
|
||||
auto mp2 = vm::ptr<CellVdecMpeg2Info>::make(info.addr() + sizeof32(CellVdecPicItem));
|
||||
|
||||
cellVdec.Fatal("cellVdecGetPicItem(MPEG2)");
|
||||
throw EXCEPTION("MPEG2");
|
||||
}
|
||||
|
||||
*picItem = info;
|
||||
|
|
|
@ -230,7 +230,7 @@ s32 sys_lwmutex_lock(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex, u64 timeout
|
|||
|
||||
if (old != lwmutex_reserved)
|
||||
{
|
||||
sysPrxForUser.Fatal("sys_lwmutex_lock(lwmutex=*0x%x): locking failed (owner=0x%x)", lwmutex, old);
|
||||
throw EXCEPTION("Locking failed (lwmutex=*0x%x, owner=0x%x)", lwmutex, old);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
|
@ -301,7 +301,7 @@ s32 sys_lwmutex_trylock(PPUThread& CPU, vm::ptr<sys_lwmutex_t> lwmutex)
|
|||
|
||||
if (old != lwmutex_reserved)
|
||||
{
|
||||
sysPrxForUser.Fatal("sys_lwmutex_trylock(lwmutex=*0x%x): locking failed (owner=0x%x)", lwmutex, old);
|
||||
throw EXCEPTION("Locking failed (lwmutex=*0x%x, owner=0x%x)", lwmutex, old);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -590,7 +590,7 @@ s32 sys_lwcond_wait(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond, u64 timeout)
|
|||
|
||||
if (old != lwmutex_reserved)
|
||||
{
|
||||
sysPrxForUser.Fatal("sys_lwcond_wait(lwcond=*0x%x): locking failed (lwmutex->owner=0x%x)", lwcond, old);
|
||||
throw EXCEPTION("Locking failed (lwmutex=*0x%x, owner=0x%x)", lwmutex, old);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -619,14 +619,13 @@ s32 sys_lwcond_wait(PPUThread& CPU, vm::ptr<sys_lwcond_t> lwcond, u64 timeout)
|
|||
|
||||
if (old != lwmutex_reserved)
|
||||
{
|
||||
sysPrxForUser.Fatal("sys_lwcond_wait(lwcond=*0x%x): locking failed after timeout (lwmutex->owner=0x%x)", lwcond, old);
|
||||
throw EXCEPTION("Locking failed (lwmutex=*0x%x, owner=0x%x)", lwmutex, old);
|
||||
}
|
||||
|
||||
return CELL_ETIMEDOUT;
|
||||
}
|
||||
|
||||
sysPrxForUser.Fatal("sys_lwcond_wait(lwcond=*0x%x): unexpected syscall result (0x%x)", lwcond, res);
|
||||
return res;
|
||||
throw EXCEPTION("Unexpected syscall result (lwcond=*0x%x, result=0x%x)", lwcond, res);
|
||||
}
|
||||
|
||||
s64 sys_time_get_system_time()
|
||||
|
@ -1168,9 +1167,7 @@ s32 _sys_printf(vm::cptr<char> fmt, ppu_va_args_t va_args)
|
|||
sysPrxForUser.Todo("_sys_printf(fmt=*0x%x, ...)", fmt);
|
||||
|
||||
// probably, assertion failed
|
||||
sysPrxForUser.Fatal("_sys_printf: \n%s", fmt.get_ptr());
|
||||
Emu.Pause();
|
||||
return CELL_OK;
|
||||
throw EXCEPTION("%s", fmt.get_ptr());
|
||||
}
|
||||
|
||||
s32 sys_process_get_paramsfo(vm::ptr<char> buffer)
|
||||
|
|
|
@ -97,7 +97,7 @@ s32 sys_fs_open(vm::cptr<char> path, s32 flags, vm::ptr<u32> fd, s32 mode, vm::c
|
|||
|
||||
if (!open_mode)
|
||||
{
|
||||
sys_fs.Fatal("sys_fs_open('%s'): invalid or unimplemented flags (%#o)", path.get_ptr(), flags);
|
||||
throw EXCEPTION("Invalid or unimplemented flags (%#o): '%s'", flags, path.get_ptr());
|
||||
}
|
||||
|
||||
std::shared_ptr<vfsStream> file(Emu.GetVFS().OpenFile(path.get_ptr(), open_mode));
|
||||
|
|
|
@ -133,7 +133,7 @@ s32 _sys_lwmutex_unlock(u32 lwmutex_id)
|
|||
|
||||
if (mutex->signaled)
|
||||
{
|
||||
sys_lwmutex.Fatal("_sys_lwmutex_unlock(lwmutex_id=0x%x): already signaled", lwmutex_id);
|
||||
throw EXCEPTION("Already signaled (lwmutex_id=0x%x)", lwmutex_id);
|
||||
}
|
||||
|
||||
mutex->signaled++;
|
||||
|
|
|
@ -5,95 +5,196 @@
|
|||
#include "Emu/SysCalls/SysCalls.h"
|
||||
|
||||
#include "sys_memory.h"
|
||||
#include <map>
|
||||
|
||||
SysCallBase sys_memory("sys_memory");
|
||||
|
||||
s32 sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr)
|
||||
lv2_memory_container_t::lv2_memory_container_t(u32 size)
|
||||
: size(size)
|
||||
, id(Emu.GetIdManager().get_current_id())
|
||||
{
|
||||
sys_memory.Log("sys_memory_allocate(size=0x%x, flags=0x%x)", size, flags);
|
||||
|
||||
// Check page size.
|
||||
u32 addr;
|
||||
}
|
||||
|
||||
s32 sys_memory_allocate(u32 size, u64 flags, vm::ptr<u32> alloc_addr)
|
||||
{
|
||||
sys_memory.Warning("sys_memory_allocate(size=0x%x, flags=0x%llx, alloc_addr=*0x%x)", size, flags, alloc_addr);
|
||||
|
||||
LV2_LOCK;
|
||||
|
||||
// Check allocation size
|
||||
switch(flags)
|
||||
{
|
||||
case SYS_MEMORY_PAGE_SIZE_1M:
|
||||
if(size & 0xfffff) return CELL_EALIGN;
|
||||
addr = (u32)Memory.Alloc(size, 0x100000);
|
||||
break;
|
||||
{
|
||||
if (size % 0x100000)
|
||||
{
|
||||
return CELL_EALIGN;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SYS_MEMORY_PAGE_SIZE_64K:
|
||||
if(size & 0xffff) return CELL_EALIGN;
|
||||
addr = (u32)Memory.Alloc(size, 0x10000);
|
||||
break;
|
||||
{
|
||||
if (size % 0x10000)
|
||||
{
|
||||
return CELL_EALIGN;
|
||||
}
|
||||
|
||||
default: return CELL_EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!addr)
|
||||
default:
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
// Available memory reserved for containers
|
||||
u32 available = 0;
|
||||
|
||||
// Check all containers
|
||||
for (auto& ct : Emu.GetIdManager().get_all<lv2_memory_container_t>())
|
||||
{
|
||||
available += ct->size - ct->taken;
|
||||
}
|
||||
|
||||
// Check available memory
|
||||
if (Memory.GetUserMemAvailSize() < available + size)
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
// Allocate memory
|
||||
const u32 addr =
|
||||
flags == SYS_MEMORY_PAGE_SIZE_1M ? Memory.Alloc(size, 0x100000) :
|
||||
flags == SYS_MEMORY_PAGE_SIZE_64K ? Memory.Alloc(size, 0x10000) :
|
||||
throw EXCEPTION("Unexpected flags");
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
// Write back the start address of the allocated area.
|
||||
sys_memory.Log("Memory allocated! [addr: 0x%x, size: 0x%x]", addr, size);
|
||||
vm::write32(alloc_addr_addr, addr);
|
||||
// Write back the start address of the allocated area
|
||||
*alloc_addr = addr;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_memory_allocate_from_container(u32 size, u32 cid, u32 flags, u32 alloc_addr_addr)
|
||||
s32 sys_memory_allocate_from_container(u32 size, u32 cid, u64 flags, vm::ptr<u32> alloc_addr)
|
||||
{
|
||||
sys_memory.Log("sys_memory_allocate_from_container(size=0x%x, cid=0x%x, flags=0x%x)", size, cid, flags);
|
||||
sys_memory.Warning("sys_memory_allocate_from_container(size=0x%x, cid=0x%x, flags=0x%llx, alloc_addr=*0x%x)", size, cid, flags, alloc_addr);
|
||||
|
||||
// Check if this container ID is valid.
|
||||
const auto ct = Emu.GetIdManager().get<MemoryContainerInfo>(cid);
|
||||
LV2_LOCK;
|
||||
|
||||
// Check if this container ID is valid
|
||||
const auto ct = Emu.GetIdManager().get<lv2_memory_container_t>(cid);
|
||||
|
||||
if (!ct)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
// Check page size.
|
||||
switch(flags)
|
||||
// Check allocation size
|
||||
switch (flags)
|
||||
{
|
||||
case SYS_MEMORY_PAGE_SIZE_1M:
|
||||
if(size & 0xfffff) return CELL_EALIGN;
|
||||
ct->addr = (u32)Memory.Alloc(size, 0x100000);
|
||||
break;
|
||||
{
|
||||
if (size % 0x100000)
|
||||
{
|
||||
return CELL_EALIGN;
|
||||
}
|
||||
|
||||
case SYS_MEMORY_PAGE_SIZE_64K:
|
||||
if(size & 0xffff) return CELL_EALIGN;
|
||||
ct->addr = (u32)Memory.Alloc(size, 0x10000);
|
||||
break;
|
||||
|
||||
default: return CELL_EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
// Store the address and size in the container.
|
||||
if(!ct->addr)
|
||||
case SYS_MEMORY_PAGE_SIZE_64K:
|
||||
{
|
||||
if (size % 0x10000)
|
||||
{
|
||||
return CELL_EALIGN;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ct->taken > ct->size)
|
||||
{
|
||||
throw EXCEPTION("Unexpected amount of memory taken (0x%x, size=0x%x)", ct->taken.load(), ct->size);
|
||||
}
|
||||
|
||||
// Check memory availability
|
||||
if (size > ct->size - ct->taken)
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
ct->size = size;
|
||||
}
|
||||
|
||||
// Allocate memory
|
||||
const u32 addr =
|
||||
flags == SYS_MEMORY_PAGE_SIZE_1M ? Memory.Alloc(size, 0x100000) :
|
||||
flags == SYS_MEMORY_PAGE_SIZE_64K ? Memory.Alloc(size, 0x10000) :
|
||||
throw EXCEPTION("Unexpected flags");
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
throw EXCEPTION("Memory not allocated (ct=0x%x, size=0x%x)", cid, size);
|
||||
}
|
||||
|
||||
// Store the address and size in the container
|
||||
ct->allocs.emplace(addr, size);
|
||||
ct->taken += size;
|
||||
|
||||
// Write back the start address of the allocated area.
|
||||
sys_memory.Log("Memory allocated! [addr: 0x%x, size: 0x%x]", ct->addr, ct->size);
|
||||
vm::write32(alloc_addr_addr, ct->addr);
|
||||
*alloc_addr = addr;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_memory_free(u32 start_addr)
|
||||
s32 sys_memory_free(u32 addr)
|
||||
{
|
||||
sys_memory.Log("sys_memory_free(start_addr=0x%x)", start_addr);
|
||||
sys_memory.Warning("sys_memory_free(addr=0x%x)", addr);
|
||||
|
||||
// Release the allocated memory.
|
||||
if(!Memory.Free(start_addr))
|
||||
LV2_LOCK;
|
||||
|
||||
// Check all memory containers
|
||||
for (auto& ct : Emu.GetIdManager().get_all<lv2_memory_container_t>())
|
||||
{
|
||||
auto found = ct->allocs.find(addr);
|
||||
|
||||
if (found != ct->allocs.end())
|
||||
{
|
||||
if (!Memory.Free(addr))
|
||||
{
|
||||
throw EXCEPTION("Memory not deallocated (cid=0x%x, addr=0x%x, size=0x%x)", ct->id, addr, found->second);
|
||||
}
|
||||
|
||||
// Return memory size
|
||||
ct->taken -= found->second;
|
||||
ct->allocs.erase(found);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Memory.Free(addr))
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_memory_get_page_attribute(u32 addr, vm::ptr<sys_page_attr_t> attr)
|
||||
{
|
||||
sys_memory.Warning("sys_memory_get_page_attribute(addr=0x%x, attr_addr=0x%x)", addr, attr.addr());
|
||||
sys_memory.Error("sys_memory_get_page_attribute(addr=0x%x, attr=*0x%x)", addr, attr);
|
||||
|
||||
LV2_LOCK;
|
||||
|
||||
// TODO: Implement per thread page attribute setting.
|
||||
attr->attribute = 0x40000ull; // SYS_MEMORY_PROT_READ_WRITE
|
||||
|
@ -105,26 +206,59 @@ s32 sys_memory_get_page_attribute(u32 addr, vm::ptr<sys_page_attr_t> attr)
|
|||
|
||||
s32 sys_memory_get_user_memory_size(vm::ptr<sys_memory_info_t> mem_info)
|
||||
{
|
||||
sys_memory.Warning("sys_memory_get_user_memory_size(mem_info_addr=0x%x)", mem_info.addr());
|
||||
sys_memory.Warning("sys_memory_get_user_memory_size(mem_info=*0x%x)", mem_info);
|
||||
|
||||
LV2_LOCK;
|
||||
|
||||
u32 reserved = 0;
|
||||
u32 available = 0;
|
||||
|
||||
// Check all memory containers
|
||||
for (auto& ct : Emu.GetIdManager().get_all<lv2_memory_container_t>())
|
||||
{
|
||||
reserved += ct->size;
|
||||
available += ct->size - ct->taken;
|
||||
}
|
||||
|
||||
// Fetch the user memory available.
|
||||
mem_info->total_user_memory = Memory.GetUserMemTotalSize();
|
||||
mem_info->available_user_memory = Memory.GetUserMemAvailSize();
|
||||
// Fetch the user memory available
|
||||
mem_info->total_user_memory = Memory.GetUserMemTotalSize() - reserved;
|
||||
mem_info->available_user_memory = Memory.GetUserMemAvailSize() - available;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_memory_container_create(vm::ptr<u32> cid, u32 yield_size)
|
||||
s32 sys_memory_container_create(vm::ptr<u32> cid, u32 size)
|
||||
{
|
||||
sys_memory.Warning("sys_memory_container_create(cid_addr=0x%x, yield_size=0x%x)", cid.addr(), yield_size);
|
||||
sys_memory.Warning("sys_memory_container_create(cid=*0x%x, size=0x%x)", cid, size);
|
||||
|
||||
yield_size &= ~0xfffff; //round down to 1 MB granularity
|
||||
u32 addr = (u32)Memory.Alloc(yield_size, 0x100000); //1 MB alignment
|
||||
LV2_LOCK;
|
||||
|
||||
if(!addr)
|
||||
// Round down to 1 MB granularity
|
||||
size &= ~0xfffff;
|
||||
|
||||
if (!size)
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
// Wrap the allocated memory in a memory container.
|
||||
*cid = Emu.GetIdManager().make<MemoryContainerInfo>(addr, yield_size);
|
||||
u32 reserved = 0;
|
||||
u32 available = 0;
|
||||
|
||||
// Check all memory containers
|
||||
for (auto& ct : Emu.GetIdManager().get_all<lv2_memory_container_t>())
|
||||
{
|
||||
reserved += ct->size;
|
||||
available += ct->size - ct->taken;
|
||||
}
|
||||
|
||||
if (Memory.GetUserMemTotalSize() < reserved + size ||
|
||||
Memory.GetUserMemAvailSize() < available + size)
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
// Create the memory container
|
||||
*cid = Emu.GetIdManager().make<lv2_memory_container_t>(size);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -133,35 +267,41 @@ s32 sys_memory_container_destroy(u32 cid)
|
|||
{
|
||||
sys_memory.Warning("sys_memory_container_destroy(cid=0x%x)", cid);
|
||||
|
||||
// Check if this container ID is valid.
|
||||
const auto ct = Emu.GetIdManager().get<MemoryContainerInfo>(cid);
|
||||
LV2_LOCK;
|
||||
|
||||
const auto ct = Emu.GetIdManager().get<lv2_memory_container_t>(cid);
|
||||
|
||||
if (!ct)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
// Release the allocated memory and remove the ID.
|
||||
Memory.Free(ct->addr);
|
||||
Emu.GetIdManager().remove<MemoryContainerInfo>(cid);
|
||||
// Check if some memory is not deallocated (the container cannot be destroyed in this case)
|
||||
if (ct->taken)
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
Emu.GetIdManager().remove<lv2_memory_container_t>(cid);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_memory_container_get_size(vm::ptr<sys_memory_info_t> mem_info, u32 cid)
|
||||
{
|
||||
sys_memory.Warning("sys_memory_container_get_size(mem_info_addr=0x%x, cid=0x%x)", mem_info.addr(), cid);
|
||||
sys_memory.Warning("sys_memory_container_get_size(mem_info=*0x%x, cid=0x%x)", mem_info, cid);
|
||||
|
||||
// Check if this container ID is valid.
|
||||
const auto ct = Emu.GetIdManager().get<MemoryContainerInfo>(cid);
|
||||
LV2_LOCK;
|
||||
|
||||
const auto ct = Emu.GetIdManager().get<lv2_memory_container_t>(cid);
|
||||
|
||||
if (!ct)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
// HACK: Return all memory.
|
||||
mem_info->total_user_memory = ct->size;
|
||||
mem_info->available_user_memory = ct->size;
|
||||
mem_info->total_user_memory = ct->size; // total container memory
|
||||
mem_info->available_user_memory = ct->size - ct->taken; // available container memory
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
|
@ -20,10 +20,11 @@ enum : u64
|
|||
SYS_MEMORY_ATTR_READ_WRITE = 0x0000000000040000ULL,
|
||||
};
|
||||
|
||||
enum
|
||||
enum : u64
|
||||
{
|
||||
SYS_MEMORY_PAGE_SIZE_1M = 0x400,
|
||||
SYS_MEMORY_PAGE_SIZE_64K = 0x200,
|
||||
SYS_MEMORY_PAGE_SIZE_1M = 0x400ull,
|
||||
SYS_MEMORY_PAGE_SIZE_64K = 0x200ull,
|
||||
SYS_MEMORY_PAGE_SIZE_MASK = 0xf00ull,
|
||||
};
|
||||
|
||||
struct sys_memory_info_t
|
||||
|
@ -41,24 +42,26 @@ struct sys_page_attr_t
|
|||
be_t<u32> pad;
|
||||
};
|
||||
|
||||
struct MemoryContainerInfo
|
||||
struct lv2_memory_container_t
|
||||
{
|
||||
u32 addr;
|
||||
u32 size;
|
||||
const u32 size; // amount of "physical" memory in this container
|
||||
const u32 id;
|
||||
|
||||
MemoryContainerInfo(u32 addr, u32 size)
|
||||
: addr(addr)
|
||||
, size(size)
|
||||
{
|
||||
}
|
||||
// amount of memory allocated
|
||||
std::atomic<u32> taken{ 0 };
|
||||
|
||||
// allocations (addr -> size)
|
||||
std::map<u32, u32> allocs;
|
||||
|
||||
lv2_memory_container_t(u32 size);
|
||||
};
|
||||
|
||||
// SysCalls
|
||||
s32 sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr);
|
||||
s32 sys_memory_allocate_from_container(u32 size, u32 cid, u32 flags, u32 alloc_addr_addr);
|
||||
s32 sys_memory_allocate(u32 size, u64 flags, vm::ptr<u32> alloc_addr);
|
||||
s32 sys_memory_allocate_from_container(u32 size, u32 cid, u64 flags, vm::ptr<u32> alloc_addr);
|
||||
s32 sys_memory_free(u32 start_addr);
|
||||
s32 sys_memory_get_page_attribute(u32 addr, vm::ptr<sys_page_attr_t> attr);
|
||||
s32 sys_memory_get_user_memory_size(vm::ptr<sys_memory_info_t> mem_info);
|
||||
s32 sys_memory_container_create(vm::ptr<u32> cid, u32 yield_size);
|
||||
s32 sys_memory_container_create(vm::ptr<u32> cid, u32 size);
|
||||
s32 sys_memory_container_destroy(u32 cid);
|
||||
s32 sys_memory_container_get_size(vm::ptr<sys_memory_info_t> mem_info, u32 cid);
|
||||
|
|
|
@ -4,91 +4,133 @@
|
|||
#include "Emu/IdManager.h"
|
||||
#include "Emu/SysCalls/SysCalls.h"
|
||||
|
||||
#include "sys_memory.h"
|
||||
#include "sys_mmapper.h"
|
||||
#include <map>
|
||||
|
||||
SysCallBase sys_mmapper("sys_mmapper");
|
||||
std::map<u32, u32> mmapper_info_map;
|
||||
|
||||
s32 sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_addr)
|
||||
lv2_memory_t::lv2_memory_t(u32 size, u32 align, u64 flags, const std::shared_ptr<lv2_memory_container_t> ct)
|
||||
: size(size)
|
||||
, align(align)
|
||||
, id(Emu.GetIdManager().get_current_id())
|
||||
, flags(flags)
|
||||
, ct(ct)
|
||||
{
|
||||
sys_mmapper.Warning("sys_mmapper_allocate_address(size=0x%x, flags=0x%llx, alignment=0x%x, alloc_addr=0x%x)",
|
||||
size, flags, alignment, alloc_addr);
|
||||
}
|
||||
|
||||
// Check for valid alignment.
|
||||
if(alignment > 0x80000000)
|
||||
return CELL_EALIGN;
|
||||
s32 sys_mmapper_allocate_address(u64 size, u64 flags, u64 alignment, vm::ptr<u32> alloc_addr)
|
||||
{
|
||||
sys_mmapper.Error("sys_mmapper_allocate_address(size=0x%llx, flags=0x%llx, alignment=0x%llx, alloc_addr=*0x%x)", size, flags, alignment, alloc_addr);
|
||||
|
||||
// Check page size.
|
||||
u32 addr;
|
||||
switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K))
|
||||
LV2_LOCK;
|
||||
|
||||
if (size % 0x10000000)
|
||||
{
|
||||
default:
|
||||
case SYS_MEMORY_PAGE_SIZE_1M:
|
||||
if(align(size, alignment) & 0xfffff)
|
||||
return CELL_EALIGN;
|
||||
addr = (u32)Memory.Alloc(size, 0x100000);
|
||||
break;
|
||||
|
||||
case SYS_MEMORY_PAGE_SIZE_64K:
|
||||
if (align(size, alignment) & 0xffff)
|
||||
return CELL_EALIGN;
|
||||
addr = (u32)Memory.Alloc(size, 0x10000);
|
||||
break;
|
||||
return CELL_EALIGN;
|
||||
}
|
||||
|
||||
// Write back the start address of the allocated area.
|
||||
vm::write32(alloc_addr, addr);
|
||||
if (size > UINT32_MAX)
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
switch (alignment)
|
||||
{
|
||||
case 0x10000000:
|
||||
case 0x20000000:
|
||||
case 0x40000000:
|
||||
case 0x80000000:
|
||||
{
|
||||
for (u32 addr = ::align(0x30000000, alignment); addr < 0xC0000000; addr += static_cast<u32>(alignment))
|
||||
{
|
||||
if (Memory.Map(addr, static_cast<u32>(size)))
|
||||
{
|
||||
*alloc_addr = addr;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_EALIGN;
|
||||
}
|
||||
|
||||
s32 sys_mmapper_allocate_fixed_address()
|
||||
{
|
||||
sys_mmapper.Warning("sys_mmapper_allocate_fixed_address");
|
||||
sys_mmapper.Error("sys_mmapper_allocate_fixed_address()");
|
||||
|
||||
// Allocate a fixed size from user memory.
|
||||
if (!Memory.Alloc(SYS_MMAPPER_FIXED_SIZE, 0x100000))
|
||||
LV2_LOCK;
|
||||
|
||||
if (!Memory.Map(0xB0000000, 0x10000000))
|
||||
{
|
||||
return CELL_EEXIST;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mmapper_allocate_memory(u32 size, u64 flags, vm::ptr<u32> mem_id)
|
||||
// Allocate physical memory (create lv2_memory_t object)
|
||||
s32 sys_mmapper_allocate_memory(u64 size, u64 flags, vm::ptr<u32> mem_id)
|
||||
{
|
||||
sys_mmapper.Warning("sys_mmapper_allocate_memory(size=0x%x, flags=0x%llx, mem_id_addr=0x%x)", size, flags, mem_id.addr());
|
||||
sys_mmapper.Warning("sys_mmapper_allocate_memory(size=0x%llx, flags=0x%llx, mem_id=*0x%x)", size, flags, mem_id);
|
||||
|
||||
// Check page granularity.
|
||||
switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K))
|
||||
LV2_LOCK;
|
||||
|
||||
// Check page granularity
|
||||
switch (flags & SYS_MEMORY_PAGE_SIZE_MASK)
|
||||
{
|
||||
case SYS_MEMORY_PAGE_SIZE_1M:
|
||||
if(size & 0xfffff)
|
||||
{
|
||||
if (size % 0x100000)
|
||||
{
|
||||
return CELL_EALIGN;
|
||||
break;
|
||||
}
|
||||
|
||||
case SYS_MEMORY_PAGE_SIZE_64K:
|
||||
if(size & 0xffff)
|
||||
return CELL_EALIGN;
|
||||
break;
|
||||
|
||||
default:
|
||||
return CELL_EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
// Generate a new mem ID.
|
||||
*mem_id = Emu.GetIdManager().make<mmapper_info>(size, flags);
|
||||
case SYS_MEMORY_PAGE_SIZE_64K:
|
||||
{
|
||||
if (size % 0x10000)
|
||||
{
|
||||
return CELL_EALIGN;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (size > UINT32_MAX)
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
const u32 align =
|
||||
flags & SYS_MEMORY_PAGE_SIZE_1M ? 0x100000 :
|
||||
flags & SYS_MEMORY_PAGE_SIZE_64K ? 0x10000 :
|
||||
throw EXCEPTION("Unexpected");
|
||||
|
||||
// Generate a new mem ID
|
||||
*mem_id = Emu.GetIdManager().make<lv2_memory_t>(static_cast<u32>(size), align, flags, nullptr);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mmapper_allocate_memory_from_container(u32 size, u32 cid, u64 flags, vm::ptr<u32> mem_id)
|
||||
{
|
||||
sys_mmapper.Warning("sys_mmapper_allocate_memory_from_container(size=0x%x, cid=0x%x, flags=0x%llx, mem_id_addr=0x%x)",
|
||||
size, cid, flags, mem_id.addr());
|
||||
sys_mmapper.Error("sys_mmapper_allocate_memory_from_container(size=0x%x, cid=0x%x, flags=0x%llx, mem_id=*0x%x)", size, cid, flags, mem_id);
|
||||
|
||||
LV2_LOCK;
|
||||
|
||||
// Check if this container ID is valid.
|
||||
const auto ct = Emu.GetIdManager().get<MemoryContainerInfo>(cid);
|
||||
const auto ct = Emu.GetIdManager().get<lv2_memory_container_t>(cid);
|
||||
|
||||
if (!ct)
|
||||
{
|
||||
|
@ -96,143 +138,224 @@ s32 sys_mmapper_allocate_memory_from_container(u32 size, u32 cid, u64 flags, vm:
|
|||
}
|
||||
|
||||
// Check page granularity.
|
||||
switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K))
|
||||
switch (flags & SYS_MEMORY_PAGE_SIZE_MASK)
|
||||
{
|
||||
case SYS_MEMORY_PAGE_SIZE_1M:
|
||||
if(size & 0xfffff)
|
||||
{
|
||||
if (size % 0x100000)
|
||||
{
|
||||
return CELL_EALIGN;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SYS_MEMORY_PAGE_SIZE_64K:
|
||||
if(size & 0xffff)
|
||||
{
|
||||
if (size % 0x10000)
|
||||
{
|
||||
return CELL_EALIGN;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ct->size - ct->taken < size)
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
const u32 align =
|
||||
flags & SYS_MEMORY_PAGE_SIZE_1M ? 0x100000 :
|
||||
flags & SYS_MEMORY_PAGE_SIZE_64K ? 0x10000 :
|
||||
throw EXCEPTION("Unexpected");
|
||||
|
||||
ct->taken += size;
|
||||
|
||||
// Generate a new mem ID
|
||||
*mem_id = Emu.GetIdManager().make<lv2_memory_t>(size, align, flags, ct);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mmapper_change_address_access_right(u32 addr, u64 flags)
|
||||
{
|
||||
sys_mmapper.Todo("sys_mmapper_change_address_access_right(addr=0x%x, flags=0x%llx)", addr, flags);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mmapper_free_address(u32 addr)
|
||||
{
|
||||
sys_mmapper.Error("sys_mmapper_free_address(addr=0x%x)", addr);
|
||||
|
||||
LV2_LOCK;
|
||||
|
||||
const auto area = Memory.Get(addr);
|
||||
|
||||
if (!area)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
ct->size = size;
|
||||
if (area->GetUsedSize())
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
// Generate a new mem ID.
|
||||
*mem_id = Emu.GetIdManager().make<mmapper_info>(ct->size, flags);
|
||||
if (Memory.Unmap(addr))
|
||||
{
|
||||
throw EXCEPTION("Unexpected (failed to unmap memory ad 0x%x)", addr);
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mmapper_change_address_access_right(u32 start_addr, u64 flags)
|
||||
{
|
||||
sys_mmapper.Warning("sys_mmapper_change_address_access_right(start_addr=0x%x, flags=0x%llx)", start_addr, flags);
|
||||
|
||||
// TODO
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mmapper_free_address(u32 start_addr)
|
||||
{
|
||||
sys_mmapper.Warning("sys_mmapper_free_address(start_addr=0x%x)", start_addr);
|
||||
|
||||
// Free the address.
|
||||
Memory.Free(start_addr);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mmapper_free_memory(u32 mem_id)
|
||||
{
|
||||
sys_mmapper.Warning("sys_mmapper_free_memory(mem_id=0x%x)", mem_id);
|
||||
|
||||
// Check if this mem ID is valid.
|
||||
const auto info = Emu.GetIdManager().get<mmapper_info>(mem_id);
|
||||
LV2_LOCK;
|
||||
|
||||
if (!info)
|
||||
// Check if this mem ID is valid.
|
||||
const auto mem = Emu.GetIdManager().get<lv2_memory_t>(mem_id);
|
||||
|
||||
if (!mem)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
// Release the allocated memory and remove the ID.
|
||||
Emu.GetIdManager().remove<mmapper_info>(mem_id);
|
||||
if (mem->addr)
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
// Return physical memory to the container if necessary
|
||||
if (mem->ct)
|
||||
{
|
||||
mem->ct->taken -= mem->size;
|
||||
}
|
||||
|
||||
// Release the allocated memory and remove the ID
|
||||
Emu.GetIdManager().remove<lv2_memory_t>(mem_id);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags)
|
||||
s32 sys_mmapper_map_memory(u32 addr, u32 mem_id, u64 flags)
|
||||
{
|
||||
sys_mmapper.Warning("sys_mmapper_map_memory(start_addr=0x%x, mem_id=0x%x, flags=0x%llx)", start_addr, mem_id, flags);
|
||||
sys_mmapper.Error("sys_mmapper_map_memory(addr=0x%x, mem_id=0x%x, flags=0x%llx)", addr, mem_id, flags);
|
||||
|
||||
// Check if this mem ID is valid.
|
||||
const auto info = Emu.GetIdManager().get<mmapper_info>(mem_id);
|
||||
LV2_LOCK;
|
||||
|
||||
if (!info)
|
||||
const auto area = Memory.Get(addr & 0xf0000000);
|
||||
|
||||
if (!area || addr < 0x30000000 || addr >= 0xC0000000)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
const auto mem = Emu.GetIdManager().get<lv2_memory_t>(mem_id);
|
||||
|
||||
if (!mem)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
// Map the memory into the process address.
|
||||
if(!Memory.Map(start_addr, info->size))
|
||||
sys_mmapper.Error("sys_mmapper_map_memory failed!");
|
||||
if (addr % mem->align)
|
||||
{
|
||||
return CELL_EALIGN;
|
||||
}
|
||||
|
||||
// Keep track of mapped addresses.
|
||||
mmapper_info_map[start_addr] = mem_id;
|
||||
if (mem->addr)
|
||||
{
|
||||
throw EXCEPTION("Already mapped (mem_id=0x%x, addr=0x%x)", mem_id, mem->addr.load());
|
||||
}
|
||||
|
||||
if (!area->AllocFixed(addr, mem->size))
|
||||
{
|
||||
return CELL_EBUSY;
|
||||
}
|
||||
|
||||
mem->addr = addr;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mmapper_search_and_map(u32 start_addr, u32 mem_id, u64 flags, u32 alloc_addr)
|
||||
s32 sys_mmapper_search_and_map(u32 start_addr, u32 mem_id, u64 flags, vm::ptr<u32> alloc_addr)
|
||||
{
|
||||
sys_mmapper.Warning("sys_mmapper_search_and_map(start_addr=0x%x, mem_id=0x%x, flags=0x%llx, alloc_addr=0x%x)",
|
||||
start_addr, mem_id, flags, alloc_addr);
|
||||
sys_mmapper.Error("sys_mmapper_search_and_map(start_addr=0x%x, mem_id=0x%x, flags=0x%llx, alloc_addr=*0x%x)", start_addr, mem_id, flags, alloc_addr);
|
||||
|
||||
// Check if this mem ID is valid.
|
||||
const auto info = Emu.GetIdManager().get<mmapper_info>(mem_id);
|
||||
LV2_LOCK;
|
||||
|
||||
if (!info)
|
||||
const auto area = Memory.Get(start_addr);
|
||||
|
||||
if (!area || start_addr < 0x30000000 || start_addr >= 0xC0000000)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
const auto mem = Emu.GetIdManager().get<lv2_memory_t>(mem_id);
|
||||
|
||||
if (!mem)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
// Search for a mappable address.
|
||||
u32 addr;
|
||||
bool found;
|
||||
for (int i = 0; i < SYS_MMAPPER_FIXED_SIZE; i += 0x100000)
|
||||
|
||||
const u32 addr = area->AllocAlign(mem->size, mem->align);
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
addr = start_addr + i;
|
||||
found = Memory.Map(addr, info->size);
|
||||
if(found)
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
*alloc_addr = addr;
|
||||
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
s32 sys_mmapper_unmap_memory(u32 addr, vm::ptr<u32> mem_id)
|
||||
{
|
||||
sys_mmapper.Todo("sys_mmapper_unmap_memory(addr=0x%x, mem_id=*0x%x)", addr, mem_id);
|
||||
|
||||
LV2_LOCK;
|
||||
|
||||
const auto area = Memory.Get(addr);
|
||||
|
||||
if (!area || addr < 0x30000000 || addr >= 0xC0000000)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
for (auto& mem : Emu.GetIdManager().get_all<lv2_memory_t>())
|
||||
{
|
||||
if (mem->addr == addr)
|
||||
{
|
||||
sys_mmapper.Warning("Found and mapped address 0x%x", addr);
|
||||
break;
|
||||
if (!area->Free(addr))
|
||||
{
|
||||
throw EXCEPTION("Not mapped (mem_id=0x%x, addr=0x%x)", mem->id, addr);
|
||||
}
|
||||
|
||||
mem->addr = 0;
|
||||
|
||||
*mem_id = mem->id;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return CELL_ENOMEM;
|
||||
|
||||
// Write back the start address of the allocated area.
|
||||
vm::write32(alloc_addr, addr);
|
||||
|
||||
// Keep track of mapped addresses.
|
||||
mmapper_info_map[addr] = mem_id;
|
||||
|
||||
return CELL_OK;
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
s32 sys_mmapper_unmap_memory(u32 start_addr, u32 mem_id_addr)
|
||||
s32 sys_mmapper_enable_page_fault_notification(u32 addr, u32 eq)
|
||||
{
|
||||
sys_mmapper.Warning("sys_mmapper_unmap_memory(start_addr=0x%x, mem_id_addr=0x%x)", start_addr, mem_id_addr);
|
||||
|
||||
// Write back the mem ID of the unmapped area.
|
||||
u32 mem_id = mmapper_info_map.find(start_addr)->second;
|
||||
vm::write32(mem_id_addr, mem_id);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_mmapper_enable_page_fault_notification(u32 start_addr, u32 q_id)
|
||||
{
|
||||
sys_mmapper.Warning("sys_mmapper_enable_page_fault_notification(start_addr=0x%x, q_id=0x%x)", start_addr, q_id);
|
||||
|
||||
// TODO
|
||||
sys_mmapper.Todo("sys_mmapper_enable_page_fault_notification(addr=0x%x, eq=0x%x)", addr, eq);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
|
@ -1,37 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#include "sys_memory.h"
|
||||
|
||||
namespace vm { using namespace ps3; }
|
||||
|
||||
#define SYS_MMAPPER_FIXED_ADDR 0xB0000000
|
||||
#define SYS_MMAPPER_FIXED_SIZE 0x10000000
|
||||
|
||||
struct mmapper_info
|
||||
struct lv2_memory_t
|
||||
{
|
||||
u32 size;
|
||||
u64 flags;
|
||||
const u32 size; // memory size
|
||||
const u32 align; // required alignment
|
||||
const u32 id;
|
||||
const u64 flags;
|
||||
const std::shared_ptr<lv2_memory_container_t> ct; // memory container the physical memory is taken from
|
||||
|
||||
mmapper_info(u32 _size, u64 _flags)
|
||||
: size(_size)
|
||||
, flags(_flags)
|
||||
{
|
||||
}
|
||||
std::atomic<u32> addr{ 0 }; // actual mapping address
|
||||
|
||||
mmapper_info()
|
||||
{
|
||||
}
|
||||
lv2_memory_t(u32 size, u32 align, u64 flags, const std::shared_ptr<lv2_memory_container_t> ct);
|
||||
};
|
||||
|
||||
REG_ID_TYPE(mmapper_info, 0x08); // SYS_MEM_OBJECT
|
||||
REG_ID_TYPE(lv2_memory_t, 0x08); // SYS_MEM_OBJECT
|
||||
|
||||
// SysCalls
|
||||
s32 sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_addr);
|
||||
s32 sys_mmapper_allocate_address(u64 size, u64 flags, u64 alignment, vm::ptr<u32> alloc_addr);
|
||||
s32 sys_mmapper_allocate_fixed_address();
|
||||
s32 sys_mmapper_allocate_memory(u32 size, u64 flags, vm::ptr<u32> mem_id);
|
||||
s32 sys_mmapper_allocate_memory(u64 size, u64 flags, vm::ptr<u32> mem_id);
|
||||
s32 sys_mmapper_allocate_memory_from_container(u32 size, u32 cid, u64 flags, vm::ptr<u32> mem_id);
|
||||
s32 sys_mmapper_change_address_access_right(u32 start_addr, u64 flags);
|
||||
s32 sys_mmapper_free_address(u32 start_addr);
|
||||
s32 sys_mmapper_change_address_access_right(u32 addr, u64 flags);
|
||||
s32 sys_mmapper_free_address(u32 addr);
|
||||
s32 sys_mmapper_free_memory(u32 mem_id);
|
||||
s32 sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags);
|
||||
s32 sys_mmapper_search_and_map(u32 start_addr, u32 mem_id, u64 flags, u32 alloc_addr);
|
||||
s32 sys_mmapper_unmap_memory(u32 start_addr, u32 mem_id_addr);
|
||||
s32 sys_mmapper_enable_page_fault_notification(u32 start_addr, u32 q_id);
|
||||
s32 sys_mmapper_map_memory(u32 addr, u32 mem_id, u64 flags);
|
||||
s32 sys_mmapper_search_and_map(u32 start_addr, u32 mem_id, u64 flags, vm::ptr<u32> alloc_addr);
|
||||
s32 sys_mmapper_unmap_memory(u32 addr, vm::ptr<u32> mem_id);
|
||||
s32 sys_mmapper_enable_page_fault_notification(u32 addr, u32 eq);
|
||||
|
|
|
@ -1311,7 +1311,7 @@ s32 sys_raw_spu_set_spu_cfg(u32 id, u32 value)
|
|||
|
||||
if (value > 3)
|
||||
{
|
||||
sys_spu.Fatal("sys_raw_spu_set_spu_cfg(id=%d, value=0x%x)", id, value);
|
||||
throw EXCEPTION("Unexpected value (0x%x)", value);
|
||||
}
|
||||
|
||||
const auto thread = Emu.GetCPU().GetRawSPUThread(id);
|
||||
|
|
|
@ -8,55 +8,24 @@
|
|||
#include "sys_vm.h"
|
||||
|
||||
SysCallBase sys_vm("sys_vm");
|
||||
std::shared_ptr<MemoryContainerInfo> current_ct;
|
||||
|
||||
s32 sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 addr)
|
||||
s32 sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, vm::ptr<u32> addr)
|
||||
{
|
||||
sys_vm.Error("sys_vm_memory_map(vsize=0x%x, psize=0x%x, cid=0x%x, flags=0x%llx, policy=0x%llx, addr_addr=0x%x)",
|
||||
vsize, psize, cid, flag, policy, addr);
|
||||
sys_vm.Error("sys_vm_memory_map(vsize=0x%x, psize=0x%x, cid=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;
|
||||
}
|
||||
LV2_LOCK;
|
||||
|
||||
// Use fixed address (TODO: search and use some free address instead)
|
||||
u32 new_addr = vm::check_addr(0x60000000) ? 0x70000000 : 0x60000000;
|
||||
const u32 new_addr = vm::check_addr(0x60000000) ? 0x70000000 : 0x60000000;
|
||||
|
||||
// If container ID is SYS_MEMORY_CONTAINER_ID_INVALID, allocate directly.
|
||||
if(cid == SYS_MEMORY_CONTAINER_ID_INVALID)
|
||||
{
|
||||
// Create a new MemoryContainerInfo to act as default container with vsize.
|
||||
current_ct.reset(new MemoryContainerInfo(new_addr, vsize));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check memory container.
|
||||
const auto ct = Emu.GetIdManager().get<MemoryContainerInfo>(cid);
|
||||
|
||||
if (!ct)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
current_ct = ct;
|
||||
}
|
||||
|
||||
// Allocate actual memory using virtual size (physical size is ignored)
|
||||
// Map memory
|
||||
if (!Memory.Map(new_addr, vsize))
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
// Write a pointer for the allocated memory.
|
||||
vm::write32(addr, new_addr);
|
||||
*addr = new_addr;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -65,211 +34,99 @@ s32 sys_vm_unmap(u32 addr)
|
|||
{
|
||||
sys_vm.Error("sys_vm_unmap(addr=0x%x)", addr);
|
||||
|
||||
// Unmap memory.
|
||||
assert(addr == 0x60000000 || addr == 0x70000000);
|
||||
if(!Memory.Unmap(addr)) return CELL_EINVAL;
|
||||
LV2_LOCK;
|
||||
|
||||
if (!Memory.Unmap(addr))
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_vm_append_memory(u32 addr, u32 size)
|
||||
{
|
||||
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;
|
||||
sys_vm.Todo("sys_vm_append_memory(addr=0x%x, size=0x%x)", addr, size);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_vm_return_memory(u32 addr, u32 size)
|
||||
{
|
||||
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;
|
||||
sys_vm.Todo("sys_vm_return_memory(addr=0x%x, size=0x%x)", addr, size);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_vm_lock(u32 addr, u32 size)
|
||||
{
|
||||
sys_vm.Todo("sys_vm_lock(addr=0x%x,size=0x%x)", addr, size);
|
||||
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;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
sys_vm.Todo("sys_vm_unlock(addr=0x%x,size=0x%x)", addr, size);
|
||||
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;
|
||||
}
|
||||
|
||||
// TODO: Unlock
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_vm_touch(u32 addr, u32 size)
|
||||
{
|
||||
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.
|
||||
sys_vm.Todo("sys_vm_touch(addr=0x%x, size=0x%x)", addr, size);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_vm_flush(u32 addr, u32 size)
|
||||
{
|
||||
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.
|
||||
sys_vm.Todo("sys_vm_flush(addr=0x%x, size=0x%x)", addr, size);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_vm_invalidate(u32 addr, u32 size)
|
||||
{
|
||||
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.
|
||||
sys_vm.Todo("sys_vm_invalidate(addr=0x%x, size=0x%x)", addr, size);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_vm_store(u32 addr, u32 size)
|
||||
{
|
||||
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.
|
||||
sys_vm.Todo("sys_vm_store(addr=0x%x, size=0x%x)", addr, size);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_vm_sync(u32 addr, u32 size)
|
||||
{
|
||||
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.
|
||||
sys_vm.Todo("sys_vm_sync(addr=0x%x, size=0x%x)", addr, size);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_vm_test(u32 addr, u32 size, vm::ptr<u64> result)
|
||||
{
|
||||
sys_vm.Todo("sys_vm_test(addr=0x%x, size=0x%x, result_addr=0x%x)", addr, size, result.addr());
|
||||
sys_vm.Todo("sys_vm_test(addr=0x%x, size=0x%x, result=*0x%x)", addr, size, result);
|
||||
|
||||
// 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.
|
||||
*result = SYS_VM_TEST_ALLOCATED;
|
||||
*result = SYS_VM_STATE_ON_MEMORY;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_vm_get_statistics(u32 addr, vm::ptr<sys_vm_statistics> stat)
|
||||
s32 sys_vm_get_statistics(u32 addr, vm::ptr<sys_vm_statistics_t> stat)
|
||||
{
|
||||
sys_vm.Todo("sys_vm_get_statistics(addr=0x%x, stat_addr=0x%x)", addr, stat.addr());
|
||||
sys_vm.Todo("sys_vm_get_statistics(addr=0x%x, stat=*0x%x)", addr, stat);
|
||||
|
||||
// Check address.
|
||||
if(current_ct->addr != addr)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
// TODO
|
||||
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_total = 0;
|
||||
stat->pmem_used = 0;
|
||||
stat->timestamp = 0;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,13 @@ namespace vm { using namespace ps3; }
|
|||
|
||||
enum : u64
|
||||
{
|
||||
SYS_VM_TEST_INVALID = 0,
|
||||
SYS_VM_TEST_UNUSED = 1,
|
||||
SYS_VM_TEST_ALLOCATED = 2,
|
||||
SYS_VM_TEST_STORED = 4,
|
||||
SYS_VM_STATE_INVALID = 0ull,
|
||||
SYS_VM_STATE_UNUSED = 1ull,
|
||||
SYS_VM_STATE_ON_MEMORY = 2ull,
|
||||
SYS_VM_STATE_STORED = 4ull,
|
||||
};
|
||||
|
||||
struct sys_vm_statistics
|
||||
struct sys_vm_statistics_t
|
||||
{
|
||||
be_t<u64> page_fault_ppu; // Number of bad virtual memory accesses from a PPU thread.
|
||||
be_t<u64> page_fault_spu; // Number of bad virtual memory accesses from a SPU thread.
|
||||
|
@ -22,7 +22,7 @@ struct sys_vm_statistics
|
|||
};
|
||||
|
||||
// SysCalls
|
||||
s32 sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, u32 addr);
|
||||
s32 sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy, vm::ptr<u32> addr);
|
||||
s32 sys_vm_unmap(u32 addr);
|
||||
s32 sys_vm_append_memory(u32 addr, u32 size);
|
||||
s32 sys_vm_return_memory(u32 addr, u32 size);
|
||||
|
@ -34,4 +34,4 @@ s32 sys_vm_invalidate(u32 addr, u32 size);
|
|||
s32 sys_vm_store(u32 addr, u32 size);
|
||||
s32 sys_vm_sync(u32 addr, u32 size);
|
||||
s32 sys_vm_test(u32 addr, u32 size, vm::ptr<u64> result);
|
||||
s32 sys_vm_get_statistics(u32 addr, vm::ptr<sys_vm_statistics> stat);
|
||||
s32 sys_vm_get_statistics(u32 addr, vm::ptr<sys_vm_statistics_t> stat);
|
||||
|
|
|
@ -120,7 +120,9 @@ MainFrame::MainFrame()
|
|||
menu_help->Append(id_help_about, "&About...");
|
||||
|
||||
SetMenuBar(menubar);
|
||||
#ifdef _WIN32
|
||||
SetIcon(wxICON(frame_icon));
|
||||
#endif
|
||||
|
||||
// Panels
|
||||
m_log_frame = new LogFrame(this);
|
||||
|
|
|
@ -95,30 +95,30 @@ struct explicit_bool_t
|
|||
};
|
||||
|
||||
// return 32 bit sizeof() to avoid widening/narrowing conversions with size_t
|
||||
#define sizeof32(type) sizeof32_t<sizeof(type)>::value
|
||||
#define sizeof32(type) static_cast<u32>(sizeof32_t<sizeof(type)>::value)
|
||||
|
||||
// return 32 bit alignof() to avoid widening/narrowing conversions with size_t
|
||||
#define alignof32(type) alignof32_t<__alignof(type)>::value
|
||||
#define alignof32(type) static_cast<u32>(alignof32_t<__alignof(type)>::value)
|
||||
|
||||
template<std::size_t Size> struct sizeof32_t
|
||||
{
|
||||
static_assert(Size <= UINT32_MAX, "sizeof32() error: size is too big");
|
||||
|
||||
static const u32 value = static_cast<u32>(Size);
|
||||
enum : u32 { value = static_cast<u32>(Size) };
|
||||
};
|
||||
|
||||
template<std::size_t Align> struct alignof32_t
|
||||
{
|
||||
static_assert(Align <= UINT32_MAX, "alignof32() error: alignment is too big");
|
||||
|
||||
static const u32 value = static_cast<u32>(Align);
|
||||
enum : u32 { value = static_cast<u32>(Align) };
|
||||
};
|
||||
|
||||
template<typename T> using func_def = T; // workaround for MSVC bug: `using X = func_def<void()>;` instead of `using X = void();`
|
||||
|
||||
template<typename T> struct ID_type;
|
||||
|
||||
#define REG_ID_TYPE(t, id) template<> struct ID_type<t> { static const u32 type = id; }
|
||||
#define REG_ID_TYPE(t, id) template<> struct ID_type<t> { enum : u32 { type = id }; }
|
||||
|
||||
#define CHECK_SIZE(type, size) static_assert(sizeof(type) == size, "Invalid " #type " type size")
|
||||
#define CHECK_ALIGN(type, align) static_assert(__alignof(type) == align, "Invalid " #type " type alignment")
|
||||
|
|
Loading…
Add table
Reference in a new issue