diff options
| author | Fernando Sahmkow <fsahmkow27@gmail.com> | 2021-11-01 15:02:47 +0100 | 
|---|---|---|
| committer | Fernando Sahmkow <fsahmkow27@gmail.com> | 2022-10-06 21:00:51 +0200 | 
| commit | d30b885d713fa2b9393aeb3c515f4d881bf838f2 (patch) | |
| tree | 4445e1621b403fd6603e9773841107ba9c10822e | |
| parent | 39a5ce4e696716e48bdd1c980abc792827c68184 (diff) | |
NVDRV: Implement QueryEvent.
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvdevice.h | 8 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | 23 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp | 20 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h | 14 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | 26 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_gpu.h | 13 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/nvdrv.cpp | 46 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/nvdrv.h | 6 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/nvdrv_interface.cpp | 15 | 
10 files changed, 133 insertions, 40 deletions
| diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h index 696e8121e..204b0e757 100644 --- a/src/core/hle/service/nvdrv/devices/nvdevice.h +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h @@ -11,6 +11,10 @@ namespace Core {  class System;  } +namespace Kernel { +class KEvent; +} +  namespace Service::Nvidia::Devices {  /// Represents an abstract nvidia device node. It is to be subclassed by concrete device nodes to @@ -64,6 +68,10 @@ public:       */      virtual void OnClose(DeviceFD fd) = 0; +    virtual Kernel::KEvent* QueryEvent(u32 event_id) { +        return nullptr; +    } +  protected:      Core::System& system;  }; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index f2b015c8f..9b393521a 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp @@ -255,4 +255,27 @@ NvResult nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::v      return NvResult::Success;  } +Kernel::KEvent* nvhost_ctrl::QueryEvent(u32 event_id) { +    const auto event = SyncpointEventValue{.raw = event_id}; + +    const bool allocated = event.event_allocated.Value() != 0; +    const u32 slot{allocated ? event.partial_slot.Value() : static_cast<u32>(event.slot)}; +    if (slot >= MaxNvEvents) { +        ASSERT(false); +        return nullptr; +    } + +    const u32 syncpoint_id{allocated ? event.syncpoint_id_for_allocation.Value() +                                     : event.syncpoint_id.Value()}; + +    auto lock = events_interface.Lock(); + +    if (events_interface.registered[slot] && +        events_interface.assigned_syncpt[slot] == syncpoint_id) { +        ASSERT(events_interface.events[slot]); +        return events_interface.events[slot]; +    } +    return nullptr; +} +  } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index 0471c09b2..d548a7827 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h @@ -28,6 +28,8 @@ public:      void OnOpen(DeviceFD fd) override;      void OnClose(DeviceFD fd) override; +    Kernel::KEvent* QueryEvent(u32 event_id) override; +      union SyncpointEventValue {          u32 raw; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index 2b3b7efea..e353408eb 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp @@ -7,10 +7,15 @@  #include "core/core.h"  #include "core/core_timing.h"  #include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h" +#include "core/hle/service/nvdrv/nvdrv.h"  namespace Service::Nvidia::Devices { -nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system_) : nvdevice{system_} {} +nvhost_ctrl_gpu::nvhost_ctrl_gpu(Core::System& system_, EventInterface& events_interface_) +    : nvdevice{system_}, events_interface{events_interface_} { +    error_notifier_event = events_interface.CreateNonCtrlEvent("CtrlGpuErrorNotifier"); +    unknown_event = events_interface.CreateNonCtrlEvent("CtrlGpuUknownEvent"); +}  nvhost_ctrl_gpu::~nvhost_ctrl_gpu() = default;  NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, @@ -286,4 +291,17 @@ NvResult nvhost_ctrl_gpu::GetGpuTime(const std::vector<u8>& input, std::vector<u      return NvResult::Success;  } +Kernel::KEvent* nvhost_ctrl_gpu::QueryEvent(u32 event_id) { +    switch (event_id) { +    case 1: +        return error_notifier_event; +    case 2: +        return unknown_event; +    default: { +        LOG_CRITICAL(Service_NVDRV, "Unknown Ctrl GPU Event {}", event_id); +    } +    } +    return nullptr; +} +  } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h index 97e9a90cb..1e8f254e2 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h @@ -10,11 +10,15 @@  #include "common/swap.h"  #include "core/hle/service/nvdrv/devices/nvdevice.h" +namespace Service::Nvidia { +class EventInterface; +} +  namespace Service::Nvidia::Devices {  class nvhost_ctrl_gpu final : public nvdevice {  public: -    explicit nvhost_ctrl_gpu(Core::System& system_); +    explicit nvhost_ctrl_gpu(Core::System& system_, EventInterface& events_interface_);      ~nvhost_ctrl_gpu() override;      NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, @@ -27,6 +31,8 @@ public:      void OnOpen(DeviceFD fd) override;      void OnClose(DeviceFD fd) override; +    Kernel::KEvent* QueryEvent(u32 event_id) override; +  private:      struct IoctlGpuCharacteristics {          u32_le arch;                       // 0x120 (NVGPU_GPU_ARCH_GM200) @@ -160,6 +166,12 @@ private:      NvResult ZBCQueryTable(const std::vector<u8>& input, std::vector<u8>& output);      NvResult FlushL2(const std::vector<u8>& input, std::vector<u8>& output);      NvResult GetGpuTime(const std::vector<u8>& input, std::vector<u8>& output); + +    EventInterface& events_interface; + +    // Events +    Kernel::KEvent* error_notifier_event; +    Kernel::KEvent* unknown_event;  };  } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index b98e63011..e87fa5992 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -6,6 +6,7 @@  #include "common/logging/log.h"  #include "core/core.h"  #include "core/hle/service/nvdrv/devices/nvhost_gpu.h" +#include "core/hle/service/nvdrv/nvdrv.h"  #include "core/hle/service/nvdrv/syncpoint_manager.h"  #include "core/memory.h"  #include "video_core/gpu.h" @@ -21,10 +22,16 @@ Tegra::CommandHeader BuildFenceAction(Tegra::GPU::FenceOperation op, u32 syncpoi  } // namespace  nvhost_gpu::nvhost_gpu(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, -                       SyncpointManager& syncpoint_manager_) -    : nvdevice{system_}, nvmap_dev{std::move(nvmap_dev_)}, syncpoint_manager{syncpoint_manager_} { +                       EventInterface& events_interface_, SyncpointManager& syncpoint_manager_) +    : nvdevice{system_}, nvmap_dev{std::move(nvmap_dev_)}, events_interface{events_interface_}, +      syncpoint_manager{syncpoint_manager_} {      channel_fence.id = syncpoint_manager_.AllocateSyncpoint();      channel_fence.value = system_.GPU().GetSyncpointValue(channel_fence.id); +    sm_exception_breakpoint_int_report_event = +        events_interface.CreateNonCtrlEvent("GpuChannelSMExceptionBreakpointInt"); +    sm_exception_breakpoint_pause_report_event = +        events_interface.CreateNonCtrlEvent("GpuChannelSMExceptionBreakpointPause"); +    error_notifier_event = events_interface.CreateNonCtrlEvent("GpuChannelErrorNotifier");  }  nvhost_gpu::~nvhost_gpu() = default; @@ -328,4 +335,19 @@ NvResult nvhost_gpu::ChannelSetTimeslice(const std::vector<u8>& input, std::vect      return NvResult::Success;  } +Kernel::KEvent* nvhost_gpu::QueryEvent(u32 event_id) { +    switch (event_id) { +    case 1: +        return sm_exception_breakpoint_int_report_event; +    case 2: +        return sm_exception_breakpoint_pause_report_event; +    case 3: +        return error_notifier_event; +    default: { +        LOG_CRITICAL(Service_NVDRV, "Unknown Ctrl GPU Event {}", event_id); +    } +    } +    return nullptr; +} +  } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index 8a9f7775a..eb4936df0 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -15,7 +15,8 @@  namespace Service::Nvidia {  class SyncpointManager; -} +class EventInterface; +} // namespace Service::Nvidia  namespace Service::Nvidia::Devices { @@ -23,7 +24,7 @@ class nvmap;  class nvhost_gpu final : public nvdevice {  public:      explicit nvhost_gpu(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, -                        SyncpointManager& syncpoint_manager_); +                        EventInterface& events_interface_, SyncpointManager& syncpoint_manager_);      ~nvhost_gpu() override;      NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, @@ -36,6 +37,8 @@ public:      void OnOpen(DeviceFD fd) override;      void OnClose(DeviceFD fd) override; +    Kernel::KEvent* QueryEvent(u32 event_id) override; +  private:      enum class CtxObjects : u32_le {          Ctx2D = 0x902D, @@ -192,8 +195,14 @@ private:      NvResult ChannelSetTimeslice(const std::vector<u8>& input, std::vector<u8>& output);      std::shared_ptr<nvmap> nvmap_dev; +    EventInterface& events_interface;      SyncpointManager& syncpoint_manager;      NvFence channel_fence; + +    // Events +    Kernel::KEvent* sm_exception_breakpoint_int_report_event; +    Kernel::KEvent* sm_exception_breakpoint_pause_report_event; +    Kernel::KEvent* error_notifier_event;  };  } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index fa259abed..7c0f89c12 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -96,6 +96,12 @@ u32 EventInterface::FindFreeEvent(u32 syncpoint_id) {      return 0;  } +Kernel::KEvent* EventInterface::CreateNonCtrlEvent(std::string name) { +    Kernel::KEvent* new_event = module.service_context.CreateEvent(std::move(name)); +    basic_events.push_back(new_event); +    return new_event; +} +  void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,                         Core::System& system) {      auto module_ = std::make_shared<Module>(system); @@ -119,9 +125,10 @@ Module::Module(Core::System& system)      }      auto nvmap_dev = std::make_shared<Devices::nvmap>(system);      devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>(system, nvmap_dev); -    devices["/dev/nvhost-gpu"] = -        std::make_shared<Devices::nvhost_gpu>(system, nvmap_dev, syncpoint_manager); -    devices["/dev/nvhost-ctrl-gpu"] = std::make_shared<Devices::nvhost_ctrl_gpu>(system); +    devices["/dev/nvhost-gpu"] = std::make_shared<Devices::nvhost_gpu>( +        system, nvmap_dev, events_interface, syncpoint_manager); +    devices["/dev/nvhost-ctrl-gpu"] = +        std::make_shared<Devices::nvhost_ctrl_gpu>(system, events_interface);      devices["/dev/nvmap"] = nvmap_dev;      devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(system, nvmap_dev);      devices["/dev/nvhost-ctrl"] = @@ -255,31 +262,24 @@ void Module::SignalSyncpt(const u32 syncpoint_id, const u32 value) {      }  } -Kernel::KEvent* Module::GetEvent(u32 event_id) { -    const auto event = Devices::nvhost_ctrl::SyncpointEventValue{.raw = event_id}; - -    const bool allocated = event.event_allocated.Value() != 0; -    const u32 slot{allocated ? event.partial_slot.Value() : static_cast<u32>(event.slot)}; -    if (slot >= MaxNvEvents) { -        ASSERT(false); -        return nullptr; +NvResult Module::QueryEvent(DeviceFD fd, u32 event_id, Kernel::KEvent*& event) { +    if (fd < 0) { +        LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd); +        return NvResult::InvalidState;      } -    const u32 syncpoint_id{allocated ? event.syncpoint_id_for_allocation.Value() -                                     : event.syncpoint_id.Value()}; +    const auto itr = open_files.find(fd); -    auto lock = events_interface.Lock(); +    if (itr == open_files.end()) { +        LOG_ERROR(Service_NVDRV, "Could not find DeviceFD={}!", fd); +        return NvResult::NotImplemented; +    } -    if (events_interface.registered[slot] && -        events_interface.assigned_syncpt[slot] == syncpoint_id) { -        ASSERT(events_interface.events[slot]); -        return events_interface.events[slot]; +    event = itr->second->QueryEvent(event_id); +    if (!event) { +        return NvResult::BadParameter;      } -    // Temporary hack. -    events_interface.Create(slot); -    events_interface.assigned_syncpt[slot] = syncpoint_id; -    ASSERT(false); -    return events_interface.events[slot]; +    return NvResult::Success;  }  } // namespace Service::Nvidia diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index 8ce036508..be8813c97 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h @@ -6,6 +6,7 @@  #pragma once  #include <memory> +#include <string>  #include <unordered_map>  #include <vector> @@ -79,9 +80,12 @@ public:      u32 FindFreeEvent(u32 syncpoint_id); +    Kernel::KEvent* CreateNonCtrlEvent(std::string name); +  private:      std::mutex events_mutex;      Module& module; +    std::vector<Kernel::KEvent*> basic_events;  };  class Module final { @@ -118,7 +122,7 @@ public:      void SignalSyncpt(const u32 syncpoint_id, const u32 value); -    Kernel::KEvent* GetEvent(u32 event_id); +    NvResult QueryEvent(DeviceFD fd, u32 event_id, Kernel::KEvent*& event);  private:      friend class EventInterface; diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp index 07883feb2..81ee28f31 100644 --- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp +++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp @@ -173,25 +173,20 @@ void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) {          return;      } -    const auto nv_result = nvdrv->VerifyFD(fd); -    if (nv_result != NvResult::Success) { -        LOG_ERROR(Service_NVDRV, "Invalid FD specified DeviceFD={}!", fd); -        ServiceError(ctx, nv_result); -        return; -    } - -    auto* event = nvdrv->GetEvent(event_id); +    Kernel::KEvent* event = nullptr; +    NvResult result = nvdrv->QueryEvent(fd, event_id, event); -    if (event) { +    if (result == NvResult::Success) {          IPC::ResponseBuilder rb{ctx, 3, 1};          rb.Push(ResultSuccess);          auto& readable_event = event->GetReadableEvent();          rb.PushCopyObjects(readable_event);          rb.PushEnum(NvResult::Success);      } else { +        LOG_ERROR(Service_NVDRV, "Invalid event request!");          IPC::ResponseBuilder rb{ctx, 3};          rb.Push(ResultSuccess); -        rb.PushEnum(NvResult::BadParameter); +        rb.PushEnum(result);      }  } | 
