1
/**********************************************************************
3
* Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
5
* This program is free software; you can redistribute it and/or modify it
6
* under the terms and conditions of the GNU General Public License,
7
* version 2, as published by the Free Software Foundation.
9
* This program is distributed in the hope it will be useful but, except
10
* as otherwise stated in writing, without any warranty; without even the
11
* implied warranty of merchantability or fitness for a particular purpose.
12
* See the GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License along with
15
* this program; if not, write to the Free Software Foundation, Inc.,
16
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18
* The full GNU General Public License is included in this distribution in
19
* the file called "COPYING".
21
* Contact Information:
22
* Imagination Technologies Ltd. <gpl-support@imgtec.com>
23
* Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
25
******************************************************************************/
27
#ifndef AUTOCONF_INCLUDED
28
/*#include <linux/config.h>*/
29
#include <generated/autoconf.h>
32
#include <linux/version.h>
34
#include <linux/module.h>
35
#include <linux/vmalloc.h>
36
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
37
#include <linux/wrapper.h>
39
#include <linux/slab.h>
42
#include <asm/shmparam.h>
43
#include <asm/pgtable.h>
44
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22))
45
#include <linux/sched.h>
46
#include <asm/current.h>
48
#if defined(SUPPORT_DRI_DRM)
54
#include "servicesint.h"
59
#include "pvr_debug.h"
65
#include "env_perproc.h"
66
#include "bridged_support.h"
67
#if defined(SUPPORT_DRI_DRM)
71
#if !defined(PVR_SECURE_HANDLES)
72
#error "The mmap code requires PVR_SECURE_HANDLES"
75
static PVRSRV_LINUX_MUTEX g_sMMapMutex;
77
static LinuxKMemCache *g_psMemmapCache = NULL;
78
static LIST_HEAD(g_sMMapAreaList);
79
static LIST_HEAD(g_sMMapOffsetStructList);
80
#if defined(DEBUG_LINUX_MMAP_AREAS)
81
static IMG_UINT32 g_ui32RegisteredAreas = 0;
82
static IMG_UINT32 g_ui32TotalByteSize = 0;
86
#if defined(PVR_PROC_USE_SEQ_FILE) && defined(DEBUG_LINUX_MMAP_AREAS)
87
static struct proc_dir_entry *g_ProcMMap;
90
#define FIRST_PHYSICAL_PFN 0
91
#define LAST_PHYSICAL_PFN 0x7fffffffUL
92
#define FIRST_SPECIAL_PFN (LAST_PHYSICAL_PFN + 1)
93
#define LAST_SPECIAL_PFN 0xffffffffUL
95
#define MAX_MMAP_HANDLE 0x7fffffffUL
97
static inline IMG_BOOL
98
PFNIsPhysical(IMG_UINT32 pfn)
101
return ((pfn >= FIRST_PHYSICAL_PFN) && (pfn <= LAST_PHYSICAL_PFN)) ? IMG_TRUE : IMG_FALSE;
104
static inline IMG_BOOL
105
PFNIsSpecial(IMG_UINT32 pfn)
108
return ((pfn >= FIRST_SPECIAL_PFN) && (pfn <= LAST_SPECIAL_PFN)) ? IMG_TRUE : IMG_FALSE;
111
static inline IMG_HANDLE
112
MMapOffsetToHandle(IMG_UINT32 pfn)
114
if (PFNIsPhysical(pfn))
116
PVR_ASSERT(PFNIsPhysical(pfn));
120
return (IMG_HANDLE)(pfn - FIRST_SPECIAL_PFN);
123
static inline IMG_UINT32
124
HandleToMMapOffset(IMG_HANDLE hHandle)
126
IMG_UINT32 ulHandle = (IMG_UINT32)hHandle;
128
if (PFNIsSpecial(ulHandle))
130
PVR_ASSERT(PFNIsSpecial(ulHandle));
134
return ulHandle + FIRST_SPECIAL_PFN;
137
static inline IMG_BOOL
138
LinuxMemAreaUsesPhysicalMap(LinuxMemArea *psLinuxMemArea)
140
return LinuxMemAreaPhysIsContig(psLinuxMemArea);
143
static inline IMG_UINT32
144
GetCurrentThreadID(IMG_VOID)
147
return (IMG_UINT32)current->pid;
150
static PKV_OFFSET_STRUCT
151
CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
153
PKV_OFFSET_STRUCT psOffsetStruct;
154
#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
155
const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
158
#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
159
PVR_DPF((PVR_DBG_MESSAGE,
160
"%s(%s, psLinuxMemArea: 0x%p, ui32AllocFlags: 0x%8lx)",
161
__FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags));
164
PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
166
PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
168
psOffsetStruct = KMemCacheAllocWrapper(g_psMemmapCache, GFP_KERNEL);
169
if(psOffsetStruct == IMG_NULL)
171
PVR_DPF((PVR_DBG_ERROR,"PVRMMapRegisterArea: Couldn't alloc another mapping record from cache"));
175
psOffsetStruct->ui32MMapOffset = ui32Offset;
177
psOffsetStruct->psLinuxMemArea = psLinuxMemArea;
179
psOffsetStruct->ui32Mapped = 0;
181
psOffsetStruct->ui32RealByteSize = ui32RealByteSize;
184
psOffsetStruct->ui32TID = GetCurrentThreadID();
186
psOffsetStruct->ui32PID = OSGetCurrentProcessIDKM();
188
psOffsetStruct->bOnMMapList = IMG_FALSE;
190
psOffsetStruct->ui32RefCount = 0;
192
psOffsetStruct->ui32UserVAddr = 0;
194
#if defined(DEBUG_LINUX_MMAP_AREAS)
196
psOffsetStruct->pszName = pszName;
199
list_add_tail(&psOffsetStruct->sAreaItem, &psLinuxMemArea->sMMapOffsetStructList);
201
return psOffsetStruct;
206
DestroyOffsetStruct(PKV_OFFSET_STRUCT psOffsetStruct)
208
list_del(&psOffsetStruct->sAreaItem);
210
if (psOffsetStruct->bOnMMapList)
212
list_del(&psOffsetStruct->sMMapItem);
215
PVR_DPF((PVR_DBG_MESSAGE, "%s: Table entry: "
216
"psLinuxMemArea=0x%08lX, CpuPAddr=0x%08lX", __FUNCTION__,
217
psOffsetStruct->psLinuxMemArea,
218
LinuxMemAreaToCpuPAddr(psOffsetStruct->psLinuxMemArea, 0)));
220
KMemCacheFreeWrapper(g_psMemmapCache, psOffsetStruct);
224
static inline IMG_VOID
225
DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea,
226
IMG_UINT32 *pui32RealByteSize,
227
IMG_UINT32 *pui32ByteOffset)
229
IMG_UINT32 ui32PageAlignmentOffset;
230
IMG_CPU_PHYADDR CpuPAddr;
232
CpuPAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0);
233
ui32PageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr);
235
*pui32ByteOffset = ui32PageAlignmentOffset;
237
*pui32RealByteSize = PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset);
242
PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
244
IMG_UINT32 *pui32MMapOffset,
245
IMG_UINT32 *pui32ByteOffset,
246
IMG_UINT32 *pui32RealByteSize,
247
IMG_UINT32 *pui32UserVAddr)
249
LinuxMemArea *psLinuxMemArea;
250
PKV_OFFSET_STRUCT psOffsetStruct;
251
IMG_HANDLE hOSMemHandle;
254
LinuxLockMutex(&g_sMMapMutex);
256
PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
258
eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
259
if (eError != PVRSRV_OK)
261
PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle 0x%lx failed", __FUNCTION__, hMHandle));
266
psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
268
DetermineUsersSizeAndByteOffset(psLinuxMemArea,
273
list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
275
if (psPerProc->ui32PID == psOffsetStruct->ui32PID)
278
PVR_ASSERT(*pui32RealByteSize == psOffsetStruct->ui32RealByteSize);
280
*pui32MMapOffset = psOffsetStruct->ui32MMapOffset;
281
*pui32UserVAddr = psOffsetStruct->ui32UserVAddr;
282
psOffsetStruct->ui32RefCount++;
292
if (LinuxMemAreaUsesPhysicalMap(psLinuxMemArea))
294
*pui32MMapOffset = LinuxMemAreaToCpuPFN(psLinuxMemArea, 0);
295
PVR_ASSERT(PFNIsPhysical(*pui32MMapOffset));
299
*pui32MMapOffset = HandleToMMapOffset(hMHandle);
300
PVR_ASSERT(PFNIsSpecial(*pui32MMapOffset));
303
psOffsetStruct = CreateOffsetStruct(psLinuxMemArea, *pui32MMapOffset, *pui32RealByteSize);
304
if (psOffsetStruct == IMG_NULL)
306
eError = PVRSRV_ERROR_OUT_OF_MEMORY;
311
list_add_tail(&psOffsetStruct->sMMapItem, &g_sMMapOffsetStructList);
313
psOffsetStruct->bOnMMapList = IMG_TRUE;
315
psOffsetStruct->ui32RefCount++;
320
LinuxUnLockMutex(&g_sMMapMutex);
327
PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
330
IMG_UINT32 *pui32RealByteSize,
331
IMG_UINT32 *pui32UserVAddr)
333
LinuxMemArea *psLinuxMemArea;
334
PKV_OFFSET_STRUCT psOffsetStruct;
335
IMG_HANDLE hOSMemHandle;
337
IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
339
LinuxLockMutex(&g_sMMapMutex);
341
PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <= MAX_MMAP_HANDLE);
343
eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle, hMHandle);
344
if (eError != PVRSRV_OK)
346
PVR_DPF((PVR_DBG_ERROR, "%s: Lookup of handle 0x%lx failed", __FUNCTION__, hMHandle));
351
psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
354
list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
356
if (psOffsetStruct->ui32PID == ui32PID)
358
if (psOffsetStruct->ui32RefCount == 0)
360
PVR_DPF((PVR_DBG_ERROR, "%s: Attempt to release mmap data with zero reference count for offset struct 0x%p, memory area 0x%p", __FUNCTION__, psOffsetStruct, psLinuxMemArea));
361
eError = PVRSRV_ERROR_GENERIC;
365
psOffsetStruct->ui32RefCount--;
367
*pbMUnmap = (IMG_BOOL)((psOffsetStruct->ui32RefCount == 0) && (psOffsetStruct->ui32UserVAddr != 0));
369
*pui32UserVAddr = (*pbMUnmap) ? psOffsetStruct->ui32UserVAddr : 0;
370
*pui32RealByteSize = (*pbMUnmap) ? psOffsetStruct->ui32RealByteSize : 0;
378
PVR_DPF((PVR_DBG_ERROR, "%s: Mapping data not found for handle 0x%lx (memory area 0x%p)", __FUNCTION__, hMHandle, psLinuxMemArea));
380
eError = PVRSRV_ERROR_GENERIC;
383
LinuxUnLockMutex(&g_sMMapMutex);
388
static inline PKV_OFFSET_STRUCT
389
FindOffsetStructByOffset(IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
391
PKV_OFFSET_STRUCT psOffsetStruct;
392
IMG_UINT32 ui32TID = GetCurrentThreadID();
393
IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
395
list_for_each_entry(psOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
397
if (ui32Offset == psOffsetStruct->ui32MMapOffset && ui32RealByteSize == psOffsetStruct->ui32RealByteSize && psOffsetStruct->ui32PID == ui32PID)
400
if (!PFNIsPhysical(ui32Offset) || psOffsetStruct->ui32TID == ui32TID)
402
return psOffsetStruct;
412
DoMapToUser(LinuxMemArea *psLinuxMemArea,
413
struct vm_area_struct* ps_vma,
414
IMG_UINT32 ui32ByteOffset)
416
IMG_UINT32 ui32ByteSize;
418
if (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
420
return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea),
422
psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset + ui32ByteOffset);
426
ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
427
PVR_ASSERT(ADDR_TO_PAGE_OFFSET(ui32ByteSize) == 0);
429
#if defined (__sparc__)
431
#error "SPARC not supported"
434
if (PFNIsPhysical(ps_vma->vm_pgoff))
438
PVR_ASSERT(LinuxMemAreaPhysIsContig(psLinuxMemArea));
439
PVR_ASSERT(LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) == ps_vma->vm_pgoff);
442
result = IO_REMAP_PFN_RANGE(ps_vma, ps_vma->vm_start, ps_vma->vm_pgoff, ui32ByteSize, ps_vma->vm_page_prot);
449
PVR_DPF((PVR_DBG_MESSAGE, "%s: Failed to map contiguous physical address range (%d), trying non-contiguous path", __FUNCTION__, result));
455
IMG_UINT32 ui32ByteEnd = ui32ByteOffset + ui32ByteSize;
459
for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
461
IMG_UINT32 pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
465
PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x%lx", __FUNCTION__, pfn));
471
ulVMAPos = ps_vma->vm_start;
472
for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
478
pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
479
PVR_ASSERT(pfn_valid(pfn));
481
psPage = pfn_to_page(pfn);
483
result = VM_INSERT_PAGE(ps_vma, ulVMAPos, psPage);
486
PVR_DPF((PVR_DBG_ERROR,"%s: Error - VM_INSERT_PAGE failed (%d)", __FUNCTION__, result));
489
ulVMAPos += PAGE_SIZE;
498
MMapVOpenNoLock(struct vm_area_struct* ps_vma)
500
PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
501
PVR_ASSERT(psOffsetStruct != IMG_NULL)
502
psOffsetStruct->ui32Mapped++;
503
PVR_ASSERT(!psOffsetStruct->bOnMMapList);
505
if (psOffsetStruct->ui32Mapped > 1)
507
PVR_DPF((PVR_DBG_WARNING, "%s: Offset structure 0x%p is being shared across processes (psOffsetStruct->ui32Mapped: %lu)", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32Mapped));
508
PVR_ASSERT((ps_vma->vm_flags & VM_DONTCOPY) == 0);
511
#if defined(DEBUG_LINUX_MMAP_AREAS)
513
PVR_DPF((PVR_DBG_MESSAGE,
514
"%s: psLinuxMemArea 0x%p, KVAddress 0x%p MMapOffset %ld, ui32Mapped %d",
516
psOffsetStruct->psLinuxMemArea,
517
LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
518
psOffsetStruct->ui32MMapOffset,
519
psOffsetStruct->ui32Mapped));
522
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
529
MMapVOpen(struct vm_area_struct* ps_vma)
531
LinuxLockMutex(&g_sMMapMutex);
533
MMapVOpenNoLock(ps_vma);
535
LinuxUnLockMutex(&g_sMMapMutex);
540
MMapVCloseNoLock(struct vm_area_struct* ps_vma)
542
PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
543
PVR_ASSERT(psOffsetStruct != IMG_NULL)
545
#if defined(DEBUG_LINUX_MMAP_AREAS)
546
PVR_DPF((PVR_DBG_MESSAGE,
547
"%s: psLinuxMemArea 0x%p, CpuVAddr 0x%p ui32MMapOffset %ld, ui32Mapped %d",
549
psOffsetStruct->psLinuxMemArea,
550
LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
551
psOffsetStruct->ui32MMapOffset,
552
psOffsetStruct->ui32Mapped));
555
PVR_ASSERT(!psOffsetStruct->bOnMMapList);
556
psOffsetStruct->ui32Mapped--;
557
if (psOffsetStruct->ui32Mapped == 0)
559
if (psOffsetStruct->ui32RefCount != 0)
561
PVR_DPF((PVR_DBG_MESSAGE, "%s: psOffsetStruct 0x%p has non-zero reference count (ui32RefCount = %lu). User mode address of start of mapping: 0x%lx", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32RefCount, psOffsetStruct->ui32UserVAddr));
564
DestroyOffsetStruct(psOffsetStruct);
567
ps_vma->vm_private_data = NULL;
569
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
575
MMapVClose(struct vm_area_struct* ps_vma)
577
LinuxLockMutex(&g_sMMapMutex);
579
MMapVCloseNoLock(ps_vma);
581
LinuxUnLockMutex(&g_sMMapMutex);
585
static struct vm_operations_struct MMapIOOps =
593
PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
595
IMG_UINT32 ui32ByteSize;
596
PKV_OFFSET_STRUCT psOffsetStruct;
599
PVR_UNREFERENCED_PARAMETER(pFile);
601
LinuxLockMutex(&g_sMMapMutex);
603
ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
606
PVR_DPF((PVR_DBG_MESSAGE, "%s: Received mmap(2) request with ui32MMapOffset 0x%08lx,"
607
" and ui32ByteSize %ld(0x%08lx)",
610
ui32ByteSize, ui32ByteSize));
612
psOffsetStruct = FindOffsetStructByOffset(ps_vma->vm_pgoff, ui32ByteSize);
613
if (psOffsetStruct == IMG_NULL)
615
#if defined(SUPPORT_DRI_DRM)
616
LinuxUnLockMutex(&g_sMMapMutex);
619
return drm_mmap(pFile, ps_vma);
621
PVR_UNREFERENCED_PARAMETER(pFile);
623
#if 0 /* FIXME: crash when call to print debug messages */
624
PVR_DPF((PVR_DBG_ERROR,
625
"%s: Attempted to mmap unregistered area at vm_pgoff %ld",
626
__FUNCTION__, ps_vma->vm_pgoff));
630
goto unlock_and_return;
632
list_del(&psOffsetStruct->sMMapItem);
633
psOffsetStruct->bOnMMapList = IMG_FALSE;
636
if (((ps_vma->vm_flags & VM_WRITE) != 0) &&
637
((ps_vma->vm_flags & VM_SHARED) == 0))
639
#if 0 /* FIXME: crash when call to print debug messages */
640
PVR_DPF((PVR_DBG_ERROR, "%s: Cannot mmap non-shareable writable areas", __FUNCTION__));
643
goto unlock_and_return;
647
#if 0 /* FIXME: crash when call to print debug messages */
648
PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped psLinuxMemArea 0x%p\n",
649
__FUNCTION__, psOffsetStruct->psLinuxMemArea));
651
ps_vma->vm_flags |= VM_RESERVED;
652
ps_vma->vm_flags |= VM_IO;
655
ps_vma->vm_flags |= VM_DONTEXPAND;
658
ps_vma->vm_flags |= VM_DONTCOPY;
660
ps_vma->vm_private_data = (void *)psOffsetStruct;
662
switch(psOffsetStruct->psLinuxMemArea->ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK)
664
case PVRSRV_HAP_CACHED:
667
case PVRSRV_HAP_WRITECOMBINE:
668
ps_vma->vm_page_prot = PGPROT_WC(ps_vma->vm_page_prot);
670
case PVRSRV_HAP_UNCACHED:
671
ps_vma->vm_page_prot = PGPROT_UC(ps_vma->vm_page_prot);
674
PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type", __FUNCTION__));
676
goto unlock_and_return;
680
ps_vma->vm_ops = &MMapIOOps;
682
if(!DoMapToUser(psOffsetStruct->psLinuxMemArea, ps_vma, 0))
685
goto unlock_and_return;
688
PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0)
690
psOffsetStruct->ui32UserVAddr = ps_vma->vm_start;
693
MMapVOpenNoLock(ps_vma);
695
#if 0 /* FIXME: crash when call to print debug messages */
696
PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n",
697
__FUNCTION__, ps_vma->vm_pgoff));
701
if (iRetVal != 0 && psOffsetStruct != IMG_NULL)
703
DestroyOffsetStruct(psOffsetStruct);
706
LinuxUnLockMutex(&g_sMMapMutex);
712
#if defined(DEBUG_LINUX_MMAP_AREAS)
714
#ifdef PVR_PROC_USE_SEQ_FILE
716
static void ProcSeqStartstopMMapRegistations(struct seq_file *sfile,IMG_BOOL start)
720
LinuxLockMutex(&g_sMMapMutex);
724
LinuxUnLockMutex(&g_sMMapMutex);
729
static void* ProcSeqOff2ElementMMapRegistrations(struct seq_file *sfile, loff_t off)
731
LinuxMemArea *psLinuxMemArea;
734
return PVR_PROC_SEQ_START_TOKEN;
737
list_for_each_entry(psLinuxMemArea, &g_sMMapAreaList, sMMapItem)
739
PKV_OFFSET_STRUCT psOffsetStruct;
741
list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
746
PVR_ASSERT(psOffsetStruct->psLinuxMemArea == psLinuxMemArea);
747
return (void*)psOffsetStruct;
754
static void* ProcSeqNextMMapRegistrations(struct seq_file *sfile,void* el,loff_t off)
756
return ProcSeqOff2ElementMMapRegistrations(sfile,off);
760
static void ProcSeqShowMMapRegistrations(struct seq_file *sfile,void* el)
762
KV_OFFSET_STRUCT *psOffsetStruct = (KV_OFFSET_STRUCT*)el;
763
LinuxMemArea *psLinuxMemArea;
764
IMG_UINT32 ui32RealByteSize;
765
IMG_UINT32 ui32ByteOffset;
767
if(el == PVR_PROC_SEQ_START_TOKEN)
770
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
771
"Allocations registered for mmap: %lu\n"
772
"In total these areas correspond to %lu bytes\n"
783
"\t<count>%lu</count>\n"
784
"\t<bytes>%lu</bytes>\n"
787
g_ui32RegisteredAreas,
793
psLinuxMemArea = psOffsetStruct->psLinuxMemArea;
795
DetermineUsersSizeAndByteOffset(psLinuxMemArea,
800
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
801
"%-8p %08lx %-8p %08lx %08lx %-8ld %-24s %-5lu %-8s %08lx(%s)\n",
804
"\t<pointer>%-8p</pointer>\n"
805
"\t<user_virtual>%-8lx</user_virtual>\n"
806
"\t<kernel_virtual>%-8p</kernel_virtual>\n"
807
"\t<cpu_physical>%08lx</cpu_physical>\n"
808
"\t<mmap_offset>%08lx</mmap_offset>\n"
809
"\t<bytes>%-8ld</bytes>\n"
810
"\t<linux_mem_area_type>%-24s</linux_mem_area_type>\n"
811
"\t<pid>%-5lu</pid>\n"
812
"\t<name>%-8s</name>\n"
813
"\t<flags>%08lx</flags>\n"
814
"\t<flags_string>%s</flags_string>\n"
818
psOffsetStruct->ui32UserVAddr + ui32ByteOffset,
819
LinuxMemAreaToCpuVAddr(psLinuxMemArea),
820
LinuxMemAreaToCpuPAddr(psLinuxMemArea,0).uiAddr,
821
psOffsetStruct->ui32MMapOffset,
822
psLinuxMemArea->ui32ByteSize,
823
LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType),
824
psOffsetStruct->ui32PID,
825
psOffsetStruct->pszName,
826
psLinuxMemArea->ui32AreaFlags,
827
HAPFlagsToString(psLinuxMemArea->ui32AreaFlags));
833
PrintMMapRegistrations(IMG_CHAR *buffer, size_t size, off_t off)
835
LinuxMemArea *psLinuxMemArea;
838
LinuxLockMutex(&g_sMMapMutex);
842
Ret = printAppend(buffer, size, 0,
843
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
844
"Allocations registered for mmap: %lu\n"
845
"In total these areas correspond to %lu bytes\n"
856
"\t<count>%lu</count>\n"
857
"\t<bytes>%lu</bytes>\n"
860
g_ui32RegisteredAreas,
864
goto unlock_and_return;
870
goto unlock_and_return;
873
PVR_ASSERT(off != 0);
874
list_for_each_entry(psLinuxMemArea, &g_sMMapAreaList, sMMapItem)
876
PKV_OFFSET_STRUCT psOffsetStruct;
878
list_for_each_entry(psOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
883
IMG_UINT32 ui32RealByteSize;
884
IMG_UINT32 ui32ByteOffset;
886
PVR_ASSERT(psOffsetStruct->psLinuxMemArea == psLinuxMemArea);
888
DetermineUsersSizeAndByteOffset(psLinuxMemArea,
892
Ret = printAppend (buffer, size, 0,
893
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
894
"%-8p %08lx %-8p %08lx %08lx %-8ld %-24s %-5lu %-8s %08lx(%s)\n",
897
"\t<pointer>%-8p</pointer>\n"
898
"\t<user_virtual>%-8lx</user_virtual>\n"
899
"\t<kernel_virtual>%-8p</kernel_virtual>\n"
900
"\t<cpu_physical>%08lx</cpu_physical>\n"
901
"\t<mmap_offset>%08lx</mmap_offset>\n"
902
"\t<bytes>%-8ld</bytes>\n"
903
"\t<linux_mem_area_type>%-24s</linux_mem_area_type>\n"
904
"\t<pid>%-5lu</pid>\n"
905
"\t<name>%-8s</name>\n"
906
"\t<flags>%08lx</flags>\n"
907
"\t<flags_string>%s</flags_string>\n"
911
psOffsetStruct->ui32UserVAddr + ui32ByteOffset,
912
LinuxMemAreaToCpuVAddr(psLinuxMemArea),
913
LinuxMemAreaToCpuPAddr(psLinuxMemArea,0).uiAddr,
914
psOffsetStruct->ui32MMapOffset,
915
psLinuxMemArea->ui32ByteSize,
916
LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType),
917
psOffsetStruct->ui32PID,
918
psOffsetStruct->pszName,
919
psLinuxMemArea->ui32AreaFlags,
920
HAPFlagsToString(psLinuxMemArea->ui32AreaFlags));
921
goto unlock_and_return;
928
LinuxUnLockMutex(&g_sMMapMutex);
936
PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea)
939
#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
940
const IMG_CHAR *pszName = LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
943
LinuxLockMutex(&g_sMMapMutex);
945
#if defined(DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
946
PVR_DPF((PVR_DBG_MESSAGE,
947
"%s(%s, psLinuxMemArea 0x%p, ui32AllocFlags 0x%8lx)",
948
__FUNCTION__, pszName, psLinuxMemArea, psLinuxMemArea->ui32AreaFlags));
951
PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
954
if(psLinuxMemArea->bMMapRegistered)
956
PVR_DPF((PVR_DBG_ERROR, "%s: psLinuxMemArea 0x%p is already registered",
957
__FUNCTION__, psLinuxMemArea));
958
eError = PVRSRV_ERROR_INVALID_PARAMS;
962
list_add_tail(&psLinuxMemArea->sMMapItem, &g_sMMapAreaList);
964
psLinuxMemArea->bMMapRegistered = IMG_TRUE;
966
#if defined(DEBUG_LINUX_MMAP_AREAS)
967
g_ui32RegisteredAreas++;
969
if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
971
g_ui32TotalByteSize += psLinuxMemArea->ui32ByteSize;
978
LinuxUnLockMutex(&g_sMMapMutex);
985
PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea)
988
PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
990
LinuxLockMutex(&g_sMMapMutex);
992
PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
994
list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &psLinuxMemArea->sMMapOffsetStructList, sAreaItem)
996
if (psOffsetStruct->ui32Mapped != 0)
998
PVR_DPF((PVR_DBG_ERROR, "%s: psOffsetStruct 0x%p for memory area 0x0x%p is still mapped; psOffsetStruct->ui32Mapped %lu", __FUNCTION__, psOffsetStruct, psLinuxMemArea, psOffsetStruct->ui32Mapped));
999
eError = PVRSRV_ERROR_GENERIC;
1005
PVR_DPF((PVR_DBG_WARNING, "%s: psOffsetStruct 0x%p was never mapped", __FUNCTION__, psOffsetStruct));
1008
PVR_ASSERT((psOffsetStruct->ui32Mapped == 0) && psOffsetStruct->bOnMMapList);
1010
DestroyOffsetStruct(psOffsetStruct);
1013
list_del(&psLinuxMemArea->sMMapItem);
1015
psLinuxMemArea->bMMapRegistered = IMG_FALSE;
1017
#if defined(DEBUG_LINUX_MMAP_AREAS)
1018
g_ui32RegisteredAreas--;
1019
if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
1021
g_ui32TotalByteSize -= psLinuxMemArea->ui32ByteSize;
1028
LinuxUnLockMutex(&g_sMMapMutex);
1034
LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
1036
PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
1042
LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
1044
PKV_OFFSET_STRUCT psOffsetStruct, psTmpOffsetStruct;
1045
IMG_BOOL bWarn = IMG_FALSE;
1046
IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
1048
PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
1050
LinuxLockMutex(&g_sMMapMutex);
1052
list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct, &g_sMMapOffsetStructList, sMMapItem)
1054
if (psOffsetStruct->ui32PID == ui32PID)
1058
PVR_DPF((PVR_DBG_WARNING, "%s: process has unmapped offset structures. Removing them", __FUNCTION__));
1061
PVR_ASSERT(psOffsetStruct->ui32Mapped == 0);
1062
PVR_ASSERT(psOffsetStruct->bOnMMapList);
1064
DestroyOffsetStruct(psOffsetStruct);
1068
LinuxUnLockMutex(&g_sMMapMutex);
1072
PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
1074
PVRSRV_ERROR eError;
1076
eError = PVRSRVSetMaxHandle(psHandleBase, MAX_MMAP_HANDLE);
1077
if (eError != PVRSRV_OK)
1079
PVR_DPF((PVR_DBG_ERROR,"%s: failed to set handle limit (%d)", __FUNCTION__, eError));
1088
PVRMMapInit(IMG_VOID)
1090
LinuxInitMutex(&g_sMMapMutex);
1092
g_psMemmapCache = KMemCacheCreateWrapper("img-mmap", sizeof(KV_OFFSET_STRUCT), 0, 0);
1093
if (!g_psMemmapCache)
1095
PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__));
1099
#if defined(DEBUG_LINUX_MMAP_AREAS)
1100
#ifdef PVR_PROC_USE_SEQ_FILE
1101
g_ProcMMap = CreateProcReadEntrySeq("mmap", NULL,
1102
ProcSeqNextMMapRegistrations,
1103
ProcSeqShowMMapRegistrations,
1104
ProcSeqOff2ElementMMapRegistrations,
1105
ProcSeqStartstopMMapRegistations
1108
CreateProcReadEntry("mmap", PrintMMapRegistrations);
1120
PVRMMapCleanup(IMG_VOID)
1122
PVRSRV_ERROR eError;
1124
if (!list_empty(&g_sMMapAreaList))
1126
LinuxMemArea *psLinuxMemArea, *psTmpMemArea;
1128
PVR_DPF((PVR_DBG_ERROR, "%s: Memory areas are still registered with MMap", __FUNCTION__));
1130
PVR_TRACE(("%s: Unregistering memory areas", __FUNCTION__));
1131
list_for_each_entry_safe(psLinuxMemArea, psTmpMemArea, &g_sMMapAreaList, sMMapItem)
1133
eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
1134
if (eError != PVRSRV_OK)
1136
PVR_DPF((PVR_DBG_ERROR, "%s: PVRMMapRemoveRegisteredArea failed (%d)", __FUNCTION__, eError));
1138
PVR_ASSERT(eError == PVRSRV_OK);
1140
LinuxMemAreaDeepFree(psLinuxMemArea);
1143
PVR_ASSERT(list_empty((&g_sMMapAreaList)));
1145
#if defined(DEBUG_LINUX_MMAP_AREAS)
1146
#ifdef PVR_PROC_USE_SEQ_FILE
1147
RemoveProcEntrySeq(g_ProcMMap);
1149
RemoveProcEntry("mmap");
1155
KMemCacheDestroyWrapper(g_psMemmapCache);
1156
g_psMemmapCache = NULL;