mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Kernel: Introduce skeleton Process class to hold process data
This commit is contained in:
		
							parent
							
								
									8809d02db3
								
							
						
					
					
						commit
						6d60acf0f1
					
				
					 13 changed files with 191 additions and 48 deletions
				
			
		|  | @ -29,6 +29,7 @@ set(SRCS | |||
|             hle/kernel/event.cpp | ||||
|             hle/kernel/kernel.cpp | ||||
|             hle/kernel/mutex.cpp | ||||
|             hle/kernel/process.cpp | ||||
|             hle/kernel/semaphore.cpp | ||||
|             hle/kernel/session.cpp | ||||
|             hle/kernel/shared_memory.cpp | ||||
|  | @ -139,6 +140,7 @@ set(HEADERS | |||
|             hle/kernel/event.h | ||||
|             hle/kernel/kernel.h | ||||
|             hle/kernel/mutex.h | ||||
|             hle/kernel/process.h | ||||
|             hle/kernel/semaphore.h | ||||
|             hle/kernel/session.h | ||||
|             hle/kernel/shared_memory.h | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ | |||
| #include "core/arm/arm_interface.h" | ||||
| #include "core/core.h" | ||||
| #include "core/hle/kernel/kernel.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/kernel/thread.h" | ||||
| #include "core/hle/kernel/timer.h" | ||||
| 
 | ||||
|  | @ -149,18 +150,7 @@ void Shutdown() { | |||
|     Kernel::ThreadingShutdown(); | ||||
|     Kernel::TimersShutdown(); | ||||
|     g_handle_table.Clear(); // Free all kernel objects
 | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Loads executable stored at specified address | ||||
|  * @entry_point Entry point in memory of loaded executable | ||||
|  * @return True on success, otherwise false | ||||
|  */ | ||||
| bool LoadExec(u32 entry_point) { | ||||
|     // 0x30 is the typical main thread priority I've seen used so far
 | ||||
|     g_main_thread = Kernel::SetupMainThread(Kernel::DEFAULT_STACK_SIZE, entry_point, THREADPRIO_DEFAULT); | ||||
| 
 | ||||
|     return true; | ||||
|     g_current_process = nullptr; | ||||
| } | ||||
| 
 | ||||
| } // namespace
 | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| #include <boost/intrusive_ptr.hpp> | ||||
| 
 | ||||
| #include <array> | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
|  | @ -15,6 +16,8 @@ | |||
| #include "core/hle/hle.h" | ||||
| #include "core/hle/result.h" | ||||
| 
 | ||||
| struct ApplicationInfo; | ||||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| class Thread; | ||||
|  | @ -282,11 +285,4 @@ void Init(); | |||
| /// Shutdown the kernel
 | ||||
| void Shutdown(); | ||||
| 
 | ||||
| /**
 | ||||
|  * Loads executable stored at specified address | ||||
|  * @entry_point Entry point in memory of loaded executable | ||||
|  * @return True on success, otherwise false | ||||
|  */ | ||||
| bool LoadExec(u32 entry_point); | ||||
| 
 | ||||
| } // namespace
 | ||||
|  |  | |||
							
								
								
									
										35
									
								
								src/core/hle/kernel/process.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/core/hle/kernel/process.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | |||
| // Copyright 2015 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| 
 | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/kernel/thread.h" | ||||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| SharedPtr<Process> Process::Create(std::string name, u64 program_id) { | ||||
|     SharedPtr<Process> process(new Process); | ||||
| 
 | ||||
|     process->svc_access_mask.set(); | ||||
|     process->name = std::move(name); | ||||
|     process->program_id = program_id; | ||||
| 
 | ||||
|     return process; | ||||
| } | ||||
| 
 | ||||
| void Process::ParseKernelCaps(const u32 * kernel_caps, size_t len) { | ||||
|     //UNIMPLEMENTED();
 | ||||
| } | ||||
| 
 | ||||
| void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { | ||||
|     g_main_thread = Kernel::SetupMainThread(stack_size, entry_point, main_thread_priority); | ||||
| } | ||||
| 
 | ||||
| Kernel::Process::Process() {} | ||||
| Kernel::Process::~Process() {} | ||||
| 
 | ||||
