From 2d37c6b5e2b9bfd37db6754befe56144beff0067 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 10 Jul 2015 17:45:16 +0300 Subject: [PATCH] sys_memory, sys_mmapper rewritten LogBase::Fatal() removed --- rpcs3/Emu/Cell/PPULLVMRecompiler.cpp | 6 +- rpcs3/Emu/Cell/RawSPUThread.cpp | 6 +- rpcs3/Emu/Memory/Memory.cpp | 37 +- rpcs3/Emu/Memory/Memory.h | 12 +- rpcs3/Emu/SysCalls/LogBase.cpp | 3 +- rpcs3/Emu/SysCalls/LogBase.h | 6 - rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellVdec.cpp | 12 +- rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 15 +- rpcs3/Emu/SysCalls/lv2/sys_fs.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/sys_memory.cpp | 268 +++++++++---- rpcs3/Emu/SysCalls/lv2/sys_memory.h | 31 +- rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp | 383 ++++++++++++------- rpcs3/Emu/SysCalls/lv2/sys_mmapper.h | 42 +- rpcs3/Emu/SysCalls/lv2/sys_spu.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/sys_vm.cpp | 199 ++-------- rpcs3/Emu/SysCalls/lv2/sys_vm.h | 14 +- rpcs3/Gui/MainFrame.cpp | 2 + rpcs3/stdafx.h | 10 +- 20 files changed, 598 insertions(+), 456 deletions(-) diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp index 9fc9127815..bd862d6792 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp @@ -3292,10 +3292,10 @@ void Compiler::MFSPR(u32 rd, u32 spr) { rd_i64 = GetVrsave(); break; case 0x10C: - rd_i64 = Call("get_timebased_time", get_timebased_time); + rd_i64 = Call("get_timebased_time", get_timebased_time); break; case 0x10D: - rd_i64 = Call("get_timebased_time", get_timebased_time); + rd_i64 = Call("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("get_timebased_time", get_timebased_time); + auto tb_i64 = Call("get_timebased_time", get_timebased_time); u32 n = (spr >> 5) | ((spr & 0x1f) << 5); if (n == 0x10D) { diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index c5c7ded764..4dcd291081 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -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() diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index c3feff6e35..25d21fd717 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -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 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 lock(Memory.mutex); + + for (auto& block : MemoryBlocks) + { + if (block->GetStartAddr() == addr) + { + return block; + } + } + + return nullptr; +} + MemBlockInfo::MemBlockInfo(u32 addr, u32 size) : MemInfo(addr, size) { diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index 01d0713f8f..c21b34bb49 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -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; diff --git a/rpcs3/Emu/SysCalls/LogBase.cpp b/rpcs3/Emu/SysCalls/LogBase.cpp index fb70d09dcd..eaf112e0fb 100644 --- a/rpcs3/Emu/SysCalls/LogBase.cpp +++ b/rpcs3/Emu/SysCalls/LogBase.cpp @@ -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()); } } diff --git a/rpcs3/Emu/SysCalls/LogBase.h b/rpcs3/Emu/SysCalls/LogBase.h index d2332957e1..f5f94455a4 100644 --- a/rpcs3/Emu/SysCalls/LogBase.h +++ b/rpcs3/Emu/SysCalls/LogBase.h @@ -11,7 +11,6 @@ class LogBase LogSuccess, LogWarning, LogError, - LogFatal, LogTodo, }; @@ -63,11 +62,6 @@ public: LogPrepare(LogError, fmt, fmt::do_unveil(args)...); } - template force_inline void Fatal(const char* fmt, Args... args) const - { - LogPrepare(LogFatal, fmt, fmt::do_unveil(args)...); - } - template force_inline void Todo(const char* fmt, Args... args) const { LogPrepare(LogTodo, fmt, fmt::do_unveil(args)...); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index 825576cfd3..524d5973fc 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -777,7 +777,7 @@ s32 cellAdecGetPcm(u32 handle, vm::ptr 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); } } diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 9b83006f4b..b28068ee79 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -645,7 +645,7 @@ s32 cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, vm::cptr format, vm::ptrcolorMatrixType != 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 format, vm::ptr 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 format(CPU); @@ -924,7 +924,7 @@ s32 cellVdecGetPicItem(u32 handle, vm::pptr picItem) { auto mp2 = vm::ptr::make(info.addr() + sizeof32(CellVdecPicItem)); - cellVdec.Fatal("cellVdecGetPicItem(MPEG2)"); + throw EXCEPTION("MPEG2"); } *picItem = info; diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index 0bfae70978..4b4d4dc9c0 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -230,7 +230,7 @@ s32 sys_lwmutex_lock(PPUThread& CPU, vm::ptr 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 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 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 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 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 buffer) diff --git a/rpcs3/Emu/SysCalls/lv2/sys_fs.cpp b/rpcs3/Emu/SysCalls/lv2/sys_fs.cpp index 9c28eff974..76213f1c3d 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_fs.cpp @@ -97,7 +97,7 @@ s32 sys_fs_open(vm::cptr path, s32 flags, vm::ptr 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 file(Emu.GetVFS().OpenFile(path.get_ptr(), open_mode)); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp index 8bb547cb24..606f738426 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_lwmutex.cpp @@ -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++; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_memory.cpp b/rpcs3/Emu/SysCalls/lv2/sys_memory.cpp index bfdcd3a4a4..e680fb1372 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_memory.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_memory.cpp @@ -5,95 +5,196 @@ #include "Emu/SysCalls/SysCalls.h" #include "sys_memory.h" -#include 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 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()) + { + 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 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(cid); + LV2_LOCK; + + // Check if this container ID is valid + const auto ct = Emu.GetIdManager().get(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()) + { + 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 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 attr) s32 sys_memory_get_user_memory_size(vm::ptr 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()) + { + 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 cid, u32 yield_size) +s32 sys_memory_container_create(vm::ptr 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(addr, yield_size); + u32 reserved = 0; + u32 available = 0; + + // Check all memory containers + for (auto& ct : Emu.GetIdManager().get_all()) + { + 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(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(cid); + LV2_LOCK; + + const auto ct = Emu.GetIdManager().get(cid); if (!ct) { return CELL_ESRCH; } - // Release the allocated memory and remove the ID. - Memory.Free(ct->addr); - Emu.GetIdManager().remove(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(cid); return CELL_OK; } s32 sys_memory_container_get_size(vm::ptr 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(cid); + LV2_LOCK; + + const auto ct = Emu.GetIdManager().get(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; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_memory.h b/rpcs3/Emu/SysCalls/lv2/sys_memory.h index 998c39e095..8d39e3afb6 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_memory.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_memory.h @@ -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 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 taken{ 0 }; + + // allocations (addr -> size) + std::map 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 alloc_addr); +s32 sys_memory_allocate_from_container(u32 size, u32 cid, u64 flags, vm::ptr alloc_addr); s32 sys_memory_free(u32 start_addr); s32 sys_memory_get_page_attribute(u32 addr, vm::ptr attr); s32 sys_memory_get_user_memory_size(vm::ptr mem_info); -s32 sys_memory_container_create(vm::ptr cid, u32 yield_size); +s32 sys_memory_container_create(vm::ptr cid, u32 size); s32 sys_memory_container_destroy(u32 cid); s32 sys_memory_container_get_size(vm::ptr mem_info, u32 cid); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp b/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp index cbb6f03e1c..072da9908e 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp @@ -4,91 +4,133 @@ #include "Emu/IdManager.h" #include "Emu/SysCalls/SysCalls.h" -#include "sys_memory.h" #include "sys_mmapper.h" -#include SysCallBase sys_mmapper("sys_mmapper"); -std::map 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 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 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(alignment)) + { + if (Memory.Map(addr, static_cast(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 mem_id) +// Allocate physical memory (create lv2_memory_t object) +s32 sys_mmapper_allocate_memory(u64 size, u64 flags, vm::ptr 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(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(static_cast(size), align, flags, nullptr); return CELL_OK; } s32 sys_mmapper_allocate_memory_from_container(u32 size, u32 cid, u64 flags, vm::ptr 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(cid); + const auto ct = Emu.GetIdManager().get(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(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(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(mem_id); + LV2_LOCK; - if (!info) + // Check if this mem ID is valid. + const auto mem = Emu.GetIdManager().get(mem_id); + + if (!mem) { return CELL_ESRCH; } - // Release the allocated memory and remove the ID. - Emu.GetIdManager().remove(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(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(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(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 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(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(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 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()) + { + 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; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mmapper.h b/rpcs3/Emu/SysCalls/lv2/sys_mmapper.h index cb1ed3aff2..def4821277 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mmapper.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_mmapper.h @@ -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 ct; // memory container the physical memory is taken from - mmapper_info(u32 _size, u64 _flags) - : size(_size) - , flags(_flags) - { - } + std::atomic addr{ 0 }; // actual mapping address - mmapper_info() - { - } + lv2_memory_t(u32 size, u32 align, u64 flags, const std::shared_ptr 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 alloc_addr); s32 sys_mmapper_allocate_fixed_address(); -s32 sys_mmapper_allocate_memory(u32 size, u64 flags, vm::ptr mem_id); +s32 sys_mmapper_allocate_memory(u64 size, u64 flags, vm::ptr mem_id); s32 sys_mmapper_allocate_memory_from_container(u32 size, u32 cid, u64 flags, vm::ptr 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 alloc_addr); +s32 sys_mmapper_unmap_memory(u32 addr, vm::ptr mem_id); +s32 sys_mmapper_enable_page_fault_notification(u32 addr, u32 eq); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp index a867213b3f..4a7b53fc8e 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp @@ -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); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp b/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp index cb9f9b65ff..df3cce16a5 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_vm.cpp @@ -8,55 +8,24 @@ #include "sys_vm.h" SysCallBase sys_vm("sys_vm"); -std::shared_ptr 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 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(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 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 stat) +s32 sys_vm_get_statistics(u32 addr, vm::ptr 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; -} \ No newline at end of file +} diff --git a/rpcs3/Emu/SysCalls/lv2/sys_vm.h b/rpcs3/Emu/SysCalls/lv2/sys_vm.h index fced0279d6..cce3134611 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_vm.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_vm.h @@ -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 page_fault_ppu; // Number of bad virtual memory accesses from a PPU thread. be_t 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 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 result); -s32 sys_vm_get_statistics(u32 addr, vm::ptr stat); +s32 sys_vm_get_statistics(u32 addr, vm::ptr stat); diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index d6882a71c3..79594e8c8f 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -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); diff --git a/rpcs3/stdafx.h b/rpcs3/stdafx.h index 12dfe69691..c1bd53db80 100644 --- a/rpcs3/stdafx.h +++ b/rpcs3/stdafx.h @@ -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::value +#define sizeof32(type) static_cast(sizeof32_t::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(alignof32_t<__alignof(type)>::value) template struct sizeof32_t { static_assert(Size <= UINT32_MAX, "sizeof32() error: size is too big"); - static const u32 value = static_cast(Size); + enum : u32 { value = static_cast(Size) }; }; template struct alignof32_t { static_assert(Align <= UINT32_MAX, "alignof32() error: alignment is too big"); - static const u32 value = static_cast(Align); + enum : u32 { value = static_cast(Align) }; }; template using func_def = T; // workaround for MSVC bug: `using X = func_def;` instead of `using X = void();` template struct ID_type; -#define REG_ID_TYPE(t, id) template<> struct ID_type { static const u32 type = id; } +#define REG_ID_TYPE(t, id) template<> struct ID_type { 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")