From 95620426d5f82e336ef422ae4c82512eab02affa Mon Sep 17 00:00:00 2001 From: nimlgen <138685161+nimlgen@users.noreply.github.com> Date: Fri, 7 Nov 2025 16:08:43 +0800 Subject: [PATCH] tinygpu: unmap dma when client closed (#13129) * tinygpu: unmap dma when client closed * syn * tiny fixes --- .../installer/Shared/TinyGPUViewModel.swift | 7 -- .../TinyGPUDriverUserClient.cpp | 77 ++++++++++++++----- 2 files changed, 56 insertions(+), 28 deletions(-) diff --git a/extra/usbgpu/tbgpu/installer/Shared/TinyGPUViewModel.swift b/extra/usbgpu/tbgpu/installer/Shared/TinyGPUViewModel.swift index 82d52e3343..58f1d8090b 100644 --- a/extra/usbgpu/tbgpu/installer/Shared/TinyGPUViewModel.swift +++ b/extra/usbgpu/tbgpu/installer/Shared/TinyGPUViewModel.swift @@ -119,14 +119,7 @@ extension TinyGPUViewModel: OSSystemExtensionRequestDelegate { os_log("sysex actionForReplacingExtension: %@ %@", existing, ext) - // Add appropriate logic here to determine whether to replace the extension - // with the new extension. Common things to check for include - // testing whether the new extension's version number is newer than - // the current version number, or whether the bundleIdentifier is different. - // For simplicity, this sample always replaces the current extension - // with the new one. replacementAction = .replace - self.state = .activating return replacementAction } diff --git a/extra/usbgpu/tbgpu/installer/TinyGPUDriverExtension/TinyGPUDriverUserClient.cpp b/extra/usbgpu/tbgpu/installer/TinyGPUDriverExtension/TinyGPUDriverUserClient.cpp index cdc6d0e427..71df2e28ab 100644 --- a/extra/usbgpu/tbgpu/installer/TinyGPUDriverExtension/TinyGPUDriverUserClient.cpp +++ b/extra/usbgpu/tbgpu/installer/TinyGPUDriverExtension/TinyGPUDriverUserClient.cpp @@ -7,26 +7,61 @@ struct TinyGPUDriverUserClient_IVars { OSSharedPtr provider = nullptr; + + TinyGPUCreateDMAResp *dmas = nullptr; + size_t dmaCount = 0; + size_t dmaCap = 0; + + int ensureDMACap(size_t need) + { + // not thread-safe + if (need <= dmaCap) return 0; + + size_t newCap = dmaCap ? dmaCap * 2 : 16; + while (newCap < need) newCap *= 2; + + auto *newArr = IONewZero(TinyGPUCreateDMAResp, newCap); + if (!newArr) return -kIOReturnNoMemory; + + if (dmas && dmaCount) { + memcpy(newArr, dmas, dmaCount * sizeof(TinyGPUCreateDMAResp)); + } + + IOSafeDeleteNULL(dmas, TinyGPUCreateDMAResp, dmaCap); + dmas = newArr; + dmaCap = newCap; + return 0; + } }; bool TinyGPUDriverUserClient::init() { - auto theAnswer = super::init(); - if (!theAnswer) { - return false; - } + auto ok = super::init(); + if (!ok) return false; ivars = IONewZero(TinyGPUDriverUserClient_IVars, 1); - if (ivars == nullptr) { - return false; - } - + if (!ivars) return false; return true; } void TinyGPUDriverUserClient::free() { - if (ivars != nullptr) { + // release all DMA allocations for this client + if (ivars) { + for (uint32_t i = 0; i < ivars->dmaCount; i++) { + auto &d = ivars->dmas[i]; + if (d.dmaCmd) { + d.dmaCmd->CompleteDMA(kIODMACommandCompleteDMANoOptions); + d.dmaCmd->release(); + d.dmaCmd = nullptr; + } + if (d.sharedBuf) { + d.sharedBuf->release(); + d.sharedBuf = nullptr; + } + } + ivars->dmaCount = 0; + ivars->provider.reset(); } @@ -102,26 +137,26 @@ kern_return_t TinyGPUDriverUserClient::ExternalMethod(uint64_t selector, IOUserC kern_return_t IMPL(TinyGPUDriverUserClient, CopyClientMemoryForType) { - if (!memory) { - return kIOReturnBadArgument; - } - - if (ivars->provider.get() == nullptr) { - return kIOReturnNotAttached; - } + if (!memory) return kIOReturnBadArgument; + if (!ivars->provider.get()) return kIOReturnNotAttached; + // bar handling, type is bar num if (type < 6) { uint32_t bar = (uint32_t)type; return ivars->provider->MapBar(bar, memory); } - // dma page buffer - TinyGPUCreateDMAResp buf; - kern_return_t err = ivars->provider->CreateDMA(type, &buf); - if (err) { - return err; + // dma handling, type is size + if (ivars->ensureDMACap(ivars->dmaCount + 1)) { + os_log(OS_LOG_DEFAULT, "tinygpu: cannot grow dma array"); + return kIOReturnNoMemory; } + TinyGPUCreateDMAResp buf{}; + kern_return_t err = ivars->provider->CreateDMA(type, &buf); + if (err) return err; + + ivars->dmas[ivars->dmaCount++] = buf; *memory = buf.sharedBuf; return 0; }