mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	Merge pull request #1593 from lioncash/svc
svc: Implement svcGetInfo command 0xF0000002
This commit is contained in:
		
						commit
						2239d47112
					
				@ -202,6 +202,16 @@ public:
 | 
				
			|||||||
        return is_64bit_process;
 | 
					        return is_64bit_process;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Gets the total running time of the process instance in ticks.
 | 
				
			||||||
 | 
					    u64 GetCPUTimeTicks() const {
 | 
				
			||||||
 | 
					        return total_process_running_time_ticks;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Updates the total running time, adding the given ticks to it.
 | 
				
			||||||
 | 
					    void UpdateCPUTimeTicks(u64 ticks) {
 | 
				
			||||||
 | 
					        total_process_running_time_ticks += ticks;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Loads process-specifics configuration info with metadata provided
 | 
					     * Loads process-specifics configuration info with metadata provided
 | 
				
			||||||
     * by an executable.
 | 
					     * by an executable.
 | 
				
			||||||
@ -305,6 +315,9 @@ private:
 | 
				
			|||||||
    /// specified by metadata provided to the process during loading.
 | 
					    /// specified by metadata provided to the process during loading.
 | 
				
			||||||
    bool is_64bit_process = true;
 | 
					    bool is_64bit_process = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Total running time for the process in ticks.
 | 
				
			||||||
 | 
					    u64 total_process_running_time_ticks = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Per-process handle table for storing created object handles in.
 | 
					    /// Per-process handle table for storing created object handles in.
 | 
				
			||||||
    HandleTable handle_table;
 | 
					    HandleTable handle_table;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@
 | 
				
			|||||||
#include "common/logging/log.h"
 | 
					#include "common/logging/log.h"
 | 
				
			||||||
#include "core/arm/arm_interface.h"
 | 
					#include "core/arm/arm_interface.h"
 | 
				
			||||||
#include "core/core.h"
 | 
					#include "core/core.h"
 | 
				
			||||||
 | 
					#include "core/core_timing.h"
 | 
				
			||||||
#include "core/hle/kernel/kernel.h"
 | 
					#include "core/hle/kernel/kernel.h"
 | 
				
			||||||
#include "core/hle/kernel/process.h"
 | 
					#include "core/hle/kernel/process.h"
 | 
				
			||||||
#include "core/hle/kernel/scheduler.h"
 | 
					#include "core/hle/kernel/scheduler.h"
 | 
				
			||||||
@ -34,6 +35,10 @@ Thread* Scheduler::GetCurrentThread() const {
 | 
				
			|||||||
    return current_thread.get();
 | 
					    return current_thread.get();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					u64 Scheduler::GetLastContextSwitchTicks() const {
 | 
				
			||||||
 | 
					    return last_context_switch_time;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Thread* Scheduler::PopNextReadyThread() {
 | 
					Thread* Scheduler::PopNextReadyThread() {
 | 
				
			||||||
    Thread* next = nullptr;
 | 
					    Thread* next = nullptr;
 | 
				
			||||||
    Thread* thread = GetCurrentThread();
 | 
					    Thread* thread = GetCurrentThread();
 | 
				
			||||||
@ -54,7 +59,10 @@ Thread* Scheduler::PopNextReadyThread() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Scheduler::SwitchContext(Thread* new_thread) {
 | 
					void Scheduler::SwitchContext(Thread* new_thread) {
 | 
				
			||||||
    Thread* previous_thread = GetCurrentThread();
 | 
					    Thread* const previous_thread = GetCurrentThread();
 | 
				
			||||||
 | 
					    Process* const previous_process = Core::CurrentProcess();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    UpdateLastContextSwitchTime(previous_thread, previous_process);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Save context for previous thread
 | 
					    // Save context for previous thread
 | 
				
			||||||
    if (previous_thread) {
 | 
					    if (previous_thread) {
 | 
				
			||||||
@ -78,8 +86,6 @@ void Scheduler::SwitchContext(Thread* new_thread) {
 | 
				
			|||||||
        // Cancel any outstanding wakeup events for this thread
 | 
					        // Cancel any outstanding wakeup events for this thread
 | 
				
			||||||
        new_thread->CancelWakeupTimer();
 | 
					        new_thread->CancelWakeupTimer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto* const previous_process = Core::CurrentProcess();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        current_thread = new_thread;
 | 
					        current_thread = new_thread;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ready_queue.remove(new_thread->GetPriority(), new_thread);
 | 
					        ready_queue.remove(new_thread->GetPriority(), new_thread);
 | 
				
			||||||
@ -102,6 +108,22 @@ void Scheduler::SwitchContext(Thread* new_thread) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Scheduler::UpdateLastContextSwitchTime(Thread* thread, Process* process) {
 | 
				
			||||||
 | 
					    const u64 prev_switch_ticks = last_context_switch_time;
 | 
				
			||||||
 | 
					    const u64 most_recent_switch_ticks = CoreTiming::GetTicks();
 | 
				
			||||||
 | 
					    const u64 update_ticks = most_recent_switch_ticks - prev_switch_ticks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (thread != nullptr) {
 | 
				
			||||||
 | 
					        thread->UpdateCPUTimeTicks(update_ticks);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (process != nullptr) {
 | 
				
			||||||
 | 
					        process->UpdateCPUTimeTicks(update_ticks);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    last_context_switch_time = most_recent_switch_ticks;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Scheduler::Reschedule() {
 | 
					void Scheduler::Reschedule() {
 | 
				
			||||||
    std::lock_guard<std::mutex> lock(scheduler_mutex);
 | 
					    std::lock_guard<std::mutex> lock(scheduler_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -17,6 +17,8 @@ class ARM_Interface;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Kernel {
 | 
					namespace Kernel {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Process;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Scheduler final {
 | 
					class Scheduler final {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    explicit Scheduler(Core::ARM_Interface& cpu_core);
 | 
					    explicit Scheduler(Core::ARM_Interface& cpu_core);
 | 
				
			||||||
@ -31,6 +33,9 @@ public:
 | 
				
			|||||||
    /// Gets the current running thread
 | 
					    /// Gets the current running thread
 | 
				
			||||||
    Thread* GetCurrentThread() const;
 | 
					    Thread* GetCurrentThread() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Gets the timestamp for the last context switch in ticks.
 | 
				
			||||||
 | 
					    u64 GetLastContextSwitchTicks() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Adds a new thread to the scheduler
 | 
					    /// Adds a new thread to the scheduler
 | 
				
			||||||
    void AddThread(SharedPtr<Thread> thread, u32 priority);
 | 
					    void AddThread(SharedPtr<Thread> thread, u32 priority);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -64,6 +69,19 @@ private:
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    void SwitchContext(Thread* new_thread);
 | 
					    void SwitchContext(Thread* new_thread);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Called on every context switch to update the internal timestamp
 | 
				
			||||||
 | 
					     * This also updates the running time ticks for the given thread and
 | 
				
			||||||
 | 
					     * process using the following difference:
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * ticks += most_recent_ticks - last_context_switch_ticks
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * The internal tick timestamp for the scheduler is simply the
 | 
				
			||||||
 | 
					     * most recent tick count retrieved. No special arithmetic is
 | 
				
			||||||
 | 
					     * applied to it.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void UpdateLastContextSwitchTime(Thread* thread, Process* process);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Lists all thread ids that aren't deleted/etc.
 | 
					    /// Lists all thread ids that aren't deleted/etc.
 | 
				
			||||||
    std::vector<SharedPtr<Thread>> thread_list;
 | 
					    std::vector<SharedPtr<Thread>> thread_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -73,6 +91,7 @@ private:
 | 
				
			|||||||
    SharedPtr<Thread> current_thread = nullptr;
 | 
					    SharedPtr<Thread> current_thread = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Core::ARM_Interface& cpu_core;
 | 
					    Core::ARM_Interface& cpu_core;
 | 
				
			||||||
 | 
					    u64 last_context_switch_time = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static std::mutex scheduler_mutex;
 | 
					    static std::mutex scheduler_mutex;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -467,6 +467,37 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
 | 
				
			|||||||
    LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id,
 | 
					    LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id,
 | 
				
			||||||
              info_sub_id, handle);
 | 
					              info_sub_id, handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum class GetInfoType : u64 {
 | 
				
			||||||
 | 
					        // 1.0.0+
 | 
				
			||||||
 | 
					        AllowedCpuIdBitmask = 0,
 | 
				
			||||||
 | 
					        AllowedThreadPrioBitmask = 1,
 | 
				
			||||||
 | 
					        MapRegionBaseAddr = 2,
 | 
				
			||||||
 | 
					        MapRegionSize = 3,
 | 
				
			||||||
 | 
					        HeapRegionBaseAddr = 4,
 | 
				
			||||||
 | 
					        HeapRegionSize = 5,
 | 
				
			||||||
 | 
					        TotalMemoryUsage = 6,
 | 
				
			||||||
 | 
					        TotalHeapUsage = 7,
 | 
				
			||||||
 | 
					        IsCurrentProcessBeingDebugged = 8,
 | 
				
			||||||
 | 
					        ResourceHandleLimit = 9,
 | 
				
			||||||
 | 
					        IdleTickCount = 10,
 | 
				
			||||||
 | 
					        RandomEntropy = 11,
 | 
				
			||||||
 | 
					        PerformanceCounter = 0xF0000002,
 | 
				
			||||||
 | 
					        // 2.0.0+
 | 
				
			||||||
 | 
					        ASLRRegionBaseAddr = 12,
 | 
				
			||||||
 | 
					        ASLRRegionSize = 13,
 | 
				
			||||||
 | 
					        NewMapRegionBaseAddr = 14,
 | 
				
			||||||
 | 
					        NewMapRegionSize = 15,
 | 
				
			||||||
 | 
					        // 3.0.0+
 | 
				
			||||||
 | 
					        IsVirtualAddressMemoryEnabled = 16,
 | 
				
			||||||
 | 
					        PersonalMmHeapUsage = 17,
 | 
				
			||||||
 | 
					        TitleId = 18,
 | 
				
			||||||
 | 
					        // 4.0.0+
 | 
				
			||||||
 | 
					        PrivilegedProcessId = 19,
 | 
				
			||||||
 | 
					        // 5.0.0+
 | 
				
			||||||
 | 
					        UserExceptionContextAddr = 20,
 | 
				
			||||||
 | 
					        ThreadTickCount = 0xF0000002,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const auto* current_process = Core::CurrentProcess();
 | 
					    const auto* current_process = Core::CurrentProcess();
 | 
				
			||||||
    const auto& vm_manager = current_process->VMManager();
 | 
					    const auto& vm_manager = current_process->VMManager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -529,6 +560,36 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
 | 
				
			|||||||
                    "(STUBBED) Attempted to query user exception context address, returned 0");
 | 
					                    "(STUBBED) Attempted to query user exception context address, returned 0");
 | 
				
			||||||
        *result = 0;
 | 
					        *result = 0;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					    case GetInfoType::ThreadTickCount: {
 | 
				
			||||||
 | 
					        constexpr u64 num_cpus = 4;
 | 
				
			||||||
 | 
					        if (info_sub_id != 0xFFFFFFFFFFFFFFFF && info_sub_id >= num_cpus) {
 | 
				
			||||||
 | 
					            return ERR_INVALID_COMBINATION_KERNEL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto thread =
 | 
				
			||||||
 | 
					            current_process->GetHandleTable().Get<Thread>(static_cast<Handle>(handle));
 | 
				
			||||||
 | 
					        if (!thread) {
 | 
				
			||||||
 | 
					            return ERR_INVALID_HANDLE;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto& system = Core::System::GetInstance();
 | 
				
			||||||
 | 
					        const auto& scheduler = system.CurrentScheduler();
 | 
				
			||||||
 | 
					        const auto* const current_thread = scheduler.GetCurrentThread();
 | 
				
			||||||
 | 
					        const bool same_thread = current_thread == thread;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks();
 | 
				
			||||||
 | 
					        u64 out_ticks = 0;
 | 
				
			||||||
 | 
					        if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) {
 | 
				
			||||||
 | 
					            const u64 thread_ticks = current_thread->GetTotalCPUTimeTicks();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            out_ticks = thread_ticks + (CoreTiming::GetTicks() - prev_ctx_ticks);
 | 
				
			||||||
 | 
					        } else if (same_thread && info_sub_id == system.CurrentCoreIndex()) {
 | 
				
			||||||
 | 
					            out_ticks = CoreTiming::GetTicks() - prev_ctx_ticks;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        *result = out_ticks;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        UNIMPLEMENTED();
 | 
					        UNIMPLEMENTED();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -24,37 +24,6 @@ struct PageInfo {
 | 
				
			|||||||
    u64 flags;
 | 
					    u64 flags;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Values accepted by svcGetInfo
 | 
					 | 
				
			||||||
enum class GetInfoType : u64 {
 | 
					 | 
				
			||||||
    // 1.0.0+
 | 
					 | 
				
			||||||
    AllowedCpuIdBitmask = 0,
 | 
					 | 
				
			||||||
    AllowedThreadPrioBitmask = 1,
 | 
					 | 
				
			||||||
    MapRegionBaseAddr = 2,
 | 
					 | 
				
			||||||
    MapRegionSize = 3,
 | 
					 | 
				
			||||||
    HeapRegionBaseAddr = 4,
 | 
					 | 
				
			||||||
    HeapRegionSize = 5,
 | 
					 | 
				
			||||||
    TotalMemoryUsage = 6,
 | 
					 | 
				
			||||||
    TotalHeapUsage = 7,
 | 
					 | 
				
			||||||
    IsCurrentProcessBeingDebugged = 8,
 | 
					 | 
				
			||||||
    ResourceHandleLimit = 9,
 | 
					 | 
				
			||||||
    IdleTickCount = 10,
 | 
					 | 
				
			||||||
    RandomEntropy = 11,
 | 
					 | 
				
			||||||
    PerformanceCounter = 0xF0000002,
 | 
					 | 
				
			||||||
    // 2.0.0+
 | 
					 | 
				
			||||||
    ASLRRegionBaseAddr = 12,
 | 
					 | 
				
			||||||
    ASLRRegionSize = 13,
 | 
					 | 
				
			||||||
    NewMapRegionBaseAddr = 14,
 | 
					 | 
				
			||||||
    NewMapRegionSize = 15,
 | 
					 | 
				
			||||||
    // 3.0.0+
 | 
					 | 
				
			||||||
    IsVirtualAddressMemoryEnabled = 16,
 | 
					 | 
				
			||||||
    PersonalMmHeapUsage = 17,
 | 
					 | 
				
			||||||
    TitleId = 18,
 | 
					 | 
				
			||||||
    // 4.0.0+
 | 
					 | 
				
			||||||
    PrivilegedProcessId = 19,
 | 
					 | 
				
			||||||
    // 5.0.0+
 | 
					 | 
				
			||||||
    UserExceptionContextAddr = 20,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void CallSVC(u32 immediate);
 | 
					void CallSVC(u32 immediate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Kernel
 | 
					} // namespace Kernel
 | 
				
			||||||
 | 
				
			|||||||
@ -258,6 +258,14 @@ public:
 | 
				
			|||||||
        return last_running_ticks;
 | 
					        return last_running_ticks;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u64 GetTotalCPUTimeTicks() const {
 | 
				
			||||||
 | 
					        return total_cpu_time_ticks;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void UpdateCPUTimeTicks(u64 ticks) {
 | 
				
			||||||
 | 
					        total_cpu_time_ticks += ticks;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s32 GetProcessorID() const {
 | 
					    s32 GetProcessorID() const {
 | 
				
			||||||
        return processor_id;
 | 
					        return processor_id;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -378,7 +386,8 @@ private:
 | 
				
			|||||||
    u32 nominal_priority = 0; ///< Nominal thread priority, as set by the emulated application
 | 
					    u32 nominal_priority = 0; ///< Nominal thread priority, as set by the emulated application
 | 
				
			||||||
    u32 current_priority = 0; ///< Current thread priority, can be temporarily changed
 | 
					    u32 current_priority = 0; ///< Current thread priority, can be temporarily changed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    u64 last_running_ticks = 0; ///< CPU tick when thread was last running
 | 
					    u64 total_cpu_time_ticks = 0; ///< Total CPU running ticks.
 | 
				
			||||||
 | 
					    u64 last_running_ticks = 0;   ///< CPU tick when thread was last running
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s32 processor_id = 0;
 | 
					    s32 processor_id = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user