1 /*
2 * Copyright (c) 2018-2020, 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 mos_auxtable_mgr.cpp
24 //! \brief Container class for GMM aux table manager wrapper
25 //!
26
27 #include "mos_auxtable_mgr.h"
28 #include "mos_utilities.h"
29
30 //!
31 //! \brief Implementation of device callback for GMM PageTableMgr to allocate page table BO
32 //!
33 //! \param [in] bufMgr
34 //! MOS_BUFMGR pass to GMM PageTableMgr by media driver
35 //! \param [in] size
36 //! Size to be allocated
37 //! \param [in] alignment
38 //! Alignment requirement for the VA address of the allocated buffer
39 //! \param [out] bo
40 //! Poiner to the bo object allocated
41 //! \param [out] cpuAddr
42 //! CPU VA of the bo object allocated
43 //! \param [out] gpuAddr
44 //! CPU VA of the bo object allocated
45 //!
46 //! \return int
47 //! Error status code. 0 if success, else errno.
48 //!
AllocateCb(void * bufMgr,size_t size,size_t alignment,void ** bo,void ** cpuAddr,uint64_t * gpuAddr)49 static int AllocateCb(void *bufMgr, size_t size, size_t alignment, void **bo, void **cpuAddr, uint64_t *gpuAddr)
50 {
51 int ret = 0;
52 MOS_BUFMGR *bm;
53 void *userptr;
54 mos_linux_bo *lbo;
55
56 if (bufMgr == nullptr)
57 return -EINVAL;
58
59 bm = (MOS_BUFMGR *)bufMgr;
60 userptr = MOS_AlignedAllocMemory(size, alignment);
61 if (userptr == nullptr)
62 return -ENOMEM;
63
64 struct mos_drm_bo_alloc_userptr alloc_uptr;
65 alloc_uptr.name = "GmmAuxPageTable";
66 alloc_uptr.addr = userptr;
67 alloc_uptr.tiling_mode = TILING_NONE;
68 alloc_uptr.stride = size;
69 alloc_uptr.size = size;
70
71 lbo = mos_bo_alloc_userptr(bm, &alloc_uptr);
72 if (lbo == nullptr)
73 {
74 MOS_FreeMemory(userptr);
75 return -EAGAIN;
76 }
77
78 mos_bo_set_softpin(lbo);
79
80 *bo = lbo;
81 *cpuAddr = userptr;
82 *gpuAddr = (uint64_t)lbo->offset64;
83
84 return 0;
85 }
86
87 //!
88 //! \brief Implementation of device callback for GMM PageTableMgr to free allocated BO
89 //!
90 //! \param [in] bo
91 //! Poiner to the bo object to be freed
92 //!
93 //! \return none
94 //!
DeallocateCb(void * bo)95 static void DeallocateCb(void *bo)
96 {
97 mos_linux_bo *lbo = (mos_linux_bo *)bo;
98 if (lbo != nullptr)
99 {
100 void* virt = lbo->virt;
101
102 mos_bo_wait_rendering(lbo);
103 mos_bo_unreference(lbo);
104 if (virt)
105 {
106 MOS_FreeMemory(virt);
107 }
108 }
109 }
110
111 //!
112 //! \brief Implementation of device callback for GMM PageTableMgr to wait BO idle
113 //!
114 //! \param [in] bo
115 //! Poiner to the bo object to be waited
116 //!
117 //! \return none
118 //!
WaitFromCpuCb(void * bo)119 static void WaitFromCpuCb(void *bo)
120 {
121 mos_linux_bo *lbo = (mos_linux_bo *)bo;
122 if (lbo != nullptr)
123 {
124 mos_bo_wait_rendering((mos_linux_bo *)bo);
125 }
126 }
127
AuxTableMgr(MOS_BUFMGR * bufMgr,GMM_CLIENT_CONTEXT * gmmClientContext)128 AuxTableMgr::AuxTableMgr(MOS_BUFMGR *bufMgr, GMM_CLIENT_CONTEXT *gmmClientContext)
129 {
130 if (bufMgr)
131 {
132 GMM_DEVICE_CALLBACKS_INT deviceCb = {0};
133
134 m_gmmClientContext = gmmClientContext;
135 if (m_gmmClientContext == nullptr)
136 {
137 MOS_OS_ASSERTMESSAGE(" nullptr returned by GmmCreateClientContext");
138 }
139 else
140 {
141 deviceCb.pBufMgr = bufMgr;
142 deviceCb.DevCbPtrs_.pfnAllocate = AllocateCb;
143 deviceCb.DevCbPtrs_.pfnDeallocate = DeallocateCb;
144 deviceCb.DevCbPtrs_.pfnWaitFromCpu = WaitFromCpuCb;
145
146 m_gmmPageTableMgr = m_gmmClientContext->CreatePageTblMgrObject(&deviceCb, AUXTT);
147 if (m_gmmPageTableMgr == nullptr)
148 {
149 MOS_OS_ASSERTMESSAGE(" nullptr returned by new GMM_PAGETABLE_MGR");
150 }
151 }
152 }
153 }
154
~AuxTableMgr()155 AuxTableMgr::~AuxTableMgr()
156 {
157 if (m_gmmPageTableMgr != nullptr)
158 {
159 m_gmmClientContext->DestroyPageTblMgrObject((GMM_PAGETABLE_MGR *)m_gmmPageTableMgr);
160 m_gmmPageTableMgr = nullptr;
161 }
162 if (m_gmmClientContext != nullptr)
163 {
164 m_gmmClientContext = nullptr;
165 }
166 }
167
CreateAuxTableMgr(MOS_BUFMGR * bufMgr,MEDIA_FEATURE_TABLE * sku,GMM_CLIENT_CONTEXT * gmmClientContext)168 AuxTableMgr * AuxTableMgr::CreateAuxTableMgr(MOS_BUFMGR *bufMgr, MEDIA_FEATURE_TABLE *sku, GMM_CLIENT_CONTEXT *gmmClientContext)
169 {
170 if (MEDIA_IS_SKU(sku, FtrE2ECompression) && !MEDIA_IS_SKU(sku, FtrFlatPhysCCS))
171 {
172 AuxTableMgr *auxTableMgr = MOS_New(AuxTableMgr, bufMgr, gmmClientContext);
173 if (auxTableMgr == nullptr)
174 {
175 MOS_OS_ASSERTMESSAGE(" nullptr returned by creating AuxTableMgr");
176 }
177 return auxTableMgr;
178 }
179 return nullptr;
180 }
181
MapResource(GMM_RESOURCE_INFO * gmmResInfo,MOS_LINUX_BO * bo)182 MOS_STATUS AuxTableMgr::MapResource(GMM_RESOURCE_INFO *gmmResInfo, MOS_LINUX_BO *bo)
183 {
184 if (gmmResInfo == nullptr || bo == nullptr)
185 {
186 return MOS_STATUS_NULL_POINTER;
187 }
188
189 GMM_RESOURCE_FLAG flags = gmmResInfo->GetResFlags();
190 if ((flags.Info.MediaCompressed || flags.Info.RenderCompressed) &&
191 (flags.Gpu.MMC && flags.Gpu.CCS) &&
192 (bo->aux_mapped == false))
193 {
194 int ret = 0;
195
196 ret = mos_bo_set_softpin(bo);
197 if (ret != 0)
198 {
199 MOS_OS_ASSERTMESSAGE("Aux mapping failed: softpin failed");
200 return MOS_STATUS_UNKNOWN;
201 }
202
203 GMM_DDI_UPDATEAUXTABLE updateReq = {};
204
205 updateReq.BaseResInfo = gmmResInfo;
206 updateReq.BaseGpuVA = bo->offset64;
207 updateReq.Map = 1;
208 if (GMM_SUCCESS != ((GMM_PAGETABLE_MGR *)m_gmmPageTableMgr)->UpdateAuxTable(&updateReq))
209 {
210 MOS_OS_ASSERTMESSAGE("update AuxTable failed");
211 return MOS_STATUS_UNKNOWN;
212 }
213 bo->aux_mapped = true;
214 }
215 return MOS_STATUS_SUCCESS;
216 }
217
UnmapResource(GMM_RESOURCE_INFO * gmmResInfo,MOS_LINUX_BO * bo)218 MOS_STATUS AuxTableMgr::UnmapResource(GMM_RESOURCE_INFO *gmmResInfo, MOS_LINUX_BO *bo)
219 {
220 if (gmmResInfo && bo && bo->aux_mapped)
221 {
222 GMM_DDI_UPDATEAUXTABLE updateReq = {};
223
224 MOS_OS_ASSERT(gmmResInfo->GetResFlags().Info.MediaCompressed ||
225 gmmResInfo->GetResFlags().Info.RenderCompressed);
226
227 updateReq.BaseResInfo = gmmResInfo;
228 updateReq.BaseGpuVA = bo->offset64;
229 updateReq.Map = 0;
230 ((GMM_PAGETABLE_MGR*)m_gmmPageTableMgr)->UpdateAuxTable(&updateReq);
231 bo->aux_mapped = false;
232 }
233 return MOS_STATUS_SUCCESS;
234 }
235
EmitAuxTableBOList(MOS_LINUX_BO * cmd_bo)236 MOS_STATUS AuxTableMgr::EmitAuxTableBOList(MOS_LINUX_BO *cmd_bo)
237 {
238 // Retrieve aux table bo list from GMM and emit it to exec buffer bo list
239 int boCnt = ((GMM_PAGETABLE_MGR*)m_gmmPageTableMgr)->GetNumOfPageTableBOs(AUXTT);
240 if (boCnt <= 0) {
241 return MOS_STATUS_SUCCESS;
242 }
243
244 mos_linux_bo **boList = (MOS_LINUX_BO **)MOS_AllocAndZeroMemory(boCnt * sizeof(mos_linux_bo*));
245 if (boList == nullptr)
246 return MOS_STATUS_NO_SPACE;
247
248 ((GMM_PAGETABLE_MGR*)m_gmmPageTableMgr)->GetPageTableBOList(AUXTT, boList);
249 for (int i=0; i<boCnt; i++)
250 {
251 int ret = mos_bo_add_softpin_target(cmd_bo, boList[i], false);
252 if (ret != 0)
253 {
254 MOS_OS_ASSERTMESSAGE("Error patching alloc_bo = 0x%x, cmd_bo = 0x%x.",
255 (uintptr_t)boList[i],
256 (uintptr_t)cmd_bo);
257 return MOS_STATUS_UNKNOWN;
258 }
259 }
260 MOS_FreeMemory(boList);
261
262 return MOS_STATUS_SUCCESS;
263 }
264
GetAuxTableBase()265 uint64_t AuxTableMgr::GetAuxTableBase()
266 {
267 return m_gmmPageTableMgr ? ((GMM_PAGETABLE_MGR*)m_gmmPageTableMgr)->GetAuxL3TableAddr() : 0;
268 }
269