/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2013 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #ifndef XENIA_KERNEL_KERNEL_STATE_H_ #define XENIA_KERNEL_KERNEL_STATE_H_ #include #include #include #include #include #include #include "xenia/base/bit_map.h" #include "xenia/base/cvar.h" #include "xenia/base/mutex.h" #include "xenia/cpu/export_resolver.h" #include "xenia/kernel/util/native_list.h" #include "xenia/kernel/util/object_table.h" #include "xenia/kernel/xam/app_manager.h" #include "xenia/kernel/xam/content_manager.h" #include "xenia/kernel/xam/user_profile.h" #include "xenia/memory.h" #include "xenia/vfs/virtual_file_system.h" #include "xenia/xbox.h" namespace xe { class ByteStream; class Emulator; namespace cpu { class Processor; } // namespace cpu } // namespace xe namespace xe { namespace kernel { class Dispatcher; class XHostThread; class KernelModule; class XModule; class XNotifyListener; class XThread; class UserModule; // (?), used by KeGetCurrentProcessType constexpr uint32_t X_PROCTYPE_IDLE = 0; constexpr uint32_t X_PROCTYPE_USER = 1; constexpr uint32_t X_PROCTYPE_SYSTEM = 2; struct ProcessInfoBlock { xe::be unk_00; xe::be unk_04; // blink xe::be unk_08; // flink xe::be unk_0C; xe::be unk_10; xe::be thread_count; uint8_t unk_18; uint8_t unk_19; uint8_t unk_1A; uint8_t unk_1B; xe::be kernel_stack_size; xe::be unk_20; xe::be tls_data_size; xe::be tls_raw_data_size; xe::be tls_slot_size; uint8_t unk_2E; uint8_t process_type; xe::be bitmap[0x20 / 4]; xe::be unk_50; xe::be unk_54; // blink xe::be unk_58; // flink xe::be unk_5C; }; struct TerminateNotification { uint32_t guest_routine; uint32_t priority; }; class KernelState { public: explicit KernelState(Emulator* emulator); ~KernelState(); static KernelState* shared(); Emulator* emulator() const { return emulator_; } Memory* memory() const { return memory_; } cpu::Processor* processor() const { return processor_; } vfs::VirtualFileSystem* file_system() const { return file_system_; } uint32_t title_id() const; xam::AppManager* app_manager() const { return app_manager_.get(); } xam::ContentManager* content_manager() const { return content_manager_.get(); } xam::UserProfile* user_profile() const { return user_profile_.get(); } // Access must be guarded by the global critical region. util::ObjectTable* object_table() { return &object_table_; } uint32_t process_type() const; void set_process_type(uint32_t value); uint32_t process_info_block_address() const { return process_info_block_address_; } uint32_t AllocateTLS(); void FreeTLS(uint32_t slot); void RegisterTitleTerminateNotification(uint32_t routine, uint32_t priority); void RemoveTitleTerminateNotification(uint32_t routine); void RegisterModule(XModule* module); void UnregisterModule(XModule* module); bool RegisterUserModule(object_ref module); void UnregisterUserModule(UserModule* module); bool IsKernelModule(const char* name); object_ref GetModule(const char* name, bool user_only = false); object_ref LaunchModule(object_ref module); object_ref GetExecutableModule(); void SetExecutableModule(object_ref module); object_ref LoadUserModule(const char* name, bool call_entry = true); object_ref GetKernelModule(const char* name); template object_ref LoadKernelModule() { auto kernel_module = object_ref(new T(emulator_, this)); LoadKernelModule(kernel_module); return kernel_module; } template object_ref GetKernelModule(const char* name) { auto module = GetKernelModule(name); return object_ref(reinterpret_cast(module.release())); } // Terminates a title: Unloads all modules, and kills all guest threads. // This DOES NOT RETURN if called from a guest thread! void TerminateTitle(); void RegisterThread(XThread* thread); void UnregisterThread(XThread* thread); void OnThreadExecute(XThread* thread); void OnThreadExit(XThread* thread); object_ref GetThreadByID(uint32_t thread_id); void RegisterNotifyListener(XNotifyListener* listener); void UnregisterNotifyListener(XNotifyListener* listener); void BroadcastNotification(XNotificationID id, uint32_t data); util::NativeList* dpc_list() { return &dpc_list_; } void CompleteOverlapped(uint32_t overlapped_ptr, X_RESULT result); void CompleteOverlappedEx(uint32_t overlapped_ptr, X_RESULT result, uint32_t extended_error, uint32_t length); void CompleteOverlappedImmediate(uint32_t overlapped_ptr, X_RESULT result); void CompleteOverlappedImmediateEx(uint32_t overlapped_ptr, X_RESULT result, uint32_t extended_error, uint32_t length); void CompleteOverlappedDeferred(std::function completion_callback, uint32_t overlapped_ptr, X_RESULT result); void CompleteOverlappedDeferredEx(std::function completion_callback, uint32_t overlapped_ptr, X_RESULT result, uint32_t extended_error, uint32_t length); bool Save(ByteStream* stream); bool Restore(ByteStream* stream); private: void LoadKernelModule(object_ref kernel_module); Emulator* emulator_; Memory* memory_; cpu::Processor* processor_; vfs::VirtualFileSystem* file_system_; std::unique_ptr app_manager_; std::unique_ptr content_manager_; std::unique_ptr user_profile_; xe::global_critical_region global_critical_region_; // Must be guarded by the global critical region. util::ObjectTable object_table_; std::unordered_map threads_by_id_; std::vector> notify_listeners_; bool has_notified_startup_ = false; uint32_t process_type_ = X_PROCTYPE_USER; object_ref executable_module_; std::vector> kernel_modules_; std::vector> user_modules_; std::vector terminate_notifications_; uint32_t process_info_block_address_ = 0; std::atomic dispatch_thread_running_; object_ref dispatch_thread_; // Must be guarded by the global critical region. util::NativeList dpc_list_; std::condition_variable_any dispatch_cond_; std::list> dispatch_queue_; BitMap tls_bitmap_; friend class XObject; }; } // namespace kernel } // namespace xe #endif // XENIA_KERNEL_KERNEL_STATE_H_