From nobody Thu Apr 18 18:12:24 2024 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4VL5Th6t23z5HK3h; Thu, 18 Apr 2024 18:12:24 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4VL5Th4W72z3yv7; Thu, 18 Apr 2024 18:12:24 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1713463944; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=YVQKBcdP/jxJ4sC6hZORqTMveEBEKyGdzd2cHS5ZWys=; b=ZsbXrrTOJsQhfi+6g+g15lX0ynIYCeuzCmrfSEeyewnsUxJ9gcpVlHLXltret/tbj06wSx /f8DUbel2zfpXr2N1+xoA//M/m4bg4XeCAOtUOpG+VzderjNrKwQdm3+h/uIQe2mn1/5pc TexY82G5aDU/0GGehzazYMCQqbYgql4HDbQY3fffp1i2vuBhmPI/Cv4WttUndGW8u4aYfd s0zbVcKYnkPUv9I5RtRXvAqM1OaCNAIwp+kEYbH2tluarDLj1+afSJcGuxACOm3t1OTrht RupE8qcAaje49NLZ92s0E571XRfPe6Nyr/wCBkhr16Mft5/LYVJ7pMOOcqMsNw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1713463944; a=rsa-sha256; cv=none; b=J/xHw9WeSfCh/sduHKqLXE9dKgMalwcu86Z3/SZkcKdgDCUN1fa0K3g8LI+WU6syLqa2bG bKhPH3yVTH2nnWBBts98rghKvNIeMapwf67eS5LJySHZ/RXdBvK+vZfa0SJQftNAAKNjog GBPZOsZua4Z8nK4IpbRfFF2zSQXj3xYT0KfxXlWoXFflZ3JQ87FKaAj0M/VRwk44jOdbZT GdqDuTALYgldSbnUqxu7GuYCtDf9AtT6HtSHi/2vQ1hutSIGZ+fAn1TTs+HAtrilw5nXiL r+PzE/zZN/78ZldfbqTkcBb21PQShw32Jgm3zZeJoByDX6eElvyhHGqeNi/EEA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1713463944; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=YVQKBcdP/jxJ4sC6hZORqTMveEBEKyGdzd2cHS5ZWys=; b=b2GEXY593T5m0dNweLsGqf+tYjHXgwzE58+ZphwLwFmepRQIjtSjjRcwYyjHANgQScwJ7h OwqIZ2/FnxxiHs9zI6FjRVaPiXZXBgaqSmfJR/sq9wGHT5yrq7XrXnFbW2GkMJKfXRcKi8 GteHbNenS90B7LxevcA22G3NBw0E5/YhC7N7WFnu1VV9K6clrPAMiLrXTzOE180lJZHmpg cpoYPqa+vmBc761ErqNJ859fZfchOruFwMm+lo09mcPFqC6ky+SSRImYuv6kR9pMG61rA8 0LwlxnMFeQFaUAkmA1lh4UFyg8DH3csB40ce3Fsvx0Fz7yP5sSv+P88xiqdJEA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4VL5Th47jszKjt; Thu, 18 Apr 2024 18:12:24 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 43IICO2e016121; Thu, 18 Apr 2024 18:12:24 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 43IICOsq016118; Thu, 18 Apr 2024 18:12:24 GMT (envelope-from git) Date: Thu, 18 Apr 2024 18:12:24 GMT Message-Id: <202404181812.43IICOsq016118@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mitchell Horne Subject: git: 0a40193a6e0f - stable/14 - busdma: fix page miscount for small segment sizes List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mhorne X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 0a40193a6e0fdf73b618aec3bccfb05bd1d0ddf0 Auto-Submitted: auto-generated The branch stable/14 has been updated by mhorne: URL: https://cgit.FreeBSD.org/src/commit/?id=0a40193a6e0fdf73b618aec3bccfb05bd1d0ddf0 commit 0a40193a6e0fdf73b618aec3bccfb05bd1d0ddf0 Author: Mitchell Horne AuthorDate: 2021-05-25 21:04:56 +0000 Commit: Mitchell Horne CommitDate: 2024-04-18 18:09:02 +0000 busdma: fix page miscount for small segment sizes For small segments (< PAGE_SIZE) there is a mismatch between how required bounce pages are counted in _bus_dmamap_count_pages() and bounce_bus_dmamap_load_buffer(). This problem has been observed on the RISC-V VisionFive v2 SoC (and earlier revisions of the hardware) which has memory physically addressed above 4GB. This requires some bouncing for the dwmmc driver, which has has a maximum segment size of 2048 bytes. When attempting to load a page-aligned 4-page buffer that requires bouncing, we can end up counting 4 bounce pages for an 8-segment transfer. These pages will be incorrectly configured to cover only the first half of the transfer (4 x 2048 bytes). Fix the immediate issue by adding the maxsegsz check to _bus_dmamap_count_pages(); this is what _bus_dmamap_count_phys() does already. The result is that we will inefficiently allocate a separate bounce page for each segment (8 pages for the example above), but the transfer will proceed in its entirety. The more complete fix is to address the shortcomings in how small segments are assigned to bounce pages, so that we opportunistically batch multiple segments to a page whenever they fit (e.g. two 2048 bytes segments per 4096 page). This will be addressed more holistically in the future. For now this change will prevent the (silent) incomplete transfers that have been observed. PR: 273694 Reported by: Jari Sihvola Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D34118 (cherry picked from commit b134c10d658c3b350e04aa8dbd2628e955ddcce0) --- sys/arm/arm/busdma_machdep.c | 11 ++++++----- sys/arm64/arm64/busdma_bounce.c | 1 + sys/powerpc/powerpc/busdma_machdep.c | 1 + sys/riscv/riscv/busdma_bounce.c | 1 + sys/x86/x86/busdma_bounce.c | 1 + 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/sys/arm/arm/busdma_machdep.c b/sys/arm/arm/busdma_machdep.c index a4f2c803f30a..a24dcf94fe08 100644 --- a/sys/arm/arm/busdma_machdep.c +++ b/sys/arm/arm/busdma_machdep.c @@ -873,6 +873,7 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, pmap_t pmap, bus_dmamap_t map, vm_offset_t vaddr; vm_offset_t vendaddr; bus_addr_t paddr; + bus_size_t sg_len; if (map->pagesneeded == 0) { CTR5(KTR_BUSDMA, "lowaddr= %d, boundary= %d, alignment= %d" @@ -887,16 +888,16 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, pmap_t pmap, bus_dmamap_t map, vendaddr = (vm_offset_t)buf + buflen; while (vaddr < vendaddr) { + sg_len = MIN(vendaddr - vaddr, + (PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK))); + sg_len = MIN(sg_len, dmat->maxsegsz); if (__predict_true(pmap == kernel_pmap)) paddr = pmap_kextract(vaddr); else paddr = pmap_extract(pmap, vaddr); - if (must_bounce(dmat, map, paddr, - min(vendaddr - vaddr, (PAGE_SIZE - ((vm_offset_t)vaddr & - PAGE_MASK)))) != 0) { + if (must_bounce(dmat, map, paddr, sg_len) != 0) map->pagesneeded++; - } - vaddr += (PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK)); + vaddr += sg_len; } CTR1(KTR_BUSDMA, "pagesneeded= %d", map->pagesneeded); } diff --git a/sys/arm64/arm64/busdma_bounce.c b/sys/arm64/arm64/busdma_bounce.c index c1028f35ba7f..cd7655300dc4 100644 --- a/sys/arm64/arm64/busdma_bounce.c +++ b/sys/arm64/arm64/busdma_bounce.c @@ -717,6 +717,7 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, while (vaddr < vendaddr) { sg_len = PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK); + sg_len = MIN(sg_len, dmat->common.maxsegsz); if (pmap == kernel_pmap) paddr = pmap_kextract(vaddr); else diff --git a/sys/powerpc/powerpc/busdma_machdep.c b/sys/powerpc/powerpc/busdma_machdep.c index 873a67458dfc..6b70c0b34ede 100644 --- a/sys/powerpc/powerpc/busdma_machdep.c +++ b/sys/powerpc/powerpc/busdma_machdep.c @@ -573,6 +573,7 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, bus_size_t sg_len; sg_len = PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK); + sg_len = MIN(sg_len, dmat->maxsegsz); if (pmap == kernel_pmap) paddr = pmap_kextract(vaddr); else diff --git a/sys/riscv/riscv/busdma_bounce.c b/sys/riscv/riscv/busdma_bounce.c index 6b50dc527b66..dcd287806eaf 100644 --- a/sys/riscv/riscv/busdma_bounce.c +++ b/sys/riscv/riscv/busdma_bounce.c @@ -552,6 +552,7 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, while (vaddr < vendaddr) { sg_len = PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK); + sg_len = MIN(sg_len, dmat->common.maxsegsz); if (pmap == kernel_pmap) paddr = pmap_kextract(vaddr); else diff --git a/sys/x86/x86/busdma_bounce.c b/sys/x86/x86/busdma_bounce.c index b9943ad3792e..c60e239a5109 100644 --- a/sys/x86/x86/busdma_bounce.c +++ b/sys/x86/x86/busdma_bounce.c @@ -562,6 +562,7 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, while (vaddr < vendaddr) { sg_len = PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK); + sg_len = MIN(sg_len, dmat->common.maxsegsz); if (pmap == kernel_pmap) paddr = pmap_kextract(vaddr); else