diff options
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r-- | src/core/hle/kernel/mutex.cpp | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/mutex.h | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/process.cpp | 47 | ||||
-rw-r--r-- | src/core/hle/kernel/process.h | 17 | ||||
-rw-r--r-- | src/core/hle/kernel/semaphore.cpp | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/semaphore.h | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.cpp | 9 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.h | 8 | ||||
-rw-r--r-- | src/core/hle/kernel/vm_manager.cpp | 28 | ||||
-rw-r--r-- | src/core/hle/kernel/vm_manager.h | 20 |
10 files changed, 82 insertions, 59 deletions
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 2cbca5e5b..30dade552 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -25,10 +25,11 @@ void ReleaseThreadMutexes(Thread* thread) { Mutex::Mutex() {} Mutex::~Mutex() {} -SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) { +SharedPtr<Mutex> Mutex::Create(bool initial_locked, VAddr addr, std::string name) { SharedPtr<Mutex> mutex(new Mutex); mutex->lock_count = 0; + mutex->addr = addr; mutex->name = std::move(name); mutex->holding_thread = nullptr; diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index bacacd690..503d3ee75 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -21,7 +21,7 @@ public: * @param name Optional name of mutex * @return Pointer to new Mutex object */ - static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown"); + static SharedPtr<Mutex> Create(bool initial_locked, VAddr addr, std::string name = "Unknown"); std::string GetTypeName() const override { return "Mutex"; @@ -39,6 +39,7 @@ public: u32 priority; ///< The priority of the mutex, used for priority inheritance. std::string name; ///< Name of mutex (optional) SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex + VAddr addr; /** * Elevate the mutex priority to the best priority diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index cf3163e0f..9e145866f 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -30,10 +30,10 @@ CodeSet::~CodeSet() {} u32 Process::next_process_id; -SharedPtr<Process> Process::Create(SharedPtr<CodeSet> code_set) { +SharedPtr<Process> Process::Create(std::string&& name) { SharedPtr<Process> process(new Process); - process->codeset = std::move(code_set); + process->name = std::move(name); process->flags.raw = 0; process->flags.memory_region.Assign(MemoryRegion::APPLICATION); @@ -112,25 +112,7 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) { } } -void Process::Run(s32 main_thread_priority, u32 stack_size) { - memory_region = GetMemoryRegion(flags.memory_region); - - auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, - MemoryState memory_state) { - auto vma = vm_manager - .MapMemoryBlock(segment.addr, codeset->memory, segment.offset, segment.size, - memory_state) - .Unwrap(); - vm_manager.Reprotect(vma, permissions); - misc_memory_used += segment.size; - memory_region->used += segment.size; - }; - - // Map CodeSet segments - MapSegment(codeset->code, VMAPermission::ReadExecute, MemoryState::Code); - MapSegment(codeset->rodata, VMAPermission::Read, MemoryState::Code); - MapSegment(codeset->data, VMAPermission::ReadWrite, MemoryState::Private); - +void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { // Allocate and map stack vm_manager .MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size, @@ -147,7 +129,28 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) { } vm_manager.LogLayout(Log::Level::Debug); - Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority, this); + + Kernel::SetupMainThread(entry_point, main_thread_priority, this); +} + +void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) { + memory_region = GetMemoryRegion(flags.memory_region); + + auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, + MemoryState memory_state) { + auto vma = vm_manager + .MapMemoryBlock(segment.addr + base_addr, module_->memory, segment.offset, segment.size, + memory_state) + .Unwrap(); + vm_manager.Reprotect(vma, permissions); + misc_memory_used += segment.size; + memory_region->used += segment.size; + }; + + // Map CodeSet segments + MapSegment(module_->code, VMAPermission::ReadWrite, MemoryState::Private); + MapSegment(module_->rodata, VMAPermission::Read, MemoryState::Static); + MapSegment(module_->data, VMAPermission::ReadWrite, MemoryState::Static); } VAddr Process::GetLinearHeapAreaAddress() const { diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index b52211d2a..f05f2703e 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -79,7 +79,11 @@ struct CodeSet final : public Object { u32 size = 0; }; - Segment code, rodata, data; + Segment segments[3]; + Segment& code = segments[0]; + Segment& rodata = segments[1]; + Segment& data = segments[2]; + VAddr entrypoint; private: @@ -89,13 +93,13 @@ private: class Process final : public Object { public: - static SharedPtr<Process> Create(SharedPtr<CodeSet> code_set); + static SharedPtr<Process> Create(std::string&& name); std::string GetTypeName() const override { return "Process"; } std::string GetName() const override { - return codeset->name; + return name; } static const HandleType HANDLE_TYPE = HandleType::Process; @@ -105,7 +109,6 @@ public: static u32 next_process_id; - SharedPtr<CodeSet> codeset; /// Resource limit descriptor for this process SharedPtr<ResourceLimit> resource_limit; @@ -134,7 +137,9 @@ public: /** * Applies address space changes and launches the process main thread. */ - void Run(s32 main_thread_priority, u32 stack_size); + void Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size); + + void LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr); /////////////////////////////////////////////////////////////////////////////////////////////// // Memory Management @@ -160,6 +165,8 @@ public: /// This vector will grow as more pages are allocated for new threads. std::vector<std::bitset<8>> tls_slots; + std::string name; + VAddr GetLinearHeapAreaAddress() const; VAddr GetLinearHeapBase() const; VAddr GetLinearHeapLimit() const; diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp index fcf586728..2605b2595 100644 --- a/src/core/hle/kernel/semaphore.cpp +++ b/src/core/hle/kernel/semaphore.cpp @@ -13,7 +13,7 @@ namespace Kernel { Semaphore::Semaphore() {} Semaphore::~Semaphore() {} -ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, +ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, VAddr address, std::string name) { if (initial_count > max_count) @@ -25,6 +25,7 @@ ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_cou // and the rest is reserved for the caller thread semaphore->max_count = max_count; semaphore->available_count = initial_count; + semaphore->address = address; semaphore->name = std::move(name); return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore)); diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h index 7b0cacf2e..77c491a24 100644 --- a/src/core/hle/kernel/semaphore.h +++ b/src/core/hle/kernel/semaphore.h @@ -22,7 +22,7 @@ public: * @param name Optional name of semaphore * @return The created semaphore */ - static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count, + static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count, VAddr address, std::string name = "Unknown"); std::string GetTypeName() const override { @@ -39,6 +39,7 @@ public: s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have s32 available_count; ///< Number of free slots left in the semaphore + VAddr address; std::string name; ///< Name of semaphore (optional) bool ShouldWait(Thread* thread) const override; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 0f7970ebe..75df49ac2 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -358,8 +358,8 @@ std::tuple<u32, u32, bool> GetFreeThreadLocalSlot(std::vector<std::bitset<8>>& t * @param entry_point Address of entry point for execution * @param arg User argument for thread */ -static void ResetThreadContext(ARM_Interface::ThreadContext& context, u32 stack_top, - u32 entry_point, u32 arg) { +static void ResetThreadContext(ARM_Interface::ThreadContext& context, VAddr stack_top, + VAddr entry_point, u64 arg) { memset(&context, 0, sizeof(ARM_Interface::ThreadContext)); context.cpu_registers[0] = arg; @@ -446,7 +446,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, // Map the page to the current process' address space. // TODO(Subv): Find the correct MemoryState for this region. vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE, - linheap_memory, offset, Memory::PAGE_SIZE, MemoryState::Private); + linheap_memory, offset, Memory::PAGE_SIZE, MemoryState::Static); } // Mark the slot as used @@ -495,6 +495,9 @@ void Thread::BoostPriority(u32 priority) { } SharedPtr<Thread> SetupMainThread(u32 entry_point, u32 priority, SharedPtr<Process> owner_process) { + // Setup page table so we can write to memory + SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table); + // Initialize new "main" thread auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0, Memory::HEAP_VADDR_END, owner_process); diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 314fba81f..fafcab156 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -184,8 +184,8 @@ public: u32 thread_id; u32 status; - u32 entry_point; - u32 stack_top; + VAddr entry_point; + VAddr stack_top; u32 nominal_priority; ///< Nominal thread priority, as set by the emulated application u32 current_priority; ///< Current thread priority, can be temporarily changed @@ -250,13 +250,13 @@ void Reschedule(); * Arbitrate the highest priority thread that is waiting * @param address The address for which waiting threads should be arbitrated */ -Thread* ArbitrateHighestPriorityThread(u32 address); +Thread* ArbitrateHighestPriorityThread(VAddr address); /** * Arbitrate all threads currently waiting. * @param address The address for which waiting threads should be arbitrated */ -void ArbitrateAllThreads(u32 address); +void ArbitrateAllThreads(VAddr address); /** * Gets the current thread diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 7a007c065..9762ef535 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -4,8 +4,10 @@ #include <iterator> #include "common/assert.h" +#include "core/arm/arm_interface.h" #include "core/hle/kernel/errors.h" #include "core/hle/kernel/vm_manager.h" +#include "core/core.h" #include "core/memory.h" #include "core/memory_setup.h" #include "core/mmio.h" @@ -60,7 +62,7 @@ void VMManager::Reset() { page_table.attributes.fill(Memory::PageType::Unmapped); page_table.cached_res_count.fill(0); - UpdatePageTableForVMA(initial_vma); + //UpdatePageTableForVMA(initial_vma); } VMManager::VMAHandle VMManager::FindVMA(VAddr target) const { @@ -73,7 +75,7 @@ VMManager::VMAHandle VMManager::FindVMA(VAddr target) const { ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block, - size_t offset, u32 size, + size_t offset, u64 size, MemoryState state) { ASSERT(block != nullptr); ASSERT(offset + size <= block->size()); @@ -83,6 +85,8 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, VirtualMemoryArea& final_vma = vma_handle->second; ASSERT(final_vma.size == size); + Core::CPU().MapBackingMemory(target, size, block->data() + offset, VMAPermission::ReadWriteExecute); + final_vma.type = VMAType::AllocatedMemoryBlock; final_vma.permissions = VMAPermission::ReadWrite; final_vma.meminfo_state = state; @@ -93,7 +97,7 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); } -ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* memory, u32 size, +ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* memory, u64 size, MemoryState state) { ASSERT(memory != nullptr); @@ -102,6 +106,8 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* me VirtualMemoryArea& final_vma = vma_handle->second; ASSERT(final_vma.size == size); + Core::CPU().MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); + final_vma.type = VMAType::BackingMemory; final_vma.permissions = VMAPermission::ReadWrite; final_vma.meminfo_state = state; @@ -111,7 +117,7 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* me return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); } -ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size, +ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u64 size, MemoryState state, Memory::MMIORegionPointer mmio_handler) { // This is the appropriately sized VMA that will turn into our allocation. @@ -145,7 +151,7 @@ VMManager::VMAIter VMManager::Unmap(VMAIter vma_handle) { return MergeAdjacent(vma_handle); } -ResultCode VMManager::UnmapRange(VAddr target, u32 size) { +ResultCode VMManager::UnmapRange(VAddr target, u64 size) { CASCADE_RESULT(VMAIter vma, CarveVMARange(target, size)); VAddr target_end = target + size; @@ -170,7 +176,7 @@ VMManager::VMAHandle VMManager::Reprotect(VMAHandle vma_handle, VMAPermission ne return MergeAdjacent(iter); } -ResultCode VMManager::ReprotectRange(VAddr target, u32 size, VMAPermission new_perms) { +ResultCode VMManager::ReprotectRange(VAddr target, u64 size, VMAPermission new_perms) { CASCADE_RESULT(VMAIter vma, CarveVMARange(target, size)); VAddr target_end = target + size; @@ -213,7 +219,7 @@ VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle& iter) { return vma_map.erase(iter, iter); // Erases an empty range of elements } -ResultVal<VMManager::VMAIter> VMManager::CarveVMA(VAddr base, u32 size) { +ResultVal<VMManager::VMAIter> VMManager::CarveVMA(VAddr base, u64 size) { ASSERT_MSG((size & Memory::PAGE_MASK) == 0, "non-page aligned size: 0x%8X", size); ASSERT_MSG((base & Memory::PAGE_MASK) == 0, "non-page aligned base: 0x%08X", base); @@ -229,8 +235,8 @@ ResultVal<VMManager::VMAIter> VMManager::CarveVMA(VAddr base, u32 size) { return ERR_INVALID_ADDRESS_STATE; } - u32 start_in_vma = base - vma.base; - u32 end_in_vma = start_in_vma + size; + u64 start_in_vma = base - vma.base; + u64 end_in_vma = start_in_vma + size; if (end_in_vma > vma.size) { // Requested allocation doesn't fit inside VMA @@ -249,7 +255,7 @@ ResultVal<VMManager::VMAIter> VMManager::CarveVMA(VAddr base, u32 size) { return MakeResult<VMAIter>(vma_handle); } -ResultVal<VMManager::VMAIter> VMManager::CarveVMARange(VAddr target, u32 size) { +ResultVal<VMManager::VMAIter> VMManager::CarveVMARange(VAddr target, u64 size) { ASSERT_MSG((size & Memory::PAGE_MASK) == 0, "non-page aligned size: 0x%8X", size); ASSERT_MSG((target & Memory::PAGE_MASK) == 0, "non-page aligned base: 0x%08X", target); @@ -278,7 +284,7 @@ ResultVal<VMManager::VMAIter> VMManager::CarveVMARange(VAddr target, u32 size) { return MakeResult<VMAIter>(begin_vma); } -VMManager::VMAIter VMManager::SplitVMA(VMAIter vma_handle, u32 offset_in_vma) { +VMManager::VMAIter VMManager::SplitVMA(VMAIter vma_handle, u64 offset_in_vma) { VirtualMemoryArea& old_vma = vma_handle->second; VirtualMemoryArea new_vma = old_vma; // Make a copy of the VMA diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 1302527bb..cb5bb8243 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -64,7 +64,7 @@ struct VirtualMemoryArea { /// Virtual base address of the region. VAddr base = 0; /// Size of the region. - u32 size = 0; + u64 size = 0; VMAType type = VMAType::Free; VMAPermission permissions = VMAPermission::None; @@ -109,7 +109,7 @@ public: * used. * @note This is the limit used by the New 3DS kernel. Old 3DS used 0x20000000. */ - static const u32 MAX_ADDRESS = 0x40000000; + static const VAddr MAX_ADDRESS = 0x8000000000; /** * A map covering the entirety of the managed address space, keyed by the `base` field of each @@ -142,7 +142,7 @@ public: * @param state MemoryState tag to attach to the VMA. */ ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block, - size_t offset, u32 size, MemoryState state); + size_t offset, u64 size, MemoryState state); /** * Maps an unmanaged host memory pointer at a given address. @@ -152,7 +152,7 @@ public: * @param size Size of the mapping. * @param state MemoryState tag to attach to the VMA. */ - ResultVal<VMAHandle> MapBackingMemory(VAddr target, u8* memory, u32 size, MemoryState state); + ResultVal<VMAHandle> MapBackingMemory(VAddr target, u8* memory, u64 size, MemoryState state); /** * Maps a memory-mapped IO region at a given address. @@ -163,17 +163,17 @@ public: * @param state MemoryState tag to attach to the VMA. * @param mmio_handler The handler that will implement read and write for this MMIO region. */ - ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, + ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u64 size, MemoryState state, Memory::MMIORegionPointer mmio_handler); /// Unmaps a range of addresses, splitting VMAs as necessary. - ResultCode UnmapRange(VAddr target, u32 size); + ResultCode UnmapRange(VAddr target, u64 size); /// Changes the permissions of the given VMA. VMAHandle Reprotect(VMAHandle vma, VMAPermission new_perms); /// Changes the permissions of a range of addresses, splitting VMAs as necessary. - ResultCode ReprotectRange(VAddr target, u32 size, VMAPermission new_perms); + ResultCode ReprotectRange(VAddr target, u64 size, VMAPermission new_perms); /** * Scans all VMAs and updates the page table range of any that use the given vector as backing @@ -201,19 +201,19 @@ private: * Carves a VMA of a specific size at the specified address by splitting Free VMAs while doing * the appropriate error checking. */ - ResultVal<VMAIter> CarveVMA(VAddr base, u32 size); + ResultVal<VMAIter> CarveVMA(VAddr base, u64 size); /** * Splits the edges of the given range of non-Free VMAs so that there is a VMA split at each * end of the range. */ - ResultVal<VMAIter> CarveVMARange(VAddr base, u32 size); + ResultVal<VMAIter> CarveVMARange(VAddr base, u64 size); /** * Splits a VMA in two, at the specified offset. * @returns the right side of the split, with the original iterator becoming the left side. */ - VMAIter SplitVMA(VMAIter vma, u32 offset_in_vma); + VMAIter SplitVMA(VMAIter vma, u64 offset_in_vma); /** * Checks for and merges the specified VMA with adjacent ones if possible. |