code: Cleanup and warning fixes from the Vulkan PR (#6163)
Co-authored-by: emufan4568 <geoster3d@gmail.com> Co-authored-by: Kyle Kienapfel <Docteh@users.noreply.github.com>
This commit is contained in:
parent
aa84022704
commit
1ddea27ac8
72 changed files with 895 additions and 626 deletions
|
@ -228,6 +228,7 @@ u32 ARM_Dynarmic::GetVFPSystemReg(VFPSystemRegister reg) const {
|
|||
default:
|
||||
UNREACHABLE_MSG("Unknown VFP system register: {}", reg);
|
||||
}
|
||||
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
|
@ -261,6 +262,8 @@ u32 ARM_Dynarmic::GetCP15Register(CP15Register reg) const {
|
|||
default:
|
||||
UNREACHABLE_MSG("Unknown CP15 register: {}", reg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ARM_Dynarmic::SetCP15Register(CP15Register reg, u32 value) {
|
||||
|
|
|
@ -849,17 +849,13 @@ static int InterpreterTranslateBlock(ARMul_State* cpu, std::size_t& bb_start, u3
|
|||
// Save start addr of basicblock in CreamCache
|
||||
ARM_INST_PTR inst_base = nullptr;
|
||||
TransExtData ret = TransExtData::NON_BRANCH;
|
||||
int size = 0; // instruction size of basic block
|
||||
bb_start = trans_cache_buf_top;
|
||||
|
||||
u32 phys_addr = addr;
|
||||
u32 pc_start = cpu->Reg[15];
|
||||
|
||||
while (ret == TransExtData::NON_BRANCH) {
|
||||
unsigned int inst_size = InterpreterTranslateInstruction(cpu, phys_addr, inst_base);
|
||||
|
||||
size++;
|
||||
|
||||
u32 inst_size = InterpreterTranslateInstruction(cpu, phys_addr, inst_base);
|
||||
phys_addr += inst_size;
|
||||
|
||||
if ((phys_addr & 0xfff) == 0) {
|
||||
|
@ -972,7 +968,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
|
|||
|
||||
// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a
|
||||
// clunky switch statement.
|
||||
#if defined __GNUC__ || defined __clang__
|
||||
#if defined __GNUC__ || (defined __clang__ && !defined _MSC_VER)
|
||||
#define GOTO_NEXT_INST \
|
||||
GDB_BP_CHECK; \
|
||||
if (num_instrs >= cpu->NumInstrsToExecute) \
|
||||
|
|
|
@ -1218,7 +1218,7 @@ u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr) {
|
|||
|
||||
for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
|
||||
u32 except;
|
||||
char type;
|
||||
[[maybe_unused]] char type;
|
||||
|
||||
type = (fop->flags & OP_SD) ? 's' : 'd';
|
||||
if (op == FOP_EXT)
|
||||
|
|
|
@ -1242,7 +1242,7 @@ u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr) {
|
|||
for (vecitr = 0; vecitr <= veclen; vecitr += 1 << FPSCR_LENGTH_BIT) {
|
||||
s32 m = vfp_get_float(state, sm);
|
||||
u32 except;
|
||||
char type;
|
||||
[[maybe_unused]] char type;
|
||||
|
||||
type = (fop->flags & OP_DD) ? 'd' : 's';
|
||||
if (op == FOP_EXT)
|
||||
|
|
|
@ -47,7 +47,7 @@ void CheatEngine::AddCheat(const std::shared_ptr<CheatBase>& cheat) {
|
|||
|
||||
void CheatEngine::RemoveCheat(int index) {
|
||||
std::unique_lock<std::shared_mutex> lock(cheats_list_mutex);
|
||||
if (index < 0 || index >= cheats_list.size()) {
|
||||
if (index < 0 || index >= static_cast<int>(cheats_list.size())) {
|
||||
LOG_ERROR(Core_Cheats, "Invalid index {}", index);
|
||||
return;
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ void CheatEngine::RemoveCheat(int index) {
|
|||
|
||||
void CheatEngine::UpdateCheat(int index, const std::shared_ptr<CheatBase>& new_cheat) {
|
||||
std::unique_lock<std::shared_mutex> lock(cheats_list_mutex);
|
||||
if (index < 0 || index >= cheats_list.size()) {
|
||||
if (index < 0 || index >= static_cast<int>(cheats_list.size())) {
|
||||
LOG_ERROR(Core_Cheats, "Invalid index {}", index);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -301,10 +301,6 @@ private:
|
|||
std::vector<std::shared_ptr<Timer>> timers;
|
||||
Timer* current_timer = nullptr;
|
||||
|
||||
// Stores a scaling for the internal clockspeed. Changing this number results in
|
||||
// under/overclocking the guest cpu
|
||||
double cpu_clock_scale = 1.0;
|
||||
|
||||
// When true, the event queue can't be modified. Used while deserializing to workaround
|
||||
// destructor side effects.
|
||||
bool event_queue_locked = false;
|
||||
|
|
|
@ -849,14 +849,14 @@ static void ReadMemory() {
|
|||
SendReply("E01");
|
||||
}
|
||||
|
||||
if (!Memory::IsValidVirtualAddress(*Core::System::GetInstance().Kernel().GetCurrentProcess(),
|
||||
addr)) {
|
||||
auto& memory = Core::System::GetInstance().Memory();
|
||||
if (!memory.IsValidVirtualAddress(*Core::System::GetInstance().Kernel().GetCurrentProcess(),
|
||||
addr)) {
|
||||
return SendReply("E00");
|
||||
}
|
||||
|
||||
std::vector<u8> data(len);
|
||||
Core::System::GetInstance().Memory().ReadBlock(
|
||||
*Core::System::GetInstance().Kernel().GetCurrentProcess(), addr, data.data(), len);
|
||||
memory.ReadBlock(addr, data.data(), len);
|
||||
|
||||
MemToGdbHex(reply, data.data(), len);
|
||||
reply[len * 2] = '\0';
|
||||
|
@ -873,16 +873,16 @@ static void WriteMemory() {
|
|||
auto len_pos = std::find(start_offset, command_buffer + command_length, ':');
|
||||
u32 len = HexToInt(start_offset, static_cast<u32>(len_pos - start_offset));
|
||||
|
||||
if (!Memory::IsValidVirtualAddress(*Core::System::GetInstance().Kernel().GetCurrentProcess(),
|
||||
addr)) {
|
||||
auto& memory = Core::System::GetInstance().Memory();
|
||||
if (!memory.IsValidVirtualAddress(*Core::System::GetInstance().Kernel().GetCurrentProcess(),
|
||||
addr)) {
|
||||
return SendReply("E00");
|
||||
}
|
||||
|
||||
std::vector<u8> data(len);
|
||||
|
||||
GdbHexToMem(data.data(), len_pos + 1, len);
|
||||
Core::System::GetInstance().Memory().WriteBlock(
|
||||
*Core::System::GetInstance().Kernel().GetCurrentProcess(), addr, data.data(), len);
|
||||
memory.WriteBlock(addr, data.data(), len);
|
||||
Core::GetRunningCore().ClearInstructionCache();
|
||||
SendReply("OK");
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ private:
|
|||
std::shared_ptr<Callback> timeout_callback;
|
||||
|
||||
void WakeUp(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||
std::shared_ptr<WaitObject> object);
|
||||
std::shared_ptr<WaitObject> object) override;
|
||||
|
||||
class DummyCallback : public WakeupCallback {
|
||||
public:
|
||||
|
|
|
@ -138,10 +138,10 @@ ResultCode TranslateCommandBuffer(Kernel::KernelSystem& kernel, Memory::MemorySy
|
|||
u32 size = static_cast<u32>(descInfo.size);
|
||||
IPC::MappedBufferPermissions permissions = descInfo.perms;
|
||||
|
||||
VAddr page_start = Common::AlignDown(source_address, Memory::PAGE_SIZE);
|
||||
VAddr page_start = Common::AlignDown(source_address, Memory::CITRA_PAGE_SIZE);
|
||||
u32 page_offset = source_address - page_start;
|
||||
u32 num_pages =
|
||||
Common::AlignUp(page_offset + size, Memory::PAGE_SIZE) >> Memory::PAGE_BITS;
|
||||
u32 num_pages = Common::AlignUp(page_offset + size, Memory::CITRA_PAGE_SIZE) >>
|
||||
Memory::CITRA_PAGE_BITS;
|
||||
|
||||
// Skip when the size is zero and num_pages == 0
|
||||
if (size == 0) {
|
||||
|
@ -171,8 +171,8 @@ ResultCode TranslateCommandBuffer(Kernel::KernelSystem& kernel, Memory::MemorySy
|
|||
found->target_address, size);
|
||||
}
|
||||
|
||||
VAddr prev_reserve = page_start - Memory::PAGE_SIZE;
|
||||
VAddr next_reserve = page_start + num_pages * Memory::PAGE_SIZE;
|
||||
VAddr prev_reserve = page_start - Memory::CITRA_PAGE_SIZE;
|
||||
VAddr next_reserve = page_start + num_pages * Memory::CITRA_PAGE_SIZE;
|
||||
|
||||
auto& prev_vma = src_process->vm_manager.FindVMA(prev_reserve)->second;
|
||||
auto& next_vma = src_process->vm_manager.FindVMA(next_reserve)->second;
|
||||
|
@ -180,8 +180,9 @@ ResultCode TranslateCommandBuffer(Kernel::KernelSystem& kernel, Memory::MemorySy
|
|||
next_vma.meminfo_state == MemoryState::Reserved);
|
||||
|
||||
// Unmap the buffer and guard pages from the source process
|
||||
ResultCode result = src_process->vm_manager.UnmapRange(
|
||||
page_start - Memory::PAGE_SIZE, (num_pages + 2) * Memory::PAGE_SIZE);
|
||||
ResultCode result =
|
||||
src_process->vm_manager.UnmapRange(page_start - Memory::CITRA_PAGE_SIZE,
|
||||
(num_pages + 2) * Memory::CITRA_PAGE_SIZE);
|
||||
ASSERT(result == RESULT_SUCCESS);
|
||||
|
||||
mapped_buffer_context.erase(found);
|
||||
|
@ -196,13 +197,13 @@ ResultCode TranslateCommandBuffer(Kernel::KernelSystem& kernel, Memory::MemorySy
|
|||
|
||||
// Reserve a page of memory before the mapped buffer
|
||||
std::shared_ptr<BackingMem> reserve_buffer =
|
||||
std::make_shared<BufferMem>(Memory::PAGE_SIZE);
|
||||
std::make_shared<BufferMem>(Memory::CITRA_PAGE_SIZE);
|
||||
dst_process->vm_manager.MapBackingMemoryToBase(
|
||||
Memory::IPC_MAPPING_VADDR, Memory::IPC_MAPPING_SIZE, reserve_buffer,
|
||||
Memory::PAGE_SIZE, Kernel::MemoryState::Reserved);
|
||||
Memory::CITRA_PAGE_SIZE, Kernel::MemoryState::Reserved);
|
||||
|
||||
std::shared_ptr<BackingMem> buffer =
|
||||
std::make_shared<BufferMem>(num_pages * Memory::PAGE_SIZE);
|
||||
std::make_shared<BufferMem>(num_pages * Memory::CITRA_PAGE_SIZE);
|
||||
memory.ReadBlock(*src_process, source_address, buffer->GetPtr() + page_offset, size);
|
||||
|
||||
// Map the page(s) into the target process' address space.
|
||||
|
|
|
@ -127,7 +127,7 @@ void Process::ParseKernelCaps(const u32* kernel_caps, std::size_t len) {
|
|||
// Mapped memory page
|
||||
AddressMapping mapping;
|
||||
mapping.address = descriptor << 12;
|
||||
mapping.size = Memory::PAGE_SIZE;
|
||||
mapping.size = Memory::CITRA_PAGE_SIZE;
|
||||
mapping.read_only = false;
|
||||
mapping.unk_flag = false;
|
||||
|
||||
|
@ -265,7 +265,7 @@ ResultCode Process::HeapFree(VAddr target, u32 size) {
|
|||
|
||||
// Free heaps block by block
|
||||
CASCADE_RESULT(auto backing_blocks, vm_manager.GetBackingBlocksForRange(target, size));
|
||||
for (const auto [backing_memory, block_size] : backing_blocks) {
|
||||
for (const auto& [backing_memory, block_size] : backing_blocks) {
|
||||
memory_region->Free(kernel.memory.GetFCRAMOffset(backing_memory.GetPtr()), block_size);
|
||||
}
|
||||
|
||||
|
@ -396,7 +396,7 @@ ResultCode Process::Map(VAddr target, VAddr source, u32 size, VMAPermission perm
|
|||
|
||||
CASCADE_RESULT(auto backing_blocks, vm_manager.GetBackingBlocksForRange(source, size));
|
||||
VAddr interval_target = target;
|
||||
for (const auto [backing_memory, block_size] : backing_blocks) {
|
||||
for (const auto& [backing_memory, block_size] : backing_blocks) {
|
||||
auto target_vma =
|
||||
vm_manager.MapBackingMemory(interval_target, backing_memory, block_size, target_state);
|
||||
ASSERT(target_vma.Succeeded());
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "common/logging/log.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "common/scm_rev.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
|
@ -39,7 +38,6 @@
|
|||
#include "core/hle/kernel/wait_object.h"
|
||||
#include "core/hle/lock.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
|
@ -219,10 +217,10 @@ ResultCode SVC::ControlMemory(u32* out_addr, u32 addr0, u32 addr1, u32 size, u32
|
|||
"size=0x{:X}, permissions=0x{:08X}",
|
||||
operation, addr0, addr1, size, permissions);
|
||||
|
||||
if ((addr0 & Memory::PAGE_MASK) != 0 || (addr1 & Memory::PAGE_MASK) != 0) {
|
||||
if ((addr0 & Memory::CITRA_PAGE_MASK) != 0 || (addr1 & Memory::CITRA_PAGE_MASK) != 0) {
|
||||
return ERR_MISALIGNED_ADDRESS;
|
||||
}
|
||||
if ((size & Memory::PAGE_MASK) != 0) {
|
||||
if ((size & Memory::CITRA_PAGE_MASK) != 0) {
|
||||
return ERR_MISALIGNED_SIZE;
|
||||
}
|
||||
|
||||
|
@ -374,7 +372,7 @@ ResultCode SVC::UnmapMemoryBlock(Handle handle, u32 addr) {
|
|||
|
||||
/// Connect to an OS service given the port name, returns the handle to the port to out
|
||||
ResultCode SVC::ConnectToPort(Handle* out_handle, VAddr port_name_address) {
|
||||
if (!Memory::IsValidVirtualAddress(*kernel.GetCurrentProcess(), port_name_address))
|
||||
if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), port_name_address))
|
||||
return ERR_NOT_FOUND;
|
||||
|
||||
static constexpr std::size_t PortNameMaxLength = 11;
|
||||
|
@ -541,7 +539,7 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle
|
|||
bool wait_all, s64 nano_seconds) {
|
||||
Thread* thread = kernel.GetCurrentThreadManager().GetCurrentThread();
|
||||
|
||||
if (!Memory::IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address))
|
||||
if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address))
|
||||
return ERR_INVALID_POINTER;
|
||||
|
||||
// NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If
|
||||
|
@ -687,7 +685,7 @@ static ResultCode ReceiveIPCRequest(Kernel::KernelSystem& kernel, Memory::Memory
|
|||
/// In a single operation, sends a IPC reply and waits for a new request.
|
||||
ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_count,
|
||||
Handle reply_target) {
|
||||
if (!Memory::IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address))
|
||||
if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address))
|
||||
return ERR_INVALID_POINTER;
|
||||
|
||||
// Check if 'handle_count' is invalid
|
||||
|
@ -1288,7 +1286,7 @@ s64 SVC::GetSystemTick() {
|
|||
/// Creates a memory block at the specified address with the specified permissions and size
|
||||
ResultCode SVC::CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission,
|
||||
u32 other_permission) {
|
||||
if (size % Memory::PAGE_SIZE != 0)
|
||||
if (size % Memory::CITRA_PAGE_SIZE != 0)
|
||||
return ERR_MISALIGNED_SIZE;
|
||||
|
||||
std::shared_ptr<SharedMemory> shared_memory = nullptr;
|
||||
|
@ -1393,7 +1391,7 @@ ResultCode SVC::AcceptSession(Handle* out_server_session, Handle server_port_han
|
|||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static void CopyStringPart(char* out, const char* in, int offset, int max_length) {
|
||||
static void CopyStringPart(char* out, const char* in, size_t offset, size_t max_length) {
|
||||
size_t str_size = strlen(in);
|
||||
if (offset < str_size) {
|
||||
strncpy(out, in + offset, max_length - 1);
|
||||
|
@ -1509,7 +1507,7 @@ ResultCode SVC::GetProcessInfo(s64* out, Handle process_handle, u32 type) {
|
|||
// TODO(yuriks): Type 0 returns a slightly higher number than type 2, but I'm not sure
|
||||
// what's the difference between them.
|
||||
*out = process->memory_used;
|
||||
if (*out % Memory::PAGE_SIZE != 0) {
|
||||
if (*out % Memory::CITRA_PAGE_SIZE != 0) {
|
||||
LOG_ERROR(Kernel_SVC, "called, memory size not page-aligned");
|
||||
return ERR_MISALIGNED_SIZE;
|
||||
}
|
||||
|
|
|
@ -105,9 +105,9 @@ void Thread::Stop() {
|
|||
ReleaseThreadMutexes(this);
|
||||
|
||||
// Mark the TLS slot in the thread's page as free.
|
||||
u32 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE;
|
||||
u32 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::CITRA_PAGE_SIZE;
|
||||
u32 tls_slot =
|
||||
((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE;
|
||||
((tls_address - Memory::TLS_AREA_VADDR) % Memory::CITRA_PAGE_SIZE) / Memory::TLS_ENTRY_SIZE;
|
||||
ASSERT(owner_process.lock());
|
||||
owner_process.lock()->tls_slots[tls_page].reset(tls_slot);
|
||||
}
|
||||
|
@ -337,8 +337,7 @@ ResultVal<std::shared_ptr<Thread>> KernelSystem::CreateThread(
|
|||
}
|
||||
|
||||
// TODO(yuriks): Other checks, returning 0xD9001BEA
|
||||
|
||||
if (!Memory::IsValidVirtualAddress(*owner_process, entry_point)) {
|
||||
if (!memory.IsValidVirtualAddress(*owner_process, entry_point)) {
|
||||
LOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:08x}", name, entry_point);
|
||||
// TODO: Verify error
|
||||
return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
|
||||
|
@ -374,13 +373,13 @@ ResultVal<std::shared_ptr<Thread>> KernelSystem::CreateThread(
|
|||
auto memory_region = GetMemoryRegion(MemoryRegion::BASE);
|
||||
|
||||
// Allocate some memory from the end of the linear heap for this region.
|
||||
auto offset = memory_region->LinearAllocate(Memory::PAGE_SIZE);
|
||||
auto offset = memory_region->LinearAllocate(Memory::CITRA_PAGE_SIZE);
|
||||
if (!offset) {
|
||||
LOG_ERROR(Kernel_SVC,
|
||||
"Not enough space in region to allocate a new TLS page for thread");
|
||||
return ERR_OUT_OF_MEMORY;
|
||||
}
|
||||
owner_process->memory_used += Memory::PAGE_SIZE;
|
||||
owner_process->memory_used += Memory::CITRA_PAGE_SIZE;
|
||||
|
||||
tls_slots.emplace_back(0); // The page is completely available at the start
|
||||
available_page = tls_slots.size() - 1;
|
||||
|
@ -390,14 +389,14 @@ ResultVal<std::shared_ptr<Thread>> KernelSystem::CreateThread(
|
|||
|
||||
// Map the page to the current process' address space.
|
||||
vm_manager.MapBackingMemory(
|
||||
Memory::TLS_AREA_VADDR + static_cast<VAddr>(available_page) * Memory::PAGE_SIZE,
|
||||
memory.GetFCRAMRef(*offset), Memory::PAGE_SIZE, MemoryState::Locked);
|
||||
Memory::TLS_AREA_VADDR + static_cast<VAddr>(available_page) * Memory::CITRA_PAGE_SIZE,
|
||||
memory.GetFCRAMRef(*offset), Memory::CITRA_PAGE_SIZE, MemoryState::Locked);
|
||||
}
|
||||
|
||||
// Mark the slot as used
|
||||
tls_slots[available_page].set(available_slot);
|
||||
thread->tls_address = Memory::TLS_AREA_VADDR +
|
||||
static_cast<VAddr>(available_page) * Memory::PAGE_SIZE +
|
||||
static_cast<VAddr>(available_page) * Memory::CITRA_PAGE_SIZE +
|
||||
static_cast<VAddr>(available_slot) * Memory::TLS_ENTRY_SIZE;
|
||||
|
||||
memory.ZeroBlock(*owner_process, thread->tls_address, Memory::TLS_ENTRY_SIZE);
|
||||
|
|
|
@ -260,8 +260,8 @@ VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle& iter) {
|
|||
}
|
||||
|
||||
ResultVal<VMManager::VMAIter> VMManager::CarveVMA(VAddr base, u32 size) {
|
||||
ASSERT_MSG((size & Memory::PAGE_MASK) == 0, "non-page aligned size: {:#10X}", size);
|
||||
ASSERT_MSG((base & Memory::PAGE_MASK) == 0, "non-page aligned base: {:#010X}", base);
|
||||
ASSERT_MSG((size & Memory::CITRA_PAGE_MASK) == 0, "non-page aligned size: {:#10X}", size);
|
||||
ASSERT_MSG((base & Memory::CITRA_PAGE_MASK) == 0, "non-page aligned base: {:#010X}", base);
|
||||
|
||||
VMAIter vma_handle = StripIterConstness(FindVMA(base));
|
||||
if (vma_handle == vma_map.end()) {
|
||||
|
@ -296,8 +296,8 @@ ResultVal<VMManager::VMAIter> VMManager::CarveVMA(VAddr base, u32 size) {
|
|||
}
|
||||
|
||||
ResultVal<VMManager::VMAIter> VMManager::CarveVMARange(VAddr target, u32 size) {
|
||||
ASSERT_MSG((size & Memory::PAGE_MASK) == 0, "non-page aligned size: {:#10X}", size);
|
||||
ASSERT_MSG((target & Memory::PAGE_MASK) == 0, "non-page aligned base: {:#010X}", target);
|
||||
ASSERT_MSG((size & Memory::CITRA_PAGE_MASK) == 0, "non-page aligned size: {:#10X}", size);
|
||||
ASSERT_MSG((target & Memory::CITRA_PAGE_MASK) == 0, "non-page aligned base: {:#010X}", target);
|
||||
|
||||
const VAddr target_end = target + size;
|
||||
ASSERT(target_end >= target);
|
||||
|
|
|
@ -17,12 +17,9 @@
|
|||
#include "core/file_sys/errors.h"
|
||||
#include "core/file_sys/ncch_container.h"
|
||||
#include "core/file_sys/title_metadata.h"
|
||||
#include "core/hle/ipc.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/client_port.h"
|
||||
#include "core/hle/kernel/client_session.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/handle_table.h"
|
||||
#include "core/hle/kernel/server_session.h"
|
||||
#include "core/hle/kernel/session.h"
|
||||
#include "core/hle/service/am/am.h"
|
||||
|
@ -610,7 +607,6 @@ void Module::Interface::FindDLCContentInfos(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
std::string tmd_path = GetTitleMetadataPath(media_type, title_id);
|
||||
|
||||
u32 content_read = 0;
|
||||
FileSys::TitleMetadata tmd;
|
||||
if (tmd.Load(tmd_path) == Loader::ResultStatus::Success) {
|
||||
std::size_t write_offset = 0;
|
||||
|
@ -642,7 +638,6 @@ void Module::Interface::FindDLCContentInfos(Kernel::HLERequestContext& ctx) {
|
|||
|
||||
content_info_out.Write(&content_info, write_offset, sizeof(ContentInfo));
|
||||
write_offset += sizeof(ContentInfo);
|
||||
content_read++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/common_paths.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/applets/applet.h"
|
||||
#include "core/hle/service/apt/applet_manager.h"
|
||||
|
@ -27,47 +26,66 @@ struct AppletTitleData {
|
|||
|
||||
static constexpr std::size_t NumApplets = 29;
|
||||
static constexpr std::array<AppletTitleData, NumApplets> applet_titleids = {{
|
||||
{AppletId::HomeMenu, AppletId::None, 0x4003000008202, 0x4003000008F02, 0x4003000009802,
|
||||
0x4003000008202, 0x400300000A102, 0x400300000A902, 0x400300000B102},
|
||||
{AppletId::AlternateMenu, AppletId::None, 0x4003000008102, 0x4003000008102, 0x4003000008102,
|
||||
0x4003000008102, 0x4003000008102, 0x4003000008102, 0x4003000008102},
|
||||
{AppletId::Camera, AppletId::None, 0x4003000008402, 0x4003000009002, 0x4003000009902,
|
||||
0x4003000008402, 0x400300000A202, 0x400300000AA02, 0x400300000B202},
|
||||
{AppletId::FriendList, AppletId::None, 0x4003000008D02, 0x4003000009602, 0x4003000009F02,
|
||||
0x4003000008D02, 0x400300000A702, 0x400300000AF02, 0x400300000B702},
|
||||
{AppletId::GameNotes, AppletId::None, 0x4003000008702, 0x4003000009302, 0x4003000009C02,
|
||||
0x4003000008702, 0x400300000A502, 0x400300000AD02, 0x400300000B502},
|
||||
{AppletId::InternetBrowser, AppletId::None, 0x4003000008802, 0x4003000009402, 0x4003000009D02,
|
||||
0x4003000008802, 0x400300000A602, 0x400300000AE02, 0x400300000B602},
|
||||
{AppletId::InstructionManual, AppletId::None, 0x4003000008602, 0x4003000009202, 0x4003000009B02,
|
||||
0x4003000008602, 0x400300000A402, 0x400300000AC02, 0x400300000B402},
|
||||
{AppletId::Notifications, AppletId::None, 0x4003000008E02, 0x4003000009702, 0x400300000A002,
|
||||
0x4003000008E02, 0x400300000A802, 0x400300000B002, 0x400300000B802},
|
||||
{AppletId::Miiverse, AppletId::None, 0x400300000BC02, 0x400300000BD02, 0x400300000BE02,
|
||||
0x400300000BC02, 0x4003000009E02, 0x4003000009502, 0x400300000B902},
|
||||
{{AppletId::HomeMenu, AppletId::None},
|
||||
{0x4003000008202, 0x4003000008F02, 0x4003000009802, 0x4003000008202, 0x400300000A102,
|
||||
0x400300000A902, 0x400300000B102}},
|
||||
{{AppletId::AlternateMenu, AppletId::None},
|
||||
{0x4003000008102, 0x4003000008102, 0x4003000008102, 0x4003000008102, 0x4003000008102,
|
||||
0x4003000008102, 0x4003000008102}},
|
||||
{{AppletId::Camera, AppletId::None},
|
||||
{0x4003000008402, 0x4003000009002, 0x4003000009902, 0x4003000008402, 0x400300000A202,
|
||||
0x400300000AA02, 0x400300000B202}},
|
||||
{{AppletId::FriendList, AppletId::None},
|
||||
{0x4003000008D02, 0x4003000009602, 0x4003000009F02, 0x4003000008D02, 0x400300000A702,
|
||||
0x400300000AF02, 0x400300000B702}},
|
||||
{{AppletId::GameNotes, AppletId::None},
|
||||
{0x4003000008702, 0x4003000009302, 0x4003000009C02, 0x4003000008702, 0x400300000A502,
|
||||
0x400300000AD02, 0x400300000B502}},
|
||||
{{AppletId::InternetBrowser, AppletId::None},
|
||||
{0x4003000008802, 0x4003000009402, 0x4003000009D02, 0x4003000008802, 0x400300000A602,
|
||||
0x400300000AE02, 0x400300000B602}},
|
||||
{{AppletId::InstructionManual, AppletId::None},
|
||||
{0x4003000008602, 0x4003000009202, 0x4003000009B02, 0x4003000008602, 0x400300000A402,
|
||||
0x400300000AC02, 0x400300000B402}},
|
||||
{{AppletId::Notifications, AppletId::None},
|
||||
{0x4003000008E02, 0x4003000009702, 0x400300000A002, 0x4003000008E02, 0x400300000A802,
|
||||
0x400300000B002, 0x400300000B802}},
|
||||
{{AppletId::Miiverse, AppletId::None},
|
||||
{0x400300000BC02, 0x400300000BD02, 0x400300000BE02, 0x400300000BC02, 0x4003000009E02,
|
||||
0x4003000009502, 0x400300000B902}},
|
||||
// These values obtained from an older NS dump firmware 4.5
|
||||
{AppletId::MiiversePost, AppletId::None, 0x400300000BA02, 0x400300000BA02, 0x400300000BA02,
|
||||
0x400300000BA02, 0x400300000BA02, 0x400300000BA02, 0x400300000BA02},
|
||||
{{AppletId::MiiversePost, AppletId::None},
|
||||
{0x400300000BA02, 0x400300000BA02, 0x400300000BA02, 0x400300000BA02, 0x400300000BA02,
|
||||
0x400300000BA02, 0x400300000BA02}},
|
||||
// {AppletId::MiiversePost, AppletId::None, 0x4003000008302, 0x4003000008B02, 0x400300000BA02,
|
||||
// 0x4003000008302, 0x0, 0x0, 0x0},
|
||||
{AppletId::AmiiboSettings, AppletId::None, 0x4003000009502, 0x4003000009E02, 0x400300000B902,
|
||||
0x4003000009502, 0x0, 0x4003000008C02, 0x400300000BF02},
|
||||
{AppletId::SoftwareKeyboard1, AppletId::SoftwareKeyboard2, 0x400300000C002, 0x400300000C802,
|
||||
0x400300000D002, 0x400300000C002, 0x400300000D802, 0x400300000DE02, 0x400300000E402},
|
||||
{AppletId::Ed1, AppletId::Ed2, 0x400300000C102, 0x400300000C902, 0x400300000D102,
|
||||
0x400300000C102, 0x400300000D902, 0x400300000DF02, 0x400300000E502},
|
||||
{AppletId::PnoteApp, AppletId::PnoteApp2, 0x400300000C302, 0x400300000CB02, 0x400300000D302,
|
||||
0x400300000C302, 0x400300000DB02, 0x400300000E102, 0x400300000E702},
|
||||
{AppletId::SnoteApp, AppletId::SnoteApp2, 0x400300000C402, 0x400300000CC02, 0x400300000D402,
|
||||
0x400300000C402, 0x400300000DC02, 0x400300000E202, 0x400300000E802},
|
||||
{AppletId::Error, AppletId::Error2, 0x400300000C502, 0x400300000C502, 0x400300000C502,
|
||||
0x400300000C502, 0x400300000CF02, 0x400300000CF02, 0x400300000CF02},
|
||||
{AppletId::Mint, AppletId::Mint2, 0x400300000C602, 0x400300000CE02, 0x400300000D602,
|
||||
0x400300000C602, 0x400300000DD02, 0x400300000E302, 0x400300000E902},
|
||||
{AppletId::Extrapad, AppletId::Extrapad2, 0x400300000CD02, 0x400300000CD02, 0x400300000CD02,
|
||||
0x400300000CD02, 0x400300000D502, 0x400300000D502, 0x400300000D502},
|
||||
{AppletId::Memolib, AppletId::Memolib2, 0x400300000F602, 0x400300000F602, 0x400300000F602,
|
||||
0x400300000F602, 0x400300000F602, 0x400300000F602, 0x400300000F602},
|
||||
{{AppletId::AmiiboSettings, AppletId::None},
|
||||
{0x4003000009502, 0x4003000009E02, 0x400300000B902, 0x4003000009502, 0x0, 0x4003000008C02,
|
||||
0x400300000BF02}},
|
||||
{{AppletId::SoftwareKeyboard1, AppletId::SoftwareKeyboard2},
|
||||
{0x400300000C002, 0x400300000C802, 0x400300000D002, 0x400300000C002, 0x400300000D802,
|
||||
0x400300000DE02, 0x400300000E402}},
|
||||
{{AppletId::Ed1, AppletId::Ed2},
|
||||
{0x400300000C102, 0x400300000C902, 0x400300000D102, 0x400300000C102, 0x400300000D902,
|
||||
0x400300000DF02, 0x400300000E502}},
|
||||
{{AppletId::PnoteApp, AppletId::PnoteApp2},
|
||||
{0x400300000C302, 0x400300000CB02, 0x400300000D302, 0x400300000C302, 0x400300000DB02,
|
||||
0x400300000E102, 0x400300000E702}},
|
||||
{{AppletId::SnoteApp, AppletId::SnoteApp2},
|
||||
{0x400300000C402, 0x400300000CC02, 0x400300000D402, 0x400300000C402, 0x400300000DC02,
|
||||
0x400300000E202, 0x400300000E802}},
|
||||
{{AppletId::Error, AppletId::Error2},
|
||||
{0x400300000C502, 0x400300000C502, 0x400300000C502, 0x400300000C502, 0x400300000CF02,
|
||||
0x400300000CF02, 0x400300000CF02}},
|
||||
{{AppletId::Mint, AppletId::Mint2},
|
||||
{0x400300000C602, 0x400300000CE02, 0x400300000D602, 0x400300000C602, 0x400300000DD02,
|
||||
0x400300000E302, 0x400300000E902}},
|
||||
{{AppletId::Extrapad, AppletId::Extrapad2},
|
||||
{0x400300000CD02, 0x400300000CD02, 0x400300000CD02, 0x400300000CD02, 0x400300000D502,
|
||||
0x400300000D502, 0x400300000D502}},
|
||||
{{AppletId::Memolib, AppletId::Memolib2},
|
||||
{0x400300000F602, 0x400300000F602, 0x400300000F602, 0x400300000F602, 0x400300000F602,
|
||||
0x400300000F602, 0x400300000F602}},
|
||||
// TODO(Subv): Fill in the rest of the titleids
|
||||
}};
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <cryptopp/osrng.h>
|
||||
#include <cryptopp/sha.h>
|
||||
#include "common/archives.h"
|
||||
#include "common/common_paths.h"
|
||||
#include "common/file_util.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/string_util.h"
|
||||
|
@ -107,7 +106,7 @@ static_assert(sizeof(ConsoleCountryInfo) == 4, "ConsoleCountryInfo must be exact
|
|||
|
||||
constexpr EULAVersion MAX_EULA_VERSION{0x7F, 0x7F};
|
||||
constexpr ConsoleModelInfo CONSOLE_MODEL_OLD{NINTENDO_3DS_XL, {0, 0, 0}};
|
||||
constexpr ConsoleModelInfo CONSOLE_MODEL_NEW{NEW_NINTENDO_3DS_XL, {0, 0, 0}};
|
||||
[[maybe_unused]] constexpr ConsoleModelInfo CONSOLE_MODEL_NEW{NEW_NINTENDO_3DS_XL, {0, 0, 0}};
|
||||
constexpr u8 CONSOLE_LANGUAGE = LANGUAGE_EN;
|
||||
constexpr UsernameBlock CONSOLE_USERNAME_BLOCK{u"CITRA", 0, 0};
|
||||
constexpr BirthdayBlock PROFILE_BIRTHDAY{3, 25}; // March 25th, 2014
|
||||
|
@ -269,7 +268,7 @@ void Module::Interface::GetSystemModel(Kernel::HLERequestContext& ctx) {
|
|||
void Module::Interface::GetModelNintendo2DS(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx, 0x06, 0, 0);
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
u32 data;
|
||||
u32 data{};
|
||||
|
||||
// TODO(Subv): Find out the correct error codes
|
||||
rb.Push(cfg->GetConfigInfoBlock(ConsoleModelBlockID, 4, 0x8, reinterpret_cast<u8*>(&data)));
|
||||
|
@ -370,7 +369,7 @@ ResultVal<void*> Module::GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 f
|
|||
}
|
||||
|
||||
ResultCode Module::GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output) {
|
||||
void* pointer;
|
||||
void* pointer = nullptr;
|
||||
CASCADE_RESULT(pointer, GetConfigInfoBlockPointer(block_id, size, flag));
|
||||
memcpy(output, pointer, size);
|
||||
|
||||
|
@ -378,7 +377,7 @@ ResultCode Module::GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* ou
|
|||
}
|
||||
|
||||
ResultCode Module::SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input) {
|
||||
void* pointer;
|
||||
void* pointer = nullptr;
|
||||
CASCADE_RESULT(pointer, GetConfigInfoBlockPointer(block_id, size, flag));
|
||||
memcpy(pointer, input, size);
|
||||
return RESULT_SUCCESS;
|
||||
|
@ -701,7 +700,7 @@ void Module::SetSystemLanguage(SystemLanguage language) {
|
|||
}
|
||||
|
||||
SystemLanguage Module::GetSystemLanguage() {
|
||||
u8 block;
|
||||
u8 block{};
|
||||
GetConfigInfoBlock(LanguageBlockID, sizeof(block), 8, &block);
|
||||
return static_cast<SystemLanguage>(block);
|
||||
}
|
||||
|
@ -712,7 +711,7 @@ void Module::SetSoundOutputMode(SoundOutputMode mode) {
|
|||
}
|
||||
|
||||
SoundOutputMode Module::GetSoundOutputMode() {
|
||||
u8 block;
|
||||
u8 block{};
|
||||
GetConfigInfoBlock(SoundOutputModeBlockID, sizeof(block), 8, &block);
|
||||
return static_cast<SoundOutputMode>(block);
|
||||
}
|
||||
|
@ -723,7 +722,7 @@ void Module::SetCountryCode(u8 country_code) {
|
|||
}
|
||||
|
||||
u8 Module::GetCountryCode() {
|
||||
ConsoleCountryInfo block;
|
||||
ConsoleCountryInfo block{};
|
||||
GetConfigInfoBlock(CountryInfoBlockID, sizeof(block), 8, &block);
|
||||
return block.country_code;
|
||||
}
|
||||
|
@ -734,7 +733,7 @@ void Module::SetCountryInfo(u8 country_code, u8 state_code) {
|
|||
}
|
||||
|
||||
u8 Module::GetStateCode() {
|
||||
ConsoleCountryInfo block;
|
||||
ConsoleCountryInfo block{};
|
||||
GetConfigInfoBlock(CountryInfoBlockID, sizeof(block), 8, &block);
|
||||
return block.state_code;
|
||||
}
|
||||
|
|
|
@ -192,7 +192,7 @@ static_assert(sizeof(CaptureState) == 0x8, "CaptureState structure size is wrong
|
|||
|
||||
void CSND_SND::Initialize(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx, 0x01, 5, 0);
|
||||
const u32 size = Common::AlignUp(rp.Pop<u32>(), Memory::PAGE_SIZE);
|
||||
const u32 size = Common::AlignUp(rp.Pop<u32>(), Memory::CITRA_PAGE_SIZE);
|
||||
master_state_offset = rp.Pop<u32>();
|
||||
channel_state_offset = rp.Pop<u32>();
|
||||
capture_state_offset = rp.Pop<u32>();
|
||||
|
|
|
@ -95,6 +95,9 @@ void DSP_DSP::WriteProcessPipe(Kernel::HLERequestContext& ctx) {
|
|||
buffer[6] = 0;
|
||||
buffer[7] = 0;
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR(Service_DSP, "Unknown pipe {}", pipe);
|
||||
break;
|
||||
}
|
||||
|
||||
system.DSP().PipeWrite(pipe, buffer);
|
||||
|
|
|
@ -884,6 +884,8 @@ ResultVal<u16> FS_USER::GetSpecialContentIndexFromTMD(MediaType media_type, u64
|
|||
default:
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
return ResultCode(-1);
|
||||
}
|
||||
|
||||
FS_USER::FS_USER(Core::System& system)
|
||||
|
|
|
@ -8,9 +8,7 @@
|
|||
#include "common/microprofile.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/ipc.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/handle_table.h"
|
||||
#include "core/hle/kernel/shared_memory.h"
|
||||
#include "core/hle/kernel/shared_page.h"
|
||||
#include "core/hle/result.h"
|
||||
|
@ -83,7 +81,9 @@ u32 GSP_GPU::GetUnusedThreadId() const {
|
|||
if (!used_thread_ids[id])
|
||||
return id;
|
||||
}
|
||||
ASSERT_MSG(false, "All GSP threads are in use");
|
||||
|
||||
UNREACHABLE_MSG("All GSP threads are in use");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Gets a pointer to a thread command buffer in GSP shared memory
|
||||
|
|
|
@ -1502,7 +1502,7 @@ u32 CROHelper::Fix(u32 fix_level) {
|
|||
}
|
||||
}
|
||||
|
||||
fix_end = Common::AlignUp(fix_end, Memory::PAGE_SIZE);
|
||||
fix_end = Common::AlignUp(fix_end, Memory::CITRA_PAGE_SIZE);
|
||||
|
||||
u32 fixed_size = fix_end - module_address;
|
||||
SetField(FixedSize, fixed_size);
|
||||
|
@ -1525,8 +1525,8 @@ std::tuple<VAddr, u32> CROHelper::GetExecutablePages() const {
|
|||
SegmentEntry entry;
|
||||
GetEntry(system.Memory(), i, entry);
|
||||
if (entry.type == SegmentType::Code && entry.size != 0) {
|
||||
VAddr begin = Common::AlignDown(entry.offset, Memory::PAGE_SIZE);
|
||||
VAddr end = Common::AlignUp(entry.offset + entry.size, Memory::PAGE_SIZE);
|
||||
VAddr begin = Common::AlignDown(entry.offset, Memory::CITRA_PAGE_SIZE);
|
||||
VAddr end = Common::AlignUp(entry.offset + entry.size, Memory::CITRA_PAGE_SIZE);
|
||||
return std::make_tuple(begin, end - begin);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,19 +87,19 @@ void RO::Initialize(Kernel::HLERequestContext& ctx) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (crs_buffer_ptr & Memory::PAGE_MASK) {
|
||||
if (crs_buffer_ptr & Memory::CITRA_PAGE_MASK) {
|
||||
LOG_ERROR(Service_LDR, "CRS original address is not aligned");
|
||||
rb.Push(ERROR_MISALIGNED_ADDRESS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (crs_address & Memory::PAGE_MASK) {
|
||||
if (crs_address & Memory::CITRA_PAGE_MASK) {
|
||||
LOG_ERROR(Service_LDR, "CRS mapping address is not aligned");
|
||||
rb.Push(ERROR_MISALIGNED_ADDRESS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (crs_size & Memory::PAGE_MASK) {
|
||||
if (crs_size & Memory::CITRA_PAGE_MASK) {
|
||||
LOG_ERROR(Service_LDR, "CRS size is not aligned");
|
||||
rb.Push(ERROR_MISALIGNED_SIZE);
|
||||
return;
|
||||
|
@ -207,21 +207,21 @@ void RO::LoadCRO(Kernel::HLERequestContext& ctx, bool link_on_load_bug_fix) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (cro_buffer_ptr & Memory::PAGE_MASK) {
|
||||
if (cro_buffer_ptr & Memory::CITRA_PAGE_MASK) {
|
||||
LOG_ERROR(Service_LDR, "CRO original address is not aligned");
|
||||
rb.Push(ERROR_MISALIGNED_ADDRESS);
|
||||
rb.Push<u32>(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cro_address & Memory::PAGE_MASK) {
|
||||
if (cro_address & Memory::CITRA_PAGE_MASK) {
|
||||
LOG_ERROR(Service_LDR, "CRO mapping address is not aligned");
|
||||
rb.Push(ERROR_MISALIGNED_ADDRESS);
|
||||
rb.Push<u32>(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cro_size & Memory::PAGE_MASK) {
|
||||
if (cro_size & Memory::CITRA_PAGE_MASK) {
|
||||
LOG_ERROR(Service_LDR, "CRO size is not aligned");
|
||||
rb.Push(ERROR_MISALIGNED_SIZE);
|
||||
rb.Push<u32>(0);
|
||||
|
@ -354,7 +354,7 @@ void RO::UnloadCRO(Kernel::HLERequestContext& ctx) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (cro_address & Memory::PAGE_MASK) {
|
||||
if (cro_address & Memory::CITRA_PAGE_MASK) {
|
||||
LOG_ERROR(Service_LDR, "CRO address is not aligned");
|
||||
rb.Push(ERROR_MISALIGNED_ADDRESS);
|
||||
return;
|
||||
|
@ -421,7 +421,7 @@ void RO::LinkCRO(Kernel::HLERequestContext& ctx) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (cro_address & Memory::PAGE_MASK) {
|
||||
if (cro_address & Memory::CITRA_PAGE_MASK) {
|
||||
LOG_ERROR(Service_LDR, "CRO address is not aligned");
|
||||
rb.Push(ERROR_MISALIGNED_ADDRESS);
|
||||
return;
|
||||
|
@ -461,7 +461,7 @@ void RO::UnlinkCRO(Kernel::HLERequestContext& ctx) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (cro_address & Memory::PAGE_MASK) {
|
||||
if (cro_address & Memory::CITRA_PAGE_MASK) {
|
||||
LOG_ERROR(Service_LDR, "CRO address is not aligned");
|
||||
rb.Push(ERROR_MISALIGNED_ADDRESS);
|
||||
return;
|
||||
|
|
|
@ -92,7 +92,8 @@ u16 NWM_UDS::GetNextAvailableNodeId() {
|
|||
}
|
||||
|
||||
// Any connection attempts to an already full network should have been refused.
|
||||
ASSERT_MSG(false, "No available connection slots in the network");
|
||||
UNREACHABLE_MSG("No available connection slots in the network");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NWM_UDS::BroadcastNodeMap() {
|
||||
|
|
|
@ -15,9 +15,6 @@
|
|||
|
||||
namespace Service::NWM {
|
||||
|
||||
// 802.11 broadcast MAC address
|
||||
constexpr MacAddress BroadcastMac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
constexpr u64 DefaultNetworkUptime = 900000000; // 15 minutes in microseconds.
|
||||
|
||||
// Note: These values were taken from a packet capture of an o3DS XL
|
||||
|
|
|
@ -178,15 +178,6 @@ static const std::unordered_map<int, int> sockopt_map = {{
|
|||
{0x1009, SO_ERROR},
|
||||
}};
|
||||
|
||||
/// Converts a socket option from 3ds-specific to platform-specific
|
||||
static int TranslateSockOpt(int console_opt_name) {
|
||||
auto found = sockopt_map.find(console_opt_name);
|
||||
if (found != sockopt_map.end()) {
|
||||
return found->second;
|
||||
}
|
||||
return console_opt_name;
|
||||
}
|
||||
|
||||
/// Structure to represent the 3ds' pollfd structure, which is different than most implementations
|
||||
struct CTRPollFD {
|
||||
u32 fd; ///< Socket handle
|
||||
|
|
|
@ -68,9 +68,11 @@ struct Regs {
|
|||
case PixelFormat::RGB5A1:
|
||||
case PixelFormat::RGBA4:
|
||||
return 2;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
INSERT_PADDING_WORDS(0x4);
|
||||
|
|
|
@ -94,13 +94,13 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr<Kernel::Process>& process)
|
|||
codeset->CodeSegment().offset = 0;
|
||||
codeset->CodeSegment().addr = overlay_ncch->exheader_header.codeset_info.text.address;
|
||||
codeset->CodeSegment().size =
|
||||
overlay_ncch->exheader_header.codeset_info.text.num_max_pages * Memory::PAGE_SIZE;
|
||||
overlay_ncch->exheader_header.codeset_info.text.num_max_pages * Memory::CITRA_PAGE_SIZE;
|
||||
|
||||
codeset->RODataSegment().offset =
|
||||
codeset->CodeSegment().offset + codeset->CodeSegment().size;
|
||||
codeset->RODataSegment().addr = overlay_ncch->exheader_header.codeset_info.ro.address;
|
||||
codeset->RODataSegment().size =
|
||||
overlay_ncch->exheader_header.codeset_info.ro.num_max_pages * Memory::PAGE_SIZE;
|
||||
overlay_ncch->exheader_header.codeset_info.ro.num_max_pages * Memory::CITRA_PAGE_SIZE;
|
||||
|
||||
// TODO(yuriks): Not sure if the bss size is added to the page-aligned .data size or just
|
||||
// to the regular size. Playing it safe for now.
|
||||
|
@ -111,7 +111,8 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr<Kernel::Process>& process)
|
|||
codeset->RODataSegment().offset + codeset->RODataSegment().size;
|
||||
codeset->DataSegment().addr = overlay_ncch->exheader_header.codeset_info.data.address;
|
||||
codeset->DataSegment().size =
|
||||
overlay_ncch->exheader_header.codeset_info.data.num_max_pages * Memory::PAGE_SIZE +
|
||||
overlay_ncch->exheader_header.codeset_info.data.num_max_pages *
|
||||
Memory::CITRA_PAGE_SIZE +
|
||||
bss_page_size;
|
||||
|
||||
// Apply patches now that the entire codeset (including .bss) has been allocated
|
||||
|
|
|
@ -55,20 +55,20 @@ public:
|
|||
private:
|
||||
bool* At(VAddr addr) {
|
||||
if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) {
|
||||
return &vram[(addr - VRAM_VADDR) / PAGE_SIZE];
|
||||
return &vram[(addr - VRAM_VADDR) / CITRA_PAGE_SIZE];
|
||||
}
|
||||
if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) {
|
||||
return &linear_heap[(addr - LINEAR_HEAP_VADDR) / PAGE_SIZE];
|
||||
return &linear_heap[(addr - LINEAR_HEAP_VADDR) / CITRA_PAGE_SIZE];
|
||||
}
|
||||
if (addr >= NEW_LINEAR_HEAP_VADDR && addr < NEW_LINEAR_HEAP_VADDR_END) {
|
||||
return &new_linear_heap[(addr - NEW_LINEAR_HEAP_VADDR) / PAGE_SIZE];
|
||||
return &new_linear_heap[(addr - NEW_LINEAR_HEAP_VADDR) / CITRA_PAGE_SIZE];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::array<bool, VRAM_SIZE / PAGE_SIZE> vram{};
|
||||
std::array<bool, LINEAR_HEAP_SIZE / PAGE_SIZE> linear_heap{};
|
||||
std::array<bool, NEW_LINEAR_HEAP_SIZE / PAGE_SIZE> new_linear_heap{};
|
||||
std::array<bool, VRAM_SIZE / CITRA_PAGE_SIZE> vram{};
|
||||
std::array<bool, LINEAR_HEAP_SIZE / CITRA_PAGE_SIZE> linear_heap{};
|
||||
std::array<bool, NEW_LINEAR_HEAP_SIZE / CITRA_PAGE_SIZE> new_linear_heap{};
|
||||
|
||||
static_assert(sizeof(bool) == 1);
|
||||
friend class boost::serialization::access;
|
||||
|
@ -146,6 +146,145 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function should only be called for virtual addreses with attribute `PageType::Special`.
|
||||
*/
|
||||
MMIORegionPointer GetMMIOHandler(const PageTable& page_table, VAddr vaddr) {
|
||||
for (const auto& region : page_table.special_regions) {
|
||||
if (vaddr >= region.base && vaddr < (region.base + region.size)) {
|
||||
return region.handler;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_MSG(false, "Mapped IO page without a handler @ {:08X}", vaddr);
|
||||
return nullptr; // Should never happen
|
||||
}
|
||||
|
||||
template <bool UNSAFE>
|
||||
void ReadBlockImpl(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer,
|
||||
const std::size_t size) {
|
||||
auto& page_table = *process.vm_manager.page_table;
|
||||
|
||||
std::size_t remaining_size = size;
|
||||
std::size_t page_index = src_addr >> CITRA_PAGE_BITS;
|
||||
std::size_t page_offset = src_addr & CITRA_PAGE_MASK;
|
||||
|
||||
while (remaining_size > 0) {
|
||||
const std::size_t copy_amount = std::min(CITRA_PAGE_SIZE - page_offset, remaining_size);
|
||||
const VAddr current_vaddr =
|
||||
static_cast<VAddr>((page_index << CITRA_PAGE_BITS) + page_offset);
|
||||
|
||||
switch (page_table.attributes[page_index]) {
|
||||
case PageType::Unmapped: {
|
||||
LOG_ERROR(
|
||||
HW_Memory,
|
||||
"unmapped ReadBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC "
|
||||
"0x{:08X}",
|
||||
current_vaddr, src_addr, size, Core::GetRunningCore().GetPC());
|
||||
std::memset(dest_buffer, 0, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::Memory: {
|
||||
DEBUG_ASSERT(page_table.pointers[page_index]);
|
||||
|
||||
const u8* src_ptr = page_table.pointers[page_index] + page_offset;
|
||||
std::memcpy(dest_buffer, src_ptr, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::Special: {
|
||||
MMIORegionPointer handler = GetMMIOHandler(page_table, current_vaddr);
|
||||
DEBUG_ASSERT(handler);
|
||||
handler->ReadBlock(current_vaddr, dest_buffer, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::RasterizerCachedMemory: {
|
||||
if constexpr (!UNSAFE) {
|
||||
RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount),
|
||||
FlushMode::Flush);
|
||||
}
|
||||
std::memcpy(dest_buffer, GetPointerForRasterizerCache(current_vaddr), copy_amount);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
page_index++;
|
||||
page_offset = 0;
|
||||
dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount;
|
||||
remaining_size -= copy_amount;
|
||||
}
|
||||
}
|
||||
|
||||
template <bool UNSAFE>
|
||||
void WriteBlockImpl(const Kernel::Process& process, const VAddr dest_addr,
|
||||
const void* src_buffer, const std::size_t size) {
|
||||
auto& page_table = *process.vm_manager.page_table;
|
||||
std::size_t remaining_size = size;
|
||||
std::size_t page_index = dest_addr >> CITRA_PAGE_BITS;
|
||||
std::size_t page_offset = dest_addr & CITRA_PAGE_MASK;
|
||||
|
||||
while (remaining_size > 0) {
|
||||
const std::size_t copy_amount = std::min(CITRA_PAGE_SIZE - page_offset, remaining_size);
|
||||
const VAddr current_vaddr =
|
||||
static_cast<VAddr>((page_index << CITRA_PAGE_BITS) + page_offset);
|
||||
|
||||
switch (page_table.attributes[page_index]) {
|
||||
case PageType::Unmapped: {
|
||||
LOG_ERROR(
|
||||
HW_Memory,
|
||||
"unmapped WriteBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC "
|
||||
"0x{:08X}",
|
||||
current_vaddr, dest_addr, size, Core::GetRunningCore().GetPC());
|
||||
break;
|
||||
}
|
||||
case PageType::Memory: {
|
||||
DEBUG_ASSERT(page_table.pointers[page_index]);
|
||||
|
||||
u8* dest_ptr = page_table.pointers[page_index] + page_offset;
|
||||
std::memcpy(dest_ptr, src_buffer, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::Special: {
|
||||
MMIORegionPointer handler = GetMMIOHandler(page_table, current_vaddr);
|
||||
DEBUG_ASSERT(handler);
|
||||
handler->WriteBlock(current_vaddr, src_buffer, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::RasterizerCachedMemory: {
|
||||
if constexpr (!UNSAFE) {
|
||||
RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount),
|
||||
FlushMode::Invalidate);
|
||||
}
|
||||
std::memcpy(GetPointerForRasterizerCache(current_vaddr), src_buffer, copy_amount);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
page_index++;
|
||||
page_offset = 0;
|
||||
src_buffer = static_cast<const u8*>(src_buffer) + copy_amount;
|
||||
remaining_size -= copy_amount;
|
||||
}
|
||||
}
|
||||
|
||||
MemoryRef GetPointerForRasterizerCache(VAddr addr) const {
|
||||
if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) {
|
||||
return {fcram_mem, addr - LINEAR_HEAP_VADDR};
|
||||
}
|
||||
if (addr >= NEW_LINEAR_HEAP_VADDR && addr < NEW_LINEAR_HEAP_VADDR_END) {
|
||||
return {fcram_mem, addr - NEW_LINEAR_HEAP_VADDR};
|
||||
}
|
||||
if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) {
|
||||
return {vram_mem, addr - VRAM_VADDR};
|
||||
}
|
||||
|
||||
UNREACHABLE();
|
||||
return MemoryRef{};
|
||||
}
|
||||
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive>
|
||||
|
@ -221,10 +360,10 @@ std::shared_ptr<PageTable> MemorySystem::GetCurrentPageTable() const {
|
|||
|
||||
void MemorySystem::MapPages(PageTable& page_table, u32 base, u32 size, MemoryRef memory,
|
||||
PageType type) {
|
||||
LOG_DEBUG(HW_Memory, "Mapping {} onto {:08X}-{:08X}", (void*)memory.GetPtr(), base * PAGE_SIZE,
|
||||
(base + size) * PAGE_SIZE);
|
||||
LOG_DEBUG(HW_Memory, "Mapping {} onto {:08X}-{:08X}", (void*)memory.GetPtr(),
|
||||
base * CITRA_PAGE_SIZE, (base + size) * CITRA_PAGE_SIZE);
|
||||
|
||||
RasterizerFlushVirtualRegion(base << PAGE_BITS, size * PAGE_SIZE,
|
||||
RasterizerFlushVirtualRegion(base << CITRA_PAGE_BITS, size * CITRA_PAGE_SIZE,
|
||||
FlushMode::FlushAndInvalidate);
|
||||
|
||||
u32 end = base + size;
|
||||
|
@ -235,49 +374,42 @@ void MemorySystem::MapPages(PageTable& page_table, u32 base, u32 size, MemoryRef
|
|||
page_table.pointers[base] = memory;
|
||||
|
||||
// If the memory to map is already rasterizer-cached, mark the page
|
||||
if (type == PageType::Memory && impl->cache_marker.IsCached(base * PAGE_SIZE)) {
|
||||
if (type == PageType::Memory && impl->cache_marker.IsCached(base * CITRA_PAGE_SIZE)) {
|
||||
page_table.attributes[base] = PageType::RasterizerCachedMemory;
|
||||
page_table.pointers[base] = nullptr;
|
||||
}
|
||||
|
||||
base += 1;
|
||||
if (memory != nullptr && memory.GetSize() > PAGE_SIZE)
|
||||
memory += PAGE_SIZE;
|
||||
if (memory != nullptr && memory.GetSize() > CITRA_PAGE_SIZE)
|
||||
memory += CITRA_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void MemorySystem::MapMemoryRegion(PageTable& page_table, VAddr base, u32 size, MemoryRef target) {
|
||||
ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:08X}", size);
|
||||
ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:08X}", base);
|
||||
MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, target, PageType::Memory);
|
||||
ASSERT_MSG((size & CITRA_PAGE_MASK) == 0, "non-page aligned size: {:08X}", size);
|
||||
ASSERT_MSG((base & CITRA_PAGE_MASK) == 0, "non-page aligned base: {:08X}", base);
|
||||
MapPages(page_table, base / CITRA_PAGE_SIZE, size / CITRA_PAGE_SIZE, target, PageType::Memory);
|
||||
}
|
||||
|
||||
void MemorySystem::MapIoRegion(PageTable& page_table, VAddr base, u32 size,
|
||||
MMIORegionPointer mmio_handler) {
|
||||
ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:08X}", size);
|
||||
ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:08X}", base);
|
||||
MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, nullptr, PageType::Special);
|
||||
ASSERT_MSG((size & CITRA_PAGE_MASK) == 0, "non-page aligned size: {:08X}", size);
|
||||
ASSERT_MSG((base & CITRA_PAGE_MASK) == 0, "non-page aligned base: {:08X}", base);
|
||||
MapPages(page_table, base / CITRA_PAGE_SIZE, size / CITRA_PAGE_SIZE, nullptr,
|
||||
PageType::Special);
|
||||
|
||||
page_table.special_regions.emplace_back(SpecialRegion{base, size, mmio_handler});
|
||||
}
|
||||
|
||||
void MemorySystem::UnmapRegion(PageTable& page_table, VAddr base, u32 size) {
|
||||
ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:08X}", size);
|
||||
ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:08X}", base);
|
||||
MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, nullptr, PageType::Unmapped);
|
||||
ASSERT_MSG((size & CITRA_PAGE_MASK) == 0, "non-page aligned size: {:08X}", size);
|
||||
ASSERT_MSG((base & CITRA_PAGE_MASK) == 0, "non-page aligned base: {:08X}", base);
|
||||
MapPages(page_table, base / CITRA_PAGE_SIZE, size / CITRA_PAGE_SIZE, nullptr,
|
||||
PageType::Unmapped);
|
||||
}
|
||||
|
||||
MemoryRef MemorySystem::GetPointerForRasterizerCache(VAddr addr) const {
|
||||
if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) {
|
||||
return {impl->fcram_mem, addr - LINEAR_HEAP_VADDR};
|
||||
}
|
||||
if (addr >= NEW_LINEAR_HEAP_VADDR && addr < NEW_LINEAR_HEAP_VADDR_END) {
|
||||
return {impl->fcram_mem, addr - NEW_LINEAR_HEAP_VADDR};
|
||||
}
|
||||
if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) {
|
||||
return {impl->vram_mem, addr - VRAM_VADDR};
|
||||
}
|
||||
UNREACHABLE();
|
||||
return impl->GetPointerForRasterizerCache(addr);
|
||||
}
|
||||
|
||||
void MemorySystem::RegisterPageTable(std::shared_ptr<PageTable> page_table) {
|
||||
|
@ -291,33 +423,20 @@ void MemorySystem::UnregisterPageTable(std::shared_ptr<PageTable> page_table) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function should only be called for virtual addreses with attribute `PageType::Special`.
|
||||
*/
|
||||
static MMIORegionPointer GetMMIOHandler(const PageTable& page_table, VAddr vaddr) {
|
||||
for (const auto& region : page_table.special_regions) {
|
||||
if (vaddr >= region.base && vaddr < (region.base + region.size)) {
|
||||
return region.handler;
|
||||
}
|
||||
}
|
||||
ASSERT_MSG(false, "Mapped IO page without a handler @ {:08X}", vaddr);
|
||||
return nullptr; // Should never happen
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr);
|
||||
|
||||
template <typename T>
|
||||
T MemorySystem::Read(const VAddr vaddr) {
|
||||
const u8* page_pointer = impl->current_page_table->pointers[vaddr >> PAGE_BITS];
|
||||
const u8* page_pointer = impl->current_page_table->pointers[vaddr >> CITRA_PAGE_BITS];
|
||||
if (page_pointer) {
|
||||
// NOTE: Avoid adding any extra logic to this fast-path block
|
||||
T value;
|
||||
std::memcpy(&value, &page_pointer[vaddr & PAGE_MASK], sizeof(T));
|
||||
std::memcpy(&value, &page_pointer[vaddr & CITRA_PAGE_MASK], sizeof(T));
|
||||
return value;
|
||||
}
|
||||
|
||||
PageType type = impl->current_page_table->attributes[vaddr >> PAGE_BITS];
|
||||
PageType type = impl->current_page_table->attributes[vaddr >> CITRA_PAGE_BITS];
|
||||
switch (type) {
|
||||
case PageType::Unmapped:
|
||||
LOG_ERROR(HW_Memory, "unmapped Read{} @ 0x{:08X} at PC 0x{:08X}", sizeof(T) * 8, vaddr,
|
||||
|
@ -334,10 +453,12 @@ T MemorySystem::Read(const VAddr vaddr) {
|
|||
return value;
|
||||
}
|
||||
case PageType::Special:
|
||||
return ReadMMIO<T>(GetMMIOHandler(*impl->current_page_table, vaddr), vaddr);
|
||||
return ReadMMIO<T>(impl->GetMMIOHandler(*impl->current_page_table, vaddr), vaddr);
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
return T{};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -345,14 +466,14 @@ void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const T data);
|
|||
|
||||
template <typename T>
|
||||
void MemorySystem::Write(const VAddr vaddr, const T data) {
|
||||
u8* page_pointer = impl->current_page_table->pointers[vaddr >> PAGE_BITS];
|
||||
u8* page_pointer = impl->current_page_table->pointers[vaddr >> CITRA_PAGE_BITS];
|
||||
if (page_pointer) {
|
||||
// NOTE: Avoid adding any extra logic to this fast-path block
|
||||
std::memcpy(&page_pointer[vaddr & PAGE_MASK], &data, sizeof(T));
|
||||
std::memcpy(&page_pointer[vaddr & CITRA_PAGE_MASK], &data, sizeof(T));
|
||||
return;
|
||||
}
|
||||
|
||||
PageType type = impl->current_page_table->attributes[vaddr >> PAGE_BITS];
|
||||
PageType type = impl->current_page_table->attributes[vaddr >> CITRA_PAGE_BITS];
|
||||
switch (type) {
|
||||
case PageType::Unmapped:
|
||||
LOG_ERROR(HW_Memory, "unmapped Write{} 0x{:08X} @ 0x{:08X} at PC 0x{:08X}",
|
||||
|
@ -367,7 +488,7 @@ void MemorySystem::Write(const VAddr vaddr, const T data) {
|
|||
break;
|
||||
}
|
||||
case PageType::Special:
|
||||
WriteMMIO<T>(GetMMIOHandler(*impl->current_page_table, vaddr), vaddr, data);
|
||||
WriteMMIO<T>(impl->GetMMIOHandler(*impl->current_page_table, vaddr), vaddr, data);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
@ -376,15 +497,15 @@ void MemorySystem::Write(const VAddr vaddr, const T data) {
|
|||
|
||||
template <typename T>
|
||||
bool MemorySystem::WriteExclusive(const VAddr vaddr, const T data, const T expected) {
|
||||
u8* page_pointer = impl->current_page_table->pointers[vaddr >> PAGE_BITS];
|
||||
u8* page_pointer = impl->current_page_table->pointers[vaddr >> CITRA_PAGE_BITS];
|
||||
|
||||
if (page_pointer) {
|
||||
const auto volatile_pointer =
|
||||
reinterpret_cast<volatile T*>(&page_pointer[vaddr & PAGE_MASK]);
|
||||
reinterpret_cast<volatile T*>(&page_pointer[vaddr & CITRA_PAGE_MASK]);
|
||||
return Common::AtomicCompareAndSwap(volatile_pointer, data, expected);
|
||||
}
|
||||
|
||||
PageType type = impl->current_page_table->attributes[vaddr >> PAGE_BITS];
|
||||
PageType type = impl->current_page_table->attributes[vaddr >> CITRA_PAGE_BITS];
|
||||
switch (type) {
|
||||
case PageType::Unmapped:
|
||||
LOG_ERROR(HW_Memory, "unmapped Write{} 0x{:08X} @ 0x{:08X} at PC 0x{:08X}",
|
||||
|
@ -400,7 +521,7 @@ bool MemorySystem::WriteExclusive(const VAddr vaddr, const T data, const T expec
|
|||
return Common::AtomicCompareAndSwap(volatile_pointer, data, expected);
|
||||
}
|
||||
case PageType::Special:
|
||||
WriteMMIO<T>(GetMMIOHandler(*impl->current_page_table, vaddr), vaddr, data);
|
||||
WriteMMIO<T>(impl->GetMMIOHandler(*impl->current_page_table, vaddr), vaddr, data);
|
||||
return false;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
@ -408,20 +529,20 @@ bool MemorySystem::WriteExclusive(const VAddr vaddr, const T data, const T expec
|
|||
return true;
|
||||
}
|
||||
|
||||
bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) {
|
||||
bool MemorySystem::IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) {
|
||||
auto& page_table = *process.vm_manager.page_table;
|
||||
|
||||
auto page_pointer = page_table.pointers[vaddr >> PAGE_BITS];
|
||||
auto page_pointer = page_table.pointers[vaddr >> CITRA_PAGE_BITS];
|
||||
if (page_pointer)
|
||||
return true;
|
||||
|
||||
if (page_table.attributes[vaddr >> PAGE_BITS] == PageType::RasterizerCachedMemory)
|
||||
if (page_table.attributes[vaddr >> CITRA_PAGE_BITS] == PageType::RasterizerCachedMemory)
|
||||
return true;
|
||||
|
||||
if (page_table.attributes[vaddr >> PAGE_BITS] != PageType::Special)
|
||||
if (page_table.attributes[vaddr >> CITRA_PAGE_BITS] != PageType::Special)
|
||||
return false;
|
||||
|
||||
MMIORegionPointer mmio_region = GetMMIOHandler(page_table, vaddr);
|
||||
MMIORegionPointer mmio_region = impl->GetMMIOHandler(page_table, vaddr);
|
||||
if (mmio_region) {
|
||||
return mmio_region->IsValidAddress(vaddr);
|
||||
}
|
||||
|
@ -430,16 +551,16 @@ bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) {
|
|||
}
|
||||
|
||||
bool MemorySystem::IsValidPhysicalAddress(const PAddr paddr) const {
|
||||
return GetPhysicalPointer(paddr) != nullptr;
|
||||
return GetPhysicalRef(paddr);
|
||||
}
|
||||
|
||||
u8* MemorySystem::GetPointer(const VAddr vaddr) {
|
||||
u8* page_pointer = impl->current_page_table->pointers[vaddr >> PAGE_BITS];
|
||||
u8* page_pointer = impl->current_page_table->pointers[vaddr >> CITRA_PAGE_BITS];
|
||||
if (page_pointer) {
|
||||
return page_pointer + (vaddr & PAGE_MASK);
|
||||
return page_pointer + (vaddr & CITRA_PAGE_MASK);
|
||||
}
|
||||
|
||||
if (impl->current_page_table->attributes[vaddr >> PAGE_BITS] ==
|
||||
if (impl->current_page_table->attributes[vaddr >> CITRA_PAGE_BITS] ==
|
||||
PageType::RasterizerCachedMemory) {
|
||||
return GetPointerForRasterizerCache(vaddr);
|
||||
}
|
||||
|
@ -450,12 +571,12 @@ u8* MemorySystem::GetPointer(const VAddr vaddr) {
|
|||
}
|
||||
|
||||
const u8* MemorySystem::GetPointer(const VAddr vaddr) const {
|
||||
const u8* page_pointer = impl->current_page_table->pointers[vaddr >> PAGE_BITS];
|
||||
const u8* page_pointer = impl->current_page_table->pointers[vaddr >> CITRA_PAGE_BITS];
|
||||
if (page_pointer) {
|
||||
return page_pointer + (vaddr & PAGE_MASK);
|
||||
return page_pointer + (vaddr & CITRA_PAGE_MASK);
|
||||
}
|
||||
|
||||
if (impl->current_page_table->attributes[vaddr >> PAGE_BITS] ==
|
||||
if (impl->current_page_table->attributes[vaddr >> CITRA_PAGE_BITS] ==
|
||||
PageType::RasterizerCachedMemory) {
|
||||
return GetPointerForRasterizerCache(vaddr);
|
||||
}
|
||||
|
@ -469,11 +590,14 @@ std::string MemorySystem::ReadCString(VAddr vaddr, std::size_t max_length) {
|
|||
string.reserve(max_length);
|
||||
for (std::size_t i = 0; i < max_length; ++i) {
|
||||
char c = Read8(vaddr);
|
||||
if (c == '\0')
|
||||
if (c == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
string.push_back(c);
|
||||
++vaddr;
|
||||
}
|
||||
|
||||
string.shrink_to_fit();
|
||||
return string;
|
||||
}
|
||||
|
@ -482,40 +606,30 @@ u8* MemorySystem::GetPhysicalPointer(PAddr address) {
|
|||
return GetPhysicalRef(address);
|
||||
}
|
||||
|
||||
const u8* MemorySystem::GetPhysicalPointer(PAddr address) const {
|
||||
return GetPhysicalRef(address);
|
||||
}
|
||||
|
||||
MemoryRef MemorySystem::GetPhysicalRef(PAddr address) const {
|
||||
struct MemoryArea {
|
||||
PAddr paddr_base;
|
||||
u32 size;
|
||||
constexpr std::array memory_areas = {
|
||||
std::make_pair(VRAM_PADDR, VRAM_SIZE),
|
||||
std::make_pair(DSP_RAM_PADDR, DSP_RAM_SIZE),
|
||||
std::make_pair(FCRAM_PADDR, FCRAM_N3DS_SIZE),
|
||||
std::make_pair(N3DS_EXTRA_RAM_PADDR, N3DS_EXTRA_RAM_SIZE),
|
||||
};
|
||||
|
||||
static constexpr MemoryArea memory_areas[] = {
|
||||
{VRAM_PADDR, VRAM_SIZE},
|
||||
{DSP_RAM_PADDR, DSP_RAM_SIZE},
|
||||
{FCRAM_PADDR, FCRAM_N3DS_SIZE},
|
||||
{N3DS_EXTRA_RAM_PADDR, N3DS_EXTRA_RAM_SIZE},
|
||||
};
|
||||
const auto area = std::find_if(memory_areas.begin(), memory_areas.end(), [&](const auto& area) {
|
||||
// Note: the region end check is inclusive because the user can pass in an address that
|
||||
// represents an open right bound
|
||||
return address >= area.first && address <= area.first + area.second;
|
||||
});
|
||||
|
||||
const auto area =
|
||||
std::find_if(std::begin(memory_areas), std::end(memory_areas), [&](const auto& area) {
|
||||
// Note: the region end check is inclusive because the user can pass in an address that
|
||||
// represents an open right bound
|
||||
return address >= area.paddr_base && address <= area.paddr_base + area.size;
|
||||
});
|
||||
|
||||
if (area == std::end(memory_areas)) {
|
||||
LOG_ERROR(HW_Memory, "unknown GetPhysicalPointer @ 0x{:08X} at PC 0x{:08X}", address,
|
||||
if (area == memory_areas.end()) {
|
||||
LOG_ERROR(HW_Memory, "Unknown GetPhysicalPointer @ {:#08X} at PC {:#08X}", address,
|
||||
Core::GetRunningCore().GetPC());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
u32 offset_into_region = address - area->paddr_base;
|
||||
u32 offset_into_region = address - area->first;
|
||||
|
||||
std::shared_ptr<BackingMem> target_mem = nullptr;
|
||||
switch (area->paddr_base) {
|
||||
switch (area->first) {
|
||||
case VRAM_PADDR:
|
||||
target_mem = impl->vram_mem;
|
||||
break;
|
||||
|
@ -564,14 +678,14 @@ void MemorySystem::RasterizerMarkRegionCached(PAddr start, u32 size, bool cached
|
|||
return;
|
||||
}
|
||||
|
||||
u32 num_pages = ((start + size - 1) >> PAGE_BITS) - (start >> PAGE_BITS) + 1;
|
||||
u32 num_pages = ((start + size - 1) >> CITRA_PAGE_BITS) - (start >> CITRA_PAGE_BITS) + 1;
|
||||
PAddr paddr = start;
|
||||
|
||||
for (unsigned i = 0; i < num_pages; ++i, paddr += PAGE_SIZE) {
|
||||
for (unsigned i = 0; i < num_pages; ++i, paddr += CITRA_PAGE_SIZE) {
|
||||
for (VAddr vaddr : PhysicalToVirtualAddressForRasterizer(paddr)) {
|
||||
impl->cache_marker.Mark(vaddr, cached);
|
||||
for (auto page_table : impl->page_table_list) {
|
||||
PageType& page_type = page_table->attributes[vaddr >> PAGE_BITS];
|
||||
PageType& page_type = page_table->attributes[vaddr >> CITRA_PAGE_BITS];
|
||||
|
||||
if (cached) {
|
||||
// Switch page type to cached if now cached
|
||||
|
@ -582,7 +696,7 @@ void MemorySystem::RasterizerMarkRegionCached(PAddr start, u32 size, bool cached
|
|||
break;
|
||||
case PageType::Memory:
|
||||
page_type = PageType::RasterizerCachedMemory;
|
||||
page_table->pointers[vaddr >> PAGE_BITS] = nullptr;
|
||||
page_table->pointers[vaddr >> CITRA_PAGE_BITS] = nullptr;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
@ -596,8 +710,8 @@ void MemorySystem::RasterizerMarkRegionCached(PAddr start, u32 size, bool cached
|
|||
break;
|
||||
case PageType::RasterizerCachedMemory: {
|
||||
page_type = PageType::Memory;
|
||||
page_table->pointers[vaddr >> PAGE_BITS] =
|
||||
GetPointerForRasterizerCache(vaddr & ~PAGE_MASK);
|
||||
page_table->pointers[vaddr >> CITRA_PAGE_BITS] =
|
||||
GetPointerForRasterizerCache(vaddr & ~CITRA_PAGE_MASK);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -702,53 +816,12 @@ u64 MemorySystem::Read64(const VAddr addr) {
|
|||
|
||||
void MemorySystem::ReadBlock(const Kernel::Process& process, const VAddr src_addr,
|
||||
void* dest_buffer, const std::size_t size) {
|
||||
auto& page_table = *process.vm_manager.page_table;
|
||||
return impl->ReadBlockImpl<false>(process, src_addr, dest_buffer, size);
|
||||
}
|
||||
|
||||
std::size_t remaining_size = size;
|
||||
std::size_t page_index = src_addr >> PAGE_BITS;
|
||||
std::size_t page_offset = src_addr & PAGE_MASK;
|
||||
|
||||
while (remaining_size > 0) {
|
||||
const std::size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size);
|
||||
const VAddr current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset);
|
||||
|
||||
switch (page_table.attributes[page_index]) {
|
||||
case PageType::Unmapped: {
|
||||
LOG_ERROR(HW_Memory,
|
||||
"unmapped ReadBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC "
|
||||
"0x{:08X}",
|
||||
current_vaddr, src_addr, size, Core::GetRunningCore().GetPC());
|
||||
std::memset(dest_buffer, 0, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::Memory: {
|
||||
DEBUG_ASSERT(page_table.pointers[page_index]);
|
||||
|
||||
const u8* src_ptr = page_table.pointers[page_index] + page_offset;
|
||||
std::memcpy(dest_buffer, src_ptr, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::Special: {
|
||||
MMIORegionPointer handler = GetMMIOHandler(page_table, current_vaddr);
|
||||
DEBUG_ASSERT(handler);
|
||||
handler->ReadBlock(current_vaddr, dest_buffer, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::RasterizerCachedMemory: {
|
||||
RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount),
|
||||
FlushMode::Flush);
|
||||
std::memcpy(dest_buffer, GetPointerForRasterizerCache(current_vaddr), copy_amount);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
page_index++;
|
||||
page_offset = 0;
|
||||
dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount;
|
||||
remaining_size -= copy_amount;
|
||||
}
|
||||
void MemorySystem::ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size) {
|
||||
const auto& process = *Core::System::GetInstance().Kernel().GetCurrentProcess();
|
||||
return impl->ReadBlockImpl<false>(process, src_addr, dest_buffer, size);
|
||||
}
|
||||
|
||||
void MemorySystem::Write8(const VAddr addr, const u8 data) {
|
||||
|
@ -785,65 +858,28 @@ bool MemorySystem::WriteExclusive64(const VAddr addr, const u64 data, const u64
|
|||
|
||||
void MemorySystem::WriteBlock(const Kernel::Process& process, const VAddr dest_addr,
|
||||
const void* src_buffer, const std::size_t size) {
|
||||
auto& page_table = *process.vm_manager.page_table;
|
||||
std::size_t remaining_size = size;
|
||||
std::size_t page_index = dest_addr >> PAGE_BITS;
|
||||
std::size_t page_offset = dest_addr & PAGE_MASK;
|
||||
return impl->WriteBlockImpl<false>(process, dest_addr, src_buffer, size);
|
||||
}
|
||||
|
||||
while (remaining_size > 0) {
|
||||
const std::size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size);
|
||||
const VAddr current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset);
|
||||
|
||||
switch (page_table.attributes[page_index]) {
|
||||
case PageType::Unmapped: {
|
||||
LOG_ERROR(HW_Memory,
|
||||
"unmapped WriteBlock @ 0x{:08X} (start address = 0x{:08X}, size = {}) at PC "
|
||||
"0x{:08X}",
|
||||
current_vaddr, dest_addr, size, Core::GetRunningCore().GetPC());
|
||||
break;
|
||||
}
|
||||
case PageType::Memory: {
|
||||
DEBUG_ASSERT(page_table.pointers[page_index]);
|
||||
|
||||
u8* dest_ptr = page_table.pointers[page_index] + page_offset;
|
||||
std::memcpy(dest_ptr, src_buffer, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::Special: {
|
||||
MMIORegionPointer handler = GetMMIOHandler(page_table, current_vaddr);
|
||||
DEBUG_ASSERT(handler);
|
||||
handler->WriteBlock(current_vaddr, src_buffer, copy_amount);
|
||||
break;
|
||||
}
|
||||
case PageType::RasterizerCachedMemory: {
|
||||
RasterizerFlushVirtualRegion(current_vaddr, static_cast<u32>(copy_amount),
|
||||
FlushMode::Invalidate);
|
||||
std::memcpy(GetPointerForRasterizerCache(current_vaddr), src_buffer, copy_amount);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
page_index++;
|
||||
page_offset = 0;
|
||||
src_buffer = static_cast<const u8*>(src_buffer) + copy_amount;
|
||||
remaining_size -= copy_amount;
|
||||
}
|
||||
void MemorySystem::WriteBlock(const VAddr dest_addr, const void* src_buffer,
|
||||
const std::size_t size) {
|
||||
auto& process = *Core::System::GetInstance().Kernel().GetCurrentProcess();
|
||||
return impl->WriteBlockImpl<false>(process, dest_addr, src_buffer, size);
|
||||
}
|
||||
|
||||
void MemorySystem::ZeroBlock(const Kernel::Process& process, const VAddr dest_addr,
|
||||
const std::size_t size) {
|
||||
auto& page_table = *process.vm_manager.page_table;
|
||||
std::size_t remaining_size = size;
|
||||
std::size_t page_index = dest_addr >> PAGE_BITS;
|
||||
std::size_t page_offset = dest_addr & PAGE_MASK;
|
||||
std::size_t page_index = dest_addr >> CITRA_PAGE_BITS;
|
||||
std::size_t page_offset = dest_addr & CITRA_PAGE_MASK;
|
||||
|
||||
static const std::array<u8, PAGE_SIZE> zeros = {};
|
||||
static const std::array<u8, CITRA_PAGE_SIZE> zeros = {};
|
||||
|
||||
while (remaining_size > 0) {
|
||||
const std::size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size);
|
||||
const VAddr current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset);
|
||||
const std::size_t copy_amount = std::min(CITRA_PAGE_SIZE - page_offset, remaining_size);
|
||||
const VAddr current_vaddr =
|
||||
static_cast<VAddr>((page_index << CITRA_PAGE_BITS) + page_offset);
|
||||
|
||||
switch (page_table.attributes[page_index]) {
|
||||
case PageType::Unmapped: {
|
||||
|
@ -861,7 +897,7 @@ void MemorySystem::ZeroBlock(const Kernel::Process& process, const VAddr dest_ad
|
|||
break;
|
||||
}
|
||||
case PageType::Special: {
|
||||
MMIORegionPointer handler = GetMMIOHandler(page_table, current_vaddr);
|
||||
MMIORegionPointer handler = impl->GetMMIOHandler(page_table, current_vaddr);
|
||||
DEBUG_ASSERT(handler);
|
||||
handler->WriteBlock(current_vaddr, zeros.data(), copy_amount);
|
||||
break;
|
||||
|
@ -892,12 +928,13 @@ void MemorySystem::CopyBlock(const Kernel::Process& dest_process,
|
|||
std::size_t size) {
|
||||
auto& page_table = *src_process.vm_manager.page_table;
|
||||
std::size_t remaining_size = size;
|
||||
std::size_t page_index = src_addr >> PAGE_BITS;
|
||||
std::size_t page_offset = src_addr & PAGE_MASK;
|
||||
std::size_t page_index = src_addr >> CITRA_PAGE_BITS;
|
||||
std::size_t page_offset = src_addr & CITRA_PAGE_MASK;
|
||||
|
||||
while (remaining_size > 0) {
|
||||
const std::size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size);
|
||||
const VAddr current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset);
|
||||
const std::size_t copy_amount = std::min(CITRA_PAGE_SIZE - page_offset, remaining_size);
|
||||
const VAddr current_vaddr =
|
||||
static_cast<VAddr>((page_index << CITRA_PAGE_BITS) + page_offset);
|
||||
|
||||
switch (page_table.attributes[page_index]) {
|
||||
case PageType::Unmapped: {
|
||||
|
@ -915,7 +952,7 @@ void MemorySystem::CopyBlock(const Kernel::Process& dest_process,
|
|||
break;
|
||||
}
|
||||
case PageType::Special: {
|
||||
MMIORegionPointer handler = GetMMIOHandler(page_table, current_vaddr);
|
||||
MMIORegionPointer handler = impl->GetMMIOHandler(page_table, current_vaddr);
|
||||
DEBUG_ASSERT(handler);
|
||||
std::vector<u8> buffer(copy_amount);
|
||||
handler->ReadBlock(current_vaddr, buffer.data(), buffer.size());
|
||||
|
|
|
@ -3,12 +3,9 @@
|
|||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/serialization/array.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include "common/common_types.h"
|
||||
|
@ -27,17 +24,14 @@ class DspInterface;
|
|||
|
||||
namespace Memory {
|
||||
|
||||
// Are defined in a system header
|
||||
#undef PAGE_SIZE
|
||||
#undef PAGE_MASK
|
||||
/**
|
||||
* Page size used by the ARM architecture. This is the smallest granularity with which memory can
|
||||
* be mapped.
|
||||
*/
|
||||
const u32 PAGE_SIZE = 0x1000;
|
||||
const u32 PAGE_MASK = PAGE_SIZE - 1;
|
||||
const int PAGE_BITS = 12;
|
||||
const std::size_t PAGE_TABLE_NUM_ENTRIES = 1 << (32 - PAGE_BITS);
|
||||
constexpr u32 CITRA_PAGE_SIZE = 0x1000;
|
||||
constexpr u32 CITRA_PAGE_MASK = CITRA_PAGE_SIZE - 1;
|
||||
constexpr int CITRA_PAGE_BITS = 12;
|
||||
constexpr std::size_t PAGE_TABLE_NUM_ENTRIES = 1 << (32 - CITRA_PAGE_BITS);
|
||||
|
||||
enum class PageType {
|
||||
/// Page is unmapped and should cause an access error.
|
||||
|
@ -106,11 +100,10 @@ struct PageTable {
|
|||
|
||||
private:
|
||||
std::array<u8*, PAGE_TABLE_NUM_ENTRIES> raw;
|
||||
|
||||
std::array<MemoryRef, PAGE_TABLE_NUM_ENTRIES> refs;
|
||||
|
||||
friend struct PageTable;
|
||||
};
|
||||
|
||||
Pointers pointers;
|
||||
|
||||
/**
|
||||
|
@ -317,14 +310,108 @@ public:
|
|||
void SetCurrentPageTable(std::shared_ptr<PageTable> page_table);
|
||||
std::shared_ptr<PageTable> GetCurrentPageTable() const;
|
||||
|
||||
/**
|
||||
* Gets a pointer to the given address.
|
||||
*
|
||||
* @param vaddr Virtual address to retrieve a pointer to.
|
||||
*
|
||||
* @returns The pointer to the given address, if the address is valid.
|
||||
* If the address is not valid, nullptr will be returned.
|
||||
*/
|
||||
u8* GetPointer(VAddr vaddr);
|
||||
|
||||
/**
|
||||
* Gets a pointer to the given address.
|
||||
*
|
||||
* @param vaddr Virtual address to retrieve a pointer to.
|
||||
*
|
||||
* @returns The pointer to the given address, if the address is valid.
|
||||
* If the address is not valid, nullptr will be returned.
|
||||
*/
|
||||
const u8* GetPointer(VAddr vaddr) const;
|
||||
|
||||
/**
|
||||
* Reads an 8-bit unsigned value from the current process' address space
|
||||
* at the given virtual address.
|
||||
*
|
||||
* @param addr The virtual address to read the 8-bit value from.
|
||||
*
|
||||
* @returns the read 8-bit unsigned value.
|
||||
*/
|
||||
u8 Read8(VAddr addr);
|
||||
|
||||
/**
|
||||
* Reads a 16-bit unsigned value from the current process' address space
|
||||
* at the given virtual address.
|
||||
*
|
||||
* @param addr The virtual address to read the 16-bit value from.
|
||||
*
|
||||
* @returns the read 16-bit unsigned value.
|
||||
*/
|
||||
u16 Read16(VAddr addr);
|
||||
|
||||
/**
|
||||
* Reads a 32-bit unsigned value from the current process' address space
|
||||
* at the given virtual address.
|
||||
*
|
||||
* @param addr The virtual address to read the 32-bit value from.
|
||||
*
|
||||
* @returns the read 32-bit unsigned value.
|
||||
*/
|
||||
u32 Read32(VAddr addr);
|
||||
|
||||
/**
|
||||
* Reads a 64-bit unsigned value from the current process' address space
|
||||
* at the given virtual address.
|
||||
*
|
||||
* @param addr The virtual address to read the 64-bit value from.
|
||||
*
|
||||
* @returns the read 64-bit value.
|
||||
*/
|
||||
u64 Read64(VAddr addr);
|
||||
|
||||
/**
|
||||
* Writes an 8-bit unsigned integer to the given virtual address in
|
||||
* the current process' address space.
|
||||
*
|
||||
* @param addr The virtual address to write the 8-bit unsigned integer to.
|
||||
* @param data The 8-bit unsigned integer to write to the given virtual address.
|
||||
*
|
||||
* @post The memory at the given virtual address contains the specified data value.
|
||||
*/
|
||||
void Write8(VAddr addr, u8 data);
|
||||
|
||||
/**
|
||||
* Writes a 16-bit unsigned integer to the given virtual address in
|
||||
* the current process' address space.
|
||||
*
|
||||
* @param addr The virtual address to write the 16-bit unsigned integer to.
|
||||
* @param data The 16-bit unsigned integer to write to the given virtual address.
|
||||
*
|
||||
* @post The memory range [addr, sizeof(data)) contains the given data value.
|
||||
*/
|
||||
void Write16(VAddr addr, u16 data);
|
||||
|
||||
/**
|
||||
* Writes a 32-bit unsigned integer to the given virtual address in
|
||||
* the current process' address space.
|
||||
*
|
||||
* @param addr The virtual address to write the 32-bit unsigned integer to.
|
||||
* @param data The 32-bit unsigned integer to write to the given virtual address.
|
||||
*
|
||||
* @post The memory range [addr, sizeof(data)) contains the given data value.
|
||||
*/
|
||||
void Write32(VAddr addr, u32 data);
|
||||
|
||||
/**
|
||||
* Writes a 64-bit unsigned integer to the given virtual address in
|
||||
* the current process' address space.
|
||||
*
|
||||
* @param addr The virtual address to write the 64-bit unsigned integer to.
|
||||
* @param data The 64-bit unsigned integer to write to the given virtual address.
|
||||
*
|
||||
* @post The memory range [addr, sizeof(data)) contains the given data value.
|
||||
*/
|
||||
void Write64(VAddr addr, u64 data);
|
||||
|
||||
/**
|
||||
|
@ -344,29 +431,155 @@ public:
|
|||
bool WriteExclusive32(const VAddr addr, const u32 data, const u32 expected);
|
||||
bool WriteExclusive64(const VAddr addr, const u64 data, const u64 expected);
|
||||
|
||||
/**
|
||||
* Reads a null-terminated string from the given virtual address.
|
||||
* This function will continually read characters until either:
|
||||
*
|
||||
* - A null character ('\0') is reached.
|
||||
* - max_length characters have been read.
|
||||
*
|
||||
* @note The final null-terminating character (if found) is not included
|
||||
* in the returned string.
|
||||
*
|
||||
* @param vaddr The address to begin reading the string from.
|
||||
* @param max_length The maximum length of the string to read in characters.
|
||||
*
|
||||
* @returns The read string.
|
||||
*/
|
||||
std::string ReadCString(VAddr vaddr, std::size_t max_length);
|
||||
|
||||
/**
|
||||
* Reads a contiguous block of bytes from a specified process' address space.
|
||||
*
|
||||
* @param process The process to read the data from.
|
||||
* @param src_addr The virtual address to begin reading from.
|
||||
* @param dest_buffer The buffer to place the read bytes into.
|
||||
* @param size The amount of data to read, in bytes.
|
||||
*
|
||||
* @note If a size of 0 is specified, then this function reads nothing and
|
||||
* no attempts to access memory are made at all.
|
||||
*
|
||||
* @pre dest_buffer must be at least size bytes in length, otherwise a
|
||||
* buffer overrun will occur.
|
||||
*
|
||||
* @post The range [dest_buffer, size) contains the read bytes from the
|
||||
* process' address space.
|
||||
*/
|
||||
void ReadBlock(const Kernel::Process& process, VAddr src_addr, void* dest_buffer,
|
||||
std::size_t size);
|
||||
|
||||
/**
|
||||
* Reads a contiguous block of bytes from the current process' address space.
|
||||
*
|
||||
* @param src_addr The virtual address to begin reading from.
|
||||
* @param dest_buffer The buffer to place the read bytes into.
|
||||
* @param size The amount of data to read, in bytes.
|
||||
*
|
||||
* @note If a size of 0 is specified, then this function reads nothing and
|
||||
* no attempts to access memory are made at all.
|
||||
*
|
||||
* @pre dest_buffer must be at least size bytes in length, otherwise a
|
||||
* buffer overrun will occur.
|
||||
*
|
||||
* @post The range [dest_buffer, size) contains the read bytes from the
|
||||
* current process' address space.
|
||||
*/
|
||||
void ReadBlock(VAddr src_addr, void* dest_buffer, std::size_t size);
|
||||
|
||||
/**
|
||||
* Writes a range of bytes into a given process' address space at the specified
|
||||
* virtual address.
|
||||
*
|
||||
* @param process The process to write data into the address space of.
|
||||
* @param dest_addr The destination virtual address to begin writing the data at.
|
||||
* @param src_buffer The data to write into the process' address space.
|
||||
* @param size The size of the data to write, in bytes.
|
||||
*
|
||||
* @post The address range [dest_addr, size) in the process' address space
|
||||
* contains the data that was within src_buffer.
|
||||
*
|
||||
* @post If an attempt is made to write into an unmapped region of memory, the writes
|
||||
* will be ignored and an error will be logged.
|
||||
*
|
||||
* @post If a write is performed into a region of memory that is considered cached
|
||||
* rasterizer memory, will cause the currently active rasterizer to be notified
|
||||
* and will mark that region as invalidated to caches that the active
|
||||
* graphics backend may be maintaining over the course of execution.
|
||||
*/
|
||||
void WriteBlock(const Kernel::Process& process, VAddr dest_addr, const void* src_buffer,
|
||||
std::size_t size);
|
||||
|
||||
/**
|
||||
* Writes a range of bytes into a given process' address space at the specified
|
||||
* virtual address.
|
||||
*
|
||||
* @param dest_addr The destination virtual address to begin writing the data at.
|
||||
* @param src_buffer The data to write into the process' address space.
|
||||
* @param size The size of the data to write, in bytes.
|
||||
*
|
||||
* @post The address range [dest_addr, size) in the process' address space
|
||||
* contains the data that was within src_buffer.
|
||||
*
|
||||
* @post If an attempt is made to write into an unmapped region of memory, the writes
|
||||
* will be ignored and an error will be logged.
|
||||
*
|
||||
* @post If a write is performed into a region of memory that is considered cached
|
||||
* rasterizer memory, will cause the currently active rasterizer to be notified
|
||||
* and will mark that region as invalidated to caches that the active
|
||||
* graphics backend may be maintaining over the course of execution.
|
||||
*/
|
||||
void WriteBlock(VAddr dest_addr, const void* src_buffer, std::size_t size);
|
||||
|
||||
/**
|
||||
* Zeros a range of bytes within the current process' address space at the specified
|
||||
* virtual address.
|
||||
*
|
||||
* @param process The process that will have data zeroed within its address space.
|
||||
* @param dest_addr The destination virtual address to zero the data from.
|
||||
* @param size The size of the range to zero out, in bytes.
|
||||
*
|
||||
* @post The range [dest_addr, size) within the process' address space contains the
|
||||
* value 0.
|
||||
*/
|
||||
void ZeroBlock(const Kernel::Process& process, VAddr dest_addr, const std::size_t size);
|
||||
|
||||
/**
|
||||
* Copies data within a process' address space to another location within the
|
||||
* same address space.
|
||||
*
|
||||
* @param process The process that will have data copied within its address space.
|
||||
* @param dest_addr The destination virtual address to begin copying the data into.
|
||||
* @param src_addr The source virtual address to begin copying the data from.
|
||||
* @param size The size of the data to copy, in bytes.
|
||||
*
|
||||
* @post The range [dest_addr, size) within the process' address space contains the
|
||||
* same data within the range [src_addr, size).
|
||||
*/
|
||||
void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr,
|
||||
std::size_t size);
|
||||
void CopyBlock(const Kernel::Process& dest_process, const Kernel::Process& src_process,
|
||||
VAddr dest_addr, VAddr src_addr, std::size_t size);
|
||||
|
||||
std::string ReadCString(VAddr vaddr, std::size_t max_length);
|
||||
/**
|
||||
* Marks each page within the specified address range as cached or uncached.
|
||||
*
|
||||
* @param vaddr The virtual address indicating the start of the address range.
|
||||
* @param size The size of the address range in bytes.
|
||||
* @param cached Whether or not any pages within the address range should be
|
||||
* marked as cached or uncached.
|
||||
*/
|
||||
void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached);
|
||||
|
||||
/// Gets a pointer to the memory region beginning at the specified physical address.
|
||||
u8* GetPhysicalPointer(PAddr address);
|
||||
|
||||
/// Gets a pointer to the memory region beginning at the specified physical address.
|
||||
const u8* GetPhysicalPointer(PAddr address) const;
|
||||
|
||||
/// Returns a reference to the memory region beginning at the specified physical address
|
||||
MemoryRef GetPhysicalRef(PAddr address) const;
|
||||
|
||||
u8* GetPointer(VAddr vaddr);
|
||||
const u8* GetPointer(VAddr vaddr) const;
|
||||
/// Determines if the given VAddr is valid for the specified process.
|
||||
bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr);
|
||||
|
||||
/// Returns true if the address refers to a valid memory region
|
||||
bool IsValidPhysicalAddress(PAddr paddr) const;
|
||||
|
||||
/// Gets offset in FCRAM from a pointer inside FCRAM range
|
||||
|
@ -381,11 +594,6 @@ public:
|
|||
/// Gets a serializable ref to FCRAM with the given offset
|
||||
MemoryRef GetFCRAMRef(std::size_t offset) const;
|
||||
|
||||
/**
|
||||
* Mark each page touching the region as cached.
|
||||
*/
|
||||
void RasterizerMarkRegionCached(PAddr start, u32 size, bool cached);
|
||||
|
||||
/// Registers page table for rasterizer cache marking
|
||||
void RegisterPageTable(std::shared_ptr<PageTable> page_table);
|
||||
|
||||
|
@ -415,7 +623,6 @@ private:
|
|||
void MapPages(PageTable& page_table, u32 base, u32 size, MemoryRef memory, PageType type);
|
||||
|
||||
class Impl;
|
||||
|
||||
std::unique_ptr<Impl> impl;
|
||||
|
||||
friend class boost::serialization::access;
|
||||
|
@ -427,9 +634,6 @@ public:
|
|||
class BackingMemImpl;
|
||||
};
|
||||
|
||||
/// Determines if the given VAddr is valid for the specified process.
|
||||
bool IsValidVirtualAddress(const Kernel::Process& process, VAddr vaddr);
|
||||
|
||||
} // namespace Memory
|
||||
|
||||
BOOST_CLASS_EXPORT_KEY(Memory::MemorySystem::BackingMemImpl<Memory::Region::FCRAM>)
|
||||
|
|
|
@ -22,7 +22,6 @@ namespace Settings {
|
|||
Values values = {};
|
||||
|
||||
void Apply() {
|
||||
|
||||
GDBStub::SetServerPort(values.gdbstub_port);
|
||||
GDBStub::ToggleServer(values.use_gdbstub);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue