From owner-freebsd-arm@FreeBSD.ORG Fri Apr 24 13:11:21 2015 Return-Path: Delivered-To: freebsd-arm@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 50AFEA64 for ; Fri, 24 Apr 2015 13:11:21 +0000 (UTC) Received: from mail-ie0-x22f.google.com (mail-ie0-x22f.google.com [IPv6:2607:f8b0:4001:c03::22f]) (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 1FF0C17B8 for ; Fri, 24 Apr 2015 13:11:21 +0000 (UTC) Received: by iecrt8 with SMTP id rt8so82929083iec.0 for ; Fri, 24 Apr 2015 06:11:20 -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=EJv4D+aj0+GQ/6tscezGWQaXgJHYops7KbONX4rkcNzEgN+6GGdlqGYLqQzecwyUml pYNsBztiF4MCvBFkAOuhlXIX/Gbl0JkOjUfy8JW6sYQe91uYjp3eDADA7QckZtJxJG2T BHRNClnfG3f1FF1KvVnKbyybCU6QeEr+t2GD6rqVh6cyZf5po+xU0Rs9dJ9p5P8v7X5c uM+VaxiebBF7gPtMnLXgjERdp0wOdWsOFnA/xTOra6l1rSoCwothIp1/0NUphxpr1i1B 12MkFAlNT/T8Rb0h+Ogtt2wxwv3E61SIGYRqy5Tu7nhvP+44c4yUnSb8TH0XVuQ4XukQ kFGg== MIME-Version: 1.0 X-Received: by 10.50.61.200 with SMTP id s8mr2413936igr.7.1429881080567; Fri, 24 Apr 2015 06:11:20 -0700 (PDT) Received: by 10.64.13.81 with HTTP; Fri, 24 Apr 2015 06:11:20 -0700 (PDT) Date: Fri, 24 Apr 2015 15:11:20 +0200 Message-ID: Subject: bus_dmamap_sync() for bounced client buffers from user address space From: Svatopluk Kraus To: freebsd-arm@freebsd.org Content-Type: text/plain; charset=UTF-8 X-BeenThere: freebsd-arm@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "Porting FreeBSD to ARM processors." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 Apr 2015 13:11:21 -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