1 /* 2 * Copyright (C) 2020-2021 Intel Corporation 3 * 4 * SPDX-License-Identifier: MIT 5 * 6 */ 7 8 #pragma once 9 #include "level_zero/core/test/unit_tests/mock.h" 10 #include "level_zero/tools/source/sysman/windows/kmd_sys_manager.h" 11 #include "level_zero/tools/source/sysman/windows/os_sysman_imp.h" 12 13 #include "gmock/gmock.h" 14 15 namespace L0 { 16 namespace ult { 17 18 constexpr uint32_t mockKmdVersionMajor = 1; 19 constexpr uint32_t mockKmdVersionMinor = 0; 20 constexpr uint32_t mockKmdPatchNumber = 0; 21 constexpr uint32_t mockKmdMaxHandlesPerEvent = 20; 22 23 struct MockEventHandle { 24 HANDLE eventHandle; 25 bool inited = false; 26 }; 27 28 uint64_t convertTStoMicroSec(uint64_t TS, uint32_t freq); 29 30 class MockKmdSysManager : public KmdSysManager {}; 31 32 template <> 33 struct Mock<MockKmdSysManager> : public MockKmdSysManager { 34 35 ze_bool_t allowSetCalls = false; 36 ze_bool_t fanSupported = false; 37 uint32_t mockPowerLimit1 = 2500; 38 39 MockEventHandle handles[KmdSysman::Events::MaxEvents][mockKmdMaxHandlesPerEvent]; 40 41 MOCK_METHOD(bool, escape, (uint32_t escapeOp, uint64_t pDataIn, uint32_t dataInSize, uint64_t pDataOut, uint32_t dataOutSize)); 42 43 MOCKABLE_VIRTUAL void getInterfaceProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 44 pResponse->outDataSize = 0; 45 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 46 } 47 48 MOCKABLE_VIRTUAL void setInterfaceProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 49 pResponse->outDataSize = 0; 50 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 51 } 52 53 MOCKABLE_VIRTUAL void getPowerProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 54 uint8_t *pBuffer = reinterpret_cast<uint8_t *>(pResponse); 55 pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderOut); 56 57 if (pRequest->inRequestId == KmdSysman::Requests::Power::CurrentPowerLimit1) { 58 uint32_t *pPl1 = reinterpret_cast<uint32_t *>(pBuffer); 59 *pPl1 = mockPowerLimit1; 60 pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; 61 pResponse->outDataSize = sizeof(uint32_t); 62 } else { 63 pResponse->outDataSize = 0; 64 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 65 } 66 } 67 68 MOCKABLE_VIRTUAL void setPowerProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 69 uint8_t *pBuffer = reinterpret_cast<uint8_t *>(pRequest); 70 pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderIn); 71 72 if (pRequest->inRequestId == KmdSysman::Requests::Power::CurrentPowerLimit1) { 73 uint32_t *pPl1 = reinterpret_cast<uint32_t *>(pBuffer); 74 mockPowerLimit1 = *pPl1; 75 pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; 76 } else { 77 pResponse->outDataSize = 0; 78 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 79 } 80 } 81 82 MOCKABLE_VIRTUAL void getFrequencyProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 83 pResponse->outDataSize = 0; 84 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 85 } 86 87 MOCKABLE_VIRTUAL void setFrequencyProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 88 pResponse->outDataSize = 0; 89 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 90 } 91 92 MOCKABLE_VIRTUAL void getActivityProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 93 pResponse->outDataSize = 0; 94 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 95 } 96 97 MOCKABLE_VIRTUAL void setActivityProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 98 pResponse->outDataSize = 0; 99 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 100 } 101 102 MOCKABLE_VIRTUAL void getFanProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 103 pResponse->outDataSize = 0; 104 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 105 } 106 107 MOCKABLE_VIRTUAL void setFanProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 108 pResponse->outDataSize = 0; 109 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 110 } 111 112 MOCKABLE_VIRTUAL void getTemperatureProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 113 pResponse->outDataSize = 0; 114 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 115 } 116 117 MOCKABLE_VIRTUAL void setTemperatureProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 118 pResponse->outDataSize = 0; 119 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 120 } 121 122 MOCKABLE_VIRTUAL void getFpsProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 123 pResponse->outDataSize = 0; 124 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 125 } 126 127 MOCKABLE_VIRTUAL void setFpsProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 128 pResponse->outDataSize = 0; 129 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 130 } 131 132 MOCKABLE_VIRTUAL void getSchedulerProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 133 pResponse->outDataSize = 0; 134 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 135 } 136 137 MOCKABLE_VIRTUAL void setSchedulerProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 138 pResponse->outDataSize = 0; 139 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 140 } 141 142 MOCKABLE_VIRTUAL void getMemoryProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 143 pResponse->outDataSize = 0; 144 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 145 } 146 147 MOCKABLE_VIRTUAL void setMemoryProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 148 pResponse->outDataSize = 0; 149 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 150 } 151 152 MOCKABLE_VIRTUAL void getPciProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 153 pResponse->outDataSize = 0; 154 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 155 } 156 157 MOCKABLE_VIRTUAL void setPciProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 158 pResponse->outDataSize = 0; 159 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 160 } 161 162 MOCKABLE_VIRTUAL void getGlobalOperationsProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 163 pResponse->outDataSize = 0; 164 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 165 } 166 167 MOCKABLE_VIRTUAL void setGlobalOperationsProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 168 pResponse->outDataSize = 0; 169 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 170 } 171 172 void retrieveCorrectVersion(KmdSysman::GfxSysmanMainHeaderOut *pHeaderOut) { 173 pHeaderOut->outNumElements = 1; 174 pHeaderOut->outTotalSize = 0; 175 176 KmdSysman::GfxSysmanReqHeaderOut *pResponse = reinterpret_cast<KmdSysman::GfxSysmanReqHeaderOut *>(pHeaderOut->outBuffer); 177 uint8_t *pBuffer = nullptr; 178 179 pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; 180 pResponse->outDataSize = sizeof(KmdSysman::KmdSysmanVersion); 181 pBuffer = reinterpret_cast<uint8_t *>(pResponse); 182 pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderOut); 183 pHeaderOut->outTotalSize += sizeof(KmdSysman::GfxSysmanReqHeaderOut); 184 185 KmdSysman::KmdSysmanVersion *pCurrentVersion = reinterpret_cast<KmdSysman::KmdSysmanVersion *>(pBuffer); 186 pCurrentVersion->majorVersion = mockKmdVersionMajor; 187 pCurrentVersion->minorVersion = mockKmdVersionMinor; 188 pCurrentVersion->patchNumber = mockKmdPatchNumber; 189 190 pHeaderOut->outTotalSize += sizeof(KmdSysman::KmdSysmanVersion); 191 } 192 193 bool validateInputBuffer(KmdSysman::GfxSysmanMainHeaderIn *pHeaderIn) { 194 uint32_t sizeCheck = pHeaderIn->inTotalsize; 195 uint8_t *pBufferPtr = pHeaderIn->inBuffer; 196 197 for (uint32_t i = 0; i < pHeaderIn->inNumElements; i++) { 198 KmdSysman::GfxSysmanReqHeaderIn *pRequest = reinterpret_cast<KmdSysman::GfxSysmanReqHeaderIn *>(pBufferPtr); 199 if (pRequest->inCommand == KmdSysman::Command::Get || 200 pRequest->inCommand == KmdSysman::Command::Set || 201 pRequest->inCommand == KmdSysman::Command::RegisterEvent) { 202 if (pRequest->inComponent >= KmdSysman::Component::InterfaceProperties && pRequest->inComponent < KmdSysman::Component::MaxComponents) { 203 pBufferPtr += sizeof(KmdSysman::GfxSysmanReqHeaderIn); 204 sizeCheck -= sizeof(KmdSysman::GfxSysmanReqHeaderIn); 205 206 if (pRequest->inCommand == KmdSysman::Command::Set || 207 pRequest->inCommand == KmdSysman::Command::RegisterEvent) { 208 if (pRequest->inDataSize == 0) { 209 return false; 210 } 211 pBufferPtr += pRequest->inDataSize; 212 sizeCheck -= pRequest->inDataSize; 213 } 214 } else { 215 return false; 216 } 217 } else { 218 return false; 219 } 220 } 221 222 if (sizeCheck != 0) { 223 return false; 224 } 225 226 return true; 227 } 228 229 void registerEvent(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 230 if (!allowSetCalls) { 231 pResponse->outDataSize = 0; 232 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 233 return; 234 } 235 236 uint8_t *pBuffer = reinterpret_cast<uint8_t *>(pRequest); 237 pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderIn); 238 239 pResponse->outDataSize = 0; 240 241 switch (pRequest->inRequestId) { 242 case KmdSysman::Events::EnterD0: 243 case KmdSysman::Events::EnterD3: 244 case KmdSysman::Events::EnterTDR: 245 case KmdSysman::Events::ExitTDR: 246 case KmdSysman::Events::EnergyThresholdCrossed: { 247 bool found = false; 248 for (uint32_t i = 0; i < mockKmdMaxHandlesPerEvent; i++) { 249 if (!handles[pRequest->inRequestId][i].inited) { 250 handles[pRequest->inRequestId][i].inited = true; 251 unsigned long long eventID = *(unsigned long long *)pBuffer; 252 handles[pRequest->inRequestId][i].eventHandle = reinterpret_cast<HANDLE>(eventID); 253 found = true; 254 break; 255 } 256 } 257 pResponse->outReturnCode = found ? KmdSysman::KmdSysmanSuccess : KmdSysman::KmdSysmanFail; 258 } break; 259 default: 260 pResponse->outDataSize = 0; 261 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 262 break; 263 } 264 } 265 266 void signalEvent(uint32_t idEvent) { 267 268 uint32_t arrayID = 0; 269 if (idEvent & ZES_EVENT_TYPE_FLAG_ENERGY_THRESHOLD_CROSSED) { 270 arrayID = KmdSysman::Events::EnergyThresholdCrossed; 271 } 272 273 if (idEvent & ZES_EVENT_TYPE_FLAG_DEVICE_SLEEP_STATE_ENTER) { 274 arrayID = KmdSysman::Events::EnterD3; 275 } 276 277 if (idEvent & ZES_EVENT_TYPE_FLAG_DEVICE_SLEEP_STATE_EXIT) { 278 arrayID = KmdSysman::Events::EnterD0; 279 } 280 281 if (idEvent & ZES_EVENT_TYPE_FLAG_DEVICE_DETACH) { 282 arrayID = KmdSysman::Events::EnterTDR; 283 } 284 285 if (idEvent & ZES_EVENT_TYPE_FLAG_DEVICE_ATTACH) { 286 arrayID = KmdSysman::Events::ExitTDR; 287 } 288 289 for (uint32_t i = 0; i < mockKmdMaxHandlesPerEvent; i++) { 290 if (handles[arrayID][i].inited) { 291 SetEvent(handles[arrayID][i].eventHandle); 292 } 293 } 294 } 295 296 void setProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 297 if (!allowSetCalls) { 298 pResponse->outDataSize = 0; 299 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 300 return; 301 } 302 303 switch (pRequest->inComponent) { 304 case KmdSysman::Component::InterfaceProperties: { 305 setInterfaceProperty(pRequest, pResponse); 306 } break; 307 case KmdSysman::Component::PowerComponent: { 308 setPowerProperty(pRequest, pResponse); 309 } break; 310 case KmdSysman::Component::FrequencyComponent: { 311 setFrequencyProperty(pRequest, pResponse); 312 } break; 313 case KmdSysman::Component::ActivityComponent: { 314 setActivityProperty(pRequest, pResponse); 315 } break; 316 case KmdSysman::Component::FanComponent: { 317 setFanProperty(pRequest, pResponse); 318 } break; 319 case KmdSysman::Component::TemperatureComponent: { 320 setTemperatureProperty(pRequest, pResponse); 321 } break; 322 case KmdSysman::Component::FpsComponent: { 323 setFpsProperty(pRequest, pResponse); 324 } break; 325 case KmdSysman::Component::SchedulerComponent: { 326 setSchedulerProperty(pRequest, pResponse); 327 } break; 328 case KmdSysman::Component::MemoryComponent: { 329 setMemoryProperty(pRequest, pResponse); 330 } break; 331 case KmdSysman::Component::PciComponent: { 332 setPciProperty(pRequest, pResponse); 333 } break; 334 case KmdSysman::Component::GlobalOperationsComponent: { 335 setGlobalOperationsProperty(pRequest, pResponse); 336 } break; 337 default: { 338 pResponse->outDataSize = 0; 339 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 340 } break; 341 } 342 } 343 344 void getProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { 345 switch (pRequest->inComponent) { 346 case KmdSysman::Component::InterfaceProperties: { 347 getInterfaceProperty(pRequest, pResponse); 348 } break; 349 case KmdSysman::Component::PowerComponent: { 350 getPowerProperty(pRequest, pResponse); 351 } break; 352 case KmdSysman::Component::FrequencyComponent: { 353 getFrequencyProperty(pRequest, pResponse); 354 } break; 355 case KmdSysman::Component::ActivityComponent: { 356 getActivityProperty(pRequest, pResponse); 357 } break; 358 case KmdSysman::Component::FanComponent: { 359 getFanProperty(pRequest, pResponse); 360 } break; 361 case KmdSysman::Component::TemperatureComponent: { 362 getTemperatureProperty(pRequest, pResponse); 363 } break; 364 case KmdSysman::Component::FpsComponent: { 365 getFpsProperty(pRequest, pResponse); 366 } break; 367 case KmdSysman::Component::SchedulerComponent: { 368 getSchedulerProperty(pRequest, pResponse); 369 } break; 370 case KmdSysman::Component::MemoryComponent: { 371 getMemoryProperty(pRequest, pResponse); 372 } break; 373 case KmdSysman::Component::PciComponent: { 374 getPciProperty(pRequest, pResponse); 375 } break; 376 case KmdSysman::Component::GlobalOperationsComponent: { 377 getGlobalOperationsProperty(pRequest, pResponse); 378 } break; 379 default: { 380 pResponse->outDataSize = 0; 381 pResponse->outReturnCode = KmdSysman::KmdSysmanFail; 382 } break; 383 } 384 } 385 386 bool mock_escape(uint32_t escapeOp, uint64_t pInPtr, uint32_t dataInSize, uint64_t pOutPtr, uint32_t dataOutSize) { 387 void *pDataIn = reinterpret_cast<void *>(pInPtr); 388 void *pDataOut = reinterpret_cast<void *>(pOutPtr); 389 390 if (pDataIn == nullptr || pDataOut == nullptr) { 391 return false; 392 } 393 394 if (dataInSize != sizeof(KmdSysman::GfxSysmanMainHeaderIn) || dataOutSize != sizeof(KmdSysman::GfxSysmanMainHeaderOut)) { 395 return false; 396 } 397 398 if (escapeOp != KmdSysman::PcEscapeOperation) { 399 return false; 400 } 401 402 KmdSysman::GfxSysmanMainHeaderIn *pSysmanMainHeaderIn = reinterpret_cast<KmdSysman::GfxSysmanMainHeaderIn *>(pDataIn); 403 KmdSysman::GfxSysmanMainHeaderOut *pSysmanMainHeaderOut = reinterpret_cast<KmdSysman::GfxSysmanMainHeaderOut *>(pDataOut); 404 405 KmdSysman::KmdSysmanVersion versionSysman; 406 versionSysman.data = pSysmanMainHeaderIn->inVersion; 407 408 if (versionSysman.majorVersion != KmdSysman::KmdMajorVersion) { 409 if (versionSysman.majorVersion == 0) { 410 retrieveCorrectVersion(pSysmanMainHeaderOut); 411 return true; 412 } 413 return false; 414 } 415 416 if (pSysmanMainHeaderIn->inTotalsize == 0) { 417 return false; 418 } 419 420 if (pSysmanMainHeaderIn->inNumElements == 0) { 421 return false; 422 } 423 424 if (!validateInputBuffer(pSysmanMainHeaderIn)) { 425 return false; 426 } 427 428 uint8_t *pBufferIn = pSysmanMainHeaderIn->inBuffer; 429 uint8_t *pBufferOut = pSysmanMainHeaderOut->outBuffer; 430 uint32_t requestOffset = 0; 431 uint32_t responseOffset = 0; 432 pSysmanMainHeaderOut->outTotalSize = 0; 433 434 for (uint32_t i = 0; i < pSysmanMainHeaderIn->inNumElements; i++) { 435 KmdSysman::GfxSysmanReqHeaderIn *pRequest = reinterpret_cast<KmdSysman::GfxSysmanReqHeaderIn *>(pBufferIn); 436 KmdSysman::GfxSysmanReqHeaderOut *pResponse = reinterpret_cast<KmdSysman::GfxSysmanReqHeaderOut *>(pBufferOut); 437 438 switch (pRequest->inCommand) { 439 case KmdSysman::Command::Get: { 440 getProperty(pRequest, pResponse); 441 requestOffset = sizeof(KmdSysman::GfxSysmanReqHeaderIn); 442 responseOffset = sizeof(KmdSysman::GfxSysmanReqHeaderOut); 443 responseOffset += pResponse->outDataSize; 444 } break; 445 case KmdSysman::Command::Set: { 446 setProperty(pRequest, pResponse); 447 requestOffset = sizeof(KmdSysman::GfxSysmanReqHeaderIn); 448 requestOffset += pRequest->inDataSize; 449 responseOffset = sizeof(KmdSysman::GfxSysmanReqHeaderOut); 450 } break; 451 case KmdSysman::Command::RegisterEvent: { 452 registerEvent(pRequest, pResponse); 453 requestOffset = sizeof(KmdSysman::GfxSysmanReqHeaderIn); 454 requestOffset += pRequest->inDataSize; 455 responseOffset = sizeof(KmdSysman::GfxSysmanReqHeaderOut); 456 } break; 457 default: { 458 return false; 459 } break; 460 } 461 462 pResponse->outRequestId = pRequest->inRequestId; 463 pResponse->outComponent = pRequest->inComponent; 464 pBufferIn += requestOffset; 465 pBufferOut += responseOffset; 466 pSysmanMainHeaderOut->outTotalSize += responseOffset; 467 } 468 469 pSysmanMainHeaderOut->outNumElements = pSysmanMainHeaderIn->inNumElements; 470 pSysmanMainHeaderOut->outStatus = KmdSysman::KmdSysmanSuccess; 471 472 return true; 473 } 474 475 Mock() = default; 476 ~Mock() = default; 477 }; 478 479 } // namespace ult 480 } // namespace L0