svn commit: r258614 - head/usr.sbin/bhyve
Peter Grehan
grehan at FreeBSD.org
Tue Nov 26 03:00:55 UTC 2013
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 at 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);
More information about the svn-src-all
mailing list