diff options
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r-- | src/core/hle/kernel/event.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/event.h | 1 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.h | 9 | ||||
-rw-r--r-- | src/core/hle/kernel/process.cpp | 38 | ||||
-rw-r--r-- | src/core/hle/kernel/process.h | 47 | ||||
-rw-r--r-- | src/core/hle/kernel/session.h | 6 | ||||
-rw-r--r-- | src/core/hle/kernel/shared_memory.h | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.cpp | 29 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.h | 1 | ||||
-rw-r--r-- | src/core/hle/kernel/vm_manager.cpp | 16 | ||||
-rw-r--r-- | src/core/hle/kernel/vm_manager.h | 7 |
12 files changed, 130 insertions, 31 deletions
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index f338f3266..53feebbc0 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -21,7 +21,7 @@ SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) { SharedPtr<Event> evt(new Event); evt->signaled = false; - evt->reset_type = evt->intitial_reset_type = reset_type; + evt->reset_type = reset_type; evt->name = std::move(name); return evt; diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index fba960d2a..89d405236 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -26,7 +26,6 @@ public: static const HandleType HANDLE_TYPE = HandleType::Event; HandleType GetHandleType() const override { return HANDLE_TYPE; } - ResetType intitial_reset_type; ///< ResetType specified at Event initialization ResetType reset_type; ///< Current ResetType bool signaled; ///< Whether the event has already been signaled diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 20e11da16..5711c0405 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -7,8 +7,6 @@ #include "common/assert.h" #include "common/logging/log.h" -#include "core/arm/arm_interface.h" -#include "core/core.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/process.h" diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 64595f758..4d4276f7a 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -4,10 +4,11 @@ #pragma once -#include <boost/intrusive_ptr.hpp> +#include <boost/smart_ptr/intrusive_ptr.hpp> +#include <algorithm> #include <array> -#include <memory> +#include <cstddef> #include <string> #include <vector> @@ -16,8 +17,6 @@ #include "core/hle/hle.h" #include "core/hle/result.h" -struct ApplicationInfo; - namespace Kernel { class Thread; @@ -48,6 +47,7 @@ enum class HandleType : u32 { Semaphore = 10, Timer = 11, ResourceLimit = 12, + CodeSet = 13, }; enum { @@ -86,6 +86,7 @@ public: case HandleType::Process: case HandleType::AddressArbiter: case HandleType::ResourceLimit: + case HandleType::CodeSet: return false; } } diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index b0e75ba59..a7892c652 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -5,24 +5,39 @@ #include "common/assert.h" #include "common/common_funcs.h" #include "common/logging/log.h" +#include "common/make_unique.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/thread.h" +#include "core/hle/kernel/vm_manager.h" +#include "core/mem_map.h" #include "core/memory.h" namespace Kernel { +SharedPtr<CodeSet> CodeSet::Create(std::string name, u64 program_id) { + SharedPtr<CodeSet> codeset(new CodeSet); + + codeset->name = std::move(name); + codeset->program_id = program_id; + + return codeset; +} + +CodeSet::CodeSet() {} +CodeSet::~CodeSet() {} + u32 Process::next_process_id; -SharedPtr<Process> Process::Create(std::string name, u64 program_id) { +SharedPtr<Process> Process::Create(SharedPtr<CodeSet> code_set) { SharedPtr<Process> process(new Process); - process->name = std::move(name); - process->program_id = program_id; - + process->codeset = std::move(code_set); process->flags.raw = 0; process->flags.memory_region = MemoryRegion::APPLICATION; + process->address_space = Common::make_unique<VMManager>(); + Memory::InitLegacyAddressSpace(*process->address_space); return process; } @@ -87,8 +102,19 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) { } } -void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { - Kernel::SetupMainThread(entry_point, main_thread_priority); +void Process::Run(s32 main_thread_priority, u32 stack_size) { + auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, MemoryState memory_state) { + auto vma = address_space->MapMemoryBlock(segment.addr, codeset->memory, + segment.offset, segment.size, memory_state).Unwrap(); + address_space->Reprotect(vma, permissions); + }; + + MapSegment(codeset->code, VMAPermission::ReadExecute, MemoryState::Code); + MapSegment(codeset->rodata, VMAPermission::Read, MemoryState::Code); + MapSegment(codeset->data, VMAPermission::ReadWrite, MemoryState::Private); + + address_space->LogLayout(); + Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority); } Kernel::Process::Process() {} diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 7b8a68610..83d3aceae 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -5,6 +5,9 @@ #pragma once #include <bitset> +#include <cstddef> +#include <memory> +#include <string> #include <boost/container/static_vector.hpp> @@ -12,7 +15,6 @@ #include "common/common_types.h" #include "core/hle/kernel/kernel.h" -#include "core/hle/result.h" namespace Kernel { @@ -46,23 +48,51 @@ union ProcessFlags { }; class ResourceLimit; +class VMManager; + +struct CodeSet final : public Object { + static SharedPtr<CodeSet> Create(std::string name, u64 program_id); + + std::string GetTypeName() const override { return "CodeSet"; } + std::string GetName() const override { return name; } + + static const HandleType HANDLE_TYPE = HandleType::CodeSet; + HandleType GetHandleType() const override { return HANDLE_TYPE; } + + /// Name of the process + std::string name; + /// Title ID corresponding to the process + u64 program_id; + + std::shared_ptr<std::vector<u8>> memory; + + struct Segment { + size_t offset = 0; + VAddr addr = 0; + u32 size = 0; + }; + + Segment code, rodata, data; + VAddr entrypoint; + +private: + CodeSet(); + ~CodeSet() override; +}; class Process final : public Object { public: - static SharedPtr<Process> Create(std::string name, u64 program_id); + static SharedPtr<Process> Create(SharedPtr<CodeSet> code_set); std::string GetTypeName() const override { return "Process"; } - std::string GetName() const override { return name; } + std::string GetName() const override { return codeset->name; } static const HandleType HANDLE_TYPE = HandleType::Process; HandleType GetHandleType() const override { return HANDLE_TYPE; } static u32 next_process_id; - /// Name of the process - std::string name; - /// Title ID corresponding to the process - u64 program_id; + SharedPtr<CodeSet> codeset; /// Resource limit descriptor for this process SharedPtr<ResourceLimit> resource_limit; @@ -80,6 +110,7 @@ public: /// Bitmask of the used TLS slots std::bitset<300> used_tls_slots; + std::unique_ptr<VMManager> address_space; /** * Parses a list of kernel capability descriptors (as found in the ExHeader) and applies them @@ -90,7 +121,7 @@ public: /** * Applies address space changes and launches the process main thread. */ - void Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size); + void Run(s32 main_thread_priority, u32 stack_size); private: Process(); diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h index 257da9105..adaffcafe 100644 --- a/src/core/hle/kernel/session.h +++ b/src/core/hle/kernel/session.h @@ -4,8 +4,14 @@ #pragma once +#include <string> + +#include "common/assert.h" +#include "common/common_types.h" + #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/thread.h" +#include "core/hle/result.h" #include "core/memory.h" namespace IPC { diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h index 204266896..7a2922776 100644 --- a/src/core/hle/kernel/shared_memory.h +++ b/src/core/hle/kernel/shared_memory.h @@ -4,9 +4,12 @@ #pragma once +#include <string> + #include "common/common_types.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/result.h" namespace Kernel { diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 4729a7fe0..8b49fc7df 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -37,6 +37,10 @@ void Thread::Acquire() { ASSERT_MSG(!ShouldWait(), "object unavailable!"); } +// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, allowing +// us to simply use a pool index or similar. +static Kernel::HandleTable wakeup_callback_handle_table; + // Lists all thread ids that aren't deleted/etc. static std::vector<SharedPtr<Thread>> thread_list; @@ -93,6 +97,8 @@ void Thread::Stop() { // Cancel any outstanding wakeup events for this thread CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle); + wakeup_callback_handle_table.Close(callback_handle); + callback_handle = 0; // Clean up thread from ready queue // This is only needed when the thread is termintated forcefully (SVC TerminateProcess) @@ -108,6 +114,7 @@ void Thread::Stop() { for (auto& wait_object : wait_objects) { wait_object->RemoveWaitingThread(this); } + wait_objects.clear(); Kernel::g_current_process->used_tls_slots[tls_index] = false; @@ -210,6 +217,14 @@ static void SwitchContext(Thread* new_thread) { new_thread->context.pc -= thumb_mode ? 2 : 4; } + // Clean up the thread's wait_objects, they'll be restored if needed during + // the svcWaitSynchronization call + for (int i = 0; i < new_thread->wait_objects.size(); ++i) { + SharedPtr<WaitObject> object = new_thread->wait_objects[i]; + object->RemoveWaitingThread(new_thread); + } + new_thread->wait_objects.clear(); + ready_queue.remove(new_thread->current_priority, new_thread); new_thread->status = THREADSTATUS_RUNNING; @@ -268,10 +283,6 @@ void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) { thread->status = THREADSTATUS_WAIT_ARB; } -// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, allowing -// us to simply use a pool index or similar. -static Kernel::HandleTable wakeup_callback_handle_table; - /** * Callback that will wake up the thread it was scheduled for * @param thread_handle The handle of the thread that's been awoken @@ -503,12 +514,16 @@ void ThreadingInit() { current_thread = nullptr; next_thread_id = 1; - - thread_list.clear(); - ready_queue.clear(); } void ThreadingShutdown() { + current_thread = nullptr; + + for (auto& t : thread_list) { + t->Stop(); + } + thread_list.clear(); + ready_queue.clear(); } } // namespace diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index b8160bb2c..1ff1d9b97 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -13,6 +13,7 @@ #include "core/core.h" +#include "core/hle/hle.h" #include "core/hle/kernel/kernel.h" #include "core/hle/result.h" diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index b2dd21542..205cc7b53 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <iterator> + #include "common/assert.h" #include "core/hle/kernel/vm_manager.h" @@ -33,6 +35,10 @@ VMManager::VMManager() { Reset(); } +VMManager::~VMManager() { + Reset(); +} + void VMManager::Reset() { vma_map.clear(); @@ -128,6 +134,16 @@ void VMManager::Reprotect(VMAHandle vma_handle, VMAPermission new_perms) { MergeAdjacent(iter); } +void VMManager::LogLayout() const { + for (const auto& p : vma_map) { + const VirtualMemoryArea& vma = p.second; + LOG_DEBUG(Kernel, "%08X - %08X size: %8X %c%c%c", vma.base, vma.base + vma.size, vma.size, + (u8)vma.permissions & (u8)VMAPermission::Read ? 'R' : '-', + (u8)vma.permissions & (u8)VMAPermission::Write ? 'W' : '-', + (u8)vma.permissions & (u8)VMAPermission::Execute ? 'X' : '-'); + } +} + VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle & iter) { // This uses a neat C++ trick to convert a const_iterator to a regular iterator, given // non-const access to its container. diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 22b724603..b3795a94a 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -6,7 +6,6 @@ #include <map> #include <memory> -#include <string> #include <vector> #include "common/common_types.h" @@ -102,7 +101,7 @@ struct VirtualMemoryArea { * - http://duartes.org/gustavo/blog/post/how-the-kernel-manages-your-memory/ * - http://duartes.org/gustavo/blog/post/page-cache-the-affair-between-memory-and-files/ */ -class VMManager { +class VMManager final { // TODO(yuriks): Make page tables switchable to support multiple VMManagers public: /** @@ -122,6 +121,7 @@ public: using VMAHandle = decltype(vma_map)::const_iterator; VMManager(); + ~VMManager(); /// Clears the address space map, re-initializing with a single free area. void Reset(); @@ -169,6 +169,9 @@ public: /// Changes the permissions of the given VMA. void Reprotect(VMAHandle vma, VMAPermission new_perms); + /// Dumps the address space layout to the log, for debugging + void LogLayout() const; + private: using VMAIter = decltype(vma_map)::iterator; |