From owner-freebsd-hackers@freebsd.org Thu Jun 14 08:59:40 2018 Return-Path: Delivered-To: freebsd-hackers@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 947F81012D32 for ; Thu, 14 Jun 2018 08:59:40 +0000 (UTC) (envelope-from pratiy0100@gmail.com) Received: from mail-wm0-x243.google.com (mail-wm0-x243.google.com [IPv6:2a00:1450:400c:c09::243]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority G2" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 03B2E7E84E; Thu, 14 Jun 2018 08:59:40 +0000 (UTC) (envelope-from pratiy0100@gmail.com) Received: by mail-wm0-x243.google.com with SMTP id z6-v6so2308000wma.0; Thu, 14 Jun 2018 01:59:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to:cc; bh=D9fEalTpjLx95ussHzDr0CCH8SzcMjcx7cqxc9ksAPE=; b=Lue9rpDvkNn/0Ixj+ecQOlkoyRtR4vvF1MHWecyb4brZrvJKZuIT+4ypkGXkOnRttE LCjoPTqRkcwn3HP1ZAxHKOep7IcF741TQ78HyPR8L2JSBRZye/fDrtXT+PXMHocS8uRx IcieJuYfMwqPbzGJNCiRm2sBM/Pw23kMqUD8Xxgap8XVumYWrjio+a3AOh7JCWXj//6+ 6cA5RiyCmEpTpWWHXkE7otELELHD7fB5Uh5AQ9VkJuqNXy+YBBDGeG0TskufV6w46JWa GObvpsv2f0LIoU5jOPucdioLW2kBVeiUPt87/TCI1ViyRT3NlJm1ZwopT0glVSqdej6D XhVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to:cc; bh=D9fEalTpjLx95ussHzDr0CCH8SzcMjcx7cqxc9ksAPE=; b=i6Q9w7gIeIpDAIYY3ygdABiJxQMT1/YUqsuvyBb1fp5RVXLFj9wq6y7I7QP64+CBfI 9xdAKVX0XTlR7oWWgmKO2ZGWARyFcD8c1DIkyv3q6NQ51+FcpwSrXS/RFAtOsnRASik1 4ZjTxTafVWDvy1ZUAZPtTa3XHgRrrVSaGjkGf4TkuSMLKTsUtf9Y4XYNj8vTGYeLKlG0 HVMDKHtieply3Q+7D4R6H6l4cq0MXVSrTLP06YlbPBaFy/gcTMs/qnmr48RualCHDZc2 KlOxoN6pmFCo21wqUcjJGkvvbTv/uTdWESuwU1uaX0uUNjFinai6y3zIpjtE8I8oBCZO f65g== X-Gm-Message-State: APt69E0ukZjOl8Ck7SDny+D/LM+C5qlZdhV1EiyQid5RXr9LXD5z3I5f gkpB5mIarea/lNP32KyrkAVXqrU7HSZySKZWQJbzP3ll X-Google-Smtp-Source: ADUXVKJUk1NRh7yBehy36lNXGWCbDnhjnu0lFuJgDZMUpaR8MTEDBgWNX5P+sMUPvomSbFDA7MoUvyD/xVKDnTAhQWo= X-Received: by 2002:a50:ad78:: with SMTP id z53-v6mr1907754edc.306.1528966778764; Thu, 14 Jun 2018 01:59:38 -0700 (PDT) MIME-Version: 1.0 From: Pratyush Yadav Date: Thu, 14 Jun 2018 14:29:02 +0530 Message-ID: Subject: Bug in subr_bus_dma.c's bus_dmamap_load() when multiple dma maps are created from a single tag on x86 To: freebsd-hackers@freebsd.org Cc: Edward Napierala , =?UTF-8?Q?Roger_Pau_Monn=C3=A9?= Content-Type: text/plain; charset="UTF-8" X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 14 Jun 2018 08:59:40 -0000 Hi everyone, I was looking at the busdma code for x86 and I notice that the claim in the bus_dma(9) man page might not be correct: "Multiple maps can be associated with one DMA tag." Looking at the code of sys/x86/x86/busdma_bounce.c (which I believe is the default busdma implementation for x86), I realize that a map does not necessarily use all the segments of the dma tag (specified by the parameter nsegments on tag creation). So how many segments does a map actually use? Looking at busdma_bounce.c:644,690 it seems we can calculate that from the pointer segp. It contains the index of starting segment on entrace to the load function, and the ending segment on exit. Sounds all fine so far. But then if we look at map_complete() (busdma_bounce.c:908), it returns the entire segments array of the dma *tag*. I emphasize tag because the tag's segments array holds the segments of all the maps created with the tag. Going a layer up, sys/kern/subr_bus_dma.c:328 simply passes nsegs(= -1) in the segp parameter to load, not bothering to check if some segments have been used already by other maps. It then calculates the number of segments used using the value of nsegs after return and calls map_complete() to get the segments array. It then passes the segments array to the driver callback with the number of segments, nsegs. Effectively, to the driver it seems that the map's segments start from index 0 and go till nsegs - 1. This is not true if another map has been loaded in the meantime with the same tag. We are possibly over-writing the previous map's segments. busdma_bounce.c:669 simply uses segs[0] if the value of segp is -1, which is what bus_dmamap_load() in subr_bus_dma.c:328 passes to _bus_dmamap_load_buffer(). segs[0] would also be used by any subsequent map's load. This means the previous map's values are over-written. This might cause problems when the driver is in its callback using the segments array and another map is loaded. Unfortunately, I do not posses the knowledge or experience with FreeBSD's drivers (drivers in general) to test for this bug. I have not looked at the code in other architectures. The same problem might present itself there as well. If I made a mistake somewhere in my reasoning, let me know. -- Regards, Pratyush Yadav