| SharedPtr<Process> g_current_process; | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										61
									
								
								src/core/hle/kernel/process.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/core/hle/kernel/process.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | |||
| // Copyright 2015 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <bitset> | ||||
| 
 | ||||
| #include <boost/container/static_vector.hpp> | ||||
| 
 | ||||
| #include "core/hle/kernel/kernel.h" | ||||
| #include "core/hle/result.h" | ||||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| struct StaticAddressMapping { | ||||
|     // Address and size must be 4K-aligned
 | ||||
|     VAddr address; | ||||
|     u32 size; | ||||
|     bool writable; | ||||
| }; | ||||
| 
 | ||||
| enum class MemoryRegion { | ||||
|     APPLICATION = 1, | ||||
|     SYSTEM = 2, | ||||
|     BASE = 3, | ||||
| }; | ||||
| 
 | ||||
| class Process final : public Object { | ||||
| public: | ||||
|     static SharedPtr<Process> Create(std::string name, u64 program_id); | ||||
| 
 | ||||
|     std::string GetTypeName() const override { return "Process"; } | ||||
|     std::string GetName() const override { return name; } | ||||
| 
 | ||||
|     static const HandleType HANDLE_TYPE = HandleType::Process; | ||||
|     HandleType GetHandleType() const override { return HANDLE_TYPE; } | ||||
| 
 | ||||
|     std::string name; ///< Name of the process
 | ||||
|     u64 program_id; | ||||
| 
 | ||||
|     std::bitset<0x80> svc_access_mask; | ||||
|     unsigned int handle_table_size = 0x200; | ||||
|     boost::container::static_vector<StaticAddressMapping, 8> static_address_mappings; // TODO: Determine a good upper limit
 | ||||
| 
 | ||||
|     bool loaded_high = false; // Application loaded high (not at 0x00100000)
 | ||||
|     bool shared_page_writable = false; | ||||
|     bool privileged_priority = false; // Can use priority levels higher than 24
 | ||||
|     MemoryRegion memory_region = MemoryRegion::APPLICATION; | ||||
| 
 | ||||
|     void ParseKernelCaps(const u32* kernel_caps, size_t len); | ||||
|     void Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size); | ||||
| 
 | ||||
| private: | ||||
|     Process(); | ||||
|     ~Process() override; | ||||
| }; | ||||
| 
 | ||||
| extern SharedPtr<Process> g_current_process; | ||||
| 
 | ||||
| } | ||||
|  | @ -8,9 +8,10 @@ | |||
| #include "common/logging/log.h" | ||||
| 
 | ||||
| #include "core/file_sys/archive_romfs.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/service/fs/archive.h" | ||||
| #include "core/loader/elf.h" | ||||
| #include "core/loader/ncch.h" | ||||
| #include "core/hle/service/fs/archive.h" | ||||
| #include "core/mem_map.h" | ||||
| 
 | ||||
