nvdrv.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <memory>
  5. #include <unordered_map>
  6. #include <vector>
  7. #include "common/common_types.h"
  8. #include "core/hle/service/kernel_helpers.h"
  9. #include "core/hle/service/nvdrv/nvdata.h"
  10. #include "core/hle/service/nvdrv/syncpoint_manager.h"
  11. #include "core/hle/service/nvflinger/ui/fence.h"
  12. #include "core/hle/service/service.h"
  13. namespace Core {
  14. class System;
  15. }
  16. namespace Kernel {
  17. class KEvent;
  18. }
  19. namespace Service::NVFlinger {
  20. class NVFlinger;
  21. }
  22. namespace Service::Nvidia {
  23. class SyncpointManager;
  24. namespace Devices {
  25. class nvdevice;
  26. }
  27. /// Represents an Nvidia event
  28. struct NvEvent {
  29. Kernel::KEvent* event{};
  30. NvFence fence{};
  31. };
  32. struct EventInterface {
  33. // Mask representing currently busy events
  34. u64 events_mask{};
  35. // Each kernel event associated to an NV event
  36. std::array<NvEvent, MaxNvEvents> events;
  37. // The status of the current NVEvent
  38. std::array<EventState, MaxNvEvents> status{};
  39. // Tells if an NVEvent is registered or not
  40. std::array<bool, MaxNvEvents> registered{};
  41. // Tells the NVEvent that it has failed.
  42. std::array<u32, MaxNvEvents> fails{};
  43. // When an NVEvent is waiting on GPU interrupt, this is the sync_point
  44. // associated with it.
  45. std::array<u32, MaxNvEvents> assigned_syncpt{};
  46. // This is the value of the GPU interrupt for which the NVEvent is waiting
  47. // for.
  48. std::array<u32, MaxNvEvents> assigned_value{};
  49. // Constant to denote an unasigned syncpoint.
  50. static constexpr u32 unassigned_syncpt = 0xFFFFFFFF;
  51. std::optional<u32> GetFreeEvent() const {
  52. u64 mask = events_mask;
  53. for (u32 i = 0; i < MaxNvEvents; i++) {
  54. const bool is_free = (mask & 0x1) == 0;
  55. if (is_free) {
  56. if (status[i] == EventState::Registered || status[i] == EventState::Free) {
  57. return {i};
  58. }
  59. }
  60. mask = mask >> 1;
  61. }
  62. return std::nullopt;
  63. }
  64. void SetEventStatus(const u32 event_id, EventState new_status) {
  65. EventState old_status = status[event_id];
  66. if (old_status == new_status) {
  67. return;
  68. }
  69. status[event_id] = new_status;
  70. if (new_status == EventState::Registered) {
  71. registered[event_id] = true;
  72. }
  73. if (new_status == EventState::Waiting || new_status == EventState::Busy) {
  74. events_mask |= (1ULL << event_id);
  75. }
  76. }
  77. void RegisterEvent(const u32 event_id) {
  78. registered[event_id] = true;
  79. if (status[event_id] == EventState::Free) {
  80. status[event_id] = EventState::Registered;
  81. }
  82. }
  83. void UnregisterEvent(const u32 event_id) {
  84. registered[event_id] = false;
  85. if (status[event_id] == EventState::Registered) {
  86. status[event_id] = EventState::Free;
  87. }
  88. }
  89. void LiberateEvent(const u32 event_id) {
  90. status[event_id] = registered[event_id] ? EventState::Registered : EventState::Free;
  91. events_mask &= ~(1ULL << event_id);
  92. assigned_syncpt[event_id] = unassigned_syncpt;
  93. assigned_value[event_id] = 0;
  94. }
  95. };
  96. class Module final {
  97. public:
  98. explicit Module(Core::System& system_);
  99. ~Module();
  100. /// Returns a pointer to one of the available devices, identified by its name.
  101. template <typename T>
  102. std::shared_ptr<T> GetDevice(const std::string& name) {
  103. auto itr = devices.find(name);
  104. if (itr == devices.end())
  105. return nullptr;
  106. return std::static_pointer_cast<T>(itr->second);
  107. }
  108. NvResult VerifyFD(DeviceFD fd) const;
  109. /// Opens a device node and returns a file descriptor to it.
  110. DeviceFD Open(const std::string& device_name);
  111. /// Sends an ioctl command to the specified file descriptor.
  112. NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
  113. std::vector<u8>& output);
  114. NvResult Ioctl2(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
  115. const std::vector<u8>& inline_input, std::vector<u8>& output);
  116. NvResult Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
  117. std::vector<u8>& output, std::vector<u8>& inline_output);
  118. /// Closes a device file descriptor and returns operation success.
  119. NvResult Close(DeviceFD fd);
  120. void SignalSyncpt(const u32 syncpoint_id, const u32 value);
  121. Kernel::KReadableEvent& GetEvent(u32 event_id);
  122. Kernel::KWritableEvent& GetEventWriteable(u32 event_id);
  123. private:
  124. /// Manages syncpoints on the host
  125. SyncpointManager syncpoint_manager;
  126. /// Id to use for the next open file descriptor.
  127. DeviceFD next_fd = 1;
  128. /// Mapping of file descriptors to the devices they reference.
  129. std::unordered_map<DeviceFD, std::shared_ptr<Devices::nvdevice>> open_files;
  130. /// Mapping of device node names to their implementation.
  131. std::unordered_map<std::string, std::shared_ptr<Devices::nvdevice>> devices;
  132. EventInterface events_interface;
  133. KernelHelpers::ServiceContext service_context;
  134. };
  135. /// Registers all NVDRV services with the specified service manager.
  136. void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,
  137. Core::System& system);
  138. } // namespace Service::Nvidia