From 02f3e37c4fd85f1f71e033b14087548e8f7e4a41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=97=B1=20PixelyIon?= Date: Sun, 4 Oct 2020 23:48:34 +0530 Subject: [PATCH] Remove KProcess Memory Functions --- .../main/cpp/skyline/gpu/memory_manager.cpp | 40 +++---- app/src/main/cpp/skyline/gpu/memory_manager.h | 12 +-- app/src/main/cpp/skyline/gpu/texture.cpp | 10 +- app/src/main/cpp/skyline/gpu/texture.h | 4 +- app/src/main/cpp/skyline/kernel/ipc.cpp | 34 +++--- app/src/main/cpp/skyline/kernel/ipc.h | 12 ++- app/src/main/cpp/skyline/kernel/memory.cpp | 3 +- app/src/main/cpp/skyline/kernel/memory.h | 4 +- app/src/main/cpp/skyline/kernel/svc.cpp | 102 +++++++++--------- .../cpp/skyline/kernel/types/KProcess.cpp | 81 +++----------- .../main/cpp/skyline/kernel/types/KProcess.h | 78 ++------------ app/src/main/cpp/skyline/loader/loader.cpp | 12 +-- app/src/main/cpp/skyline/loader/loader.h | 2 +- app/src/main/cpp/skyline/loader/nca.cpp | 6 +- app/src/main/cpp/skyline/nce.cpp | 23 ++-- app/src/main/cpp/skyline/nce.h | 4 +- .../cpp/skyline/services/audio/IAudioOut.cpp | 11 +- .../services/audio/IAudioRenderer/voice.cpp | 7 +- .../services/audio/IAudioRenderer/voice.h | 4 +- .../hosbinder/GraphicBufferProducer.cpp | 2 +- .../services/nvdrv/devices/nvhost_as_gpu.cpp | 16 +-- .../services/nvdrv/devices/nvhost_as_gpu.h | 2 +- .../services/nvdrv/devices/nvhost_channel.cpp | 10 +- .../skyline/services/nvdrv/devices/nvmap.cpp | 14 +-- .../skyline/services/nvdrv/devices/nvmap.h | 8 +- 25 files changed, 192 insertions(+), 309 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu/memory_manager.cpp b/app/src/main/cpp/skyline/gpu/memory_manager.cpp index 48c9edb0..8707f85a 100644 --- a/app/src/main/cpp/skyline/gpu/memory_manager.cpp +++ b/app/src/main/cpp/skyline/gpu/memory_manager.cpp @@ -41,7 +41,7 @@ namespace skyline::gpu::vmm { } if (extension) - chunks.insert(std::next(chunk), ChunkDescriptor(newChunk.address + newChunk.size, extension, (oldChunk.state == ChunkState::Mapped) ? (oldChunk.cpuAddress + newSize + newChunk.size) : 0, oldChunk.state)); + chunks.insert(std::next(chunk), ChunkDescriptor(newChunk.address + newChunk.size, extension, (oldChunk.state == ChunkState::Mapped) ? (oldChunk.pointer + newSize + newChunk.size) : 0, oldChunk.state)); return newChunk.address; } else if (chunk->address + chunk->size > newChunk.address) { @@ -65,7 +65,7 @@ namespace skyline::gpu::vmm { tailChunk->address += chunkSliceOffset; tailChunk->size -= chunkSliceOffset; if (tailChunk->state == ChunkState::Mapped) - tailChunk->cpuAddress += chunkSliceOffset; + tailChunk->pointer += chunkSliceOffset; // If the size of the head chunk is zero then we can directly replace it with our new one rather than inserting it auto headChunk{std::prev(tailChunk)}; @@ -103,27 +103,27 @@ namespace skyline::gpu::vmm { return InsertChunk(ChunkDescriptor(address, size, 0, ChunkState::Reserved)); } - u64 MemoryManager::MapAllocate(u64 address, u64 size) { + u64 MemoryManager::MapAllocate(u8 *pointer, u64 size) { size = util::AlignUp(size, constant::GpuPageSize); auto mappedChunk{FindChunk(ChunkState::Unmapped, size)}; if (!mappedChunk) return 0; auto chunk{*mappedChunk}; - chunk.cpuAddress = address; + chunk.pointer = pointer; chunk.size = size; chunk.state = ChunkState::Mapped; return InsertChunk(chunk); } - u64 MemoryManager::MapFixed(u64 address, u64 cpuAddress, u64 size) { - if (!util::IsAligned(address, constant::GpuPageSize)) - return 0; + u64 MemoryManager::MapFixed(u64 address, u8 *pointer, u64 size) { + if (!util::IsAligned(pointer, constant::GpuPageSize)) + return false; size = util::AlignUp(size, constant::GpuPageSize); - return InsertChunk(ChunkDescriptor(address, size, cpuAddress, ChunkState::Mapped)); + return InsertChunk(ChunkDescriptor(address, size, pointer, ChunkState::Mapped)); } bool MemoryManager::Unmap(u64 address, u64 size) { @@ -151,20 +151,20 @@ namespace skyline::gpu::vmm { u64 initialSize{size}; u64 chunkOffset{address - chunk->address}; - u64 readAddress{chunk->cpuAddress + chunkOffset}; - u64 readSize{std::min(chunk->size - chunkOffset, size)}; + u8 *source{chunk->pointer + chunkOffset}; + u64 sourceSize{std::min(chunk->size - chunkOffset, size)}; // A continuous region in the GPU address space may be made up of several discontinuous regions in physical memory so we have to iterate over all chunks while (size) { - state.process->ReadMemory(destination + (initialSize - size), readAddress, readSize); + std::memcpy(destination + (initialSize - size), source, sourceSize); - size -= readSize; + size -= sourceSize; if (size) { if (++chunk == chunks.end() || chunk->state != ChunkState::Mapped) throw exception("Failed to read region in GPU address space: Address: 0x{:X}, Size: 0x{:X}", address, size); - readAddress = chunk->cpuAddress; - readSize = std::min(chunk->size, size); + source = chunk->pointer; + sourceSize = std::min(chunk->size, size); } } } @@ -181,20 +181,20 @@ namespace skyline::gpu::vmm { u64 initialSize{size}; u64 chunkOffset{address - chunk->address}; - u64 writeAddress{chunk->cpuAddress + chunkOffset}; - u64 writeSize{std::min(chunk->size - chunkOffset, size)}; + u8 *destination{chunk->pointer + chunkOffset}; + u64 destinationSize{std::min(chunk->size - chunkOffset, size)}; // A continuous region in the GPU address space may be made up of several discontinuous regions in physical memory so we have to iterate over all chunks while (size) { - state.process->WriteMemory(source + (initialSize - size), writeAddress, writeSize); + std::memcpy(destination, source + (initialSize - size), destinationSize); - size -= writeSize; + size -= destinationSize; if (size) { if (++chunk == chunks.end() || chunk->state != ChunkState::Mapped) throw exception("Failed to write region in GPU address space: Address: 0x{:X}, Size: 0x{:X}", address, size); - writeAddress = chunk->cpuAddress; - writeSize = std::min(chunk->size, size); + destination = chunk->pointer; + destinationSize = std::min(chunk->size, size); } } } diff --git a/app/src/main/cpp/skyline/gpu/memory_manager.h b/app/src/main/cpp/skyline/gpu/memory_manager.h index 3fe60224..905dbf32 100644 --- a/app/src/main/cpp/skyline/gpu/memory_manager.h +++ b/app/src/main/cpp/skyline/gpu/memory_manager.h @@ -20,10 +20,10 @@ namespace skyline { struct ChunkDescriptor { u64 address; //!< The address of the chunk in the GPU address space u64 size; //!< The size of the chunk in bytes - u64 cpuAddress; //!< The address of the chunk in the CPU address space (if mapped) + u8* pointer; //!< A pointer to the chunk in the CPU address space (if mapped) ChunkState state; - ChunkDescriptor(u64 address, u64 size, u64 cpuAddress, ChunkState state) : address(address), size(size), cpuAddress(cpuAddress), state(state) {} + ChunkDescriptor(u64 address, u64 size, u8* pointer, ChunkState state) : address(address), size(size), pointer(pointer), state(state) {} /** * @return If the given chunk can be contained wholly within this chunk @@ -78,20 +78,20 @@ namespace skyline { /** * @brief Maps a physical CPU memory region to an automatically chosen virtual memory region - * @param address The physical CPU address of the region to be mapped into the GPU's address space + * @param pointer A pointer to the region to be mapped into the GPU's address space * @param size The size of the region to map * @return The virtual address of the region base */ - u64 MapAllocate(u64 address, u64 size); + u64 MapAllocate(u8* pointer, u64 size); /** * @brief Maps a physical CPU memory region to a fixed virtual memory region * @param address The target virtual address of the region - * @param cpuAddress The physical CPU address of the region to be mapped into the GPU's address space + * @param pointer A pointer to the region to be mapped into the GPU's address space * @param size The size of the region to map * @return The virtual address of the region base */ - u64 MapFixed(u64 address, u64 cpuAddress, u64 size); + u64 MapFixed(u64 address, u8* pointer, u64 size); /** * @brief Unmaps all chunks in the given region from the GPU address space diff --git a/app/src/main/cpp/skyline/gpu/texture.cpp b/app/src/main/cpp/skyline/gpu/texture.cpp index 0feaba0b..5ea03e64 100644 --- a/app/src/main/cpp/skyline/gpu/texture.cpp +++ b/app/src/main/cpp/skyline/gpu/texture.cpp @@ -7,7 +7,7 @@ #include "texture.h" namespace skyline::gpu { - GuestTexture::GuestTexture(const DeviceState &state, u64 address, texture::Dimensions dimensions, texture::Format format, texture::TileMode tiling, texture::TileConfig layout) : state(state), address(address), dimensions(dimensions), format(format), tileMode(tiling), tileConfig(layout) {} + GuestTexture::GuestTexture(const DeviceState &state, u8* pointer, texture::Dimensions dimensions, texture::Format format, texture::TileMode tiling, texture::TileConfig layout) : state(state), pointer(pointer), dimensions(dimensions), format(format), tileMode(tiling), tileConfig(layout) {} std::shared_ptr GuestTexture::InitializeTexture(std::optional format, std::optional dimensions, texture::Swizzle swizzle) { if (!host.expired()) @@ -30,7 +30,7 @@ namespace skyline::gpu { } void Texture::SynchronizeHost() { - auto texture{state.process->GetPointer(guest->address)}; + auto pointer{guest->pointer}; auto size{format.GetSize(dimensions)}; backing.resize(size); auto output{reinterpret_cast(backing.data())}; @@ -51,7 +51,7 @@ namespace skyline::gpu { auto robBytes{robWidthBytes * robHeight}; // The size of a ROB in bytes auto gobYOffset{robWidthBytes * gobHeight}; // The offset of the next Y-axis GOB from the current one in linear space - auto inputSector{texture}; // The address of the input sector + auto inputSector{pointer}; // The address of the input sector auto outputRob{output}; // The address of the output block for (u32 rob{}, y{}, paddingY{}; rob < surfaceHeightRobs; rob++) { // Every Surface contains `surfaceHeightRobs` ROBs @@ -80,7 +80,7 @@ namespace skyline::gpu { auto sizeLine{guest->format.GetSize(dimensions.width, 1)}; // The size of a single line of pixel data auto sizeStride{guest->format.GetSize(guest->tileConfig.pitch, 1)}; // The size of a single stride of pixel data - auto inputLine{texture}; // The address of the input line + auto inputLine{pointer}; // The address of the input line auto outputLine{output}; // The address of the output line for (u32 line{}; line < dimensions.height; line++) { @@ -89,7 +89,7 @@ namespace skyline::gpu { outputLine += sizeLine; } } else if (guest->tileMode == texture::TileMode::Linear) { - std::memcpy(output, texture, size); + std::memcpy(output, pointer, size); } } diff --git a/app/src/main/cpp/skyline/gpu/texture.h b/app/src/main/cpp/skyline/gpu/texture.h index cdd8a778..4c66f349 100644 --- a/app/src/main/cpp/skyline/gpu/texture.h +++ b/app/src/main/cpp/skyline/gpu/texture.h @@ -124,14 +124,14 @@ namespace skyline { const DeviceState &state; public: - u64 address; //!< The address of the texture in guest memory + u8* pointer; //!< The address of the texture in guest memory std::weak_ptr host; //!< A host texture (if any) that was created from this guest texture texture::Dimensions dimensions; texture::Format format; texture::TileMode tileMode; texture::TileConfig tileConfig; - GuestTexture(const DeviceState &state, u64 address, texture::Dimensions dimensions, texture::Format format, texture::TileMode tileMode = texture::TileMode::Linear, texture::TileConfig tileConfig = {}); + GuestTexture(const DeviceState &state, u8* pointer, texture::Dimensions dimensions, texture::Format format, texture::TileMode tileMode = texture::TileMode::Linear, texture::TileConfig tileConfig = {}); constexpr size_t Size() { return format.GetSize(dimensions); diff --git a/app/src/main/cpp/skyline/kernel/ipc.cpp b/app/src/main/cpp/skyline/kernel/ipc.cpp index 0cbfc875..e3edb272 100644 --- a/app/src/main/cpp/skyline/kernel/ipc.cpp +++ b/app/src/main/cpp/skyline/kernel/ipc.cpp @@ -29,37 +29,37 @@ namespace skyline::kernel::ipc { for (u8 index{}; header->xNo > index; index++) { auto bufX{reinterpret_cast(pointer)}; - if (bufX->Address()) { - inputBuf.emplace_back(state.process->GetPointer(bufX->Address()), u16(bufX->size)); - state.logger->Debug("Buf X #{} AD: 0x{:X} SZ: 0x{:X} CTR: {}", index, u64(bufX->Address()), u16(bufX->size), u16(bufX->Counter())); + if (bufX->Pointer()) { + inputBuf.emplace_back(bufX->Pointer(), u16(bufX->size)); + state.logger->Debug("Buf X #{} AD: 0x{:X} SZ: 0x{:X} CTR: {}", index, u64(bufX->Pointer()), u16(bufX->size), u16(bufX->Counter())); } pointer += sizeof(BufferDescriptorX); } for (u8 index{}; header->aNo > index; index++) { auto bufA{reinterpret_cast(pointer)}; - if (bufA->Address()) { - inputBuf.emplace_back(state.process->GetPointer(bufA->Address()), bufA->Size()); - state.logger->Debug("Buf A #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufA->Address()), u64(bufA->Size())); + if (bufA->Pointer()) { + inputBuf.emplace_back(bufA->Pointer(), bufA->Size()); + state.logger->Debug("Buf A #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufA->Pointer()), u64(bufA->Size())); } pointer += sizeof(BufferDescriptorABW); } for (u8 index{}; header->bNo > index; index++) { auto bufB{reinterpret_cast(pointer)}; - if (bufB->Address()) { - outputBuf.emplace_back(state.process->GetPointer(bufB->Address()), bufB->Size()); - state.logger->Debug("Buf B #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufB->Address()), u64(bufB->Size())); + if (bufB->Pointer()) { + outputBuf.emplace_back(bufB->Pointer(), bufB->Size()); + state.logger->Debug("Buf B #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufB->Pointer()), u64(bufB->Size())); } pointer += sizeof(BufferDescriptorABW); } for (u8 index{}; header->wNo > index; index++) { auto bufW{reinterpret_cast(pointer)}; - if (bufW->Address()) { - outputBuf.emplace_back(state.process->GetPointer(bufW->Address()), bufW->Size()); - outputBuf.emplace_back(state.process->GetPointer(bufW->Address()), bufW->Size()); - state.logger->Debug("Buf W #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufW->Address()), u16(bufW->Size())); + if (bufW->Pointer()) { + outputBuf.emplace_back(bufW->Pointer(), bufW->Size()); + outputBuf.emplace_back(bufW->Pointer(), bufW->Size()); + state.logger->Debug("Buf W #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufW->Pointer()), u16(bufW->Size())); } pointer += sizeof(BufferDescriptorABW); } @@ -102,15 +102,15 @@ namespace skyline::kernel::ipc { if (header->cFlag == BufferCFlag::SingleDescriptor) { auto bufC{reinterpret_cast(pointer)}; if (bufC->address) { - outputBuf.emplace_back(state.process->GetPointer(bufC->address), u16(bufC->size)); - state.logger->Debug("Buf C: AD: 0x{:X} SZ: 0x{:X}", u64(bufC->address), u16(bufC->size)); + outputBuf.emplace_back(bufC->Pointer(), u16(bufC->size)); + state.logger->Debug("Buf C: AD: 0x{:X} SZ: 0x{:X}", fmt::ptr(bufC->Pointer()), u16(bufC->size)); } } else if (header->cFlag > BufferCFlag::SingleDescriptor) { for (u8 index{}; (static_cast(header->cFlag) - 2) > index; index++) { // (cFlag - 2) C descriptors are present auto bufC{reinterpret_cast(pointer)}; if (bufC->address) { - outputBuf.emplace_back(state.process->GetPointer(bufC->address), u16(bufC->size)); - state.logger->Debug("Buf C #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(bufC->address), u16(bufC->size)); + outputBuf.emplace_back(bufC->Pointer(), u16(bufC->size)); + state.logger->Debug("Buf C #{} AD: 0x{:X} SZ: 0x{:X}", index, fmt::ptr(bufC->Pointer()), u16(bufC->size)); } pointer += sizeof(BufferDescriptorC); } diff --git a/app/src/main/cpp/skyline/kernel/ipc.h b/app/src/main/cpp/skyline/kernel/ipc.h index 99e42bdf..bb54ed02 100644 --- a/app/src/main/cpp/skyline/kernel/ipc.h +++ b/app/src/main/cpp/skyline/kernel/ipc.h @@ -137,8 +137,8 @@ namespace skyline { counter9_11 = static_cast(address & 0x38); } - inline u64 Address() { - return static_cast(address0_31) | static_cast(address32_35) << 32 | static_cast(address36_38) << 36; + inline u8* Pointer() { + return reinterpret_cast(static_cast(address0_31) | static_cast(address32_35) << 32 | static_cast(address36_38) << 36); } inline u16 Counter() { @@ -167,8 +167,8 @@ namespace skyline { size32_35 = static_cast(size & 0x78000000); } - inline u64 Address() { - return static_cast(address0_31) | static_cast(address32_35) << 32 | static_cast(address36_38) << 36; + inline u8* Pointer() { + return reinterpret_cast(static_cast(address0_31) | static_cast(address32_35) << 32 | static_cast(address36_38) << 36); } inline u64 Size() { @@ -184,6 +184,10 @@ namespace skyline { u64 address : 48; //!< The 48-bit address of the buffer u32 size : 16; //!< The 16-bit size of the buffer + inline u8* Pointer() { + return reinterpret_cast(address); + } + BufferDescriptorC(u64 address, u16 size) : address(address), size(size) {} }; static_assert(sizeof(BufferDescriptorC) == 8); diff --git a/app/src/main/cpp/skyline/kernel/memory.cpp b/app/src/main/cpp/skyline/kernel/memory.cpp index 5af136e4..67ab626d 100644 --- a/app/src/main/cpp/skyline/kernel/memory.cpp +++ b/app/src/main/cpp/skyline/kernel/memory.cpp @@ -7,7 +7,8 @@ namespace skyline::kernel { MemoryManager::MemoryManager(const DeviceState &state) : state(state) {} - void MemoryManager::InitializeRegions(u64 address, u64 size, memory::AddressSpaceType type) { + void MemoryManager::InitializeRegions(u8* codeStart, u64 size, memory::AddressSpaceType type) { + u64 address{reinterpret_cast(codeStart)}; switch (type) { case memory::AddressSpaceType::AddressSpace32Bit: throw exception("32-bit address spaces are not supported"); diff --git a/app/src/main/cpp/skyline/kernel/memory.h b/app/src/main/cpp/skyline/kernel/memory.h index 614dd16c..a08dec05 100644 --- a/app/src/main/cpp/skyline/kernel/memory.h +++ b/app/src/main/cpp/skyline/kernel/memory.h @@ -219,10 +219,8 @@ namespace skyline { /** * @brief Initializes all of the regions in the address space - * @param address The starting address of the code region - * @param size The size of the code region */ - void InitializeRegions(u64 address, u64 size, memory::AddressSpaceType type); + void InitializeRegions(u8* codeStart, u64 size, memory::AddressSpaceType type); void InsertChunk(const ChunkDescriptor &chunk); diff --git a/app/src/main/cpp/skyline/kernel/svc.cpp b/app/src/main/cpp/skyline/kernel/svc.cpp index bc55f28d..057dd445 100644 --- a/app/src/main/cpp/skyline/kernel/svc.cpp +++ b/app/src/main/cpp/skyline/kernel/svc.cpp @@ -28,10 +28,10 @@ namespace skyline::kernel::svc { } void SetMemoryAttribute(DeviceState &state) { - auto ptr{reinterpret_cast(state.ctx->registers.x0)}; - if (!util::PageAligned(ptr)) { + auto pointer{reinterpret_cast(state.ctx->registers.x0)}; + if (!util::PageAligned(pointer)) { state.ctx->registers.w0 = result::InvalidAddress; - state.logger->Warn("svcSetMemoryAttribute: 'address' not page aligned: 0x{:X}", fmt::ptr(ptr)); + state.logger->Warn("svcSetMemoryAttribute: 'pointer' not page aligned: 0x{:X}", fmt::ptr(pointer)); return; } @@ -52,26 +52,26 @@ namespace skyline::kernel::svc { return; } - auto chunk{state.os->memory.Get(ptr)}; + auto chunk{state.os->memory.Get(pointer)}; if (!chunk) { state.ctx->registers.w0 = result::InvalidAddress; - state.logger->Warn("svcSetMemoryAttribute: Cannot find memory region: 0x{:X}", fmt::ptr(ptr)); + state.logger->Warn("svcSetMemoryAttribute: Cannot find memory region: 0x{:X}", fmt::ptr(pointer)); return; } if (!chunk->state.attributeChangeAllowed) { state.ctx->registers.w0 = result::InvalidState; - state.logger->Warn("svcSetMemoryAttribute: Attribute change not allowed for chunk: 0x{:X}", fmt::ptr(ptr)); + state.logger->Warn("svcSetMemoryAttribute: Attribute change not allowed for chunk: 0x{:X}", fmt::ptr(pointer)); return; } auto newChunk{*chunk}; - newChunk.ptr = ptr; + newChunk.ptr = pointer; newChunk.size = size; newChunk.attributes.isUncached = value.isUncached; state.os->memory.InsertChunk(newChunk); - state.logger->Debug("svcSetMemoryAttribute: Set caching to {} at 0x{:X} for 0x{:X} bytes", bool(value.isUncached), fmt::ptr(ptr), size); + state.logger->Debug("svcSetMemoryAttribute: Set caching to {} at 0x{:X} for 0x{:X} bytes", bool(value.isUncached), fmt::ptr(pointer), size); state.ctx->registers.w0 = Result{}; } @@ -182,8 +182,8 @@ namespace skyline::kernel::svc { void QueryMemory(DeviceState &state) { memory::MemoryInfo memInfo{}; - auto ptr{reinterpret_cast(state.ctx->registers.x2)}; - auto chunk{state.os->memory.Get(ptr)}; + auto pointer{reinterpret_cast(state.ctx->registers.x2)}; + auto chunk{state.os->memory.Get(pointer)}; if (chunk) { memInfo = { @@ -206,10 +206,10 @@ namespace skyline::kernel::svc { .type = static_cast(memory::MemoryType::Reserved), }; - state.logger->Debug("svcQueryMemory: Trying to query memory outside of the application's address space: 0x{:X}", fmt::ptr(ptr)); + state.logger->Debug("svcQueryMemory: Trying to query memory outside of the application's address space: 0x{:X}", fmt::ptr(pointer)); } - state.process->WriteMemory(memInfo, state.ctx->registers.x0); + *reinterpret_cast(state.ctx->registers.x0) = memInfo; state.ctx->registers.w0 = Result{}; } @@ -312,11 +312,11 @@ namespace skyline::kernel::svc { void MapSharedMemory(DeviceState &state) { try { auto object{state.process->GetHandle(state.ctx->registers.w0)}; - auto ptr{reinterpret_cast(state.ctx->registers.x1)}; + auto pointer{reinterpret_cast(state.ctx->registers.x1)}; - if (!util::PageAligned(ptr)) { + if (!util::PageAligned(pointer)) { state.ctx->registers.w0 = result::InvalidAddress; - state.logger->Warn("svcMapSharedMemory: 'ptr' not page aligned: 0x{:X}", ptr); + state.logger->Warn("svcMapSharedMemory: 'pointer' not page aligned: 0x{:X}", pointer); return; } @@ -334,9 +334,9 @@ namespace skyline::kernel::svc { return; } - state.logger->Debug("svcMapSharedMemory: Mapping shared memory at 0x{:X} for {} bytes ({}{}{})", ptr, size, permission.r ? 'R' : '-', permission.w ? 'W' : '-', permission.x ? 'X' : '-'); + state.logger->Debug("svcMapSharedMemory: Mapping shared memory at 0x{:X} for {} bytes ({}{}{})", pointer, size, permission.r ? 'R' : '-', permission.w ? 'W' : '-', permission.x ? 'X' : '-'); - object->Map(ptr, size, permission); + object->Map(pointer, size, permission); state.ctx->registers.w0 = Result{}; } catch (const std::exception &) { @@ -346,10 +346,10 @@ namespace skyline::kernel::svc { } void CreateTransferMemory(DeviceState &state) { - auto ptr{reinterpret_cast(state.ctx->registers.x1)}; - if (!util::PageAligned(ptr)) { + auto pointer{reinterpret_cast(state.ctx->registers.x1)}; + if (!util::PageAligned(pointer)) { state.ctx->registers.w0 = result::InvalidAddress; - state.logger->Warn("svcCreateTransferMemory: 'ptr' not page aligned: 0x{:X}", ptr); + state.logger->Warn("svcCreateTransferMemory: 'pointer' not page aligned: 0x{:X}", pointer); return; } @@ -367,8 +367,8 @@ namespace skyline::kernel::svc { return; } - auto tmem{state.process->NewHandle(ptr, size, permission)}; - state.logger->Debug("svcCreateTransferMemory: Creating transfer memory at 0x{:X} for {} bytes ({}{}{})", fmt::ptr(ptr), size, permission.r ? 'R' : '-', permission.w ? 'W' : '-', permission.x ? 'X' : '-'); + auto tmem{state.process->NewHandle(pointer, size, permission)}; + state.logger->Debug("svcCreateTransferMemory: Creating transfer memory at 0x{:X} for {} bytes ({}{}{})", fmt::ptr(pointer), size, permission.r ? 'R' : '-', permission.w ? 'W' : '-', permission.x ? 'X' : '-'); state.ctx->registers.w0 = Result{}; state.ctx->registers.w1 = tmem.handle; @@ -426,9 +426,7 @@ namespace skyline::kernel::svc { std::string handleStr; std::vector> objectTable; - std::vector waitHandles(numHandles); - - state.process->ReadMemory(waitHandles.data(), state.ctx->registers.x1, numHandles * sizeof(KHandle)); + span waitHandles(reinterpret_cast(state.ctx->registers.x1), numHandles); for (const auto &handle : waitHandles) { handleStr += fmt::format("* 0x{:X}\n", handle); @@ -464,7 +462,7 @@ namespace skyline::kernel::svc { uint index{}; for (const auto &object : objectTable) { if (object->signalled) { - state.logger->Debug("svcWaitSynchronization: Signalled handle: 0x{:X}", waitHandles.at(index)); + state.logger->Debug("svcWaitSynchronization: Signalled handle: 0x{:X}", waitHandles[index]); state.ctx->registers.w0 = Result{}; state.ctx->registers.w1 = index; return; @@ -490,9 +488,9 @@ namespace skyline::kernel::svc { } void ArbitrateLock(DeviceState &state) { - auto address{state.ctx->registers.x1}; - if (!util::WordAligned(address)) { - state.logger->Warn("svcArbitrateLock: 'address' not word aligned: 0x{:X}", address); + auto pointer{reinterpret_cast(state.ctx->registers.x1)}; + if (!util::WordAligned(pointer)) { + state.logger->Warn("svcArbitrateLock: 'pointer' not word aligned: 0x{:X}", fmt::ptr(pointer)); state.ctx->registers.w0 = result::InvalidAddress; return; } @@ -502,58 +500,58 @@ namespace skyline::kernel::svc { if (requesterHandle != state.thread->handle) throw exception("svcWaitProcessWideKeyAtomic: Handle doesn't match current thread: 0x{:X} for thread 0x{:X}", requesterHandle, state.thread->handle); - state.logger->Debug("svcArbitrateLock: Locking mutex at 0x{:X}", address); + state.logger->Debug("svcArbitrateLock: Locking mutex at 0x{:X}", fmt::ptr(pointer)); - if (state.process->MutexLock(address, ownerHandle)) - state.logger->Debug("svcArbitrateLock: Locked mutex at 0x{:X}", address); + if (state.process->MutexLock(pointer, ownerHandle)) + state.logger->Debug("svcArbitrateLock: Locked mutex at 0x{:X}", fmt::ptr(pointer)); else - state.logger->Debug("svcArbitrateLock: Owner handle did not match current owner for mutex or didn't have waiter flag at 0x{:X}", address); + state.logger->Debug("svcArbitrateLock: Owner handle did not match current owner for mutex or didn't have waiter flag at 0x{:X}", fmt::ptr(pointer)); state.ctx->registers.w0 = Result{}; } void ArbitrateUnlock(DeviceState &state) { - auto address{state.ctx->registers.x0}; - if (!util::WordAligned(address)) { - state.logger->Warn("svcArbitrateUnlock: 'address' not word aligned: 0x{:X}", address); + auto mutex{reinterpret_cast(state.ctx->registers.x0)}; + if (!util::WordAligned(mutex)) { + state.logger->Warn("svcArbitrateUnlock: mutex pointer not word aligned: 0x{:X}", fmt::ptr(mutex)); state.ctx->registers.w0 = result::InvalidAddress; return; } - state.logger->Debug("svcArbitrateUnlock: Unlocking mutex at 0x{:X}", address); + state.logger->Debug("svcArbitrateUnlock: Unlocking mutex at 0x{:X}", fmt::ptr(mutex)); - if (state.process->MutexUnlock(address)) { - state.logger->Debug("svcArbitrateUnlock: Unlocked mutex at 0x{:X}", address); + if (state.process->MutexUnlock(mutex)) { + state.logger->Debug("svcArbitrateUnlock: Unlocked mutex at 0x{:X}", fmt::ptr(mutex)); state.ctx->registers.w0 = Result{}; } else { - state.logger->Debug("svcArbitrateUnlock: A non-owner thread tried to release a mutex at 0x{:X}", address); + state.logger->Debug("svcArbitrateUnlock: A non-owner thread tried to release a mutex at 0x{:X}", fmt::ptr(mutex)); state.ctx->registers.w0 = result::InvalidAddress; } } void WaitProcessWideKeyAtomic(DeviceState &state) { - auto mtxAddress{state.ctx->registers.x0}; - if (!util::WordAligned(mtxAddress)) { - state.logger->Warn("svcWaitProcessWideKeyAtomic: mutex address not word aligned: 0x{:X}", mtxAddress); + auto mutex{reinterpret_cast(state.ctx->registers.x0)}; + if (!util::WordAligned(mutex)) { + state.logger->Warn("svcWaitProcessWideKeyAtomic: mutex pointer not word aligned: 0x{:X}", fmt::ptr(mutex)); state.ctx->registers.w0 = result::InvalidAddress; return; } - auto condAddress{state.ctx->registers.x1}; + auto conditional{reinterpret_cast(state.ctx->registers.x1)}; auto handle{state.ctx->registers.w2}; if (handle != state.thread->handle) throw exception("svcWaitProcessWideKeyAtomic: Handle doesn't match current thread: 0x{:X} for thread 0x{:X}", handle, state.thread->handle); - if (!state.process->MutexUnlock(mtxAddress)) { - state.logger->Debug("WaitProcessWideKeyAtomic: A non-owner thread tried to release a mutex at 0x{:X}", mtxAddress); + if (!state.process->MutexUnlock(mutex)) { + state.logger->Debug("WaitProcessWideKeyAtomic: A non-owner thread tried to release a mutex at 0x{:X}", fmt::ptr(mutex)); state.ctx->registers.w0 = result::InvalidAddress; return; } auto timeout{state.ctx->registers.x3}; - state.logger->Debug("svcWaitProcessWideKeyAtomic: Mutex: 0x{:X}, Conditional-Variable: 0x{:X}, Timeout: {} ns", mtxAddress, condAddress, timeout); + state.logger->Debug("svcWaitProcessWideKeyAtomic: Mutex: 0x{:X}, Conditional-Variable: 0x{:X}, Timeout: {} ns", fmt::ptr(mutex), conditional, timeout); - if (state.process->ConditionalVariableWait(condAddress, mtxAddress, timeout)) { + if (state.process->ConditionalVariableWait(conditional, mutex, timeout)) { state.logger->Debug("svcWaitProcessWideKeyAtomic: Waited for conditional variable and relocked mutex"); state.ctx->registers.w0 = Result{}; } else { @@ -563,11 +561,11 @@ namespace skyline::kernel::svc { } void SignalProcessWideKey(DeviceState &state) { - auto address{state.ctx->registers.x0}; + auto conditional{reinterpret_cast(state.ctx->registers.x0)}; auto count{state.ctx->registers.w1}; - state.logger->Debug("svcSignalProcessWideKey: Signalling Conditional-Variable at 0x{:X} for {}", address, count); - state.process->ConditionalVariableSignal(address, count); + state.logger->Debug("svcSignalProcessWideKey: Signalling Conditional-Variable at 0x{:X} for {}", conditional, count); + state.process->ConditionalVariableSignal(conditional, count); state.ctx->registers.w0 = Result{}; } @@ -586,7 +584,7 @@ namespace skyline::kernel::svc { void ConnectToNamedPort(DeviceState &state) { constexpr u8 portSize = 0x8; //!< The size of a port name string - std::string_view port(span(state.process->GetPointer(state.ctx->registers.x1), portSize).as_string(true)); + std::string_view port(span(reinterpret_cast(state.ctx->registers.x1), portSize).as_string(true)); KHandle handle{}; if (port.compare("sm:") >= 0) { diff --git a/app/src/main/cpp/skyline/kernel/types/KProcess.cpp b/app/src/main/cpp/skyline/kernel/types/KProcess.cpp index 77553d2d..ba7e5a45 100644 --- a/app/src/main/cpp/skyline/kernel/types/KProcess.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KProcess.cpp @@ -102,54 +102,6 @@ namespace skyline::kernel::type { return thread; } - void KProcess::ReadMemory(void *destination, u64 offset, size_t size, bool forceGuest) { - if (!forceGuest) { - auto source{reinterpret_cast(offset)}; - - if (source) { - std::memcpy(destination, reinterpret_cast(source), size); - return; - } - } - - struct iovec local{ - .iov_base = destination, - .iov_len = size, - }; - - struct iovec remote{ - .iov_base = reinterpret_cast(offset), - .iov_len = size, - }; - - if (process_vm_readv(pid, &local, 1, &remote, 1, 0) < 0) - pread64(memFd, destination, size, offset); - } - - void KProcess::WriteMemory(const void *source, u64 offset, size_t size, bool forceGuest) { - if (!forceGuest) { - auto destination{reinterpret_cast(offset)}; - - if (destination) { - std::memcpy(reinterpret_cast(destination), source, size); - return; - } - } - - struct iovec local{ - .iov_base = const_cast(source), - .iov_len = size, - }; - - struct iovec remote{ - .iov_base = reinterpret_cast(offset), - .iov_len = size, - }; - - if (process_vm_writev(pid, &local, 1, &remote, 1, 0) < 0) - pwrite64(memFd, source, size, offset); - } - std::optional> KProcess::GetMemoryObject(u8* ptr) { for (KHandle index{}; index < handles.size(); index++) { auto& object{handles[index]}; @@ -169,19 +121,17 @@ namespace skyline::kernel::type { return std::nullopt; } - bool KProcess::MutexLock(u64 address, KHandle owner) { + bool KProcess::MutexLock(u32* mutex, KHandle owner) { std::unique_lock lock(mutexLock); - auto mtx{GetPointer(address)}; - auto &mtxWaiters{mutexes[address]}; - + auto &mtxWaiters{mutexes[reinterpret_cast(mutex)]}; if (mtxWaiters.empty()) { u32 mtxExpected{}; - if (__atomic_compare_exchange_n(mtx, &mtxExpected, (constant::MtxOwnerMask & state.thread->handle), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) + if (__atomic_compare_exchange_n(mutex, &mtxExpected, (constant::MtxOwnerMask & state.thread->handle), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) return true; } - if (__atomic_load_n(mtx, __ATOMIC_SEQ_CST) != (owner | ~constant::MtxOwnerMask)) + if (__atomic_load_n(mutex, __ATOMIC_SEQ_CST) != (owner | ~constant::MtxOwnerMask)) return false; std::shared_ptr status; @@ -209,20 +159,19 @@ namespace skyline::kernel::type { return true; } - bool KProcess::MutexUnlock(u64 address) { + bool KProcess::MutexUnlock(u32* mutex) { std::unique_lock lock(mutexLock); - auto mtx{GetPointer(address)}; - auto &mtxWaiters{mutexes[address]}; + auto &mtxWaiters{mutexes[reinterpret_cast(mutex)]}; u32 mtxDesired{}; if (!mtxWaiters.empty()) mtxDesired = (*mtxWaiters.begin())->handle | ((mtxWaiters.size() > 1) ? ~constant::MtxOwnerMask : 0); u32 mtxExpected{(constant::MtxOwnerMask & state.thread->handle) | ~constant::MtxOwnerMask}; - if (!__atomic_compare_exchange_n(mtx, &mtxExpected, mtxDesired, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { + if (!__atomic_compare_exchange_n(mutex, &mtxExpected, mtxDesired, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) { mtxExpected &= constant::MtxOwnerMask; - if (!__atomic_compare_exchange_n(mtx, &mtxExpected, mtxDesired, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) + if (!__atomic_compare_exchange_n(mutex, &mtxExpected, mtxDesired, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) return false; } @@ -237,16 +186,16 @@ namespace skyline::kernel::type { return true; } - bool KProcess::ConditionalVariableWait(u64 conditionalAddress, u64 mutexAddress, u64 timeout) { + bool KProcess::ConditionalVariableWait(void* conditional, u32* mutex, u64 timeout) { std::unique_lock lock(conditionalLock); - auto &condWaiters{conditionals[conditionalAddress]}; + auto &condWaiters{conditionals[reinterpret_cast(conditional)]}; std::shared_ptr status; for (auto it{condWaiters.begin()};; it++) { if (it != condWaiters.end() && (*it)->priority >= state.thread->priority) continue; - status = std::make_shared(state.thread->priority, state.thread->handle, mutexAddress); + status = std::make_shared(state.thread->priority, state.thread->handle, mutex); condWaiters.insert(it, status); break; } @@ -278,16 +227,16 @@ namespace skyline::kernel::type { return !timedOut; } - void KProcess::ConditionalVariableSignal(u64 address, u64 amount) { + void KProcess::ConditionalVariableSignal(void* conditional, u64 amount) { std::unique_lock condLock(conditionalLock); - auto &condWaiters{conditionals[address]}; + auto &condWaiters{conditionals[reinterpret_cast(conditional)]}; u64 count{}; auto iter{condWaiters.begin()}; while (iter != condWaiters.end() && count < amount) { auto &thread{*iter}; - auto mtx{GetPointer(thread->mutexAddress)}; + auto mtx{thread->mutex}; u32 mtxValue{__atomic_load_n(mtx, __ATOMIC_SEQ_CST)}; while (true) { @@ -308,7 +257,7 @@ namespace skyline::kernel::type { if (mtxValue && ((mtxValue & constant::MtxOwnerMask) != state.thread->handle)) { std::unique_lock mtxLock(mutexLock); - auto &mtxWaiters{mutexes[thread->mutexAddress]}; + auto &mtxWaiters{mutexes[reinterpret_cast(thread->mutex)]}; std::shared_ptr status; for (auto it{mtxWaiters.begin()};; it++) { diff --git a/app/src/main/cpp/skyline/kernel/types/KProcess.h b/app/src/main/cpp/skyline/kernel/types/KProcess.h index 154658f1..e2b0ef20 100644 --- a/app/src/main/cpp/skyline/kernel/types/KProcess.h +++ b/app/src/main/cpp/skyline/kernel/types/KProcess.h @@ -95,11 +95,11 @@ namespace skyline { std::atomic_bool flag{false}; //!< The underlying atomic flag of the thread u8 priority; //!< The priority of the thread KHandle handle; //!< The handle of the thread - u64 mutexAddress{}; //!< The address of the mutex + u32* mutex{}; WaitStatus(u8 priority, KHandle handle) : priority(priority), handle(handle) {} - WaitStatus(u8 priority, KHandle handle, u64 mutexAddress) : priority(priority), handle(handle), mutexAddress(mutexAddress) {} + WaitStatus(u8 priority, KHandle handle, u32* mutex) : priority(priority), handle(handle), mutex(mutex) {} }; pid_t pid; //!< The PID of the process or TGID of the threads @@ -136,67 +136,6 @@ namespace skyline { */ std::shared_ptr CreateThread(u64 entryPoint, u64 entryArg, u64 stackTop, i8 priority); - /** - * @tparam Type The type of the pointer to return - * @param address The address on the guest - * @return A pointer corresponding to a certain address on the guest - * @note If the address is invalid then nullptr will be returned - */ - template - inline Type *GetPointer(u64 address) { - return reinterpret_cast(address); - } - - /** - * @brief Writes an object to guest memory - * @tparam Type The type of the object to be written - * @param item The object to write - * @param address The address of the object - */ - template - inline void WriteMemory(Type &item, u64 address) { - auto destination{GetPointer(address)}; - if (destination) { - *destination = item; - } else { - WriteMemory(&item, address, sizeof(Type)); - } - } - - /** - * @brief Writes an object to guest memory - * @tparam Type The type of the object to be written - * @param item The object to write - * @param address The address of the object - */ - template - inline void WriteMemory(const Type &item, u64 address) { - auto destination{GetPointer(address)}; - if (destination) { - *destination = item; - } else { - WriteMemory(&item, address, sizeof(Type)); - } - } - - /** - * @brief Read data from the guest's memory - * @param destination The address to the location where the process memory is written - * @param offset The address to read from in process memory - * @param size The amount of memory to be read - * @param forceGuest Forces the write to be performed in guest address space - */ - void ReadMemory(void *destination, u64 offset, size_t size, bool forceGuest = false); - - /** - * @brief Write to the guest's memory - * @param source The address of where the data to be written is present - * @param offset The address to write to in process memory - * @param size The amount of memory to be written - * @param forceGuest Forces the write to be performed in guest address space - */ - void WriteMemory(const void *source, u64 offset, size_t size, bool forceGuest = false); - /** * @brief Creates a new handle to a KObject and adds it to the process handle_table * @tparam objectClass The class of the kernel object to create @@ -279,33 +218,28 @@ namespace skyline { /** * @brief Locks the Mutex at the specified address - * @param address The address of the mutex * @param owner The handle of the current mutex owner * @return If the mutex was successfully locked */ - bool MutexLock(u64 address, KHandle owner); + bool MutexLock(u32* mutex, KHandle owner); /** * @brief Unlocks the Mutex at the specified address - * @param address The address of the mutex * @return If the mutex was successfully unlocked */ - bool MutexUnlock(u64 address); + bool MutexUnlock(u32* mutex); /** - * @param conditionalAddress The address of the conditional variable - * @param mutexAddress The address of the mutex * @param timeout The amount of time to wait for the conditional variable * @return If the conditional variable was successfully waited for or timed out */ - bool ConditionalVariableWait(u64 conditionalAddress, u64 mutexAddress, u64 timeout); + bool ConditionalVariableWait(void* conditional, u32* mutex, u64 timeout); /** * @brief Signals a number of conditional variable waiters - * @param address The address of the conditional variable * @param amount The amount of waiters to signal */ - void ConditionalVariableSignal(u64 address, u64 amount); + void ConditionalVariableSignal(void* conditional, u64 amount); /** * @brief Resets the object to an unsignalled state diff --git a/app/src/main/cpp/skyline/loader/loader.cpp b/app/src/main/cpp/skyline/loader/loader.cpp index 9e7e3dee..86744471 100644 --- a/app/src/main/cpp/skyline/loader/loader.cpp +++ b/app/src/main/cpp/skyline/loader/loader.cpp @@ -9,7 +9,7 @@ namespace skyline::loader { Loader::ExecutableLoadInfo Loader::LoadExecutable(const std::shared_ptr process, const DeviceState &state, Executable &executable, size_t offset) { - u8* base{reinterpret_cast(constant::BaseAddress + offset)}; + u8 *base{reinterpret_cast(constant::BaseAddress + offset)}; u64 textSize{executable.text.contents.size()}; u64 roSize{executable.ro.contents.size()}; @@ -40,11 +40,11 @@ namespace skyline::loader { process->NewHandle(base + patchOffset, patchSize + padding, memory::Permission{true, true, true}, memory::states::CodeMutable); // RWX state.logger->Debug("Successfully mapped section .patch @ 0x{0:X}, Size = 0x{1:X}", base + patchOffset, patchSize + padding); - process->WriteMemory(executable.text.contents.data(), reinterpret_cast(base + executable.text.offset), textSize); - process->WriteMemory(executable.ro.contents.data(), reinterpret_cast(base + executable.ro.offset), roSize); - process->WriteMemory(executable.data.contents.data(), reinterpret_cast(base + executable.data.offset), dataSize - executable.bssSize); - process->WriteMemory(patch.data(), reinterpret_cast(base + patchOffset), patchSize); + std::memcpy(executable.text.contents.data(), base + executable.text.offset, textSize); + std::memcpy(executable.ro.contents.data(), base + executable.ro.offset, roSize); + std::memcpy(executable.data.contents.data(), base + executable.data.offset, dataSize - executable.bssSize); + std::memcpy(patch.data(), base + patchOffset, patchSize); - return {reinterpret_cast(base), patchOffset + patchSize + padding}; + return {base, patchOffset + patchSize + padding}; } } diff --git a/app/src/main/cpp/skyline/loader/loader.h b/app/src/main/cpp/skyline/loader/loader.h index 4cd431a2..3a487fb1 100644 --- a/app/src/main/cpp/skyline/loader/loader.h +++ b/app/src/main/cpp/skyline/loader/loader.h @@ -51,7 +51,7 @@ namespace skyline::loader { * @brief Information about the placement of an executable in memory */ struct ExecutableLoadInfo { - size_t base; //!< The base of the loaded executable + u8* base; //!< The base of the loaded executable size_t size; //!< The total size of the loaded executable }; diff --git a/app/src/main/cpp/skyline/loader/nca.cpp b/app/src/main/cpp/skyline/loader/nca.cpp index fb085b6c..00f8ca12 100644 --- a/app/src/main/cpp/skyline/loader/nca.cpp +++ b/app/src/main/cpp/skyline/loader/nca.cpp @@ -23,9 +23,9 @@ namespace skyline::loader { auto loadInfo{NsoLoader::LoadNso(nsoFile, process, state)}; u64 offset{loadInfo.size}; - u64 base{loadInfo.base}; + u8* base{loadInfo.base}; - state.logger->Info("Loaded nso 'rtld' at 0x{:X}", base); + state.logger->Info("Loaded nso 'rtld' at 0x{:X}", fmt::ptr(base)); for (const auto &nso : {"main", "subsdk0", "subsdk1", "subsdk2", "subsdk3", "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) { nsoFile = exeFs->OpenFile(nso); @@ -34,7 +34,7 @@ namespace skyline::loader { continue; loadInfo = NsoLoader::LoadNso(nsoFile, process, state, offset); - state.logger->Info("Loaded nso '{}' at 0x{:X}", nso, base + offset); + state.logger->Info("Loaded nso '{}' at 0x{:X}", nso, fmt::ptr(base + offset)); offset += loadInfo.size; } diff --git a/app/src/main/cpp/skyline/nce.cpp b/app/src/main/cpp/skyline/nce.cpp index 7336d7dc..ae02c615 100644 --- a/app/src/main/cpp/skyline/nce.cpp +++ b/app/src/main/cpp/skyline/nce.cpp @@ -162,29 +162,26 @@ namespace skyline { threadMap[thread->tid] = std::make_shared(&NCE::KernelThread, this, thread->tid); } - void NCE::ThreadTrace(u16 numHist, ThreadContext *ctx) { + void NCE::ThreadTrace(u16 instructionCount, ThreadContext *ctx) { std::string raw; std::string trace; std::string regStr; ctx = ctx ? ctx : state.ctx; - if (numHist) { - std::vector instrs(numHist); - u64 size{sizeof(u32) * numHist}; - u64 offset{ctx->pc - size + (2 * sizeof(u32))}; + if (instructionCount) { + auto offset{ctx->pc - ((instructionCount - 2) * sizeof(u32))}; + span instructions(reinterpret_cast(offset), instructionCount); - state.process->ReadMemory(instrs.data(), offset, size); - - for (auto &instr : instrs) { - instr = __builtin_bswap32(instr); + for (auto &instruction : instructions) { + instruction = __builtin_bswap32(instruction); if (offset == ctx->pc) - trace += fmt::format("\n-> 0x{:X} : 0x{:08X}", offset, instr); + trace += fmt::format("\n-> 0x{:X} : 0x{:08X}", offset, instruction); else - trace += fmt::format("\n 0x{:X} : 0x{:08X}", offset, instr); + trace += fmt::format("\n 0x{:X} : 0x{:08X}", offset, instruction); - raw += fmt::format("{:08X}", instr); + raw += fmt::format("{:08X}", instruction); offset += sizeof(u32); } } @@ -201,7 +198,7 @@ namespace skyline { regStr += fmt::format("\n{}{}: 0x{:<16X} {}{}: 0x{:X}", xStr, index, ctx->registers.regs[index], xStr, index + 1, ctx->registers.regs[index + 1]); } - if (numHist) { + if (instructionCount) { state.logger->Debug("Process Trace:{}", trace); state.logger->Debug("Raw Instructions: 0x{}", raw); state.logger->Debug("CPU Context:{}", regStr); diff --git a/app/src/main/cpp/skyline/nce.h b/app/src/main/cpp/skyline/nce.h index 0e48c9ab..c348a6d4 100644 --- a/app/src/main/cpp/skyline/nce.h +++ b/app/src/main/cpp/skyline/nce.h @@ -66,10 +66,10 @@ namespace skyline { /** * @brief Prints out a trace and the CPU context - * @param numHist The amount of previous instructions to print (Can be 0) + * @param instructionCount The amount of previous instructions to print (Can be 0) * @param ctx The ThreadContext of the thread to log */ - void ThreadTrace(u16 numHist = 10, ThreadContext *ctx = nullptr); + void ThreadTrace(u16 instructionCount = 10, ThreadContext *ctx = nullptr); /** * @brief Patches specific parts of the code diff --git a/app/src/main/cpp/skyline/services/audio/IAudioOut.cpp b/app/src/main/cpp/skyline/services/audio/IAudioOut.cpp index 04ad0347..af214249 100644 --- a/app/src/main/cpp/skyline/services/audio/IAudioOut.cpp +++ b/app/src/main/cpp/skyline/services/audio/IAudioOut.cpp @@ -32,21 +32,22 @@ namespace skyline::service::audio { Result IAudioOut::AppendAudioOutBuffer(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { struct Data { - u64 nextBufferPtr; - u64 sampleBufferPtr; + i16* nextBuffer; + i16* sampleBuffer; u64 sampleCapacity; u64 sampleSize; u64 sampleOffset; } &data{request.inputBuf.at(0).as()}; auto tag{request.Pop()}; - state.logger->Debug("Appending buffer with address: 0x{:X}, size: 0x{:X}", data.sampleBufferPtr, data.sampleSize); + state.logger->Debug("Appending buffer with address: 0x{:X}, size: 0x{:X}", fmt::ptr(data.sampleBuffer), data.sampleSize); + span samples(data.sampleBuffer, data.sampleSize / sizeof(i16)); if (sampleRate != constant::SampleRate) { - auto resampledBuffer{resampler.ResampleBuffer(span(state.process->GetPointer(data.sampleBufferPtr), data.sampleSize / sizeof(i16)), static_cast(sampleRate) / constant::SampleRate, channelCount)}; + auto resampledBuffer{resampler.ResampleBuffer(samples, static_cast(sampleRate) / constant::SampleRate, channelCount)}; track->AppendBuffer(tag, resampledBuffer); } else { - track->AppendBuffer(tag, span(state.process->GetPointer(data.sampleBufferPtr), data.sampleSize / sizeof(i16))); + track->AppendBuffer(tag, samples); } return {}; diff --git a/app/src/main/cpp/skyline/services/audio/IAudioRenderer/voice.cpp b/app/src/main/cpp/skyline/services/audio/IAudioRenderer/voice.cpp index cd49f27c..4c4752f2 100644 --- a/app/src/main/cpp/skyline/services/audio/IAudioRenderer/voice.cpp +++ b/app/src/main/cpp/skyline/services/audio/IAudioRenderer/voice.cpp @@ -43,7 +43,7 @@ namespace skyline::service::audio::IAudioRenderer { if (input.format == skyline::audio::AudioFormat::ADPCM) { std::vector> adpcmCoefficients(input.adpcmCoeffsSize / (sizeof(u16) * 2)); - state.process->ReadMemory(adpcmCoefficients.data(), input.adpcmCoeffsPosition, input.adpcmCoeffsSize); + span(adpcmCoefficients).copy_from(span(input.adpcmCoeffs, input.adpcmCoeffsSize)); adpcmDecoder = skyline::audio::AdpcmDecoder(adpcmCoefficients); } @@ -58,6 +58,7 @@ namespace skyline::service::audio::IAudioRenderer { void Voice::UpdateBuffers() { const auto ¤tBuffer{waveBuffers.at(bufferIndex)}; + span buffer(currentBuffer.pointer, currentBuffer.size); if (currentBuffer.size == 0) return; @@ -65,10 +66,10 @@ namespace skyline::service::audio::IAudioRenderer { switch (format) { case skyline::audio::AudioFormat::Int16: samples.resize(currentBuffer.size / sizeof(i16)); - state.process->ReadMemory(samples.data(), currentBuffer.address, currentBuffer.size); + buffer.copy_from(samples); break; case skyline::audio::AudioFormat::ADPCM: { - samples = adpcmDecoder->Decode(span(state.process->GetPointer(currentBuffer.address), currentBuffer.size)); + samples = adpcmDecoder->Decode(buffer); break; } default: diff --git a/app/src/main/cpp/skyline/services/audio/IAudioRenderer/voice.h b/app/src/main/cpp/skyline/services/audio/IAudioRenderer/voice.h index 97857687..bddf5919 100644 --- a/app/src/main/cpp/skyline/services/audio/IAudioRenderer/voice.h +++ b/app/src/main/cpp/skyline/services/audio/IAudioRenderer/voice.h @@ -20,7 +20,7 @@ namespace skyline::service::audio::IAudioRenderer { static_assert(sizeof(BiquadFilter) == 0xC); struct WaveBuffer { - u64 address; + u8* pointer; u64 size; u32 firstSampleOffset; u32 lastSampleOffset; @@ -51,7 +51,7 @@ namespace skyline::service::audio::IAudioRenderer { u32 appendedWaveBuffersCount; u32 baseWaveBufferIndex; u32 _unk1_; - u64 adpcmCoeffsPosition; + u32* adpcmCoeffs; u64 adpcmCoeffsSize; u32 destination; u32 _pad0_; diff --git a/app/src/main/cpp/skyline/services/hosbinder/GraphicBufferProducer.cpp b/app/src/main/cpp/skyline/services/hosbinder/GraphicBufferProducer.cpp index 24511edb..70b9cd3d 100644 --- a/app/src/main/cpp/skyline/services/hosbinder/GraphicBufferProducer.cpp +++ b/app/src/main/cpp/skyline/services/hosbinder/GraphicBufferProducer.cpp @@ -149,7 +149,7 @@ namespace skyline::service::hosbinder { throw exception("Unknown pixel format used for FB"); } - auto texture{std::make_shared(state, nvBuffer->address + gbpBuffer.offset, gpu::texture::Dimensions(gbpBuffer.width, gbpBuffer.height), format, gpu::texture::TileMode::Block, gpu::texture::TileConfig{.surfaceWidth = static_cast(gbpBuffer.stride), .blockHeight = static_cast(1U << gbpBuffer.blockHeightLog2), .blockDepth = 1})}; + auto texture{std::make_shared(state, nvBuffer->pointer + gbpBuffer.offset, gpu::texture::Dimensions(gbpBuffer.width, gbpBuffer.height), format, gpu::texture::TileMode::Block, gpu::texture::TileConfig{.surfaceWidth = static_cast(gbpBuffer.stride), .blockHeight = static_cast(1U << gbpBuffer.blockHeightLog2), .blockDepth = 1})}; queue[data.slot] = std::make_shared(gbpBuffer, texture->InitializePresentationTexture()); state.gpu->bufferEvent->Signal(); diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_as_gpu.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_as_gpu.cpp index fdc47a3a..42feae1f 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_as_gpu.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_as_gpu.cpp @@ -98,9 +98,9 @@ namespace skyline::service::nvdrv::device { } u64 gpuAddress{data.offset + data.bufferOffset}; - u64 cpuAddress{region->second.cpuAddress + data.bufferOffset}; + u8 *cpuPtr{region->second.cpuPtr + data.bufferOffset}; - if (state.gpu->memoryManager.MapFixed(gpuAddress, cpuAddress, data.mappingSize)) { + if (state.gpu->memoryManager.MapFixed(gpuAddress, cpuPtr, data.mappingSize)) { state.logger->Warn("Failed to remap GPU address space region: 0x{:X}", gpuAddress); return NvStatus::BadParameter; } @@ -108,20 +108,20 @@ namespace skyline::service::nvdrv::device { return NvStatus::Success; } - u64 mapPhysicalAddress{data.bufferOffset + mapping->address}; + u8* mapPointer{data.bufferOffset + mapping->pointer}; u64 mapSize{data.mappingSize ? data.mappingSize : mapping->size}; if (data.flags.fixed) - data.offset = state.gpu->memoryManager.MapFixed(data.offset, mapPhysicalAddress, mapSize); + data.offset = state.gpu->memoryManager.MapFixed(data.offset, mapPointer, mapSize); else - data.offset = state.gpu->memoryManager.MapAllocate(mapPhysicalAddress, mapSize); + data.offset = state.gpu->memoryManager.MapAllocate(mapPointer, mapSize); if (data.offset == 0) { state.logger->Warn("Failed to map GPU address space region!"); return NvStatus::BadParameter; } - regionMap[data.offset] = {mapPhysicalAddress, mapSize, data.flags.fixed}; + regionMap[data.offset] = {mapPointer, mapSize, data.flags.fixed}; return NvStatus::Success; } catch (const std::out_of_range &) { @@ -183,10 +183,10 @@ namespace skyline::service::nvdrv::device { auto mapping{nvmap->handleTable.at(entry.nvmapHandle)}; u64 mapAddress{static_cast(entry.gpuOffset) << MinAlignmentShift}; - u64 mapPhysicalAddress{mapping->address + (static_cast(entry.mapOffset) << MinAlignmentShift)}; + u8* mapPointer{mapping->pointer + (static_cast(entry.mapOffset) << MinAlignmentShift)}; u64 mapSize{static_cast(entry.pages) << MinAlignmentShift}; - state.gpu->memoryManager.MapFixed(mapAddress, mapPhysicalAddress, mapSize); + state.gpu->memoryManager.MapFixed(mapAddress, mapPointer, mapSize); } catch (const std::out_of_range &) { state.logger->Warn("Invalid NvMap handle: 0x{:X}", entry.nvmapHandle); return NvStatus::BadParameter; diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_as_gpu.h b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_as_gpu.h index 3b130c31..31a65c4d 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_as_gpu.h +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_as_gpu.h @@ -13,7 +13,7 @@ namespace skyline::service::nvdrv::device { class NvHostAsGpu : public NvDevice { private: struct AddressSpaceRegion { - u64 cpuAddress; + u8 *cpuPtr; u64 size; bool fixed; }; diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_channel.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_channel.cpp index 29b67250..b87a53aa 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_channel.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvhost_channel.cpp @@ -26,8 +26,8 @@ namespace skyline::service::nvdrv::device { NvStatus NvHostChannel::SubmitGpfifo(IoctlType type, span buffer, span inlineBuffer) { struct Data { - u64 address; // In - u32 numEntries; // In + gpu::gpfifo::GpEntry* entries; // In + u32 numEntries; // In union { struct __attribute__((__packed__)) { bool fenceWait : 1; @@ -39,8 +39,8 @@ namespace skyline::service::nvdrv::device { bool incrementWithValue : 1; }; u32 raw; - } flags; // In - Fence fence; // InOut + } flags; // In + Fence fence; // InOut } &data = buffer.as(); auto driver{nvdrv::driver.lock()}; @@ -58,7 +58,7 @@ namespace skyline::service::nvdrv::device { if (type == IoctlType::Ioctl2) return inlineBuffer.cast(); else - return span(state.process->GetPointer(data.address), data.numEntries); + return span(data.entries, data.numEntries); }()); data.fence.id = channelFence.id; diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.cpp index 63913006..22c1b6d4 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.cpp +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.cpp @@ -47,7 +47,7 @@ namespace skyline::service::nvdrv::device { u32 align; // In u8 kind; // In u8 _pad0_[7]; - u64 address; // InOut + u8* pointer; // InOut } &data = buffer.as(); try { @@ -56,10 +56,10 @@ namespace skyline::service::nvdrv::device { object->flags = data.flags; object->align = data.align; object->kind = data.kind; - object->address = data.address; + object->pointer = data.pointer; object->status = NvMapObject::Status::Allocated; - state.logger->Debug("Handle: 0x{:X}, HeapMask: 0x{:X}, Flags: {}, Align: 0x{:X}, Kind: {}, Address: 0x{:X}", data.handle, data.heapMask, data.flags, data.align, data.kind, data.address); + state.logger->Debug("Handle: 0x{:X}, HeapMask: 0x{:X}, Flags: {}, Align: 0x{:X}, Kind: {}, Address: 0x{:X}", data.handle, data.heapMask, data.flags, data.align, data.kind, fmt::ptr(data.pointer)); return NvStatus::Success; } catch (const std::out_of_range &) { state.logger->Warn("Invalid NvMap handle: 0x{:X}", data.handle); @@ -71,7 +71,7 @@ namespace skyline::service::nvdrv::device { struct Data { u32 handle; // In u32 _pad0_; - u64 address; // Out + u8* pointer; // Out u32 size; // Out u32 flags; // Out } &data = buffer.as(); @@ -79,17 +79,17 @@ namespace skyline::service::nvdrv::device { try { const auto &object{handleTable.at(data.handle)}; if (object.use_count() > 1) { - data.address = static_cast(object->address); + data.pointer = object->pointer; data.flags = 0x0; } else { - data.address = 0x0; + data.pointer = nullptr; data.flags = 0x1; // Not free yet } data.size = object->size; handleTable.erase(data.handle); - state.logger->Debug("Handle: 0x{:X} -> Address: 0x{:X}, Size: 0x{:X}, Flags: 0x{:X}", data.handle, data.address, data.size, data.flags); + state.logger->Debug("Handle: 0x{:X} -> Address: 0x{:X}, Size: 0x{:X}, Flags: 0x{:X}", data.handle, fmt::ptr(data.pointer), data.size, data.flags); return NvStatus::Success; } catch (const std::out_of_range &) { state.logger->Warn("Invalid NvMap handle: 0x{:X}", data.handle); diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.h b/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.h index b68db2ed..9d471805 100644 --- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.h +++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvmap.h @@ -16,11 +16,11 @@ namespace skyline::service::nvdrv::device { * @brief NvMapObject is used to hold the state of held objects */ struct NvMapObject { - u32 id; //!< The ID of this object - u32 size; //!< The size of this object - u64 address{}; //!< The address of the allocation + u32 id; + u32 size; + u8* pointer{}; u32 flags{}; //!< The flag of the memory (0 = Read Only, 1 = Read-Write) - u32 align{}; //!< The alignment of the allocation + u32 align{}; u32 heapMask{}; //!< This is set during Alloc and returned during Param u8 kind{}; //!< This is same as heapMask