| #include "3dsx.h" | ||||
|  | @ -229,8 +230,12 @@ ResultStatus AppLoader_THREEDSX::Load() { | |||
|     if (!file->IsOpen()) | ||||
|         return ResultStatus::Error; | ||||
| 
 | ||||
|     Load3DSXFile(*file, 0x00100000); | ||||
|     Kernel::LoadExec(0x00100000); | ||||
|     Kernel::g_current_process = Kernel::Process::Create(filename, 0); | ||||
|     Kernel::g_current_process->static_address_mappings = default_address_mappings; | ||||
| 
 | ||||
|     Load3DSXFile(*file, Memory::EXEFS_CODE_VADDR); | ||||
| 
 | ||||
|     Kernel::g_current_process->Run(Memory::EXEFS_CODE_VADDR, 48, Kernel::DEFAULT_STACK_SIZE); | ||||
| 
 | ||||
|     is_loaded = true; | ||||
|     return ResultStatus::Success; | ||||
|  |  | |||
|  | @ -4,6 +4,8 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| #include "core/loader/loader.h" | ||||
| 
 | ||||
|  | @ -15,7 +17,8 @@ namespace Loader { | |||
| /// Loads an 3DSX file
 | ||||
| class AppLoader_THREEDSX final : public AppLoader { | ||||
| public: | ||||
|     AppLoader_THREEDSX(std::unique_ptr<FileUtil::IOFile>&& file) : AppLoader(std::move(file)) { } | ||||
|     AppLoader_THREEDSX(std::unique_ptr<FileUtil::IOFile>&& file, std::string filename) | ||||
|         : AppLoader(std::move(file)), filename(std::move(filename)) {} | ||||
| 
 | ||||
|     /**
 | ||||
|      * Returns the type of the file | ||||
|  | @ -29,6 +32,9 @@ public: | |||
|      * @return ResultStatus result of function | ||||
|      */ | ||||
|     ResultStatus Load() override; | ||||
| 
 | ||||
| private: | ||||
|     std::string filename; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Loader
 | ||||
|  |  | |||
|  | @ -10,9 +10,9 @@ | |||
| #include "common/logging/log.h" | ||||
| #include "common/symbols.h" | ||||
| 
 | ||||
| #include "core/mem_map.h" | ||||
| #include "core/loader/elf.h" | ||||
| #include "core/hle/kernel/kernel.h" | ||||
| #include "core/loader/elf.h" | ||||
| #include "core/mem_map.h" | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // ELF Header Constants
 | ||||
|  | @ -350,9 +350,14 @@ ResultStatus AppLoader_ELF::Load() { | |||
|     if (file->ReadBytes(&buffer[0], size) != size) | ||||
|         return ResultStatus::Error; | ||||
| 
 | ||||
|     Kernel::g_current_process = Kernel::Process::Create(filename, 0); | ||||
|     Kernel::g_current_process->static_address_mappings = default_address_mappings; | ||||
| 
 | ||||
|     ElfReader elf_reader(&buffer[0]); | ||||
|     elf_reader.LoadInto(0x00100000); | ||||
|     Kernel::LoadExec(elf_reader.GetEntryPoint()); | ||||
|     elf_reader.LoadInto(Memory::EXEFS_CODE_VADDR); | ||||
|     // TODO: Fill application title
 | ||||
| 
 | ||||
|     Kernel::g_current_process->Run(elf_reader.GetEntryPoint(), 48, Kernel::DEFAULT_STACK_SIZE); | ||||
| 
 | ||||
|     is_loaded = true; | ||||
|     return ResultStatus::Success; | ||||
|  |  | |||
|  | @ -4,6 +4,8 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| #include "core/loader/loader.h" | ||||
| 
 | ||||
|  | @ -15,7 +17,8 @@ namespace Loader { | |||
| /// Loads an ELF/AXF file
 | ||||
| class AppLoader_ELF final : public AppLoader { | ||||
| public: | ||||
|     AppLoader_ELF(std::unique_ptr<FileUtil::IOFile>&& file) : AppLoader(std::move(file)) { } | ||||
|     AppLoader_ELF(std::unique_ptr<FileUtil::IOFile>&& file, std::string filename) | ||||
|         : AppLoader(std::move(file)), filename(std::move(filename)) { } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Returns the type of the file | ||||
|  | @ -29,6 +32,9 @@ public: | |||
|      * @return ResultStatus result of function | ||||
|      */ | ||||
|     ResultStatus Load() override; | ||||
| 
 | ||||
| private: | ||||
|     std::string filename; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Loader
 | ||||
|  |  | |||
|  | @ -8,16 +8,23 @@ | |||
| #include "common/make_unique.h" | ||||
| 
 | ||||
| #include "core/file_sys/archive_romfs.h" | ||||
| #include "core/hle/kernel/process.h" | ||||
| #include "core/hle/service/fs/archive.h" | ||||
| #include "core/loader/3dsx.h" | ||||
| #include "core/loader/elf.h" | ||||
| #include "core/loader/ncch.h" | ||||
| #include "core/hle/service/fs/archive.h" | ||||
| #include "core/mem_map.h" | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| namespace Loader { | ||||
| 
 | ||||
| const std::initializer_list<Kernel::StaticAddressMapping> default_address_mappings = { | ||||
|     { 0x1FF50000,   0x8000, true  }, // part of DSP RAM
 | ||||
|     { 0x1FF70000,   0x8000, true  }, // part of DSP RAM
 | ||||
|     { 0x1F000000, 0x600000, false }, // entire VRAM
 | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * Identifies the type of a bootable file | ||||
|  * @param file open file | ||||
|  | @ -42,19 +49,11 @@ static FileType IdentifyFile(FileUtil::IOFile& file) { | |||
| 
 | ||||
| /**
 | ||||
|  * Guess the type of a bootable file from its extension | ||||
|  * @param filename String filename of bootable file | ||||
|  * @param extension String extension of bootable file | ||||
|  * @return FileType of file | ||||
|  */ | ||||
| static FileType GuessFromFilename(const std::string& filename) { | ||||
|     if (filename.size() == 0) { | ||||
|         LOG_ERROR(Loader, "invalid filename %s", filename.c_str()); | ||||
|         return FileType::Error; | ||||
|     } | ||||
| 
 | ||||
|     size_t extension_loc = filename.find_last_of('.'); | ||||
|     if (extension_loc == std::string::npos) | ||||
|         return FileType::Unknown; | ||||
|     std::string extension = Common::ToLower(filename.substr(extension_loc)); | ||||
| static FileType GuessFromExtension(const std::string& extension_) { | ||||
|     std::string extension = Common::ToLower(extension_); | ||||
| 
 | ||||
|     if (extension == ".elf") | ||||
|         return FileType::ELF; | ||||
|  | @ -100,8 +99,11 @@ ResultStatus LoadFile(const std::string& filename) { | |||
|         return ResultStatus::Error; | ||||
|     } | ||||
| 
 | ||||
|     std::string filename_filename, filename_extension; | ||||
|     Common::SplitPath(filename, nullptr, &filename_filename, &filename_extension); | ||||
| 
 | ||||
|     FileType type = IdentifyFile(*file); | ||||
|     FileType filename_type = GuessFromFilename(filename); | ||||
|     FileType filename_type = GuessFromExtension(filename_extension); | ||||
| 
 | ||||
|     if (type != filename_type) { | ||||
|         LOG_WARNING(Loader, "File %s has a different type than its extension.", filename.c_str()); | ||||
|  | @ -115,11 +117,11 @@ ResultStatus LoadFile(const std::string& filename) { | |||
| 
 | ||||
|     //3DSX file format...
 | ||||
|     case FileType::THREEDSX: | ||||
|         return AppLoader_THREEDSX(std::move(file)).Load(); | ||||
|         return AppLoader_THREEDSX(std::move(file), filename_filename).Load(); | ||||
| 
 | ||||
|     // Standard ELF file format...
 | ||||
|     case FileType::ELF: | ||||
|         return AppLoader_ELF(std::move(file)).Load(); | ||||
|         return AppLoader_ELF(std::move(file), filename_filename).Load(); | ||||
| 
 | ||||
|     // NCCH/NCSD container formats...
 | ||||
|     case FileType::CXI: | ||||
|  | @ -139,11 +141,14 @@ ResultStatus LoadFile(const std::string& filename) { | |||
|     // Raw BIN file format...
 | ||||
|     case FileType::BIN: | ||||
|     { | ||||
|         Kernel::g_current_process = Kernel::Process::Create(filename_filename, 0); | ||||
|         Kernel::g_current_process->static_address_mappings = default_address_mappings; | ||||
| 
 | ||||
|         size_t size = (size_t)file->GetSize(); | ||||
|         if (file->ReadBytes(Memory::GetPointer(Memory::EXEFS_CODE_VADDR), size) != size) | ||||
|             return ResultStatus::Error; | ||||
| 
 | ||||
|         Kernel::LoadExec(Memory::EXEFS_CODE_VADDR); | ||||
|         Kernel::g_current_process->Run(Memory::EXEFS_CODE_VADDR, 0x30, Kernel::DEFAULT_STACK_SIZE); | ||||
|         return ResultStatus::Success; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ | |||
| #include "common/common_types.h" | ||||
| #include "common/file_util.h" | ||||
| 
 | ||||
| #include "core/hle/kernel/process.h" | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Loader namespace
 | ||||
| 
 | ||||
|  | @ -104,6 +106,12 @@ protected: | |||
|     bool                              is_loaded = false; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * Common address mappings found in most games, used for binary formats that don't have this | ||||
|  * information. | ||||
|  */ | ||||
| extern const std::initializer_list<Kernel::StaticAddressMapping> default_address_mappings; | ||||
| 
 | ||||
| /**
 | ||||
|  * Identifies and loads a bootable file | ||||
|  * @param filename String filename of bootable file | ||||
|  |  | |||
|  | @ -5,9 +5,12 @@ | |||
| #include <memory> | ||||
| 
 | ||||
| #include "common/logging/log.h" | ||||
| #include "common/make_unique.h" | ||||
| #include "common/string_util.h" | ||||
| #include "common/swap.h" | ||||
| 
 | ||||
| #include "core/loader/ncch.h" | ||||
| #include "core/hle/kernel/kernel.h" | ||||
| #include "core/loader/ncch.h" | ||||
| #include "core/mem_map.h" | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|  | @ -117,8 +120,21 @@ ResultStatus AppLoader_NCCH::LoadExec() const { | |||
| 
 | ||||
|     std::vector<u8> code; | ||||
|     if (ResultStatus::Success == ReadCode(code)) { | ||||
|         std::string process_name = Common::StringFromFixedZeroTerminatedBuffer( | ||||
|                 (const char*)exheader_header.codeset_info.name, 8); | ||||
|         u64 program_id = *reinterpret_cast<u64_le const*>(&ncch_header.program_id[0]); | ||||
|         Kernel::g_current_process = Kernel::Process::Create(process_name, program_id); | ||||
| 
 | ||||
|         // Copy data while converting endianess
 | ||||
|         std::array<u32, ARRAY_SIZE(exheader_header.arm11_kernel_caps.descriptors)> kernel_caps; | ||||
|         std::copy_n(exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(), begin(kernel_caps)); | ||||
|         Kernel::g_current_process->ParseKernelCaps(kernel_caps.data(), kernel_caps.size()); | ||||
| 
 | ||||
|         Memory::WriteBlock(entry_point, &code[0], code.size()); | ||||
|         Kernel::LoadExec(entry_point); | ||||
| 
 | ||||
|         s32 priority = exheader_header.arm11_system_local_caps.priority; | ||||
|         u32 stack_size = exheader_header.codeset_info.stack_size; | ||||
|         Kernel::g_current_process->Run(entry_point, priority, stack_size); | ||||
|         return ResultStatus::Success; | ||||
|     } | ||||
|     return ResultStatus::Error; | ||||
|  |  | |||
|  | @ -6,7 +6,9 @@ | |||
| 
 | ||||
| #include <memory> | ||||
| 
 | ||||
| #include "common/bit_field.h" | ||||
| #include "common/common_types.h" | ||||
| #include "common/swap.h" | ||||
| 
 | ||||
| #include "core/loader/loader.h" | ||||
| 
 | ||||
|  | @ -109,7 +111,13 @@ struct ExHeader_StorageInfo{ | |||
| struct ExHeader_ARM11_SystemLocalCaps{ | ||||
|     u8 program_id[8]; | ||||
|     u32 core_version; | ||||
|     u8 flags[3]; | ||||
|     u8 reserved_flags[2]; | ||||
|     union { | ||||
|         u8 flags0; | ||||
|         BitField<0, 2, u8> ideal_processor; | ||||
|         BitField<2, 2, u8> affinity_mask; | ||||
|         BitField<4, 4, u8> system_mode; | ||||
|     }; | ||||
|     u8 priority; | ||||
|     u8 resource_limit_descriptor[0x10][2]; | ||||
|     ExHeader_StorageInfo storage_info; | ||||
|  | @ -120,7 +128,7 @@ struct ExHeader_ARM11_SystemLocalCaps{ | |||
| }; | ||||
| 
 | ||||
| struct ExHeader_ARM11_KernelCaps{ | ||||
|     u8 descriptors[28][4]; | ||||
|     u32_le descriptors[28]; | ||||
|     u8 reserved[0x10]; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue