Start implementing PMR
PMRs are essentially the PowerVR equivalent of PlatformBuffers.
Change-Id: I5743a4a8fd768326193177111d3220d035da3e18
diff --git a/BUILD.gn b/BUILD.gn
index a41f1ea..c5b83f8 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -209,6 +209,7 @@
deps = [
"//garnet/lib/magma/include:msd_abi",
"//garnet/lib/magma/src/magma_util",
+ "//garnet/lib/magma/src/magma_util/platform:buffer",
"//garnet/lib/magma/src/magma_util/platform:device",
"//zircon/public/lib/zx",
]
diff --git a/services/server/env/fuchsia/physmem_osmem_fuchsia.cc b/services/server/env/fuchsia/physmem_osmem_fuchsia.cc
index 8dd61e3..a5bfe0c 100644
--- a/services/server/env/fuchsia/physmem_osmem_fuchsia.cc
+++ b/services/server/env/fuchsia/physmem_osmem_fuchsia.cc
@@ -31,6 +31,9 @@
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ /**************************************************************************/
/* include/ */
+
+#include <vector>
+
extern "C" {
#include "rgx_heaps.h"
#include "img_types.h"
@@ -47,8 +50,148 @@
#include "physmem_osmem.h"
}
+#include "fuchsia/msd_img_device.h"
+#include "magma_util/macros.h"
+#include "platform_buffer.h"
+#include "platform_bus_mapper.h"
+
#define NOT_IMPLEMENTED() fprintf(stderr, "msd-img-rgx-mtk: Not implemented in %s:%s:%d\n", __func__, __FILE__, __LINE__);
+struct MagmaPhysicalMemoryResource
+{
+ PVRSRV_DEVICE_NODE *psDevNode;
+ std::unique_ptr<magma::PlatformBuffer> buffer;
+ std::unique_ptr<magma::PlatformBusMapper::BusMapping> bus_mapping;
+};
+
+static PVRSRV_ERROR
+LockPhysAddresses(PMR_IMPL_PRIVDATA data)
+{
+ MagmaPhysicalMemoryResource *pmr = reinterpret_cast<MagmaPhysicalMemoryResource *>(data);
+ auto device = MsdImgDevice::cast(pmr->psDevNode->psDevConfig->pvOSDevice);
+ pmr->bus_mapping =
+ device->bus_mapper()->MapPageRangeBus(pmr->buffer.get(), 0, pmr->buffer->size() / magma::page_size());
+ if (!pmr->bus_mapping)
+ {
+ // Could instead be PVRSRV_ERROR_DEVICEMEM_OUT_OF_RANGE, or similar.
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+UnlockPhysAddresses(PMR_IMPL_PRIVDATA data)
+{
+ MagmaPhysicalMemoryResource *pmr = reinterpret_cast<MagmaPhysicalMemoryResource *>(data);
+ pmr->bus_mapping.reset();
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+DevPhysAddr(PMR_IMPL_PRIVDATA pvPriv,
+ IMG_UINT32 ui32Log2PageSize,
+ IMG_UINT32 ui32NumOfAddr,
+ IMG_DEVMEM_OFFSET_T *puiOffset,
+ IMG_BOOL *pbValid,
+ IMG_DEV_PHYADDR *psDevAddrPtr)
+{
+ MagmaPhysicalMemoryResource *pmr = reinterpret_cast<MagmaPhysicalMemoryResource *>(pvPriv);
+ if (ui32Log2PageSize != magma::page_shift())
+ {
+ NOT_IMPLEMENTED();
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+ }
+ for (uint32_t i = 0; i < ui32NumOfAddr; i++)
+ {
+ if (pbValid[i])
+ {
+ uint64_t page_index = puiOffset[i] >> magma::page_shift();
+ uint64_t in_page_offset = puiOffset[i] & (magma::page_size() - 1);
+ psDevAddrPtr[i].uiAddr = pmr->bus_mapping->Get()[page_index] + in_page_offset;
+ }
+ }
+ return PVRSRV_OK;
+}
+
+struct MapHandle
+{
+ uint32_t unused;
+};
+
+static PVRSRV_ERROR
+AcquireKernelMappingData(PMR_IMPL_PRIVDATA pvPriv,
+ size_t uiOffset,
+ size_t uiSize,
+ void **ppvKernelAddressOut,
+ IMG_HANDLE *phHandleOut,
+ PMR_FLAGS_T ulFlags)
+{
+ MagmaPhysicalMemoryResource *pmr = reinterpret_cast<MagmaPhysicalMemoryResource *>(pvPriv);
+ void *cpu_map;
+ // Map entire buffer for now. Also ignore flags.
+ if (!pmr->buffer->MapCpu(&cpu_map))
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ *ppvKernelAddressOut = reinterpret_cast<uint8_t *>(cpu_map) + uiOffset;
+ *phHandleOut = new MapHandle;
+ return PVRSRV_OK;
+}
+
+static void
+ReleaseKernelMappingData(PMR_IMPL_PRIVDATA pvPriv, IMG_HANDLE hHandle)
+{
+ MagmaPhysicalMemoryResource *pmr = reinterpret_cast<MagmaPhysicalMemoryResource *>(pvPriv);
+ pmr->buffer->UnmapCpu();
+ delete reinterpret_cast<MapHandle *>(hHandle);
+}
+
+static PVRSRV_ERROR
+ChangeSparseMem(PMR_IMPL_PRIVDATA pPriv,
+ const PMR *psPMR,
+ IMG_UINT32 ui32AllocPageCount,
+ IMG_UINT32 *pai32AllocIndices,
+ IMG_UINT32 ui32FreePageCount,
+ IMG_UINT32 *pai32FreeIndices,
+ IMG_UINT32 uiFlags)
+{
+ NOT_IMPLEMENTED();
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+static PVRSRV_ERROR
+ChangeSparseMemCpuMap(PMR_IMPL_PRIVDATA pPriv,
+ const PMR *psPMR,
+ IMG_UINT64 sCpuVAddrBase,
+ IMG_UINT32 ui32AllocPageCount,
+ IMG_UINT32 *pai32AllocIndices,
+ IMG_UINT32 ui32FreePageCount,
+ IMG_UINT32 *pai32FreeIndices)
+{
+ NOT_IMPLEMENTED();
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+static PVRSRV_ERROR
+Finalize(PMR_IMPL_PRIVDATA data)
+{
+ MagmaPhysicalMemoryResource *pmr = reinterpret_cast<MagmaPhysicalMemoryResource *>(data);
+ delete pmr;
+ return PVRSRV_OK;
+}
+
+static const PMR_IMPL_FUNCTAB kPmrTable = {
+ .pfnLockPhysAddresses = LockPhysAddresses,
+ .pfnUnlockPhysAddresses = UnlockPhysAddresses,
+ .pfnDevPhysAddr = DevPhysAddr,
+ .pfnAcquireKernelMappingData = AcquireKernelMappingData,
+ .pfnReleaseKernelMappingData = ReleaseKernelMappingData,
+ .pfnChangeSparseMem = ChangeSparseMem,
+ .pfnChangeSparseMemCPUMap = ChangeSparseMemCpuMap,
+ .pfnFinalize = Finalize,
+};
+
+
PVRSRV_ERROR
PhysmemNewOSRamBackedPMR(PVRSRV_DEVICE_NODE *psDevNode,
IMG_DEVMEM_SIZE_T uiSize,
@@ -62,6 +205,41 @@
IMG_PID uiPid,
PMR **ppsPMRPtr)
{
- NOT_IMPLEMENTED();
- return PVRSRV_ERROR_NOT_SUPPORTED;
+ auto pmr = std::make_unique<MagmaPhysicalMemoryResource>();
+ // This may be called before the pvOSDevice is initialized, so store the
+ // entire device node for use later.
+ pmr->psDevNode = psDevNode;
+
+ pmr->buffer = magma::PlatformBuffer::Create(uiSize, pszAnnotation);
+ if (PVRSRV_CHECK_CPU_UNCACHED(uiFlags))
+ {
+ if (!pmr->buffer->SetCachePolicy(MAGMA_CACHE_POLICY_UNCACHED))
+ {
+ return DRET(PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+ }
+ if (PVRSRV_CHECK_CPU_WRITE_COMBINE(uiFlags))
+ {
+ if (!pmr->buffer->SetCachePolicy(MAGMA_CACHE_POLICY_WRITE_COMBINING))
+ {
+ return DRET(PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+ }
+
+ PHYS_HEAP *psPhysHeap = psDevNode->apsPhysHeap[PVRSRV_DEVICE_PHYS_HEAP_CPU_LOCAL];
+ return PMRCreatePMR(psDevNode,
+ psPhysHeap,
+ uiSize,
+ uiChunkSize,
+ ui32NumPhysChunks,
+ ui32NumVirtChunks,
+ puiAllocIndices,
+ magma::page_shift(),
+ 0,
+ pszAnnotation,
+ &kPmrTable,
+ pmr.release(),
+ PMR_TYPE_OSMEM,
+ ppsPMRPtr,
+ 0);
}