DECLHIDDEN(int) rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment) { AssertMsgReturn(PhysHighest >= 16 *_1M, ("PhysHigest=%RHp\n", PhysHighest), VERR_NOT_SUPPORTED); /** @todo alignment */ if (uAlignment != PAGE_SIZE) return VERR_NOT_SUPPORTED; /* create the object. */ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_PHYS, NULL, cb); if (!pMemOs2) return VERR_NO_MEMORY; /* do the allocation. */ ULONG ulPhys = ~0UL; int rc = KernVMAlloc(cb, VMDHA_FIXED | VMDHA_CONTIG | (PhysHighest < _4G ? VMDHA_16M : 0), &pMemOs2->Core.pv, (PPVOID)&ulPhys, NULL); if (!rc) { Assert(ulPhys != ~0UL); pMemOs2->Core.u.Phys.fAllocated = true; pMemOs2->Core.u.Phys.PhysBase = ulPhys; *ppMem = &pMemOs2->Core; return VINF_SUCCESS; } rtR0MemObjDelete(&pMemOs2->Core); return RTErrConvertFromOS2(rc); }
DECLHIDDEN(int) rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable) { NOREF(fExecutable); /* create the object. */ const ULONG cPages = cb >> PAGE_SHIFT; PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, aPages[cPages]), RTR0MEMOBJTYPE_LOW, NULL, cb); if (!pMemOs2) return VERR_NO_MEMORY; /* do the allocation. */ int rc = KernVMAlloc(cb, VMDHA_FIXED, &pMemOs2->Core.pv, (PPVOID)-1, NULL); if (!rc) { ULONG cPagesRet = cPages; rc = KernLinToPageList(pMemOs2->Core.pv, cb, &pMemOs2->aPages[0], &cPagesRet); if (!rc) { rtR0MemObjFixPageList(&pMemOs2->aPages[0], cPages, cPagesRet); *ppMem = &pMemOs2->Core; return VINF_SUCCESS; } KernVMFree(pMemOs2->Core.pv); } rtR0MemObjDelete(&pMemOs2->Core); rc = RTErrConvertFromOS2(rc); return rc == VERR_NO_MEMORY ? VERR_NO_LOW_MEMORY : rc; }
DECLHIDDEN(int) rtR0MemAllocEx(size_t cb, uint32_t fFlags, PRTMEMHDR *ppHdr) { if (fFlags & RTMEMHDR_FLAG_ANY_CTX) return VERR_NOT_SUPPORTED; void *pv = NULL; APIRET rc = KernVMAlloc(cb + sizeof(RTMEMHDR), VMDHA_FIXED, &pv, (void **)-1, NULL); if (RT_UNLIKELY(rc != NO_ERROR)) return RTErrConvertFromOS2(rc); PRTMEMHDR pHdr = (PRTMEMHDR)pv; pHdr->u32Magic = RTMEMHDR_MAGIC; pHdr->fFlags = fFlags; pHdr->cb = cb; pHdr->cbReq = cb; *ppHdr = pHdr; return VINF_SUCCESS; }
DECLHIDDEN(int) rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable) { NOREF(fExecutable); /* create the object. */ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_CONT, NULL, cb); if (!pMemOs2) return VERR_NO_MEMORY; /* do the allocation. */ ULONG ulPhys = ~0UL; int rc = KernVMAlloc(cb, VMDHA_FIXED | VMDHA_CONTIG, &pMemOs2->Core.pv, (PPVOID)&ulPhys, NULL); if (!rc) { Assert(ulPhys != ~0UL); pMemOs2->Core.u.Cont.Phys = ulPhys; *ppMem = &pMemOs2->Core; return VINF_SUCCESS; } rtR0MemObjDelete(&pMemOs2->Core); return RTErrConvertFromOS2(rc); }
RTR0DECL(void *) RTMemContAlloc(PRTCCPHYS pPhys, size_t cb) { /* * Validate input. */ AssertPtr(pPhys); Assert(cb > 0); /* * All physical memory in OS/2 is below 4GB, so this should be kind of easy. */ cb = RT_ALIGN_Z(cb, PAGE_SIZE); /* -> page aligned result. */ PVOID pv = NULL; PVOID PhysAddr = (PVOID)~0UL; APIRET rc = KernVMAlloc(cb, VMDHA_FIXED | VMDHA_CONTIG, &pv, &PhysAddr, NULL); if (!rc) { Assert(PhysAddr != (PVOID)~0UL); Assert(!((uintptr_t)pv & PAGE_OFFSET_MASK)); *pPhys = (uintptr_t)PhysAddr; return pv; } return NULL; }
DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process) { AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED); AssertMsgReturn(R3PtrFixed == (RTR3PTR)-1, ("%p\n", R3PtrFixed), VERR_NOT_SUPPORTED); if (uAlignment > PAGE_SIZE) return VERR_NOT_SUPPORTED; int rc; void *pvR0; void *pvR3 = NULL; PRTR0MEMOBJOS2 pMemToMapOs2 = (PRTR0MEMOBJOS2)pMemToMap; switch (pMemToMapOs2->Core.enmType) { /* * These has kernel mappings. */ case RTR0MEMOBJTYPE_PAGE: case RTR0MEMOBJTYPE_LOW: case RTR0MEMOBJTYPE_CONT: pvR0 = pMemToMapOs2->Core.pv; break; case RTR0MEMOBJTYPE_PHYS: pvR0 = pMemToMapOs2->Core.pv; #if 0/* this is wrong. */ if (!pvR0) { /* no ring-0 mapping, so allocate a mapping in the process. */ AssertMsgReturn(fProt & RTMEM_PROT_WRITE, ("%#x\n", fProt), VERR_NOT_SUPPORTED); Assert(!pMemToMapOs2->Core.u.Phys.fAllocated); ULONG ulPhys = pMemToMapOs2->Core.u.Phys.PhysBase; rc = KernVMAlloc(pMemToMapOs2->Core.cb, VMDHA_PHYS | VMDHA_PROCESS, &pvR3, (PPVOID)&ulPhys, NULL); if (rc) return RTErrConvertFromOS2(rc); } break; #endif return VERR_NOT_SUPPORTED; case RTR0MEMOBJTYPE_PHYS_NC: AssertMsgFailed(("RTR0MEMOBJTYPE_PHYS_NC\n")); return VERR_INTERNAL_ERROR_5; break; case RTR0MEMOBJTYPE_LOCK: if (pMemToMapOs2->Core.u.Lock.R0Process != NIL_RTR0PROCESS) return VERR_NOT_SUPPORTED; /** @todo implement this... */ pvR0 = pMemToMapOs2->Core.pv; break; case RTR0MEMOBJTYPE_RES_VIRT: case RTR0MEMOBJTYPE_MAPPING: default: AssertMsgFailed(("enmType=%d\n", pMemToMapOs2->Core.enmType)); return VERR_INTERNAL_ERROR; } /* * Map the ring-0 memory into the current process. */ if (!pvR3) { Assert(pvR0); ULONG flFlags = 0; if (uAlignment == PAGE_SIZE) flFlags |= VMDHGP_4MB; if (fProt & RTMEM_PROT_WRITE) flFlags |= VMDHGP_WRITE; rc = RTR0Os2DHVMGlobalToProcess(flFlags, pvR0, pMemToMapOs2->Core.cb, &pvR3); if (rc) return RTErrConvertFromOS2(rc); } Assert(pvR3); /* * Create a mapping object for it. */ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_MAPPING, pvR3, pMemToMapOs2->Core.cb); if (pMemOs2) { Assert(pMemOs2->Core.pv == pvR3); pMemOs2->Core.u.Mapping.R0Process = R0Process; *ppMem = &pMemOs2->Core; return VINF_SUCCESS; } KernVMFree(pvR3); return VERR_NO_MEMORY; }
DECLHIDDEN(int) rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment, unsigned fProt, size_t offSub, size_t cbSub) { AssertMsgReturn(!offSub && !cbSub, ("%#x %#x\n", offSub, cbSub), VERR_NOT_SUPPORTED); AssertMsgReturn(pvFixed == (void *)-1, ("%p\n", pvFixed), VERR_NOT_SUPPORTED); /* * Check that the specified alignment is supported. */ if (uAlignment > PAGE_SIZE) return VERR_NOT_SUPPORTED; /** @todo finish the implementation. */ int rc; void *pvR0 = NULL; PRTR0MEMOBJOS2 pMemToMapOs2 = (PRTR0MEMOBJOS2)pMemToMap; switch (pMemToMapOs2->Core.enmType) { /* * These has kernel mappings. */ case RTR0MEMOBJTYPE_PAGE: case RTR0MEMOBJTYPE_LOW: case RTR0MEMOBJTYPE_CONT: pvR0 = pMemToMapOs2->Core.pv; break; case RTR0MEMOBJTYPE_PHYS: pvR0 = pMemToMapOs2->Core.pv; if (!pvR0) { /* no ring-0 mapping, so allocate a mapping in the process. */ AssertMsgReturn(fProt & RTMEM_PROT_WRITE, ("%#x\n", fProt), VERR_NOT_SUPPORTED); Assert(!pMemToMapOs2->Core.u.Phys.fAllocated); ULONG ulPhys = pMemToMapOs2->Core.u.Phys.PhysBase; rc = KernVMAlloc(pMemToMapOs2->Core.cb, VMDHA_PHYS, &pvR0, (PPVOID)&ulPhys, NULL); if (rc) return RTErrConvertFromOS2(rc); pMemToMapOs2->Core.pv = pvR0; } break; case RTR0MEMOBJTYPE_PHYS_NC: AssertMsgFailed(("RTR0MEMOBJTYPE_PHYS_NC\n")); return VERR_INTERNAL_ERROR_3; break; case RTR0MEMOBJTYPE_LOCK: if (pMemToMapOs2->Core.u.Lock.R0Process != NIL_RTR0PROCESS) return VERR_NOT_SUPPORTED; /** @todo implement this... */ pvR0 = pMemToMapOs2->Core.pv; break; case RTR0MEMOBJTYPE_RES_VIRT: case RTR0MEMOBJTYPE_MAPPING: default: AssertMsgFailed(("enmType=%d\n", pMemToMapOs2->Core.enmType)); return VERR_INTERNAL_ERROR; } /* * Create a dummy mapping object for it. * * All mappings are read/write/execute in OS/2 and there isn't * any cache options, so sharing is ok. And the main memory object * isn't actually freed until all the mappings have been freed up * (reference counting). */ PRTR0MEMOBJOS2 pMemOs2 = (PRTR0MEMOBJOS2)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJOS2, Lock), RTR0MEMOBJTYPE_MAPPING, pvR0, pMemToMapOs2->Core.cb); if (pMemOs2) { pMemOs2->Core.u.Mapping.R0Process = NIL_RTR0PROCESS; *ppMem = &pMemOs2->Core; return VINF_SUCCESS; } return VERR_NO_MEMORY; }