From patchwork Wed Dec 4 03:21:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexey Kardashevskiy X-Patchwork-Id: 1203965 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47SPKn3rDqz9sPh for ; Wed, 4 Dec 2019 14:22:21 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ozlabs.ru Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 47SPKn20v1zDqSR for ; Wed, 4 Dec 2019 14:22:21 +1100 (AEDT) X-Original-To: slof@lists.ozlabs.org Delivered-To: slof@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=ozlabs.ru (client-ip=107.174.27.60; helo=ozlabs.ru; envelope-from=aik@ozlabs.ru; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=ozlabs.ru Received: from ozlabs.ru (unknown [107.174.27.60]) by lists.ozlabs.org (Postfix) with ESMTP id 47SPKg0xfxzDqSJ for ; Wed, 4 Dec 2019 14:22:15 +1100 (AEDT) Received: from fstn1-p1.ozlabs.ibm.com (localhost [IPv6:::1]) by ozlabs.ru (Postfix) with ESMTP id 8177CAE80045; Tue, 3 Dec 2019 22:20:40 -0500 (EST) From: Alexey Kardashevskiy To: slof@lists.ozlabs.org Date: Wed, 4 Dec 2019 14:21:34 +1100 Message-Id: <20191204032138.127624-2-aik@ozlabs.ru> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191204032138.127624-1-aik@ozlabs.ru> References: <20191204032138.127624-1-aik@ozlabs.ru> Subject: [SLOF] [PATCH slof v4 1/5] pci-phb: Reimplement dma-map-in/out X-BeenThere: slof@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Patches for https://github.com/aik/SLOF" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: slof-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "SLOF" The immediate problem with the code is that it relies on memory allocator aligning addresses to the size. This is true for SLOF but not for GRUB and in unaligned situations we end up mapping more pages than bm-alloc allocated. This fixes the problem by calculating aligned DMA size before calling bm-alloc. While at this, simplify the code by removing global variables. Also replace 1000/fff (the default 4K IOMMU page size) with tce-ps/mask. Signed-off-by: Alexey Kardashevskiy Reviewed-by: Michael Roth --- Changes: v4: * fixed code comments, tab/spaces * fixed bm-alloc failure handling --- board-qemu/slof/pci-phb.fs | 95 ++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 56 deletions(-) diff --git a/board-qemu/slof/pci-phb.fs b/board-qemu/slof/pci-phb.fs index 06729bcf77a0..2a003fca4a30 100644 --- a/board-qemu/slof/pci-phb.fs +++ b/board-qemu/slof/pci-phb.fs @@ -14,6 +14,8 @@ 0 VALUE phb-debug? +1000 CONSTANT tce-ps \ Default TCE page size is 4K +tce-ps 1- CONSTANT tce-mask ." Populating " pwd cr @@ -86,17 +88,17 @@ setup-puid : dma-alloc ( size -- virt ) phb-debug? IF cr ." dma-alloc called: " .s cr THEN - fff + fff not and \ Align size to next 4k boundary + tce-ps #aligned alloc-mem \ alloc-mem always returns aligned memory - double check just to be sure - dup fff and IF + dup tce-mask and IF ." Warning: dma-alloc got unaligned memory!" cr THEN ; : dma-free ( virt size -- ) phb-debug? IF cr ." dma-free called: " .s cr THEN - fff + fff not and \ Align size to next 4k boundary + tce-ps #aligned free-mem ; @@ -107,10 +109,6 @@ setup-puid 0 VALUE dma-window-size \ Size of the window 0 VALUE bm-handle \ Bitmap allocator handle -0 VALUE my-virt -0 VALUE my-size -0 VALUE dev-addr -0 VALUE tmp-dev-addr \ Read helper variables (LIOBN, DMA window base and size) from the \ "ibm,dma-window" property. This property can be either located @@ -130,11 +128,11 @@ setup-puid decode-64 TO dma-window-size 2drop bm-handle 0= IF - dma-window-base dma-window-size 1000 bm-allocator-init to bm-handle + dma-window-base dma-window-size tce-ps bm-allocator-init to bm-handle \ Sometimes the window-base appears as zero, that does not \ go well with NULL pointers. So block this address dma-window-base 0= IF - bm-handle 1000 bm-alloc drop + bm-handle tce-ps bm-alloc drop THEN THEN ; @@ -145,69 +143,54 @@ setup-puid 0 TO dma-window-size ; -\ We assume that firmware never maps more than the whole dma-window-size -\ so we cheat by calculating the remainder of addr/windowsize instead -\ of taking care to maintain a list of assigned device addresses -: dma-virt2dev ( virt -- devaddr ) - dma-window-size mod dma-window-base + -; +\ grub does not align allocated addresses to the size so when mapping, +\ we might need to ask bm-alloc for an extra IOMMU page +: dma-align ( size virt -- aligned-size ) tce-mask and + tce-ps #aligned ; +: dma-trunc ( addr -- addr&~fff ) tce-mask not and ; : dma-map-in ( virt size cachable? -- devaddr ) phb-debug? IF cr ." dma-map-in called: " .s cr THEN (init-dma-window-vars) - drop ( virt size ) - - to my-size - to my-virt - bm-handle my-size bm-alloc - to dev-addr - dev-addr 0 < IF - ." Bitmap allocation Failed " dev-addr . - FALSE EXIT + drop + over dma-align ( virt size ) \ size is aligned now + tuck ( size virt size ) + bm-handle swap bm-alloc ( size virt dev-addr ) \ dev-addr is aligned + dup 0 < IF + ." Bitmap allocation Failed " + 3drop + 0 EXIT THEN - dev-addr to tmp-dev-addr - my-virt my-size - bounds dup >r ( v+s virt R: virt ) - swap fff + fff not and \ Align end to next 4k boundary - swap fff not and ( v+s' virt' R: virt ) + swap ( size dev-addr virt ) + 2dup tce-mask and or >r \ add page offset to the return value + + dma-trunc 3 OR \ Truncate and add read and write perm + rot ( dev-addr virt size r: dev-addr ) + 0 ?DO - \ ." mapping " i . cr - dma-window-liobn \ liobn - tmp-dev-addr \ ioba - i 3 OR \ Make a read- & writeable TCE - ( liobn ioba tce R: virt ) + 2dup dma-window-liobn -rot ( dev-addr virt liobn dev-addr virt r: dev-addr ) hv-put-tce ABORT" H_PUT_TCE failed" - tmp-dev-addr 1000 + to tmp-dev-addr - 1000 +LOOP - r> drop - my-virt FFF and dev-addr or + tce-ps + swap tce-ps + swap ( dev-addr' virt' r: dev-addr ) + tce-ps +LOOP (clear-dma-window-vars) + 2drop + r> ; : dma-map-out ( virt devaddr size -- ) phb-debug? IF cr ." dma-map-out called: " .s cr THEN (init-dma-window-vars) - to my-size - to dev-addr - to my-virt - dev-addr fff not and to dev-addr - dev-addr to tmp-dev-addr - - my-virt my-size ( virt size ) - bounds ( v+s virt ) - swap fff + fff not and \ Align end to next 4k boundary - swap fff not and ( v+s' virt' ) + rot drop ( devaddr size ) + over dma-align + swap dma-trunc swap ( devaddr-trunc size-extended ) + 2dup bm-handle -rot bm-free + 0 ?DO - \ ." unmapping " i . cr - dma-window-liobn \ liobn - tmp-dev-addr \ ioba - i \ Lowest bits not set => invalid TCE - ( liobn ioba tce ) + dup 0 dma-window-liobn -rot hv-put-tce ABORT" H_PUT_TCE failed" - tmp-dev-addr 1000 + to tmp-dev-addr - 1000 +LOOP - bm-handle dev-addr my-size bm-free + tce-ps + + tce-ps +LOOP + drop (clear-dma-window-vars) ;