mirror of
https://github.com/pound-emu/pound.git
synced 2025-12-23 07:36:58 +00:00
fix more of /fs, introduce core/hle and probably fix REM soon
This commit is contained in:
parent
3c780828b6
commit
549dd4f6f5
14 changed files with 1336 additions and 60 deletions
82
common/string_util.h
Executable file
82
common/string_util.h
Executable file
|
|
@ -0,0 +1,82 @@
|
||||||
|
// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project
|
||||||
|
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <span>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "common_types.h"
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
/// Make a string lowercase
|
||||||
|
[[nodiscard]] std::string ToLower(std::string str);
|
||||||
|
|
||||||
|
/// Make a string uppercase
|
||||||
|
[[nodiscard]] std::string ToUpper(std::string str);
|
||||||
|
|
||||||
|
[[nodiscard]] std::string StringFromBuffer(std::span<const u8> data);
|
||||||
|
[[nodiscard]] std::string StringFromBuffer(std::span<const char> data);
|
||||||
|
|
||||||
|
[[nodiscard]] std::string StripSpaces(const std::string& s);
|
||||||
|
[[nodiscard]] std::string StripQuotes(const std::string& s);
|
||||||
|
|
||||||
|
[[nodiscard]] std::string StringFromBool(bool value);
|
||||||
|
|
||||||
|
[[nodiscard]] std::string TabsToSpaces(int tab_size, std::string in);
|
||||||
|
|
||||||
|
void SplitString(const std::string& str, char delim, std::vector<std::string>& output);
|
||||||
|
|
||||||
|
// "C:/Windows/winhelp.exe" to "C:/Windows/", "winhelp", ".exe"
|
||||||
|
bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename,
|
||||||
|
std::string* _pExtension);
|
||||||
|
|
||||||
|
[[nodiscard]] std::string ReplaceAll(std::string result, const std::string& src,
|
||||||
|
const std::string& dest);
|
||||||
|
|
||||||
|
[[nodiscard]] std::string UTF16ToUTF8(std::u16string_view input);
|
||||||
|
[[nodiscard]] std::u16string UTF8ToUTF16(std::string_view input);
|
||||||
|
[[nodiscard]] std::u32string UTF8ToUTF32(std::string_view input);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
[[nodiscard]] std::string UTF16ToUTF8(std::wstring_view input);
|
||||||
|
[[nodiscard]] std::wstring UTF8ToUTF16W(std::string_view str);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[[nodiscard]] std::u16string U16StringFromBuffer(const u16* input, std::size_t length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares the string defined by the range [`begin`, `end`) to the null-terminated C-string
|
||||||
|
* `other` for equality.
|
||||||
|
*/
|
||||||
|
template <typename InIt>
|
||||||
|
[[nodiscard]] bool ComparePartialString(InIt begin, InIt end, const char* other) {
|
||||||
|
for (; begin != end && *other != '\0'; ++begin, ++other) {
|
||||||
|
if (*begin != *other) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Only return true if both strings finished at the same point
|
||||||
|
return (begin == end) == (*other == '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a std::string from a fixed-size NUL-terminated char buffer. If the buffer isn't
|
||||||
|
* NUL-terminated then the string ends at max_len characters.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] std::string StringFromFixedZeroTerminatedBuffer(std::string_view buffer,
|
||||||
|
std::size_t max_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a UTF-16 std::u16string from a fixed-size NUL-terminated char buffer. If the buffer isn't
|
||||||
|
* null-terminated, then the string ends at the greatest multiple of two less then or equal to
|
||||||
|
* max_len_bytes.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buffer,
|
||||||
|
std::size_t max_len);
|
||||||
|
|
||||||
|
} // namespace Common
|
||||||
131
common/uuid.h
Executable file
131
common/uuid.h
Executable file
|
|
@ -0,0 +1,131 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "common_types.h"
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
struct UUID {
|
||||||
|
std::array<u8, 0x10> uuid;
|
||||||
|
|
||||||
|
constexpr UUID() = default;
|
||||||
|
|
||||||
|
/// Constructs a UUID from a reference to a 128 bit array.
|
||||||
|
constexpr explicit UUID(const std::array<u8, 16>& uuid_) : uuid{uuid_} {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a UUID from either:
|
||||||
|
* 1. A 32 hexadecimal character string representing the bytes of the UUID
|
||||||
|
* 2. A RFC 4122 formatted UUID string, in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
|
*
|
||||||
|
* The input string may contain uppercase or lowercase characters, but they must:
|
||||||
|
* 1. Contain valid hexadecimal characters (0-9, a-f, A-F)
|
||||||
|
* 2. Not contain the "0x" hexadecimal prefix
|
||||||
|
*
|
||||||
|
* Should the input string not meet the above requirements,
|
||||||
|
* an assert will be triggered and an invalid UUID is set instead.
|
||||||
|
*/
|
||||||
|
explicit UUID(std::string_view uuid_string);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the stored UUID is valid or not.
|
||||||
|
*
|
||||||
|
* @returns True if the stored UUID is valid, false otherwise.
|
||||||
|
*/
|
||||||
|
constexpr bool IsValid() const {
|
||||||
|
return uuid != std::array<u8, 0x10>{};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the stored UUID is invalid or not.
|
||||||
|
*
|
||||||
|
* @returns True if the stored UUID is invalid, false otherwise.
|
||||||
|
*/
|
||||||
|
constexpr bool IsInvalid() const {
|
||||||
|
return !IsValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a 32 hexadecimal character string representing the bytes of the UUID.
|
||||||
|
*
|
||||||
|
* @returns A 32 hexadecimal character string of the UUID.
|
||||||
|
*/
|
||||||
|
std::string RawString() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a RFC 4122 formatted UUID string in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
|
||||||
|
*
|
||||||
|
* @returns A RFC 4122 formatted UUID string.
|
||||||
|
*/
|
||||||
|
std::string FormattedString() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a 64-bit hash of the UUID for use in hash table data structures.
|
||||||
|
*
|
||||||
|
* @returns A 64-bit hash of the UUID.
|
||||||
|
*/
|
||||||
|
size_t Hash() const noexcept;
|
||||||
|
|
||||||
|
/// DO NOT USE. Copies the contents of the UUID into a u128.
|
||||||
|
u128 AsU128() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a default UUID "yuzu Default UID".
|
||||||
|
*
|
||||||
|
* @returns A UUID with its bytes set to the ASCII values of "yuzu Default UID".
|
||||||
|
*/
|
||||||
|
static constexpr UUID MakeDefault() {
|
||||||
|
return UUID{
|
||||||
|
{'y', 'u', 'z', 'u', ' ', 'D', 'e', 'f', 'a', 'u', 'l', 't', ' ', 'U', 'I', 'D'},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a random UUID.
|
||||||
|
*
|
||||||
|
* @returns A random UUID.
|
||||||
|
*/
|
||||||
|
static UUID MakeRandom();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a random UUID with a seed.
|
||||||
|
*
|
||||||
|
* @param seed A seed to initialize the Mersenne-Twister RNG
|
||||||
|
*
|
||||||
|
* @returns A random UUID.
|
||||||
|
*/
|
||||||
|
static UUID MakeRandomWithSeed(u32 seed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a random UUID. The generated UUID is RFC 4122 Version 4 compliant.
|
||||||
|
*
|
||||||
|
* @returns A random UUID that is RFC 4122 Version 4 compliant.
|
||||||
|
*/
|
||||||
|
static UUID MakeRandomRFC4122V4();
|
||||||
|
|
||||||
|
friend constexpr bool operator==(const UUID& lhs, const UUID& rhs) = default;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(UUID) == 0x10, "UUID has incorrect size.");
|
||||||
|
static_assert(std::is_trivial_v<UUID>);
|
||||||
|
|
||||||
|
/// An invalid UUID. This UUID has all its bytes set to 0.
|
||||||
|
constexpr UUID InvalidUUID = {};
|
||||||
|
|
||||||
|
} // namespace Common
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct hash<Common::UUID> {
|
||||||
|
size_t operator()(const Common::UUID& uuid) const noexcept {
|
||||||
|
return uuid.Hash();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace std
|
||||||
471
core/core.h
Executable file
471
core/core.h
Executable file
|
|
@ -0,0 +1,471 @@
|
||||||
|
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <deque>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <span>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../common/common_types.h"
|
||||||
|
#include "../core/fs/vfs/vfs_types.h"
|
||||||
|
|
||||||
|
namespace Core::Frontend {
|
||||||
|
class EmuWindow;
|
||||||
|
} // namespace Core::Frontend
|
||||||
|
|
||||||
|
namespace FileSys {
|
||||||
|
class ContentProvider;
|
||||||
|
class ContentProviderUnion;
|
||||||
|
enum class ContentProviderUnionSlot;
|
||||||
|
class VfsFilesystem;
|
||||||
|
} // namespace FileSys
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
class GlobalSchedulerContext;
|
||||||
|
class KernelCore;
|
||||||
|
class PhysicalCore;
|
||||||
|
class KProcess;
|
||||||
|
class KScheduler;
|
||||||
|
} // namespace Kernel
|
||||||
|
|
||||||
|
namespace Loader {
|
||||||
|
class AppLoader;
|
||||||
|
enum class ResultStatus : u16;
|
||||||
|
} // namespace Loader
|
||||||
|
|
||||||
|
namespace Core::Memory {
|
||||||
|
struct CheatEntry;
|
||||||
|
class Memory;
|
||||||
|
} // namespace Core::Memory
|
||||||
|
|
||||||
|
namespace Service {
|
||||||
|
|
||||||
|
namespace Account {
|
||||||
|
class ProfileManager;
|
||||||
|
} // namespace Account
|
||||||
|
|
||||||
|
namespace AM {
|
||||||
|
struct FrontendAppletParameters;
|
||||||
|
class AppletManager;
|
||||||
|
} // namespace AM
|
||||||
|
|
||||||
|
namespace AM::Frontend {
|
||||||
|
struct FrontendAppletSet;
|
||||||
|
class FrontendAppletHolder;
|
||||||
|
} // namespace AM::Frontend
|
||||||
|
|
||||||
|
namespace APM {
|
||||||
|
class Controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace FileSystem {
|
||||||
|
class FileSystemController;
|
||||||
|
} // namespace FileSystem
|
||||||
|
|
||||||
|
namespace Glue {
|
||||||
|
class ARPManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ServerManager;
|
||||||
|
|
||||||
|
namespace SM {
|
||||||
|
class ServiceManager;
|
||||||
|
} // namespace SM
|
||||||
|
|
||||||
|
} // namespace Service
|
||||||
|
|
||||||
|
namespace Tegra {
|
||||||
|
class DebugContext;
|
||||||
|
class GPU;
|
||||||
|
namespace Host1x {
|
||||||
|
class Host1x;
|
||||||
|
} // namespace Host1x
|
||||||
|
} // namespace Tegra
|
||||||
|
|
||||||
|
namespace VideoCore {
|
||||||
|
class RendererBase;
|
||||||
|
} // namespace VideoCore
|
||||||
|
|
||||||
|
namespace AudioCore {
|
||||||
|
class AudioCore;
|
||||||
|
} // namespace AudioCore
|
||||||
|
|
||||||
|
namespace Core::Timing {
|
||||||
|
class CoreTiming;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Core::HID {
|
||||||
|
class HIDCore;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Network {
|
||||||
|
class RoomNetwork;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Tools {
|
||||||
|
class RenderdocAPI;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
|
||||||
|
class CpuManager;
|
||||||
|
class Debugger;
|
||||||
|
class DeviceMemory;
|
||||||
|
class ExclusiveMonitor;
|
||||||
|
class GPUDirtyMemoryManager;
|
||||||
|
class PerfStats;
|
||||||
|
class Reporter;
|
||||||
|
class SpeedLimiter;
|
||||||
|
class TelemetrySession;
|
||||||
|
|
||||||
|
struct PerfStatsResults;
|
||||||
|
|
||||||
|
FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
|
||||||
|
const std::string& path);
|
||||||
|
|
||||||
|
/// Enumeration representing the return values of the System Initialize and Load process.
|
||||||
|
enum class SystemResultStatus : u32 {
|
||||||
|
Success, ///< Succeeded
|
||||||
|
ErrorNotInitialized, ///< Error trying to use core prior to initialization
|
||||||
|
ErrorGetLoader, ///< Error finding the correct application loader
|
||||||
|
ErrorSystemFiles, ///< Error in finding system files
|
||||||
|
ErrorSharedFont, ///< Error in finding shared font
|
||||||
|
ErrorVideoCore, ///< Error in the video core
|
||||||
|
ErrorUnknown, ///< Any other error
|
||||||
|
ErrorLoader, ///< The base for loader errors (too many to repeat)
|
||||||
|
};
|
||||||
|
|
||||||
|
class System {
|
||||||
|
public:
|
||||||
|
using CurrentBuildProcessID = std::array<u8, 0x20>;
|
||||||
|
|
||||||
|
explicit System();
|
||||||
|
|
||||||
|
~System();
|
||||||
|
|
||||||
|
System(const System&) = delete;
|
||||||
|
System& operator=(const System&) = delete;
|
||||||
|
|
||||||
|
System(System&&) = delete;
|
||||||
|
System& operator=(System&&) = delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the system
|
||||||
|
* This function will initialize core functionality used for system emulation
|
||||||
|
*/
|
||||||
|
void Initialize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the OS and Application
|
||||||
|
* This function will start emulation and run the relevant devices
|
||||||
|
*/
|
||||||
|
void Run();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pause the OS and Application
|
||||||
|
* This function will pause emulation and stop the relevant devices
|
||||||
|
*/
|
||||||
|
void Pause();
|
||||||
|
|
||||||
|
/// Check if the core is currently paused.
|
||||||
|
[[nodiscard]] bool IsPaused() const;
|
||||||
|
|
||||||
|
/// Shutdown the main emulated process.
|
||||||
|
void ShutdownMainProcess();
|
||||||
|
|
||||||
|
/// Check if the core is shutting down.
|
||||||
|
[[nodiscard]] bool IsShuttingDown() const;
|
||||||
|
|
||||||
|
/// Set the shutting down state.
|
||||||
|
void SetShuttingDown(bool shutting_down);
|
||||||
|
|
||||||
|
/// Forcibly detach the debugger if it is running.
|
||||||
|
void DetachDebugger();
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> StallApplication();
|
||||||
|
void UnstallApplication();
|
||||||
|
|
||||||
|
void SetNVDECActive(bool is_nvdec_active);
|
||||||
|
[[nodiscard]] bool GetNVDECActive();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the debugger.
|
||||||
|
*/
|
||||||
|
void InitializeDebugger();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load an executable application.
|
||||||
|
* @param emu_window Reference to the host-system window used for video output and keyboard
|
||||||
|
* input.
|
||||||
|
* @param filepath String path to the executable application to load on the host file system.
|
||||||
|
* @param program_index Specifies the index within the container of the program to launch.
|
||||||
|
* @returns SystemResultStatus code, indicating if the operation succeeded.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] SystemResultStatus Load(Frontend::EmuWindow& emu_window,
|
||||||
|
const std::string& filepath,
|
||||||
|
Service::AM::FrontendAppletParameters& params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if the emulated system is powered on (all subsystems initialized and able to run an
|
||||||
|
* application).
|
||||||
|
* @returns True if the emulated system is powered on, otherwise false.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] bool IsPoweredOn() const;
|
||||||
|
|
||||||
|
/// Gets a reference to the telemetry session for this emulation session.
|
||||||
|
[[nodiscard]] Core::TelemetrySession& TelemetrySession();
|
||||||
|
|
||||||
|
/// Gets a reference to the telemetry session for this emulation session.
|
||||||
|
[[nodiscard]] const Core::TelemetrySession& TelemetrySession() const;
|
||||||
|
|
||||||
|
/// Prepare the core emulation for a reschedule
|
||||||
|
void PrepareReschedule(u32 core_index);
|
||||||
|
|
||||||
|
std::span<GPUDirtyMemoryManager> GetGPUDirtyMemoryManager();
|
||||||
|
|
||||||
|
void GatherGPUDirtyMemory(std::function<void(PAddr, size_t)>& callback);
|
||||||
|
|
||||||
|
[[nodiscard]] size_t GetCurrentHostThreadID() const;
|
||||||
|
|
||||||
|
/// Gets and resets core performance statistics
|
||||||
|
[[nodiscard]] PerfStatsResults GetAndResetPerfStats();
|
||||||
|
|
||||||
|
/// Gets the physical core for the CPU core that is currently running
|
||||||
|
[[nodiscard]] Kernel::PhysicalCore& CurrentPhysicalCore();
|
||||||
|
|
||||||
|
/// Gets the physical core for the CPU core that is currently running
|
||||||
|
[[nodiscard]] const Kernel::PhysicalCore& CurrentPhysicalCore() const;
|
||||||
|
|
||||||
|
/// Gets a reference to the underlying CPU manager.
|
||||||
|
[[nodiscard]] CpuManager& GetCpuManager();
|
||||||
|
|
||||||
|
/// Gets a const reference to the underlying CPU manager
|
||||||
|
[[nodiscard]] const CpuManager& GetCpuManager() const;
|
||||||
|
|
||||||
|
/// Gets a mutable reference to the system memory instance.
|
||||||
|
[[nodiscard]] Core::Memory::Memory& ApplicationMemory();
|
||||||
|
|
||||||
|
/// Gets a constant reference to the system memory instance.
|
||||||
|
[[nodiscard]] const Core::Memory::Memory& ApplicationMemory() const;
|
||||||
|
|
||||||
|
/// Gets a mutable reference to the GPU interface
|
||||||
|
[[nodiscard]] Tegra::GPU& GPU();
|
||||||
|
|
||||||
|
/// Gets an immutable reference to the GPU interface.
|
||||||
|
[[nodiscard]] const Tegra::GPU& GPU() const;
|
||||||
|
|
||||||
|
/// Gets a mutable reference to the Host1x interface
|
||||||
|
[[nodiscard]] Tegra::Host1x::Host1x& Host1x();
|
||||||
|
|
||||||
|
/// Gets an immutable reference to the Host1x interface.
|
||||||
|
[[nodiscard]] const Tegra::Host1x::Host1x& Host1x() const;
|
||||||
|
|
||||||
|
/// Gets a mutable reference to the renderer.
|
||||||
|
[[nodiscard]] VideoCore::RendererBase& Renderer();
|
||||||
|
|
||||||
|
/// Gets an immutable reference to the renderer.
|
||||||
|
[[nodiscard]] const VideoCore::RendererBase& Renderer() const;
|
||||||
|
|
||||||
|
/// Gets a mutable reference to the audio interface
|
||||||
|
[[nodiscard]] AudioCore::AudioCore& AudioCore();
|
||||||
|
|
||||||
|
/// Gets an immutable reference to the audio interface.
|
||||||
|
[[nodiscard]] const AudioCore::AudioCore& AudioCore() const;
|
||||||
|
|
||||||
|
/// Gets the global scheduler
|
||||||
|
[[nodiscard]] Kernel::GlobalSchedulerContext& GlobalSchedulerContext();
|
||||||
|
|
||||||
|
/// Gets the global scheduler
|
||||||
|
[[nodiscard]] const Kernel::GlobalSchedulerContext& GlobalSchedulerContext() const;
|
||||||
|
|
||||||
|
/// Gets the manager for the guest device memory
|
||||||
|
[[nodiscard]] Core::DeviceMemory& DeviceMemory();
|
||||||
|
|
||||||
|
/// Gets the manager for the guest device memory
|
||||||
|
[[nodiscard]] const Core::DeviceMemory& DeviceMemory() const;
|
||||||
|
|
||||||
|
/// Provides a pointer to the application process
|
||||||
|
[[nodiscard]] Kernel::KProcess* ApplicationProcess();
|
||||||
|
|
||||||
|
/// Provides a constant pointer to the application process.
|
||||||
|
[[nodiscard]] const Kernel::KProcess* ApplicationProcess() const;
|
||||||
|
|
||||||
|
/// Provides a reference to the core timing instance.
|
||||||
|
[[nodiscard]] Timing::CoreTiming& CoreTiming();
|
||||||
|
|
||||||
|
/// Provides a constant reference to the core timing instance.
|
||||||
|
[[nodiscard]] const Timing::CoreTiming& CoreTiming() const;
|
||||||
|
|
||||||
|
/// Provides a reference to the kernel instance.
|
||||||
|
[[nodiscard]] Kernel::KernelCore& Kernel();
|
||||||
|
|
||||||
|
/// Provides a constant reference to the kernel instance.
|
||||||
|
[[nodiscard]] const Kernel::KernelCore& Kernel() const;
|
||||||
|
|
||||||
|
/// Gets a mutable reference to the HID interface.
|
||||||
|
[[nodiscard]] HID::HIDCore& HIDCore();
|
||||||
|
|
||||||
|
/// Gets an immutable reference to the HID interface.
|
||||||
|
[[nodiscard]] const HID::HIDCore& HIDCore() const;
|
||||||
|
|
||||||
|
/// Provides a reference to the internal PerfStats instance.
|
||||||
|
[[nodiscard]] Core::PerfStats& GetPerfStats();
|
||||||
|
|
||||||
|
/// Provides a constant reference to the internal PerfStats instance.
|
||||||
|
[[nodiscard]] const Core::PerfStats& GetPerfStats() const;
|
||||||
|
|
||||||
|
/// Provides a reference to the speed limiter;
|
||||||
|
[[nodiscard]] Core::SpeedLimiter& SpeedLimiter();
|
||||||
|
|
||||||
|
/// Provides a constant reference to the speed limiter
|
||||||
|
[[nodiscard]] const Core::SpeedLimiter& SpeedLimiter() const;
|
||||||
|
|
||||||
|
[[nodiscard]] u64 GetApplicationProcessProgramID() const;
|
||||||
|
|
||||||
|
/// Gets the name of the current game
|
||||||
|
[[nodiscard]] Loader::ResultStatus GetGameName(std::string& out) const;
|
||||||
|
|
||||||
|
void SetStatus(SystemResultStatus new_status, const char* details);
|
||||||
|
|
||||||
|
[[nodiscard]] const std::string& GetStatusDetails() const;
|
||||||
|
|
||||||
|
[[nodiscard]] Loader::AppLoader& GetAppLoader();
|
||||||
|
[[nodiscard]] const Loader::AppLoader& GetAppLoader() const;
|
||||||
|
|
||||||
|
[[nodiscard]] Service::SM::ServiceManager& ServiceManager();
|
||||||
|
[[nodiscard]] const Service::SM::ServiceManager& ServiceManager() const;
|
||||||
|
|
||||||
|
void SetFilesystem(FileSys::VirtualFilesystem vfs);
|
||||||
|
|
||||||
|
[[nodiscard]] FileSys::VirtualFilesystem GetFilesystem() const;
|
||||||
|
|
||||||
|
void RegisterCheatList(const std::vector<Memory::CheatEntry>& list,
|
||||||
|
const std::array<u8, 0x20>& build_id, u64 main_region_begin,
|
||||||
|
u64 main_region_size);
|
||||||
|
|
||||||
|
void SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set);
|
||||||
|
|
||||||
|
[[nodiscard]] Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder();
|
||||||
|
[[nodiscard]] const Service::AM::Frontend::FrontendAppletHolder& GetFrontendAppletHolder()
|
||||||
|
const;
|
||||||
|
|
||||||
|
[[nodiscard]] Service::AM::AppletManager& GetAppletManager();
|
||||||
|
|
||||||
|
void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider);
|
||||||
|
|
||||||
|
[[nodiscard]] FileSys::ContentProvider& GetContentProvider();
|
||||||
|
[[nodiscard]] const FileSys::ContentProvider& GetContentProvider() const;
|
||||||
|
|
||||||
|
[[nodiscard]] FileSys::ContentProviderUnion& GetContentProviderUnion();
|
||||||
|
[[nodiscard]] const FileSys::ContentProviderUnion& GetContentProviderUnion() const;
|
||||||
|
|
||||||
|
[[nodiscard]] Service::FileSystem::FileSystemController& GetFileSystemController();
|
||||||
|
[[nodiscard]] const Service::FileSystem::FileSystemController& GetFileSystemController() const;
|
||||||
|
|
||||||
|
void RegisterContentProvider(FileSys::ContentProviderUnionSlot slot,
|
||||||
|
FileSys::ContentProvider* provider);
|
||||||
|
|
||||||
|
void ClearContentProvider(FileSys::ContentProviderUnionSlot slot);
|
||||||
|
|
||||||
|
[[nodiscard]] const Reporter& GetReporter() const;
|
||||||
|
|
||||||
|
[[nodiscard]] Service::Glue::ARPManager& GetARPManager();
|
||||||
|
[[nodiscard]] const Service::Glue::ARPManager& GetARPManager() const;
|
||||||
|
|
||||||
|
[[nodiscard]] Service::APM::Controller& GetAPMController();
|
||||||
|
[[nodiscard]] const Service::APM::Controller& GetAPMController() const;
|
||||||
|
|
||||||
|
[[nodiscard]] Service::Account::ProfileManager& GetProfileManager();
|
||||||
|
[[nodiscard]] const Service::Account::ProfileManager& GetProfileManager() const;
|
||||||
|
|
||||||
|
[[nodiscard]] Core::Debugger& GetDebugger();
|
||||||
|
[[nodiscard]] const Core::Debugger& GetDebugger() const;
|
||||||
|
|
||||||
|
/// Gets a mutable reference to the Room Network.
|
||||||
|
[[nodiscard]] Network::RoomNetwork& GetRoomNetwork();
|
||||||
|
|
||||||
|
/// Gets an immutable reference to the Room Network.
|
||||||
|
[[nodiscard]] const Network::RoomNetwork& GetRoomNetwork() const;
|
||||||
|
|
||||||
|
[[nodiscard]] Tools::RenderdocAPI& GetRenderdocAPI();
|
||||||
|
|
||||||
|
void SetExitLocked(bool locked);
|
||||||
|
bool GetExitLocked() const;
|
||||||
|
|
||||||
|
void SetExitRequested(bool requested);
|
||||||
|
bool GetExitRequested() const;
|
||||||
|
|
||||||
|
void SetApplicationProcessBuildID(const CurrentBuildProcessID& id);
|
||||||
|
[[nodiscard]] const CurrentBuildProcessID& GetApplicationProcessBuildID() const;
|
||||||
|
|
||||||
|
/// Register a host thread as an emulated CPU Core.
|
||||||
|
void RegisterCoreThread(std::size_t id);
|
||||||
|
|
||||||
|
/// Register a host thread as an auxiliary thread.
|
||||||
|
void RegisterHostThread();
|
||||||
|
|
||||||
|
/// Enter CPU Microprofile
|
||||||
|
void EnterCPUProfile();
|
||||||
|
|
||||||
|
/// Exit CPU Microprofile
|
||||||
|
void ExitCPUProfile();
|
||||||
|
|
||||||
|
/// Tells if system is running on multicore.
|
||||||
|
[[nodiscard]] bool IsMulticore() const;
|
||||||
|
|
||||||
|
/// Tells if the system debugger is enabled.
|
||||||
|
[[nodiscard]] bool DebuggerEnabled() const;
|
||||||
|
|
||||||
|
/// Runs a server instance until shutdown.
|
||||||
|
void RunServer(std::unique_ptr<Service::ServerManager>&& server_manager);
|
||||||
|
|
||||||
|
/// Type used for the frontend to designate a callback for System to re-launch the application
|
||||||
|
/// using a specified program index.
|
||||||
|
using ExecuteProgramCallback = std::function<void(std::size_t)>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a callback from the frontend for System to re-launch the application using a
|
||||||
|
* specified program index.
|
||||||
|
* @param callback Callback from the frontend to relaunch the application.
|
||||||
|
*/
|
||||||
|
void RegisterExecuteProgramCallback(ExecuteProgramCallback&& callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instructs the frontend to re-launch the application using the specified program_index.
|
||||||
|
* @param program_index Specifies the index within the application of the program to launch.
|
||||||
|
*/
|
||||||
|
void ExecuteProgram(std::size_t program_index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a reference to the user channel stack.
|
||||||
|
* It is used to transfer data between programs.
|
||||||
|
*/
|
||||||
|
[[nodiscard]] std::deque<std::vector<u8>>& GetUserChannel();
|
||||||
|
|
||||||
|
/// Type used for the frontend to designate a callback for System to exit the application.
|
||||||
|
using ExitCallback = std::function<void()>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a callback from the frontend for System to exit the application.
|
||||||
|
* @param callback Callback from the frontend to exit the application.
|
||||||
|
*/
|
||||||
|
void RegisterExitCallback(ExitCallback&& callback);
|
||||||
|
|
||||||
|
/// Instructs the frontend to exit the application.
|
||||||
|
void Exit();
|
||||||
|
|
||||||
|
/// Applies any changes to settings to this core instance.
|
||||||
|
void ApplySettings();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Impl;
|
||||||
|
std::unique_ptr<Impl> impl;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Core
|
||||||
24
core/crypto/xts_encryption_layer.h
Executable file
24
core/crypto/xts_encryption_layer.h
Executable file
|
|
@ -0,0 +1,24 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "aes_util.h"
|
||||||
|
#include "encryption_layer.h"
|
||||||
|
#include "key_manager.h"
|
||||||
|
|
||||||
|
namespace Core::Crypto {
|
||||||
|
|
||||||
|
// Sits on top of a VirtualFile and provides XTS-mode AES description.
|
||||||
|
class XTSEncryptionLayer : public EncryptionLayer {
|
||||||
|
public:
|
||||||
|
XTSEncryptionLayer(FileSys::VirtualFile base, Key256 key);
|
||||||
|
|
||||||
|
std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Must be mutable as operations modify cipher contexts.
|
||||||
|
mutable AESCipher<Key256> cipher;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Core::Crypto
|
||||||
|
|
@ -3,17 +3,17 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "../common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "../common/common_types.h"
|
||||||
#include "core/fs/fs_string_util.h"
|
#include "fs_string_util.h"
|
||||||
#include "common/swap.h"
|
#include "../common/swap.h"
|
||||||
#include "core/fs/fsmitm_romfsbuild.h"
|
#include "fsmitm_romfsbuild.h"
|
||||||
#include "core/fs/romfs.h"
|
#include "romfs.h"
|
||||||
#include "core/fs/vfs/vfs.h"
|
#include "../core/fs/vfs/vfs.h"
|
||||||
#include "core/fs/vfs/vfs_cached.h"
|
#include "../core/fs/vfs/vfs_cached.h"
|
||||||
#include "core/fs/vfs/vfs_concat.h"
|
#include "../core/fs/vfs/vfs_concat.h"
|
||||||
#include "core/fs/vfs/vfs_offset.h"
|
#include "../core/fs/vfs/vfs_offset.h"
|
||||||
#include "core/fs/vfs/vfs_vector.h"
|
#include "../core/fs/vfs/vfs_vector.h"
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/fs/vfs/vfs.h"
|
#include "../core/fs/vfs/vfs.h"
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,18 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "common/assert.h"
|
#include "../common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "../common/common_types.h"
|
||||||
#include "common/logging/log.h"
|
#include "../common/logging/log.h"
|
||||||
#include "core/file_sys/common_funcs.h"
|
#include "../common_funcs.h"
|
||||||
#include "core/file_sys/content_archive.h"
|
#include "../content_archive.h"
|
||||||
#include "core/file_sys/nca_metadata.h"
|
#include "nca_metadata.h"
|
||||||
#include "core/file_sys/patch_manager.h"
|
#include "patch_manager.h"
|
||||||
#include "core/file_sys/registered_cache.h"
|
#include "registered_cache.h"
|
||||||
#include "core/file_sys/romfs_factory.h"
|
#include "romfs_factory.h"
|
||||||
#include "core/hle/kernel/k_process.h"
|
#include "../core/hle/kernel/k_process.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "../core/hle/service/filesystem/filesystem.h"
|
||||||
#include "core/loader/loader.h"
|
#include "../core/loader/loader.h"
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "../common/common_types.h"
|
||||||
#include "core/file_sys/vfs/vfs_types.h"
|
#include "../core/fs/vfs/vfs_types.h"
|
||||||
#include "core/hle/result.h"
|
#include "../core/hle/result.h"
|
||||||
|
|
||||||
namespace Loader {
|
namespace Loader {
|
||||||
class AppLoader;
|
class AppLoader;
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "common/assert.h"
|
#include "../common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "../common/common_types.h"
|
||||||
#include "common/logging/log.h"
|
#include "../common/logging/log.h"
|
||||||
#include "common/uuid.h"
|
#include "../common/uuid.h"
|
||||||
#include "core/core.h"
|
#include "../core/core.h"
|
||||||
#include "core/file_sys/savedata_factory.h"
|
#include "savedata_factory.h"
|
||||||
#include "core/file_sys/vfs/vfs.h"
|
#include "../core/fs/vfs/vfs.h"
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/file_sys/fs_save_data_types.h"
|
#include "fs_save_data_types.h"
|
||||||
#include "core/file_sys/vfs/vfs.h"
|
#include "../core/fs/vfs/vfs.h"
|
||||||
#include "core/hle/result.h"
|
#include "../core/hle/result.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,15 @@
|
||||||
|
|
||||||
#include <fmt/ostream.h>
|
#include <fmt/ostream.h>
|
||||||
|
|
||||||
#include "common/hex_util.h"
|
#include "../common/hex_util.h"
|
||||||
#include "common/logging/log.h"
|
#include "../common/logging/log.h"
|
||||||
#include "core/crypto/key_manager.h"
|
#include "../core/crypto/key_manager.h"
|
||||||
#include "core/file_sys/content_archive.h"
|
#include "content_archive.h"
|
||||||
#include "core/file_sys/nca_metadata.h"
|
#include "nca_metadata.h"
|
||||||
#include "core/file_sys/partition_filesystem.h"
|
#include "partition_filesystem.h"
|
||||||
#include "core/file_sys/program_metadata.h"
|
#include "program_metadata.h"
|
||||||
#include "core/file_sys/submission_package.h"
|
#include "submission_package.h"
|
||||||
#include "core/loader/loader.h"
|
#include "../core/loader/loader.h"
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,16 +10,16 @@
|
||||||
#include <mbedtls/md.h>
|
#include <mbedtls/md.h>
|
||||||
#include <mbedtls/sha256.h>
|
#include <mbedtls/sha256.h>
|
||||||
|
|
||||||
#include "common/fs/path_util.h"
|
#include "../common/fs/path_util.h"
|
||||||
#include "common/hex_util.h"
|
#include "../common/hex_util.h"
|
||||||
#include "common/string_util.h"
|
#include "../common/string_util.h"
|
||||||
#include "core/crypto/aes_util.h"
|
#include "../core/crypto/aes_util.h"
|
||||||
#include "core/crypto/key_manager.h"
|
#include "../core/crypto/key_manager.h"
|
||||||
#include "core/crypto/xts_encryption_layer.h"
|
#include "../core/crypto/xts_encryption_layer.h"
|
||||||
#include "core/file_sys/content_archive.h"
|
#include "content_archive.h"
|
||||||
#include "core/file_sys/vfs/vfs_offset.h"
|
#include "../core/fs/vfs/vfs_offset.h"
|
||||||
#include "core/file_sys/xts_archive.h"
|
#include "xts_archive.h"
|
||||||
#include "core/loader/loader.h"
|
#include "../core/loader/loader.h"
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "common/common_types.h"
|
#include "../common/common_types.h"
|
||||||
#include "common/swap.h"
|
#include "../common/swap.h"
|
||||||
#include "core/crypto/key_manager.h"
|
#include "../core/crypto/key_manager.h"
|
||||||
#include "core/file_sys/vfs/vfs.h"
|
#include "../core/fs/vfs/vfs.h"
|
||||||
|
|
||||||
namespace Loader {
|
namespace Loader {
|
||||||
enum class ResultStatus : u16;
|
enum class ResultStatus : u16;
|
||||||
|
|
|
||||||
568
core/hle/kernel/k_process.h
Executable file
568
core/hle/kernel/k_process.h
Executable file
|
|
@ -0,0 +1,568 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
// #include "core/arm/arm_interface.h" (will make REM do this soon)
|
||||||
|
// #include <rem/src/assembly/aarch64/aarch64_interface.h> (wip)
|
||||||
|
#include "../core/fs/program_metadata.h"
|
||||||
|
#include "../core/hle/kernel/code_set.h"
|
||||||
|
#include "../core/hle/kernel/k_address_arbiter.h"
|
||||||
|
#include "../core/hle/kernel/k_capabilities.h"
|
||||||
|
#include "../core/hle/kernel/k_condition_variable.h"
|
||||||
|
#include "../core/hle/kernel/k_handle_table.h"
|
||||||
|
#include "../core/hle/kernel/k_page_table_manager.h"
|
||||||
|
#include "../core/hle/kernel/k_process_page_table.h"
|
||||||
|
#include "../core/hle/kernel/k_system_resource.h"
|
||||||
|
#include "../core/hle/kernel/k_thread.h"
|
||||||
|
#include "../core/hle/kernel/k_thread_local_page.h"
|
||||||
|
#include "../core/memory.h"
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
|
||||||
|
enum class DebugWatchpointType : u8 {
|
||||||
|
None = 0,
|
||||||
|
Read = 1 << 0,
|
||||||
|
Write = 1 << 1,
|
||||||
|
ReadOrWrite = Read | Write,
|
||||||
|
};
|
||||||
|
DECLARE_ENUM_FLAG_OPERATORS(DebugWatchpointType);
|
||||||
|
|
||||||
|
struct DebugWatchpoint {
|
||||||
|
KProcessAddress start_address;
|
||||||
|
KProcessAddress end_address;
|
||||||
|
DebugWatchpointType type;
|
||||||
|
};
|
||||||
|
|
||||||
|
class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> {
|
||||||
|
KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject);
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum class State {
|
||||||
|
Created = static_cast<u32>(Svc::ProcessState::Created),
|
||||||
|
CreatedAttached = static_cast<u32>(Svc::ProcessState::CreatedAttached),
|
||||||
|
Running = static_cast<u32>(Svc::ProcessState::Running),
|
||||||
|
Crashed = static_cast<u32>(Svc::ProcessState::Crashed),
|
||||||
|
RunningAttached = static_cast<u32>(Svc::ProcessState::RunningAttached),
|
||||||
|
Terminating = static_cast<u32>(Svc::ProcessState::Terminating),
|
||||||
|
Terminated = static_cast<u32>(Svc::ProcessState::Terminated),
|
||||||
|
DebugBreak = static_cast<u32>(Svc::ProcessState::DebugBreak),
|
||||||
|
};
|
||||||
|
|
||||||
|
using ThreadList = Common::IntrusiveListMemberTraits<&KThread::m_process_list_node>::ListType;
|
||||||
|
|
||||||
|
static constexpr size_t AslrAlignment = 2_MiB;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr u64 InitialProcessIdMin = 1;
|
||||||
|
static constexpr u64 InitialProcessIdMax = 0x50;
|
||||||
|
|
||||||
|
static constexpr u64 ProcessIdMin = InitialProcessIdMax + 1;
|
||||||
|
static constexpr u64 ProcessIdMax = std::numeric_limits<u64>::max();
|
||||||
|
|
||||||
|
private:
|
||||||
|
using SharedMemoryInfoList = Common::IntrusiveListBaseTraits<KSharedMemoryInfo>::ListType;
|
||||||
|
using TLPTree =
|
||||||
|
Common::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>;
|
||||||
|
using TLPIterator = TLPTree::iterator;
|
||||||
|
|
||||||
|
private:
|
||||||
|
KProcessPageTable m_page_table;
|
||||||
|
std::atomic<size_t> m_used_kernel_memory_size{};
|
||||||
|
TLPTree m_fully_used_tlp_tree{};
|
||||||
|
TLPTree m_partially_used_tlp_tree{};
|
||||||
|
s32 m_ideal_core_id{};
|
||||||
|
KResourceLimit* m_resource_limit{};
|
||||||
|
KSystemResource* m_system_resource{};
|
||||||
|
size_t m_memory_release_hint{};
|
||||||
|
State m_state{};
|
||||||
|
KLightLock m_state_lock;
|
||||||
|
KLightLock m_list_lock;
|
||||||
|
KConditionVariable m_cond_var;
|
||||||
|
KAddressArbiter m_address_arbiter;
|
||||||
|
std::array<u64, 4> m_entropy{};
|
||||||
|
bool m_is_signaled{};
|
||||||
|
bool m_is_initialized{};
|
||||||
|
bool m_is_application{};
|
||||||
|
bool m_is_default_application_system_resource{};
|
||||||
|
bool m_is_hbl{};
|
||||||
|
std::array<char, 13> m_name{};
|
||||||
|
std::atomic<u16> m_num_running_threads{};
|
||||||
|
Svc::CreateProcessFlag m_flags{};
|
||||||
|
KMemoryManager::Pool m_memory_pool{};
|
||||||
|
s64 m_schedule_count{};
|
||||||
|
KCapabilities m_capabilities{};
|
||||||
|
u64 m_program_id{};
|
||||||
|
u64 m_process_id{};
|
||||||
|
KProcessAddress m_code_address{};
|
||||||
|
size_t m_code_size{};
|
||||||
|
size_t m_main_thread_stack_size{};
|
||||||
|
size_t m_max_process_memory{};
|
||||||
|
u32 m_version{};
|
||||||
|
KHandleTable m_handle_table;
|
||||||
|
KProcessAddress m_plr_address{};
|
||||||
|
KThread* m_exception_thread{};
|
||||||
|
ThreadList m_thread_list{};
|
||||||
|
SharedMemoryInfoList m_shared_memory_list{};
|
||||||
|
bool m_is_suspended{};
|
||||||
|
bool m_is_immortal{};
|
||||||
|
bool m_is_handle_table_initialized{};
|
||||||
|
std::array<std::unique_ptr<Core::ArmInterface>, Core::Hardware::NUM_CPU_CORES>
|
||||||
|
m_arm_interfaces{};
|
||||||
|
std::array<KThread*, Core::Hardware::NUM_CPU_CORES> m_running_threads{};
|
||||||
|
std::array<u64, Core::Hardware::NUM_CPU_CORES> m_running_thread_idle_counts{};
|
||||||
|
std::array<u64, Core::Hardware::NUM_CPU_CORES> m_running_thread_switch_counts{};
|
||||||
|
std::array<KThread*, Core::Hardware::NUM_CPU_CORES> m_pinned_threads{};
|
||||||
|
std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS> m_watchpoints{};
|
||||||
|
std::map<KProcessAddress, u64> m_debug_page_refcounts{};
|
||||||
|
std::atomic<s64> m_cpu_time{};
|
||||||
|
std::atomic<s64> m_num_process_switches{};
|
||||||
|
std::atomic<s64> m_num_thread_switches{};
|
||||||
|
std::atomic<s64> m_num_fpu_switches{};
|
||||||
|
std::atomic<s64> m_num_supervisor_calls{};
|
||||||
|
std::atomic<s64> m_num_ipc_messages{};
|
||||||
|
std::atomic<s64> m_num_ipc_replies{};
|
||||||
|
std::atomic<s64> m_num_ipc_receives{};
|
||||||
|
#ifdef HAS_NCE
|
||||||
|
std::unordered_map<u64, u64> m_post_handlers{};
|
||||||
|
#endif
|
||||||
|
std::unique_ptr<Core::ExclusiveMonitor> m_exclusive_monitor;
|
||||||
|
Core::Memory::Memory m_memory;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result StartTermination();
|
||||||
|
void FinishTermination();
|
||||||
|
|
||||||
|
void PinThread(s32 core_id, KThread* thread) {
|
||||||
|
ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES));
|
||||||
|
ASSERT(thread != nullptr);
|
||||||
|
ASSERT(m_pinned_threads[core_id] == nullptr);
|
||||||
|
m_pinned_threads[core_id] = thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnpinThread(s32 core_id, KThread* thread) {
|
||||||
|
ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES));
|
||||||
|
ASSERT(thread != nullptr);
|
||||||
|
ASSERT(m_pinned_threads[core_id] == thread);
|
||||||
|
m_pinned_threads[core_id] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit KProcess(KernelCore& kernel);
|
||||||
|
~KProcess() override;
|
||||||
|
|
||||||
|
Result Initialize(const Svc::CreateProcessParameter& params, KResourceLimit* res_limit,
|
||||||
|
bool is_real);
|
||||||
|
|
||||||
|
Result Initialize(const Svc::CreateProcessParameter& params, const KPageGroup& pg,
|
||||||
|
std::span<const u32> caps, KResourceLimit* res_limit,
|
||||||
|
KMemoryManager::Pool pool, bool immortal);
|
||||||
|
Result Initialize(const Svc::CreateProcessParameter& params, std::span<const u32> user_caps,
|
||||||
|
KResourceLimit* res_limit, KMemoryManager::Pool pool,
|
||||||
|
KProcessAddress aslr_space_start);
|
||||||
|
void Exit();
|
||||||
|
|
||||||
|
const char* GetName() const {
|
||||||
|
return m_name.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 GetProgramId() const {
|
||||||
|
return m_program_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 GetProcessId() const {
|
||||||
|
return m_process_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
State GetState() const {
|
||||||
|
return m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 GetCoreMask() const {
|
||||||
|
return m_capabilities.GetCoreMask();
|
||||||
|
}
|
||||||
|
u64 GetPhysicalCoreMask() const {
|
||||||
|
return m_capabilities.GetPhysicalCoreMask();
|
||||||
|
}
|
||||||
|
u64 GetPriorityMask() const {
|
||||||
|
return m_capabilities.GetPriorityMask();
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 GetIdealCoreId() const {
|
||||||
|
return m_ideal_core_id;
|
||||||
|
}
|
||||||
|
void SetIdealCoreId(s32 core_id) {
|
||||||
|
m_ideal_core_id = core_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckThreadPriority(s32 prio) const {
|
||||||
|
return ((1ULL << prio) & this->GetPriorityMask()) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GetCreateProcessFlags() const {
|
||||||
|
return static_cast<u32>(m_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Is64Bit() const {
|
||||||
|
return True(m_flags & Svc::CreateProcessFlag::Is64Bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
KProcessAddress GetEntryPoint() const {
|
||||||
|
return m_code_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetMainStackSize() const {
|
||||||
|
return m_main_thread_stack_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
KMemoryManager::Pool GetMemoryPool() const {
|
||||||
|
return m_memory_pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 GetRandomEntropy(size_t i) const {
|
||||||
|
return m_entropy[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsApplication() const {
|
||||||
|
return m_is_application;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsDefaultApplicationSystemResource() const {
|
||||||
|
return m_is_default_application_system_resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsSuspended() const {
|
||||||
|
return m_is_suspended;
|
||||||
|
}
|
||||||
|
void SetSuspended(bool suspended) {
|
||||||
|
m_is_suspended = suspended;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result Terminate();
|
||||||
|
|
||||||
|
bool IsTerminated() const {
|
||||||
|
return m_state == State::Terminated;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsPermittedSvc(u32 svc_id) const {
|
||||||
|
return m_capabilities.IsPermittedSvc(svc_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsPermittedInterrupt(s32 interrupt_id) const {
|
||||||
|
return m_capabilities.IsPermittedInterrupt(interrupt_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsPermittedDebug() const {
|
||||||
|
return m_capabilities.IsPermittedDebug();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CanForceDebug() const {
|
||||||
|
return m_capabilities.CanForceDebug();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsHbl() const {
|
||||||
|
return m_is_hbl;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GetAllocateOption() const {
|
||||||
|
return m_page_table.GetAllocateOption();
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadList& GetThreadList() {
|
||||||
|
return m_thread_list;
|
||||||
|
}
|
||||||
|
const ThreadList& GetThreadList() const {
|
||||||
|
return m_thread_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EnterUserException();
|
||||||
|
bool LeaveUserException();
|
||||||
|
bool ReleaseUserException(KThread* thread);
|
||||||
|
|
||||||
|
KThread* GetPinnedThread(s32 core_id) const {
|
||||||
|
ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES));
|
||||||
|
return m_pinned_threads[core_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
const Svc::SvcAccessFlagSet& GetSvcPermissions() const {
|
||||||
|
return m_capabilities.GetSvcPermissions();
|
||||||
|
}
|
||||||
|
|
||||||
|
KResourceLimit* GetResourceLimit() const {
|
||||||
|
return m_resource_limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReserveResource(Svc::LimitableResource which, s64 value);
|
||||||
|
bool ReserveResource(Svc::LimitableResource which, s64 value, s64 timeout);
|
||||||
|
void ReleaseResource(Svc::LimitableResource which, s64 value);
|
||||||
|
void ReleaseResource(Svc::LimitableResource which, s64 value, s64 hint);
|
||||||
|
|
||||||
|
KLightLock& GetStateLock() {
|
||||||
|
return m_state_lock;
|
||||||
|
}
|
||||||
|
KLightLock& GetListLock() {
|
||||||
|
return m_list_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
KProcessPageTable& GetPageTable() {
|
||||||
|
return m_page_table;
|
||||||
|
}
|
||||||
|
const KProcessPageTable& GetPageTable() const {
|
||||||
|
return m_page_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
KHandleTable& GetHandleTable() {
|
||||||
|
return m_handle_table;
|
||||||
|
}
|
||||||
|
const KHandleTable& GetHandleTable() const {
|
||||||
|
return m_handle_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetUsedUserPhysicalMemorySize() const;
|
||||||
|
size_t GetTotalUserPhysicalMemorySize() const;
|
||||||
|
size_t GetUsedNonSystemUserPhysicalMemorySize() const;
|
||||||
|
size_t GetTotalNonSystemUserPhysicalMemorySize() const;
|
||||||
|
|
||||||
|
Result AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size);
|
||||||
|
void RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size);
|
||||||
|
|
||||||
|
Result CreateThreadLocalRegion(KProcessAddress* out);
|
||||||
|
Result DeleteThreadLocalRegion(KProcessAddress addr);
|
||||||
|
|
||||||
|
KProcessAddress GetProcessLocalRegionAddress() const {
|
||||||
|
return m_plr_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
KThread* GetExceptionThread() const {
|
||||||
|
return m_exception_thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddCpuTime(s64 diff) {
|
||||||
|
m_cpu_time += diff;
|
||||||
|
}
|
||||||
|
s64 GetCpuTime() {
|
||||||
|
return m_cpu_time.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 GetScheduledCount() const {
|
||||||
|
return m_schedule_count;
|
||||||
|
}
|
||||||
|
void IncrementScheduledCount() {
|
||||||
|
++m_schedule_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IncrementRunningThreadCount();
|
||||||
|
void DecrementRunningThreadCount();
|
||||||
|
|
||||||
|
size_t GetRequiredSecureMemorySizeNonDefault() const {
|
||||||
|
if (!this->IsDefaultApplicationSystemResource() && m_system_resource->IsSecureResource()) {
|
||||||
|
auto* secure_system_resource = static_cast<KSecureSystemResource*>(m_system_resource);
|
||||||
|
return secure_system_resource->CalculateRequiredSecureMemorySize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetRequiredSecureMemorySize() const {
|
||||||
|
if (m_system_resource->IsSecureResource()) {
|
||||||
|
auto* secure_system_resource = static_cast<KSecureSystemResource*>(m_system_resource);
|
||||||
|
return secure_system_resource->CalculateRequiredSecureMemorySize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetTotalSystemResourceSize() const {
|
||||||
|
if (!this->IsDefaultApplicationSystemResource() && m_system_resource->IsSecureResource()) {
|
||||||
|
auto* secure_system_resource = static_cast<KSecureSystemResource*>(m_system_resource);
|
||||||
|
return secure_system_resource->GetSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t GetUsedSystemResourceSize() const {
|
||||||
|
if (!this->IsDefaultApplicationSystemResource() && m_system_resource->IsSecureResource()) {
|
||||||
|
auto* secure_system_resource = static_cast<KSecureSystemResource*>(m_system_resource);
|
||||||
|
return secure_system_resource->GetUsedSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetRunningThread(s32 core, KThread* thread, u64 idle_count, u64 switch_count) {
|
||||||
|
m_running_threads[core] = thread;
|
||||||
|
m_running_thread_idle_counts[core] = idle_count;
|
||||||
|
m_running_thread_switch_counts[core] = switch_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearRunningThread(KThread* thread) {
|
||||||
|
for (size_t i = 0; i < m_running_threads.size(); ++i) {
|
||||||
|
if (m_running_threads[i] == thread) {
|
||||||
|
m_running_threads[i] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const KSystemResource& GetSystemResource() const {
|
||||||
|
return *m_system_resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
const KMemoryBlockSlabManager& GetMemoryBlockSlabManager() const {
|
||||||
|
return m_system_resource->GetMemoryBlockSlabManager();
|
||||||
|
}
|
||||||
|
const KBlockInfoManager& GetBlockInfoManager() const {
|
||||||
|
return m_system_resource->GetBlockInfoManager();
|
||||||
|
}
|
||||||
|
const KPageTableManager& GetPageTableManager() const {
|
||||||
|
return m_system_resource->GetPageTableManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
KThread* GetRunningThread(s32 core) const {
|
||||||
|
return m_running_threads[core];
|
||||||
|
}
|
||||||
|
u64 GetRunningThreadIdleCount(s32 core) const {
|
||||||
|
return m_running_thread_idle_counts[core];
|
||||||
|
}
|
||||||
|
u64 GetRunningThreadSwitchCount(s32 core) const {
|
||||||
|
return m_running_thread_switch_counts[core];
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterThread(KThread* thread);
|
||||||
|
void UnregisterThread(KThread* thread);
|
||||||
|
|
||||||
|
Result Run(s32 priority, size_t stack_size);
|
||||||
|
|
||||||
|
Result Reset();
|
||||||
|
|
||||||
|
void SetDebugBreak() {
|
||||||
|
if (m_state == State::RunningAttached) {
|
||||||
|
this->ChangeState(State::DebugBreak);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetAttached() {
|
||||||
|
if (m_state == State::DebugBreak) {
|
||||||
|
this->ChangeState(State::RunningAttached);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetActivity(Svc::ProcessActivity activity);
|
||||||
|
|
||||||
|
void PinCurrentThread();
|
||||||
|
void UnpinCurrentThread();
|
||||||
|
void UnpinThread(KThread* thread);
|
||||||
|
|
||||||
|
void SignalConditionVariable(uintptr_t cv_key, int32_t count) {
|
||||||
|
return m_cond_var.Signal(cv_key, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result WaitConditionVariable(KProcessAddress address, uintptr_t cv_key, u32 tag, s64 ns) {
|
||||||
|
R_RETURN(m_cond_var.Wait(address, cv_key, tag, ns));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SignalAddressArbiter(uintptr_t address, Svc::SignalType signal_type, s32 value,
|
||||||
|
s32 count) {
|
||||||
|
R_RETURN(m_address_arbiter.SignalToAddress(address, signal_type, value, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result WaitAddressArbiter(uintptr_t address, Svc::ArbitrationType arb_type, s32 value,
|
||||||
|
s64 timeout) {
|
||||||
|
R_RETURN(m_address_arbiter.WaitForAddress(address, arb_type, value, timeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ids, s32 max_out_count);
|
||||||
|
|
||||||
|
static void Switch(KProcess* cur_process, KProcess* next_process);
|
||||||
|
|
||||||
|
#ifdef HAS_NCE
|
||||||
|
std::unordered_map<u64, u64>& GetPostHandlers() noexcept {
|
||||||
|
return m_post_handlers;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Core::ArmInterface* GetArmInterface(size_t core_index) const {
|
||||||
|
return m_arm_interfaces[core_index].get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Attempts to insert a watchpoint into a free slot. Returns false if none are available.
|
||||||
|
bool InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type);
|
||||||
|
|
||||||
|
// Attempts to remove the watchpoint specified by the given parameters.
|
||||||
|
bool RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type);
|
||||||
|
|
||||||
|
const std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>& GetWatchpoints() const {
|
||||||
|
return m_watchpoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size,
|
||||||
|
KProcessAddress aslr_space_start, bool is_hbl);
|
||||||
|
|
||||||
|
void LoadModule(CodeSet code_set, KProcessAddress base_addr);
|
||||||
|
|
||||||
|
void InitializeInterfaces();
|
||||||
|
|
||||||
|
Core::Memory::Memory& GetMemory() {
|
||||||
|
return m_memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
Core::ExclusiveMonitor& GetExclusiveMonitor() const {
|
||||||
|
return *m_exclusive_monitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Overridden parent functions.
|
||||||
|
bool IsInitialized() const override {
|
||||||
|
return m_is_initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PostDestroy(uintptr_t arg) {}
|
||||||
|
|
||||||
|
void Finalize() override;
|
||||||
|
|
||||||
|
u64 GetIdImpl() const {
|
||||||
|
return this->GetProcessId();
|
||||||
|
}
|
||||||
|
u64 GetId() const override {
|
||||||
|
return this->GetIdImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool IsSignaled() const override {
|
||||||
|
ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel));
|
||||||
|
return m_is_signaled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoWorkerTaskImpl();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ChangeState(State new_state) {
|
||||||
|
if (m_state != new_state) {
|
||||||
|
m_state = new_state;
|
||||||
|
m_is_signaled = true;
|
||||||
|
this->NotifyAvailable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result InitializeHandleTable(s32 size) {
|
||||||
|
// Try to initialize the handle table.
|
||||||
|
R_TRY(m_handle_table.Initialize(size));
|
||||||
|
|
||||||
|
// We succeeded, so note that we did.
|
||||||
|
m_is_handle_table_initialized = true;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FinalizeHandleTable() {
|
||||||
|
// Finalize the table.
|
||||||
|
m_handle_table.Finalize();
|
||||||
|
|
||||||
|
// Note that the table is finalized.
|
||||||
|
m_is_handle_table_initialized = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Kernel
|
||||||
Loading…
Add table
Add a link
Reference in a new issue