From nobody Fri Feb 16 18:39:36 2024 X-Original-To: dev-commits-src-main@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 4Tc11h3xs2z542ly; Fri, 16 Feb 2024 18:39:36 +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 4Tc11h3Mv4z44p3; Fri, 16 Feb 2024 18:39:36 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1708108776; 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=kdsQn4jfD2aJsMDLJ/9gzg3RyHPuQLvtME+ou9xbzw4=; b=uyl1jKEXn3t+UdkxSx/bTn0UVVLvHX0v6UCczC2hcqVaEUm5Qpbku0XUPsz6EZc3xsz6Ao JKumCeM1mpwIw8XA6ImYCN9pIQGmzoNBmOtElmOnuTio5Sm4K8omPCbTfyoF5C3+sXUs8j xTQBVkoDyPFRU9sGv65wI2bqyeGv3ifPOgP1wGftL6B4i/Zp6luchEAxHBdWROeHxb7+Pu 6CjEAoxvhX9KgC4uC68yuWyKCXOOOGFvtANZro28Dt/kiow8LV0cTq04LZF4qLQVSHn0XT R9uSufnoi4vj/rHJ7N7/vhrVQocZHQpyRN1mAv9J0VKA317T+FfhCLdggI3feg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1708108776; 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=kdsQn4jfD2aJsMDLJ/9gzg3RyHPuQLvtME+ou9xbzw4=; b=ZcIjD4xyYUyKJ8F4+dtkRXqUtrz3/sBSrzxQD+HrYCwwPRoIWS9brdC32dAHSeduu0jOHp e+WRh3shk4PvwBt2foQH+FUAc2huh8OTMILlJR3pIGCbzFgXZkhRwOTMrTBPfjQBViOMXD upP4t4g9tv/bJkvsRlCizOh6fWt1L2Lcbi6L8tlfSKOCWTRVH3gfefG+qYBLZF4jeBTeUb SqyBgFiEzP7iLgPeNUf8Dk/huGMfbvNNEDrLGB0SgiW1fhNRg/FbIECkqUZQs5dGMNuvnw kbr4qHocARnSSIu7o9wAIktGdYcxtezXkLXwiVfQ3BWfN23QEaxgFL0jeRUD/A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1708108776; a=rsa-sha256; cv=none; b=Z9M9rPPiYgUEYBolLBYe4GT4BfTehnyhcdNKElH76clIe3QbtldMAw5IBfTLgk2I5SApkc DI98qdP6jJEwfccl10FILhsElaVdq6Xv7ITKbXGeAvW2hrODCD5KGz1S0oP24z2+Y5y1CO jO5ImRGKshFudIa7bruLBLF7FgbDrWMPrdHqe4J6RrkegJFmlCU4Klw20sV0qxsk9zlJWU MQvHXQPtOV89S1LTBkbqxXZNdRbYYeB7IkZ0xjc0u/Gjv/SE4rU0lQSr7rvZjQGB9misBV P8bU8sfiGcGmDarcwGPhJV1rtuozvYeqaz8xVNjevNK/BMt1DtEcgTV+/wEgtw== 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 4Tc11h2Kpjzbvc; Fri, 16 Feb 2024 18:39:36 +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 41GIdaef093039; Fri, 16 Feb 2024 18:39:36 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 41GIdaGo093036; Fri, 16 Feb 2024 18:39:36 GMT (envelope-from git) Date: Fri, 16 Feb 2024 18:39:36 GMT Message-Id: <202402161839.41GIdaGo093036@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Mitchell Horne Subject: git: b134c10d658c - main - busdma: fix page miscount for small segment sizes List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@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/main X-Git-Reftype: branch X-Git-Commit: b134c10d658c3b350e04aa8dbd2628e955ddcce0 Auto-Submitted: auto-generated The branch main has been updated by mhorne: URL: https://cgit.FreeBSD.org/src/commit/?id=b134c10d658c3b350e04aa8dbd2628e955ddcce0 commit b134c10d658c3b350e04aa8dbd2628e955ddcce0 Author: Mitchell Horne AuthorDate: 2021-05-25 21:04:56 +0000 Commit: Mitchell Horne CommitDate: 2024-02-16 18:38:48 +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 --- 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 9f4c6e561bbc..9ae74892ebd4 100644 --- a/sys/arm/arm/busdma_machdep.c +++ b/sys/arm/arm/busdma_machdep.c @@ -812,6 +812,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" @@ -826,16 +827,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 57551a2edb47..ec2dfe76894c 100644 --- a/sys/arm64/arm64/busdma_bounce.c +++ b/sys/arm64/arm64/busdma_bounce.c @@ -693,6 +693,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 aa1a29e1f1ce..bc28619372f0 100644 --- a/sys/powerpc/powerpc/busdma_machdep.c +++ b/sys/powerpc/powerpc/busdma_machdep.c @@ -520,6 +520,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 c9fdb0e38e40..e504b122ebd1 100644 --- a/sys/riscv/riscv/busdma_bounce.c +++ b/sys/riscv/riscv/busdma_bounce.c @@ -531,6 +531,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 f56ecd9e7e1e..ef96f5ba7bdc 100644 --- a/sys/x86/x86/busdma_bounce.c +++ b/sys/x86/x86/busdma_bounce.c @@ -560,6 +560,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