diff --git a/level_zero/tools/source/sysman/events/events.h b/level_zero/tools/source/sysman/events/events.h index 6efef8fb04..9eb84fdbe2 100644 --- a/level_zero/tools/source/sysman/events/events.h +++ b/level_zero/tools/source/sysman/events/events.h @@ -13,7 +13,7 @@ class Events { public: virtual ~Events(){}; virtual ze_result_t eventRegister(zes_event_type_flags_t events) = 0; - virtual bool eventListen(zes_event_type_flags_t &pEvent) = 0; + virtual bool eventListen(zes_event_type_flags_t &pEvent, uint32_t timeout) = 0; virtual void init() = 0; }; diff --git a/level_zero/tools/source/sysman/events/events_imp.cpp b/level_zero/tools/source/sysman/events/events_imp.cpp index 99a5d7a87b..6f8fd8dc51 100644 --- a/level_zero/tools/source/sysman/events/events_imp.cpp +++ b/level_zero/tools/source/sysman/events/events_imp.cpp @@ -15,8 +15,8 @@ ze_result_t EventsImp::eventRegister(zes_event_type_flags_t events) { return pOsEvents->eventRegister(events); } -bool EventsImp::eventListen(zes_event_type_flags_t &pEvent) { - return pOsEvents->eventListen(pEvent); +bool EventsImp::eventListen(zes_event_type_flags_t &pEvent, uint32_t timeout) { + return pOsEvents->eventListen(pEvent, timeout); } void EventsImp::init() { diff --git a/level_zero/tools/source/sysman/events/events_imp.h b/level_zero/tools/source/sysman/events/events_imp.h index 03e0a8b8b9..84ed778b5b 100644 --- a/level_zero/tools/source/sysman/events/events_imp.h +++ b/level_zero/tools/source/sysman/events/events_imp.h @@ -17,7 +17,7 @@ class EventsImp : public Events, NEO::NonCopyableOrMovableClass { public: void init() override; ze_result_t eventRegister(zes_event_type_flags_t events) override; - bool eventListen(zes_event_type_flags_t &pEvent) override; + bool eventListen(zes_event_type_flags_t &pEvent, uint32_t timeout) override; OsEvents *pOsEvents = nullptr; EventsImp() = default; diff --git a/level_zero/tools/source/sysman/events/linux/os_events_imp.cpp b/level_zero/tools/source/sysman/events/linux/os_events_imp.cpp index 03438043cf..12485fabb7 100644 --- a/level_zero/tools/source/sysman/events/linux/os_events_imp.cpp +++ b/level_zero/tools/source/sysman/events/linux/os_events_imp.cpp @@ -64,7 +64,7 @@ bool LinuxEventsImp::checkDeviceAttachEvent(zes_event_type_flags_t &pEvent) { return false; } -bool LinuxEventsImp::eventListen(zes_event_type_flags_t &pEvent) { +bool LinuxEventsImp::eventListen(zes_event_type_flags_t &pEvent, uint32_t timeout) { if (registeredEvents & ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED) { if (isResetRequired(pEvent)) { return true; diff --git a/level_zero/tools/source/sysman/events/linux/os_events_imp.h b/level_zero/tools/source/sysman/events/linux/os_events_imp.h index de2670a715..a3f815576a 100644 --- a/level_zero/tools/source/sysman/events/linux/os_events_imp.h +++ b/level_zero/tools/source/sysman/events/linux/os_events_imp.h @@ -13,7 +13,7 @@ namespace L0 { class LinuxEventsImp : public OsEvents, NEO::NonCopyableOrMovableClass { public: - bool eventListen(zes_event_type_flags_t &pEvent) override; + bool eventListen(zes_event_type_flags_t &pEvent, uint32_t timeout) override; ze_result_t eventRegister(zes_event_type_flags_t events) override; LinuxEventsImp() = default; LinuxEventsImp(OsSysman *pOsSysman); diff --git a/level_zero/tools/source/sysman/events/os_events.h b/level_zero/tools/source/sysman/events/os_events.h index 7038e1a34b..9dd58ea02b 100644 --- a/level_zero/tools/source/sysman/events/os_events.h +++ b/level_zero/tools/source/sysman/events/os_events.h @@ -15,7 +15,7 @@ namespace L0 { class OsEvents { public: static OsEvents *create(OsSysman *pOsSysman); - virtual bool eventListen(zes_event_type_flags_t &pEvent) = 0; + virtual bool eventListen(zes_event_type_flags_t &pEvent, uint32_t timeout) = 0; virtual ze_result_t eventRegister(zes_event_type_flags_t events) = 0; virtual ~OsEvents() {} }; diff --git a/level_zero/tools/source/sysman/events/windows/CMakeLists.txt b/level_zero/tools/source/sysman/events/windows/CMakeLists.txt index e5d865fa7a..0ecc506990 100644 --- a/level_zero/tools/source/sysman/events/windows/CMakeLists.txt +++ b/level_zero/tools/source/sysman/events/windows/CMakeLists.txt @@ -6,6 +6,7 @@ set(L0_SRCS_TOOLS_SYSMAN_EVENTS_WINDOWS ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/os_events_imp.h ${CMAKE_CURRENT_SOURCE_DIR}/os_events_imp.cpp ) diff --git a/level_zero/tools/source/sysman/events/windows/os_events_imp.cpp b/level_zero/tools/source/sysman/events/windows/os_events_imp.cpp index 21659a5b68..0fe3d2c9fa 100644 --- a/level_zero/tools/source/sysman/events/windows/os_events_imp.cpp +++ b/level_zero/tools/source/sysman/events/windows/os_events_imp.cpp @@ -5,32 +5,113 @@ * */ -#include "level_zero/tools/source/sysman/events/os_events.h" +#include "level_zero/tools/source/sysman/events/windows/os_events_imp.h" + #include "level_zero/tools/source/sysman/windows/os_sysman_imp.h" namespace L0 { -class WddmEventsImp : public OsEvents { - public: - bool eventListen(zes_event_type_flags_t &pEvent) override; - ze_result_t eventRegister(zes_event_type_flags_t events) override; - WddmEventsImp(OsSysman *pOsSysman); - ~WddmEventsImp() = default; +void WddmEventsImp::registerEvents(zes_event_type_flags_t eventId, uint32_t requestId) { + ze_result_t status = ZE_RESULT_SUCCESS; + EventHandler event; + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; - // Don't allow copies of the WddmEventsImp object - WddmEventsImp(const WddmEventsImp &obj) = delete; - WddmEventsImp &operator=(const WddmEventsImp &obj) = delete; -}; + request.requestId = requestId; + request.commandId = KmdSysman::Command::RegisterEvent; + request.componentId = KmdSysman::Component::InterfaceProperties; + request.dataSize = sizeof(HANDLE); -bool WddmEventsImp::eventListen(zes_event_type_flags_t &pEvent) { - return false; + event.requestId = requestId; + event.id = eventId; + + event.windowsHandle = CreateEvent(NULL, FALSE, FALSE, NULL); + memcpy_s(request.dataBuffer, sizeof(HANDLE), &event.windowsHandle, sizeof(HANDLE)); + + status = pKmdSysManager->requestSingle(request, response); + + if (status != ZE_RESULT_SUCCESS) { + CloseHandle(event.windowsHandle); + return; + } + + eventList.push_back(event); +} + +void WddmEventsImp::unregisterEvents() { + ze_result_t status = ZE_RESULT_SUCCESS; + EventHandler event; + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + + request.commandId = KmdSysman::Command::UnregisterEvent; + request.componentId = KmdSysman::Component::InterfaceProperties; + request.dataSize = sizeof(HANDLE); + + for (uint32_t i = 0; i < eventList.size(); i++) { + request.requestId = eventList[i].requestId; + event.windowsHandle = eventList[i].windowsHandle; + + memcpy_s(request.dataBuffer, sizeof(HANDLE), &event.windowsHandle, sizeof(HANDLE)); + + status = pKmdSysManager->requestSingle(request, response); + + if (status == ZE_RESULT_SUCCESS) { + CloseHandle(event.windowsHandle); + } + } + + eventList.clear(); } ze_result_t WddmEventsImp::eventRegister(zes_event_type_flags_t events) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + + unregisterEvents(); + + if (events & ZES_EVENT_TYPE_FLAG_ENERGY_THRESHOLD_CROSSED) { + registerEvents(ZES_EVENT_TYPE_FLAG_ENERGY_THRESHOLD_CROSSED, KmdSysman::Events::EnergyThresholdCrossed); + } + + if (events & ZES_EVENT_TYPE_FLAG_DEVICE_SLEEP_STATE_ENTER) { + registerEvents(ZES_EVENT_TYPE_FLAG_DEVICE_SLEEP_STATE_ENTER, KmdSysman::Events::EnterD3); + } + + if (events & ZES_EVENT_TYPE_FLAG_DEVICE_SLEEP_STATE_EXIT) { + registerEvents(ZES_EVENT_TYPE_FLAG_DEVICE_SLEEP_STATE_EXIT, KmdSysman::Events::EnterD0); + } + + if (events & ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED) { + registerEvents(ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED, KmdSysman::Events::EnterTDR); + } + + return (eventList.size() == 0) ? ZE_RESULT_ERROR_UNSUPPORTED_FEATURE : ZE_RESULT_SUCCESS; +} + +bool WddmEventsImp::eventListen(zes_event_type_flags_t &pEvent, uint32_t timeout) { + HANDLE events[MAXIMUM_WAIT_OBJECTS]; + + if (eventList.size() == 0) { + return false; + } + + for (uint32_t i = 0; i < eventList.size(); i++) { + events[i] = eventList[i].windowsHandle; + } + + uint32_t signaledEvent = WaitForMultipleObjects(static_cast(eventList.size()), events, FALSE, timeout); + + if (signaledEvent >= eventList.size()) { + return false; + } + + pEvent = eventList[signaledEvent].id; + + return true; } WddmEventsImp::WddmEventsImp(OsSysman *pOsSysman) { + WddmSysmanImp *pWddmSysmanImp = static_cast(pOsSysman); + pKmdSysManager = &pWddmSysmanImp->getKmdSysManager(); } OsEvents *OsEvents::create(OsSysman *pOsSysman) { diff --git a/level_zero/tools/source/sysman/events/windows/os_events_imp.h b/level_zero/tools/source/sysman/events/windows/os_events_imp.h new file mode 100644 index 0000000000..0e92164280 --- /dev/null +++ b/level_zero/tools/source/sysman/events/windows/os_events_imp.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include "shared/source/helpers/non_copyable_or_moveable.h" + +#include "level_zero/tools/source/sysman/events/os_events.h" +#include "level_zero/tools/source/sysman/windows/os_sysman_imp.h" + +#include "sysman/windows/os_sysman_imp.h" + +namespace L0 { +class KmdSysManager; + +struct EventHandler { + HANDLE windowsHandle; + zes_event_type_flags_t id; + uint32_t requestId; +}; + +class WddmEventsImp : public OsEvents, NEO::NonCopyableOrMovableClass { + public: + bool eventListen(zes_event_type_flags_t &pEvent, uint32_t timeout) override; + ze_result_t eventRegister(zes_event_type_flags_t events) override; + WddmEventsImp(OsSysman *pOsSysman); + ~WddmEventsImp() = default; + + // Don't allow copies of the WddmEventsImp object + WddmEventsImp(const WddmEventsImp &obj) = delete; + WddmEventsImp &operator=(const WddmEventsImp &obj) = delete; + + private: + void registerEvents(zes_event_type_flags_t eventId, uint32_t requestId); + void unregisterEvents(); + + protected: + KmdSysManager *pKmdSysManager = nullptr; + std::vector eventList; +}; + +} // namespace L0 diff --git a/level_zero/tools/source/sysman/sysman.cpp b/level_zero/tools/source/sysman/sysman.cpp index 5c9fc40b56..08c981c1d3 100644 --- a/level_zero/tools/source/sysman/sysman.cpp +++ b/level_zero/tools/source/sysman/sysman.cpp @@ -45,7 +45,7 @@ ze_result_t DriverHandleImp::sysmanEventsListen( auto timeToExitLoop = std::chrono::steady_clock::now() + std::chrono::milliseconds(timeout); do { for (uint32_t devIndex = 0; devIndex < count; devIndex++) { - gotSysmanEvent = L0::SysmanDevice::fromHandle(phDevices[devIndex])->deviceEventListen(pEvents[devIndex]); + gotSysmanEvent = L0::SysmanDevice::fromHandle(phDevices[devIndex])->deviceEventListen(pEvents[devIndex], timeout); if (gotSysmanEvent) { *pNumDeviceEvents = 1; break; diff --git a/level_zero/tools/source/sysman/sysman.h b/level_zero/tools/source/sysman/sysman.h index 1ff4dad83c..f6536d452e 100644 --- a/level_zero/tools/source/sysman/sysman.h +++ b/level_zero/tools/source/sysman/sysman.h @@ -50,7 +50,7 @@ struct SysmanDevice : _ze_device_handle_t { virtual ze_result_t fanGet(uint32_t *pCount, zes_fan_handle_t *phFan) = 0; virtual ze_result_t firmwareGet(uint32_t *pCount, zes_firmware_handle_t *phFirmware) = 0; virtual ze_result_t deviceEventRegister(zes_event_type_flags_t events) = 0; - virtual bool deviceEventListen(zes_event_type_flags_t &pEvent) = 0; + virtual bool deviceEventListen(zes_event_type_flags_t &pEvent, uint32_t timeout) = 0; virtual ~SysmanDevice() = default; }; diff --git a/level_zero/tools/source/sysman/sysman_imp.cpp b/level_zero/tools/source/sysman/sysman_imp.cpp index 61aa7332c3..9c51765ef7 100644 --- a/level_zero/tools/source/sysman/sysman_imp.cpp +++ b/level_zero/tools/source/sysman/sysman_imp.cpp @@ -133,8 +133,8 @@ ze_result_t SysmanDeviceImp::deviceEventRegister(zes_event_type_flags_t events) return pEvents->eventRegister(events); } -bool SysmanDeviceImp::deviceEventListen(zes_event_type_flags_t &pEvent) { - return pEvents->eventListen(pEvent); +bool SysmanDeviceImp::deviceEventListen(zes_event_type_flags_t &pEvent, uint32_t timeout) { + return pEvents->eventListen(pEvent, timeout); } ze_result_t SysmanDeviceImp::deviceGetState(zes_device_state_t *pState) { diff --git a/level_zero/tools/source/sysman/sysman_imp.h b/level_zero/tools/source/sysman/sysman_imp.h index 6edf5f5a44..d2eaf96837 100644 --- a/level_zero/tools/source/sysman/sysman_imp.h +++ b/level_zero/tools/source/sysman/sysman_imp.h @@ -61,7 +61,7 @@ struct SysmanDeviceImp : SysmanDevice, NEO::NonCopyableOrMovableClass { ze_result_t fanGet(uint32_t *pCount, zes_fan_handle_t *phFan) override; ze_result_t firmwareGet(uint32_t *pCount, zes_firmware_handle_t *phFirmware) override; ze_result_t deviceEventRegister(zes_event_type_flags_t events) override; - bool deviceEventListen(zes_event_type_flags_t &pEvent) override; + bool deviceEventListen(zes_event_type_flags_t &pEvent, uint32_t timeout) override; private: template diff --git a/level_zero/tools/test/unit_tests/sources/sysman/events/windows/CMakeLists.txt b/level_zero/tools/test/unit_tests/sources/sysman/events/windows/CMakeLists.txt new file mode 100644 index 0000000000..864c90ddea --- /dev/null +++ b/level_zero/tools/test/unit_tests/sources/sysman/events/windows/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# Copyright (C) 2020 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +if(WIN32) + target_sources(${TARGET_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/test_zes_events.cpp + ) +endif() diff --git a/level_zero/tools/test/unit_tests/sources/sysman/events/windows/test_zes_events.cpp b/level_zero/tools/test/unit_tests/sources/sysman/events/windows/test_zes_events.cpp new file mode 100644 index 0000000000..c860c2222c --- /dev/null +++ b/level_zero/tools/test/unit_tests/sources/sysman/events/windows/test_zes_events.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/tools/source/sysman/events/events_imp.h" +#include "level_zero/tools/source/sysman/events/windows/os_events_imp.h" +#include "level_zero/tools/source/sysman/global_operations/global_operations_imp.h" +#include "level_zero/tools/test/unit_tests/sources/sysman/windows/mock_kmd_sys_manager.h" +#include "level_zero/tools/test/unit_tests/sources/sysman/windows/mock_sysman_fixture.h" + +using ::testing::Matcher; + +namespace L0 { +namespace ult { + +class SysmanEventsFixture : public SysmanDeviceFixture { + protected: + std::unique_ptr> pKmdSysManager; + std::unique_ptr pGlobalOperations; + OsEvents *pOsEventsPrev = nullptr; + L0::EventsImp *pEventsImp; + KmdSysManager *pOriginalKmdSysManager = nullptr; + GlobalOperations *pGlobalOperationsOld = nullptr; + + void SetUp(bool allowSetCalls) { // NOLINT(readability-identifier-naming) + SysmanDeviceFixture::SetUp(); + + pKmdSysManager.reset(new Mock); + + pKmdSysManager->allowSetCalls = allowSetCalls; + + EXPECT_CALL(*pKmdSysManager, escape(_, _, _, _, _)) + .WillRepeatedly(::testing::Invoke(pKmdSysManager.get(), &Mock::mock_escape)); + + pOriginalKmdSysManager = pWddmSysmanImp->pKmdSysManager; + pWddmSysmanImp->pKmdSysManager = pKmdSysManager.get(); + + pEventsImp = static_cast(pSysmanDeviceImp->pEvents); + pOsEventsPrev = pEventsImp->pOsEvents; + pEventsImp->pOsEvents = nullptr; + pGlobalOperations = std::make_unique(pWddmSysmanImp); + pGlobalOperationsOld = pSysmanDeviceImp->pGlobalOperations; + pSysmanDeviceImp->pGlobalOperations = pGlobalOperations.get(); + pSysmanDeviceImp->pGlobalOperations->init(); + pEventsImp->init(); + } + + void TearDown() override { + if (nullptr != pEventsImp->pOsEvents) { + delete pEventsImp->pOsEvents; + } + pEventsImp->pOsEvents = pOsEventsPrev; + pEventsImp = nullptr; + pSysmanDeviceImp->pGlobalOperations = pGlobalOperationsOld; + pWddmSysmanImp->pKmdSysManager = pOriginalKmdSysManager; + SysmanDeviceFixture::TearDown(); + } +}; + +TEST_F(SysmanEventsFixture, GivenValidDeviceHandleWhenListeningForResetRequiredEventsThenEventListenAPIReturnsAfterTimingOutWithNoEvent) { + SetUp(true); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEventRegister(device->toHandle(), ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED)); + zes_device_handle_t *phDevices = new zes_device_handle_t[1]; + phDevices[0] = device->toHandle(); + uint32_t numDeviceEvents = 0; + zes_event_type_flags_t *pDeviceEvents = new zes_event_type_flags_t[1]; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), 100u, 1u, phDevices, &numDeviceEvents, pDeviceEvents)); + EXPECT_EQ(0u, numDeviceEvents); + delete[] phDevices; + delete[] pDeviceEvents; +} + +TEST_F(SysmanEventsFixture, GivenValidDeviceHandleWhenListeningForResetRequiredEventsThenEventListenAPIReturnsAfterReceivingEventOnInfiniteWait) { + SetUp(true); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEventRegister(device->toHandle(), ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED)); + zes_device_handle_t *phDevices = new zes_device_handle_t[1]; + phDevices[0] = device->toHandle(); + uint32_t numDeviceEvents = 0; + zes_event_type_flags_t *pDeviceEvents = new zes_event_type_flags_t[1]; + + pKmdSysManager->signalEvent(ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), INFINITE, 1u, phDevices, &numDeviceEvents, pDeviceEvents)); + EXPECT_EQ(1u, numDeviceEvents); + delete[] phDevices; + delete[] pDeviceEvents; +} + +TEST_F(SysmanEventsFixture, GivenValidDeviceHandleWhenListeningForResetRequiredEventsThenEventListenAPIReturnsAfterReceivingEventOnInfiniteWaitMultipleTimes) { + SetUp(true); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEventRegister(device->toHandle(), ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED)); + zes_device_handle_t *phDevices = new zes_device_handle_t[1]; + phDevices[0] = device->toHandle(); + uint32_t numDeviceEvents = 0; + zes_event_type_flags_t *pDeviceEvents = new zes_event_type_flags_t[1]; + + pKmdSysManager->signalEvent(ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), INFINITE, 1u, phDevices, &numDeviceEvents, pDeviceEvents)); + EXPECT_EQ(1u, numDeviceEvents); + + pKmdSysManager->signalEvent(ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED); + + EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), INFINITE, 1u, phDevices, &numDeviceEvents, pDeviceEvents)); + EXPECT_EQ(1u, numDeviceEvents); + + delete[] phDevices; + delete[] pDeviceEvents; +} + +} // namespace ult +} // namespace L0 diff --git a/level_zero/tools/test/unit_tests/sources/sysman/windows/mock_kmd_sys_manager.h b/level_zero/tools/test/unit_tests/sources/sysman/windows/mock_kmd_sys_manager.h index 86dcc932c6..04e8dcf18a 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/windows/mock_kmd_sys_manager.h +++ b/level_zero/tools/test/unit_tests/sources/sysman/windows/mock_kmd_sys_manager.h @@ -6,6 +6,7 @@ */ #pragma once +#include "level_zero/core/test/unit_tests/mock.h" #include "level_zero/tools/source/sysman/windows/kmd_sys_manager.h" #include "level_zero/tools/source/sysman/windows/os_sysman_imp.h" @@ -14,11 +15,17 @@ namespace L0 { namespace ult { -class MockKmdSysManager : public KmdSysManager {}; - constexpr uint32_t mockKmdVersionMajor = 1; constexpr uint32_t mockKmdVersionMinor = 0; constexpr uint32_t mockKmdPatchNumber = 0; +constexpr uint32_t mockKmdMaxHandlesPerEvent = 20; + +struct MockEventHandle { + HANDLE eventHandle; + bool inited = false; +}; + +class MockKmdSysManager : public KmdSysManager {}; template <> struct Mock : public MockKmdSysManager { @@ -27,6 +34,8 @@ struct Mock : public MockKmdSysManager { uint32_t mockPowerLimit1 = 2500; + MockEventHandle handles[KmdSysman::Events::MaxEvents][mockKmdMaxHandlesPerEvent]; + MOCK_METHOD(bool, escape, (uint32_t escapeOp, uint64_t pDataIn, uint32_t dataInSize, uint64_t pDataOut, uint32_t dataOutSize)); MOCKABLE_VIRTUAL void getInterfaceProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { @@ -175,12 +184,15 @@ struct Mock : public MockKmdSysManager { for (uint32_t i = 0; i < pHeaderIn->inNumElements; i++) { KmdSysman::GfxSysmanReqHeaderIn *pRequest = reinterpret_cast(pBufferPtr); - if (pRequest->inCommand == KmdSysman::Command::Get || pRequest->inCommand == KmdSysman::Command::Set) { + if (pRequest->inCommand == KmdSysman::Command::Get || + pRequest->inCommand == KmdSysman::Command::Set || + pRequest->inCommand == KmdSysman::Command::RegisterEvent) { if (pRequest->inComponent >= KmdSysman::Component::InterfaceProperties && pRequest->inComponent < KmdSysman::Component::MaxComponents) { pBufferPtr += sizeof(KmdSysman::GfxSysmanReqHeaderIn); sizeCheck -= sizeof(KmdSysman::GfxSysmanReqHeaderIn); - if (pRequest->inCommand == KmdSysman::Command::Set) { + if (pRequest->inCommand == KmdSysman::Command::Set || + pRequest->inCommand == KmdSysman::Command::RegisterEvent) { if (pRequest->inDataSize == 0) { return false; } @@ -202,6 +214,69 @@ struct Mock : public MockKmdSysManager { return true; } + void registerEvent(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + if (!allowSetCalls) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + return; + } + + uint8_t *pBuffer = reinterpret_cast(pRequest); + pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderIn); + + pResponse->outDataSize = 0; + + switch (pRequest->inRequestId) { + case KmdSysman::Events::EnterD0: + case KmdSysman::Events::EnterD3: + case KmdSysman::Events::EnterTDR: + case KmdSysman::Events::ExitTDR: + case KmdSysman::Events::EnergyThresholdCrossed: { + bool found = false; + for (uint32_t i = 0; i < mockKmdMaxHandlesPerEvent; i++) { + if (!handles[pRequest->inRequestId][i].inited) { + handles[pRequest->inRequestId][i].inited = true; + unsigned long long eventID = *(unsigned long long *)pBuffer; + handles[pRequest->inRequestId][i].eventHandle = reinterpret_cast(eventID); + found = true; + break; + } + } + pResponse->outReturnCode = found ? KmdSysman::KmdSysmanSuccess : KmdSysman::KmdSysmanFail; + } break; + default: + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + break; + } + } + + void signalEvent(uint32_t idEvent) { + + uint32_t arrayID = 0; + if (idEvent & ZES_EVENT_TYPE_FLAG_ENERGY_THRESHOLD_CROSSED) { + arrayID = KmdSysman::Events::EnergyThresholdCrossed; + } + + if (idEvent & ZES_EVENT_TYPE_FLAG_DEVICE_SLEEP_STATE_ENTER) { + arrayID = KmdSysman::Events::EnterD3; + } + + if (idEvent & ZES_EVENT_TYPE_FLAG_DEVICE_SLEEP_STATE_EXIT) { + arrayID = KmdSysman::Events::EnterD0; + } + + if (idEvent & ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED) { + arrayID = KmdSysman::Events::EnterTDR; + } + + for (uint32_t i = 0; i < mockKmdMaxHandlesPerEvent; i++) { + if (handles[arrayID][i].inited) { + SetEvent(handles[arrayID][i].eventHandle); + } + } + } + void setProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { if (!allowSetCalls) { pResponse->outDataSize = 0; @@ -351,6 +426,12 @@ struct Mock : public MockKmdSysManager { requestOffset += pRequest->inDataSize; responseOffset = sizeof(KmdSysman::GfxSysmanReqHeaderOut); } break; + case KmdSysman::Command::RegisterEvent: { + registerEvent(pRequest, pResponse); + requestOffset = sizeof(KmdSysman::GfxSysmanReqHeaderIn); + requestOffset += pRequest->inDataSize; + responseOffset = sizeof(KmdSysman::GfxSysmanReqHeaderOut); + } break; default: { return false; } break;