From owner-svn-src-all@FreeBSD.ORG Tue Nov 26 03:00:55 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 9DAE77A6; Tue, 26 Nov 2013 03:00:55 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 740772BDE; Tue, 26 Nov 2013 03:00:55 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id rAQ30tVP062983; Tue, 26 Nov 2013 03:00:55 GMT (envelope-from grehan@svn.freebsd.org) Received: (from grehan@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id rAQ30tKS062982; Tue, 26 Nov 2013 03:00:55 GMT (envelope-from grehan@svn.freebsd.org) Message-Id: <201311260300.rAQ30tKS062982@svn.freebsd.org> From: Peter Grehan Date: Tue, 26 Nov 2013 03:00:55 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r258614 - head/usr.sbin/bhyve X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 Nov 2013 03:00:55 -0000 Author: grehan Date: Tue Nov 26 03:00:54 2013 New Revision: 258614 URL: http://svnweb.freebsd.org/changeset/base/258614 Log: The Data Byte Count (DBC) field of a Physical Region Descriptor Table is 22 bits, with the bit 31 being the interrupt-on-completion bit. OpenBSD and UEFI set this bit, resulting in large block i/o lengths being sent to bhyve and coredumping the process. Fix by masking off the relevant 22 bits when using the DBC field as a length. Reviewed by: Zhixiang Yu Discussed with: Tycho Nightingale (tycho.nightingale@pluribusnetworks.com) MFC after: 10.0 Modified: head/usr.sbin/bhyve/pci_ahci.c Modified: head/usr.sbin/bhyve/pci_ahci.c ============================================================================== --- head/usr.sbin/bhyve/pci_ahci.c Tue Nov 26 02:02:05 2013 (r258613) +++ head/usr.sbin/bhyve/pci_ahci.c Tue Nov 26 03:00:54 2013 (r258614) @@ -165,6 +165,7 @@ struct ahci_cmd_hdr { struct ahci_prdt_entry { uint64_t dba; uint32_t reserved; +#define DBCMASK 0x3fffff uint32_t dbc; }; @@ -461,10 +462,13 @@ ahci_handle_dma(struct ahci_port *p, int * Build up the iovec based on the prdt */ for (i = 0; i < iovcnt; i++) { + uint32_t dbcsz; + + dbcsz = (prdt->dbc & DBCMASK) + 1; breq->br_iov[i].iov_base = paddr_guest2host(ahci_ctx(sc), - prdt->dba, prdt->dbc + 1); - breq->br_iov[i].iov_len = prdt->dbc + 1; - aior->done += (prdt->dbc + 1); + prdt->dba, dbcsz); + breq->br_iov[i].iov_len = dbcsz; + aior->done += dbcsz; prdt++; } if (readop) @@ -513,11 +517,14 @@ write_prdt(struct ahci_port *p, int slot from = buf; prdt = (struct ahci_prdt_entry *)(cfis + 0x80); for (i = 0; i < hdr->prdtl && len; i++) { - uint8_t *ptr = paddr_guest2host(ahci_ctx(p->pr_sc), - prdt->dba, prdt->dbc + 1); - memcpy(ptr, from, prdt->dbc + 1); - len -= (prdt->dbc + 1); - from += (prdt->dbc + 1); + uint8_t *ptr; + uint32_t dbcsz; + + dbcsz = (prdt->dbc & DBCMASK) + 1; + ptr = paddr_guest2host(ahci_ctx(p->pr_sc), prdt->dba, dbcsz); + memcpy(ptr, from, dbcsz); + len -= dbcsz; + from += dbcsz; prdt++; } hdr->prdbc = size - len; @@ -908,10 +915,13 @@ atapi_read(struct ahci_port *p, int slot * Build up the iovec based on the prdt */ for (i = 0; i < iovcnt; i++) { + uint32_t dbcsz; + + dbcsz = (prdt->dbc & DBCMASK) + 1; breq->br_iov[i].iov_base = paddr_guest2host(ahci_ctx(sc), - prdt->dba, prdt->dbc + 1); - breq->br_iov[i].iov_len = prdt->dbc + 1; - aior->done += (prdt->dbc + 1); + prdt->dba, dbcsz); + breq->br_iov[i].iov_len = dbcsz; + aior->done += dbcsz; prdt++; } err = blockif_read(p->bctx, breq);