@@ -49,9 +49,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4949#include "allocmem.h"
5050#include "pvr_debug.h"
5151#include "process_stats.h"
52- #if defined(DEBUG ) && defined(SUPPORT_VALIDATION )
53- #include "pvrsrv.h"
54- #endif
5552#include "osfunc.h"
5653
5754
@@ -65,9 +62,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6562 * enabled, since all allocations are tracked in DebugFS mem_area files.
6663 */
6764#if defined(PVRSRV_ENABLE_PROCESS_STATS ) && !defined(PVRSRV_ENABLE_MEMORY_STATS )
68- #define ALLOCMEM_MEMSTATS_PADDING sizeof(IMG_UINT32)
65+ /* kmalloc guarantees a minimal alignment which is ARCH_KMALLOC_MINALIGN. This
66+ * alignment is architecture specific and can be quite big, e.g. on Aarch64
67+ * it can be 64 bytes. This is too much for keeping a single PID field and could
68+ * lead to a lot of wasted memory. This is a reason why we're defaulting to 8
69+ * bytes alignment which should be enough for any architecture.
70+ */
71+ #define ALLOCMEM_PID_SIZE_PADDING PVR_ALIGN(sizeof(IMG_UINT32), 8)
6972#else
70- #define ALLOCMEM_MEMSTATS_PADDING 0UL
73+ #define ALLOCMEM_PID_SIZE_PADDING 0UL
7174#endif
7275
7376/* How many times kmalloc can fail before the allocation threshold is reduced */
@@ -79,10 +82,6 @@ static IMG_UINT32 g_ui32kmallocThreshold = PVR_LINUX_KMALLOC_ALLOCATION_THRESHOL
7982/* Spinlock used so that the global variables above may not be modified by more than 1 thread at a time */
8083static DEFINE_SPINLOCK (kmalloc_lock );
8184
82- #if defined(DEBUG ) && defined(SUPPORT_VALIDATION )
83- static DEFINE_SPINLOCK (kmalloc_leak_lock );
84- static IMG_UINT32 g_ui32kmallocLeakCounter = 0 ;
85- #endif
8685
8786static inline void OSTryDecreaseKmallocThreshold (void )
8887{
@@ -137,7 +136,7 @@ static inline void _pvr_kfree(const void* pvAddr)
137136 kfree (pvAddr );
138137}
139138
140- static inline void _pvr_alloc_stats_add (void * pvAddr , IMG_UINT32 ui32Size DEBUG_MEMSTATS_PARAMS )
139+ static inline void * _pvr_alloc_stats_add (void * pvAddr , IMG_UINT32 ui32Size DEBUG_MEMSTATS_PARAMS )
141140{
142141#if !defined(PVRSRV_ENABLE_PROCESS_STATS )
143142 PVR_UNREFERENCED_PARAMETER (pvAddr );
@@ -152,16 +151,18 @@ static inline void _pvr_alloc_stats_add(void *pvAddr, IMG_UINT32 ui32Size DEBUG_
152151 pvAddr ,
153152 sCpuPAddr ,
154153 ksize (pvAddr ),
155- NULL ,
156154 OSGetCurrentClientProcessIDKM ()
157155 DEBUG_MEMSTATS_ARGS );
158156#else
159- {
160- /* Store the PID in the final additional 4 bytes allocated */
161- IMG_UINT32 * puiTemp = IMG_OFFSET_ADDR (pvAddr , ksize (pvAddr ) - ALLOCMEM_MEMSTATS_PADDING );
162- * puiTemp = OSGetCurrentClientProcessIDKM ();
163- }
164- PVRSRVStatsIncrMemAllocStat (PVRSRV_MEM_ALLOC_TYPE_KMALLOC , ksize (pvAddr ), OSGetCurrentClientProcessIDKM ());
157+ /* because clang has some features that allow detection out-of-bounds
158+ * access we need to put the metadata in the beginning of the allocation */
159+ * (IMG_UINT32 * ) pvAddr = OSGetCurrentClientProcessIDKM ();
160+ PVRSRVStatsIncrMemAllocStat (PVRSRV_MEM_ALLOC_TYPE_KMALLOC , ksize (pvAddr ),
161+ * (IMG_UINT32 * ) pvAddr );
162+
163+ /* because metadata is kept in the beginning of the allocation we need
164+ * to return address offset by the ALLOCMEM_PID_SIZE_PADDING */
165+ pvAddr = (IMG_UINT8 * ) pvAddr + ALLOCMEM_PID_SIZE_PADDING ;
165166#endif /* defined(PVRSRV_ENABLE_MEMORY_STATS) */
166167 }
167168 else
@@ -173,32 +174,36 @@ static inline void _pvr_alloc_stats_add(void *pvAddr, IMG_UINT32 ui32Size DEBUG_
173174 PVRSRVStatsAddMemAllocRecord (PVRSRV_MEM_ALLOC_TYPE_VMALLOC ,
174175 pvAddr ,
175176 sCpuPAddr ,
176- ((ui32Size + PAGE_SIZE - 1 ) & ~(PAGE_SIZE - 1 )),
177- NULL ,
177+ PVR_ALIGN (ui32Size , PAGE_SIZE ),
178178 OSGetCurrentClientProcessIDKM ()
179179 DEBUG_MEMSTATS_ARGS );
180180#else
181181 PVRSRVStatsIncrMemAllocStatAndTrack (PVRSRV_MEM_ALLOC_TYPE_VMALLOC ,
182- (( ui32Size + PAGE_SIZE - 1 ) & ~( PAGE_SIZE - 1 ) ),
182+ PVR_ALIGN ( ui32Size , PAGE_SIZE ),
183183 (IMG_UINT64 )(uintptr_t ) pvAddr ,
184184 OSGetCurrentClientProcessIDKM ());
185185#endif /* defined(PVRSRV_ENABLE_MEMORY_STATS) */
186186 }
187187#endif /* !defined(PVRSRV_ENABLE_PROCESS_STATS) */
188+
189+ return pvAddr ;
188190}
189191
190- static inline void _pvr_alloc_stats_remove (void * pvAddr )
192+ static inline void * _pvr_alloc_stats_remove (void * pvAddr )
191193{
192194#if !defined(PVRSRV_ENABLE_PROCESS_STATS )
193195 PVR_UNREFERENCED_PARAMETER (pvAddr );
194196#else
195197 if (!is_vmalloc_addr (pvAddr ))
196198 {
197199#if !defined(PVRSRV_ENABLE_MEMORY_STATS )
198- {
199- IMG_UINT32 * puiTemp = IMG_OFFSET_ADDR (pvAddr , ksize (pvAddr ) - ALLOCMEM_MEMSTATS_PADDING );
200- PVRSRVStatsDecrMemKAllocStat (ksize (pvAddr ), * puiTemp );
201- }
200+ /* because metadata is kept in the beginning of the allocation we need
201+ * shift address offset by the ALLOCMEM_PID_SIZE_PADDING to the original
202+ * value */
203+ pvAddr = (IMG_UINT8 * ) pvAddr - ALLOCMEM_PID_SIZE_PADDING ;
204+
205+ /* first 4 bytes of the allocation are the process' PID */
206+ PVRSRVStatsDecrMemKAllocStat (ksize (pvAddr ), * (IMG_UINT32 * ) pvAddr );
202207#else
203208 PVRSRVStatsRemoveMemAllocRecord (PVRSRV_MEM_ALLOC_TYPE_KMALLOC ,
204209 (IMG_UINT64 )(uintptr_t ) pvAddr ,
@@ -217,15 +222,17 @@ static inline void _pvr_alloc_stats_remove(void *pvAddr)
217222#endif
218223 }
219224#endif /* !defined(PVRSRV_ENABLE_PROCESS_STATS) */
225+
226+ return pvAddr ;
220227}
221228
222229void * (OSAllocMem )(IMG_UINT32 ui32Size DEBUG_MEMSTATS_PARAMS )
223230{
224231 void * pvRet = NULL ;
225232
226- if ((ui32Size + ALLOCMEM_MEMSTATS_PADDING ) <= g_ui32kmallocThreshold )
233+ if ((ui32Size + ALLOCMEM_PID_SIZE_PADDING ) <= g_ui32kmallocThreshold )
227234 {
228- pvRet = kmalloc (ui32Size + ALLOCMEM_MEMSTATS_PADDING , GFP_KERNEL );
235+ pvRet = kmalloc (ui32Size + ALLOCMEM_PID_SIZE_PADDING , GFP_KERNEL );
229236 if (pvRet == NULL )
230237 {
231238 OSTryDecreaseKmallocThreshold ();
@@ -243,7 +250,7 @@ void *(OSAllocMem)(IMG_UINT32 ui32Size DEBUG_MEMSTATS_PARAMS)
243250
244251 if (pvRet != NULL )
245252 {
246- _pvr_alloc_stats_add (pvRet , ui32Size DEBUG_MEMSTATS_ARGS );
253+ pvRet = _pvr_alloc_stats_add (pvRet , ui32Size DEBUG_MEMSTATS_ARGS );
247254 }
248255
249256 return pvRet ;
@@ -253,9 +260,9 @@ void *(OSAllocZMem)(IMG_UINT32 ui32Size DEBUG_MEMSTATS_PARAMS)
253260{
254261 void * pvRet = NULL ;
255262
256- if ((ui32Size + ALLOCMEM_MEMSTATS_PADDING ) <= g_ui32kmallocThreshold )
263+ if ((ui32Size + ALLOCMEM_PID_SIZE_PADDING ) <= g_ui32kmallocThreshold )
257264 {
258- pvRet = kzalloc (ui32Size + ALLOCMEM_MEMSTATS_PADDING , GFP_KERNEL );
265+ pvRet = kzalloc (ui32Size + ALLOCMEM_PID_SIZE_PADDING , GFP_KERNEL );
259266 if (pvRet == NULL )
260267 {
261268 OSTryDecreaseKmallocThreshold ();
@@ -273,7 +280,7 @@ void *(OSAllocZMem)(IMG_UINT32 ui32Size DEBUG_MEMSTATS_PARAMS)
273280
274281 if (pvRet != NULL )
275282 {
276- _pvr_alloc_stats_add (pvRet , ui32Size DEBUG_MEMSTATS_ARGS );
283+ pvRet = _pvr_alloc_stats_add (pvRet , ui32Size DEBUG_MEMSTATS_ARGS );
277284 }
278285
279286 return pvRet ;
@@ -285,35 +292,9 @@ void *(OSAllocZMem)(IMG_UINT32 ui32Size DEBUG_MEMSTATS_PARAMS)
285292 */
286293void (OSFreeMem )(void * pvMem )
287294{
288- #if defined(DEBUG ) && defined(SUPPORT_VALIDATION )
289- unsigned long flags ;
290- PVRSRV_DATA * psPVRSRVData = PVRSRVGetPVRSRVData ();
291-
292- if (psPVRSRVData )
293- {
294- IMG_UINT32 ui32kmallocLeakMax = psPVRSRVData -> sMemLeakIntervals .ui32OSAlloc ;
295-
296- spin_lock_irqsave (& kmalloc_leak_lock , flags );
297-
298- g_ui32kmallocLeakCounter ++ ;
299- if (ui32kmallocLeakMax && (g_ui32kmallocLeakCounter >= ui32kmallocLeakMax ))
300- {
301- g_ui32kmallocLeakCounter = 0 ;
302- spin_unlock_irqrestore (& kmalloc_leak_lock , flags );
303-
304- PVR_DPF ((PVR_DBG_WARNING ,
305- "%s: Skipped freeing of pointer 0x%p to trigger memory leak." ,
306- __func__ ,
307- pvMem ));
308- return ;
309- }
310-
311- spin_unlock_irqrestore (& kmalloc_leak_lock , flags );
312- }
313- #endif
314295 if (pvMem != NULL )
315296 {
316- _pvr_alloc_stats_remove (pvMem );
297+ pvMem = _pvr_alloc_stats_remove (pvMem );
317298
318299 if (!is_vmalloc_addr (pvMem ))
319300 {
@@ -382,32 +363,6 @@ void *OSAllocZMemNoStats(IMG_UINT32 ui32Size)
382363 */
383364void (OSFreeMemNoStats )(void * pvMem )
384365{
385- #if defined(DEBUG ) && defined(SUPPORT_VALIDATION )
386- unsigned long flags ;
387- PVRSRV_DATA * psPVRSRVData = PVRSRVGetPVRSRVData ();
388-
389- if (psPVRSRVData )
390- {
391- IMG_UINT32 ui32kmallocLeakMax = psPVRSRVData -> sMemLeakIntervals .ui32OSAlloc ;
392-
393- spin_lock_irqsave (& kmalloc_leak_lock , flags );
394-
395- g_ui32kmallocLeakCounter ++ ;
396- if (ui32kmallocLeakMax && (g_ui32kmallocLeakCounter >= ui32kmallocLeakMax ))
397- {
398- g_ui32kmallocLeakCounter = 0 ;
399- spin_unlock_irqrestore (& kmalloc_leak_lock , flags );
400-
401- PVR_DPF ((PVR_DBG_WARNING ,
402- "%s: Skipped freeing of pointer 0x%p to trigger memory leak." ,
403- __func__ ,
404- pvMem ));
405- return ;
406- }
407-
408- spin_unlock_irqrestore (& kmalloc_leak_lock , flags );
409- }
410- #endif
411366 if (pvMem != NULL )
412367 {
413368 if (!is_vmalloc_addr (pvMem ))
0 commit comments