From owner-freebsd-arch@FreeBSD.ORG Fri Apr 24 13:13:06 2015 Return-Path: Delivered-To: freebsd-arch@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 58CBDC35 for ; Fri, 24 Apr 2015 13:13:06 +0000 (UTC) Received: from mail-ie0-x22d.google.com (mail-ie0-x22d.google.com [IPv6:2607:f8b0:4001:c03::22d]) (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 27C941890 for ; Fri, 24 Apr 2015 13:13:06 +0000 (UTC) Received: by iedfl3 with SMTP id fl3so93501106ied.1 for ; Fri, 24 Apr 2015 06:13:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:date:message-id:subject:from:to:content-type; bh=+2ZMCbbMUrrG+EeTnUUOVcxqc55aEdO4iE5JtF+AHBk=; b=EKwOs2Z7A8PuL60En4rR2oRHqvAZTgc9Iwx0tlGBv2tfhftsFlQvW7KheB0Gy7P2jo q7qIqAopb8d3kQZAVDs+yUptjdINwh+4X9Nlkz+x627kMUulEJCTwWtJpSsghWuqSrMX N1DxelZd4CAisvbMexjJ/F609PEKxkXwOlm0cvGEu9CRA7C5pePYR1sRJ5j4SCkg8jsM mimwAZqkUA8ECoIxIhgufBzPKiWHZqfglIcY4d0VPvhZI11qV94+uI+ZVk6BpzXuds0a w4/NZKsrkPeFqT0D+T2bd4XiSLwkUhYeZrTWlF+QzC9TURCNgjCCKbzEU9MHcR8ks0JG Cykg== MIME-Version: 1.0 X-Received: by 10.107.18.65 with SMTP id a62mr11034041ioj.67.1429881185685; Fri, 24 Apr 2015 06:13:05 -0700 (PDT) Received: by 10.64.13.81 with HTTP; Fri, 24 Apr 2015 06:13:05 -0700 (PDT) Date: Fri, 24 Apr 2015 15:13:05 +0200 Message-ID: Subject: bus_dmamap_sync() for bounced client buffers from user address space From: Svatopluk Kraus To: FreeBSD Arch Content-Type: text/plain; charset=UTF-8 X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 Apr 2015 13:13:06 -0000 DMA can be done on client buffer from user address space. For example, thru bus_dmamap_load_uio() when uio->uio_segflg is UIO_USERSPACE. Such client buffer can bounce and then, it must be copied to and from bounce buffer in bus_dmamap_sync(). Current implementations (in all archs) do not take into account that bus_dmamap_sync() is asynchronous for POSTWRITE and POSTREAD in general. It can be asynchronous for PREWRITE and PREREAD too. For example, in some driver implementations where DMA client buffers operations are buffered. In those cases, simple bcopy() is not correct. Demonstration of current implementation (x86) is the following: ----------------------------- struct bounce_page { vm_offset_t vaddr; /* kva of bounce buffer */ bus_addr_t busaddr; /* Physical address */ vm_offset_t datavaddr; /* kva of client data */ bus_addr_t dataaddr; /* client physical address */ bus_size_t datacount; /* client data count */ STAILQ_ENTRY(bounce_page) links; }; if ((op & BUS_DMASYNC_PREWRITE) != 0) { while (bpage != NULL) { if (bpage->datavaddr != 0) { bcopy((void *)bpage->datavaddr, (void *)bpage->vaddr, bpage->datacount); } else { physcopyout(bpage->dataaddr, (void *)bpage->vaddr, bpage->datacount); } bpage = STAILQ_NEXT(bpage, links); } dmat->bounce_zone->total_bounced++; } ----------------------------- There are two things: (1) datavaddr is not always kva of client data, but sometimes it can be uva of client data. (2) bcopy() can be used only if datavaddr is kva or when map->pmap is current pmap. Note that there is an implication for bus_dmamap_load_uio() with uio->uio_segflg set to UIO_USERSPACE that used physical pages are in-core and wired. See "man bus_dma". There is not public interface to check that map->pmap is current pmap. So one solution is the following: if (bpage->datavaddr >= VM_MIN_KERNEL_ADDRESS) { bcopy(); } else { physcopy(); } If there will be public pmap_is_current() then another solution is the following: if (bpage->datavaddr != 0) && pmap_is_current(map->pmap)) { bcopy(); } else { physcopy(); } The second solution implies that context switch must not happen during bus_dmamap_sync() called from an interrupt routine. However, IMO, it's granted. Note that map->pmap should be always kernel_pmap for datavaddr >= VM_MIN_KERNEL_ADDRESS. Comments, different solutions, or objections? Svatopluk Kraus