Skip to content

Commit

Permalink
windows: Address a bunch of address space problems
Browse files Browse the repository at this point in the history
  • Loading branch information
raphaelthegreat committed Nov 9, 2024
1 parent 1240dd5 commit 9107576
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 43 deletions.
43 changes: 30 additions & 13 deletions src/core/address_space.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ struct AddressSpace::Impl {

// Take the reduction off of the system managed area, and leave the others unchanged.
system_managed_base = virtual_base;
system_managed_size = SystemManagedSize - reduction;
system_managed_size = SystemManagedSize - size_t(virtual_base - SYSTEM_MANAGED_MIN);
system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN);
system_reserved_size = SystemReservedSize;
user_base = reinterpret_cast<u8*>(USER_MIN);
Expand Down Expand Up @@ -251,18 +251,35 @@ struct AddressSpace::Impl {
return;
}

DWORD old_flags{};
bool success =
VirtualProtect(reinterpret_cast<void*>(virtual_addr), size, new_flags, &old_flags);

if (!success) {
LOG_ERROR(Common_Memory,
"Failed to change virtual memory protection for address {:#x}, size {}",
virtual_addr, size);
}

// Use assert to ensure success in debug builds
DEBUG_ASSERT(success && "Failed to change virtual memory protection");
const auto ForEachMapped = [&](VAddr base, size_t size, auto&& func) {
const VAddr base_addr = base;
const VAddr end_addr = base_addr + size;
auto [it, end_it] = placeholders.equal_range({base_addr, end_addr});
while (it != end_it) {
const size_t range_addr = std::max(it->lower(), base_addr);
const size_t range_end = std::min(it->upper(), end_addr);
if (base != range_addr) {
func(base, range_addr);
}
base = range_end;
it++;
}
if (base != end_addr) {
func(base, end_addr);
}
};

const VAddr virtual_end = virtual_addr + size;
ForEachMapped(virtual_addr, virtual_end, [&](VAddr map_base, VAddr map_end) {
DWORD old_flags{};
const size_t range_addr = std::max(map_base, virtual_addr);
const size_t range_size = std::min(map_end, virtual_end) - range_addr;
if (!VirtualProtect(LPVOID(range_addr), range_size, new_flags, &old_flags)) {
LOG_ERROR(Common_Memory,
"Failed to change virtual memory protection for address {:#x}, size {}",
range_addr, range_size);
}
});
}

HANDLE process{};
Expand Down
6 changes: 5 additions & 1 deletion src/core/libraries/ajm/ajm_mp3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,12 @@ static constexpr std::array<s32, 2> UnkTable = {0x48, 0x90};
SwrContext* swr_context{};

