1 /*
2 * Copyright (c) 2024, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     encode_check_huc_load_packet.cpp
24 //! \brief
25 //!
26 
27 #include "encode_check_huc_load_packet.h"
28 
29 namespace encode
30 {
Init()31     MOS_STATUS EncodeCheckHucLoadPkt::Init()
32     {
33         ENCODE_FUNC_CALL();
34 
35         ENCODE_CHK_NULL_RETURN(m_pipeline);
36         m_allocator = m_pipeline->GetEncodeAllocator();
37         ENCODE_CHK_NULL_RETURN(m_allocator);
38 
39         MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
40         MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
41         allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
42         allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
43         allocParamsForBufferLinear.Format = Format_Buffer;
44 
45         // HUC STATUS 2 Buffer for HuC status check in COND_BB_END
46         allocParamsForBufferLinear.dwBytes = sizeof(uint64_t);
47         allocParamsForBufferLinear.pBufName = "Huc authentication status Buffer";
48         allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
49         PMOS_RESOURCE allocatedbuffer       = m_allocator->AllocateResource(allocParamsForBufferLinear, true);
50         ENCODE_CHK_NULL_RETURN(allocatedbuffer);
51         m_hucAuthBuf = allocatedbuffer;
52 
53         for (auto j = 0; j < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; j++)
54         {
55             // VDENC uses second level batch buffer
56             MOS_ZeroMemory(&m_2ndLevelBB[j], sizeof(MHW_BATCH_BUFFER));
57             m_2ndLevelBB[j].bSecondLevel = true;
58             ENCODE_CHK_STATUS_RETURN(Mhw_AllocateBb(
59                 m_hwInterface->GetOsInterface(),
60                 &m_2ndLevelBB[j],
61                 nullptr,
62                 CODECHAL_CACHELINE_SIZE));
63         }
64 
65         return MOS_STATUS_SUCCESS;
66     }
67 
~EncodeCheckHucLoadPkt()68     EncodeCheckHucLoadPkt::~EncodeCheckHucLoadPkt()
69     {
70         ENCODE_CHK_NULL_NO_STATUS_RETURN(m_hwInterface);
71 
72         for (auto j = 0; j < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; j++)
73         {
74             MOS_STATUS eStatus = Mhw_FreeBb(m_hwInterface->GetOsInterface(), &m_2ndLevelBB[j], nullptr);
75             ENCODE_ASSERT(eStatus == MOS_STATUS_SUCCESS);
76         }
77     }
78 
AddForceWakeup(MOS_COMMAND_BUFFER * cmdBuffer)79     MOS_STATUS EncodeCheckHucLoadPkt::AddForceWakeup(MOS_COMMAND_BUFFER *cmdBuffer)
80     {
81         ENCODE_FUNC_CALL();
82 
83         auto &forceWakeupParams                     = m_miItf->MHW_GETPAR_F(MI_FORCE_WAKEUP)();
84         forceWakeupParams                           = {};
85         forceWakeupParams.bMFXPowerWellControl      = true;
86         forceWakeupParams.bMFXPowerWellControlMask  = true;
87         forceWakeupParams.bHEVCPowerWellControl     = true;
88         forceWakeupParams.bHEVCPowerWellControlMask = true;
89 
90         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FORCE_WAKEUP)(cmdBuffer));
91 
92         return MOS_STATUS_SUCCESS;
93     }
94 
SendPrologCmds(MOS_COMMAND_BUFFER * cmdBuffer)95     MOS_STATUS EncodeCheckHucLoadPkt::SendPrologCmds(MOS_COMMAND_BUFFER *cmdBuffer)
96     {
97         MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
98 
99         ENCODE_FUNC_CALL();
100         bool mmcEnabled = false;
101 #ifdef _MMC_SUPPORTED
102         EncodeMemComp *mmcState = m_pipeline->GetMmcState();
103         ENCODE_CHK_NULL_RETURN(mmcState);
104         mmcEnabled = mmcState->IsMmcEnabled();
105         ENCODE_CHK_STATUS_RETURN(mmcState->SendPrologCmd(cmdBuffer, false));
106 #endif
107 
108         MHW_GENERIC_PROLOG_PARAMS genericPrologParams;
109         MOS_ZeroMemory(&genericPrologParams, sizeof(genericPrologParams));
110         ENCODE_CHK_NULL_RETURN(m_hwInterface);
111         genericPrologParams.pOsInterface = m_hwInterface->GetOsInterface();
112         genericPrologParams.pvMiInterface = nullptr;
113         genericPrologParams.bMmcEnabled   = mmcEnabled;
114         ENCODE_CHK_STATUS_RETURN(Mhw_SendGenericPrologCmdNext(cmdBuffer, &genericPrologParams, m_miItf));
115 
116         return eStatus;
117     }
118 
Submit(MOS_COMMAND_BUFFER * commandBuffer,uint8_t packetPhase)119     MOS_STATUS EncodeCheckHucLoadPkt::Submit(MOS_COMMAND_BUFFER *commandBuffer, uint8_t packetPhase)
120     {
121         ENCODE_FUNC_CALL();
122 
123         // add media reset check 100ms, which equals to 1080p WDT threshold
124         ENCODE_CHK_STATUS_RETURN(m_miItf->SetWatchdogTimerThreshold(1920, 1080, true));
125 
126         bool firstTaskInPhase = packetPhase & firstPacket;
127         if (!m_pipeline->IsSingleTaskPhaseSupported() || firstTaskInPhase)
128         {
129             ENCODE_CHK_STATUS_RETURN(AddForceWakeup(commandBuffer));
130             // Send command buffer header at the beginning (OS dependent)
131             ENCODE_CHK_STATUS_RETURN(SendPrologCmds(commandBuffer));
132         }
133 
134         // program 2nd level chained BB for Huc auth
135         m_batchBuf = &m_2ndLevelBB[m_pipeline->m_currRecycledBufIdx];
136         ENCODE_CHK_NULL_RETURN(m_batchBuf);
137         uint8_t *data = (uint8_t *)m_allocator->LockResourceForWrite(&(m_batchBuf->OsResource));
138         ENCODE_CHK_NULL_RETURN(data);
139 
140         MOS_COMMAND_BUFFER hucAuthCmdBuffer = {};
141         hucAuthCmdBuffer.pCmdBase   = (uint32_t *)data;
142         hucAuthCmdBuffer.pCmdPtr    = hucAuthCmdBuffer.pCmdBase;
143         hucAuthCmdBuffer.iRemaining = m_batchBuf->iSize;
144         hucAuthCmdBuffer.OsResource = m_batchBuf->OsResource;
145         hucAuthCmdBuffer.cmdBuf1stLvl = commandBuffer;
146 
147         //pak check huc status command
148         ENCODE_CHK_STATUS_RETURN(PackHucAuthCmds(hucAuthCmdBuffer));
149 
150         ENCODE_CHK_STATUS_RETURN(m_allocator->UnLock(&(m_batchBuf->OsResource)));
151 
152         // BB start for 2nd level BB
153         auto &miBatchBufferStartParams = m_miItf->MHW_GETPAR_F(MI_BATCH_BUFFER_START)();
154         miBatchBufferStartParams       = {};
155         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_BATCH_BUFFER_START)(commandBuffer, m_batchBuf));
156 
157         return MOS_STATUS_SUCCESS;
158     }
159 
PackHucAuthCmds(MOS_COMMAND_BUFFER & cmdBuffer)160     MOS_STATUS EncodeCheckHucLoadPkt::PackHucAuthCmds(MOS_COMMAND_BUFFER &cmdBuffer)
161     {
162         ENCODE_FUNC_CALL();
163 
164         ENCODE_CHK_NULL_RETURN(m_hucItf);
165         auto mmioRegisters = m_hucItf->GetMmioRegisters(m_vdboxIndex);
166         ENCODE_CHK_NULL_RETURN(mmioRegisters);
167 
168         // Write HuC Load Info Mask
169         auto &storeDataParams            = m_miItf->MHW_GETPAR_F(MI_STORE_DATA_IMM)();
170         storeDataParams                  = {};
171         storeDataParams.pOsResource      = m_hucAuthBuf;
172         storeDataParams.dwResourceOffset = 0;
173         storeDataParams.dwValue          = m_hucLoadInfoMask;
174         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_DATA_IMM)(&cmdBuffer));
175 
176         // Store Huc Auth register
177         auto &miStoreRegMemParams           = m_miItf->MHW_GETPAR_F(MI_STORE_REGISTER_MEM)();
178         miStoreRegMemParams                 = {};
179         miStoreRegMemParams.presStoreBuffer = m_hucAuthBuf;
180         miStoreRegMemParams.dwOffset        = sizeof(uint32_t);
181         miStoreRegMemParams.dwRegister      = mmioRegisters->hucLoadInfoOffset;
182         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_STORE_REGISTER_MEM)(&cmdBuffer));
183 
184         // Flush the engine to ensure memory written out
185         auto &flushDwParams = m_miItf->MHW_GETPAR_F(MI_FLUSH_DW)();
186         flushDwParams       = {};
187         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_FLUSH_DW)(&cmdBuffer));
188 
189         // Check Huc load status: if equals to 0 continue chained BB until reset, otherwise send BB end cmd.
190         auto &conditionalBatchBufferEndParams                          = m_miItf->MHW_GETPAR_F(MI_CONDITIONAL_BATCH_BUFFER_END)();
191         conditionalBatchBufferEndParams                                = {};
192         conditionalBatchBufferEndParams.presSemaphoreBuffer            = m_hucAuthBuf;
193         conditionalBatchBufferEndParams.dwOffset                       = 0;
194         conditionalBatchBufferEndParams.dwValue                        = 0;
195         conditionalBatchBufferEndParams.bDisableCompareMask            = false;
196         conditionalBatchBufferEndParams.dwParamsType                   = mhw::mi::MHW_MI_ENHANCED_CONDITIONAL_BATCH_BUFFER_END_PARAMS::ENHANCED_PARAMS;
197         conditionalBatchBufferEndParams.enableEndCurrentBatchBuffLevel = true;
198         conditionalBatchBufferEndParams.compareOperation               = COMPARE_OPERATION_MADEQUALIDD;
199         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_CONDITIONAL_BATCH_BUFFER_END)(&cmdBuffer));
200 
201         // Chained BB loop
202         auto &miBatchBufferStartParams                  = m_miItf->MHW_GETPAR_F(MI_BATCH_BUFFER_START)();
203         miBatchBufferStartParams                        = {};
204         miBatchBufferStartParams.secondLevelBatchBuffer = false;
205         ENCODE_CHK_STATUS_RETURN(m_miItf->MHW_ADDCMD_F(MI_BATCH_BUFFER_START)(&cmdBuffer, m_batchBuf));
206 
207         return MOS_STATUS_SUCCESS;
208     }
209 }
210