AVFrame* ConvertAudioFrame(AVFrame* frame) {
auto pcm16_frame = av_frame_clone(frame);
auto pcm16_frame = av_frame_alloc();
pcm16_frame->pts = frame->pts;
pcm16_frame->pkt_dts = frame->pkt_dts < 0 ? 0 : frame->pkt_dts;
pcm16_frame->format = AV_SAMPLE_FMT_S16;
pcm16_frame->ch_layout = frame->ch_layout;
pcm16_frame->sample_rate = frame->sample_rate;

if (swr_context) {
swr_free(&swr_context);
Expand Down
25 changes: 14 additions & 11 deletions src/core/libraries/kernel/memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "common/alignment.h"
#include "common/assert.h"
#include "common/scope_exit.h"
#include "common/logging/log.h"
#include "common/singleton.h"
#include "core/file_sys/fs.h"
Expand Down Expand Up @@ -145,11 +146,6 @@ s32 PS4_SYSV_ABI sceKernelReserveVirtualRange(void** addr, u64 len, int flags, u
int PS4_SYSV_ABI sceKernelMapNamedDirectMemory(void** addr, u64 len, int prot, int flags,
s64 directMemoryStart, u64 alignment,
const char* name) {
LOG_INFO(Kernel_Vmm,
"addr = {}, len = {:#x}, prot = {:#x}, flags = {:#x}, directMemoryStart = {:#x}, "
"alignment = {:#x}",
fmt::ptr(*addr), len, prot, flags, directMemoryStart, alignment);

if (len == 0 || !Common::Is16KBAligned(len)) {
LOG_ERROR(Kernel_Vmm, "Map size is either zero or not 16KB aligned!");
return SCE_KERNEL_ERROR_EINVAL;
Expand All @@ -168,6 +164,13 @@ int PS4_SYSV_ABI sceKernelMapNamedDirectMemory(void** addr, u64 len, int prot, i
const VAddr in_addr = reinterpret_cast<VAddr>(*addr);
const auto mem_prot = static_cast<Core::MemoryProt>(prot);
const auto map_flags = static_cast<Core::MemoryMapFlags>(flags);
SCOPE_EXIT {
LOG_INFO(Kernel_Vmm,
"in_addr = {:#x}, out_addr = {}, len = {:#x}, prot = {:#x}, flags = {:#x}, directMemoryStart = {:#x}, "
"alignment = {:#x}",
in_addr, fmt::ptr(*addr), len, prot, flags, directMemoryStart, alignment);
};

auto* memory = Core::Memory::Instance();
return memory->MapMemory(addr, in_addr, len, mem_prot, map_flags, Core::VMAType::Direct, "",
false, directMemoryStart, alignment);
Expand Down Expand Up @@ -201,13 +204,13 @@ s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addr_in_out, std::size_t
const VAddr in_addr = reinterpret_cast<VAddr>(*addr_in_out);
const auto mem_prot = static_cast<Core::MemoryProt>(prot);
const auto map_flags = static_cast<Core::MemoryMapFlags>(flags);
SCOPE_EXIT {
LOG_INFO(Kernel_Vmm, "in_addr = {:#x}, out_addr = {}, len = {:#x}, prot = {:#x}, flags = {:#x}",
in_addr, fmt::ptr(*addr_in_out), len, prot, flags);
};
auto* memory = Core::Memory::Instance();
const int ret = memory->MapMemory(addr_in_out, in_addr, len, mem_prot, map_flags,
Core::VMAType::Flexible, name);

LOG_INFO(Kernel_Vmm, "addr = {}, len = {:#x}, prot = {:#x}, flags = {:#x}",
fmt::ptr(*addr_in_out), len, prot, flags);
return ret;
return memory->MapMemory(addr_in_out, in_addr, len, mem_prot, map_flags,
Core::VMAType::Flexible, name);
}

s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, std::size_t len, int prot,
Expand Down
4 changes: 2 additions & 2 deletions src/core/libraries/kernel/threads/pthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ struct PthreadAttr {
};
using PthreadAttrT = PthreadAttr*;

static constexpr u32 ThrStackDefault = 2_MB;
static constexpr u32 ThrStackInitial = 2 * ThrStackDefault;
static constexpr u32 ThrStackDefault = 1_MB;
static constexpr u32 ThrStackInitial = 2_MB;
static constexpr u32 ThrPageSize = 16_KB;
static constexpr u32 ThrGuardDefault = ThrPageSize;

Expand Down
4 changes: 1 addition & 3 deletions src/core/libraries/kernel/threads/stack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ int ThreadState::CreateStack(PthreadAttr* attr) {
return 0;
}

VAddr stackaddr;

/*
* Round up stack size to nearest multiple of _thr_page_size so
* that mmap() * will work. If the stack size is not an even
Expand Down Expand Up @@ -83,7 +81,7 @@ int ThreadState::CreateStack(PthreadAttr* attr) {
}

/* Allocate a new stack. */
stackaddr = last_stack - stacksize - guardsize;
VAddr stackaddr = last_stack - stacksize - guardsize;

/*
* Even if stack allocation fails, we don't want to try to
Expand Down
4 changes: 4 additions & 0 deletions src/core/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ class MemoryManager {
rasterizer = rasterizer_;
}

AddressSpace& GetAddressSpace() {
return impl;
}

u64 GetTotalDirectSize() const {
return total_direct_size;
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/module.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma clang optimize off

#include <cryptopp/sha.h>

#include "common/alignment.h"
Expand Down
4 changes: 2 additions & 2 deletions src/video_core/amdgpu/liverpool.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma clang optimize off

#include "common/assert.h"
#include "common/config.h"
#include "common/debug.h"
Expand Down Expand Up @@ -550,7 +550,7 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
sizeof(u32), false);
} else if (dma_data->src_sel == DmaDataSrc::Gds &&
dma_data->dst_sel == DmaDataDst::Memory) {
LOG_WARNING(Render_Vulkan, "GDS memory read");
//LOG_WARNING(Render_Vulkan, "GDS memory read");
} else if (dma_data->src_sel == DmaDataSrc::Memory &&
dma_data->dst_sel == DmaDataDst::Memory) {
rasterizer->InlineData(dma_data->DstAddress<VAddr>(),
Expand Down
15 changes: 6 additions & 9 deletions src/video_core/page_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "common/assert.h"
#include "common/error.h"
#include "common/signal_context.h"
#include "core/memory.h"
#include "core/signals.h"
#include "video_core/page_manager.h"
#include "video_core/renderer_vulkan/vk_rasterizer.h"
Expand Down Expand Up @@ -145,15 +146,11 @@ struct PageManager::Impl {
ASSERT_MSG(owned_ranges.find(address) != owned_ranges.end(),
"Attempted to track non-GPU memory at address {:#x}, size {:#x}.", address,
size);
#ifdef _WIN32
DWORD prot = allow_write ? PAGE_READWRITE : PAGE_READONLY;
DWORD old_prot{};
BOOL result = VirtualProtect(std::bit_cast<LPVOID>(address), size, prot, &old_prot);
ASSERT_MSG(result != 0, "Region protection failed");
#else
mprotect(reinterpret_cast<void*>(address), size,
PROT_READ | (allow_write ? PROT_WRITE : 0));
#endif
auto* memory = Core::Memory::Instance();
auto& impl = memory->GetAddressSpace();
impl.Protect(address, size,
allow_write ? Core::MemoryPermission::ReadWrite
: Core::MemoryPermission::Read);
}

static bool GuestFaultSignalHandler(void* context, void* fault_address) {
Expand Down
2 changes: 1 addition & 1 deletion src/video_core/renderer_vulkan/vk_platform.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma clang optimize off

// Include the vulkan platform specific header
#if defined(ANDROID)
#define VK_USE_PLATFORM_ANDROID_KHR
Expand Down

0 comments on commit 9107576

Please sign in to comment.