Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_ahci.c
Show First 20 Lines • Show All 998 Lines • ▼ Show 20 Lines | ata_identify_init(struct ahci_port* p, int atapi) | ||||
struct ata_params* ata_ident = &p->ata_ident; | struct ata_params* ata_ident = &p->ata_ident; | ||||
if (atapi) { | if (atapi) { | ||||
ata_ident->config = ATA_PROTO_ATAPI | ATA_ATAPI_TYPE_CDROM | | ata_ident->config = ATA_PROTO_ATAPI | ATA_ATAPI_TYPE_CDROM | | ||||
ATA_ATAPI_REMOVABLE | ATA_DRQ_FAST; | ATA_ATAPI_REMOVABLE | ATA_DRQ_FAST; | ||||
ata_ident->capabilities1 = ATA_SUPPORT_LBA | | ata_ident->capabilities1 = ATA_SUPPORT_LBA | | ||||
ATA_SUPPORT_DMA; | ATA_SUPPORT_DMA; | ||||
ata_ident->capabilities2 = (1 << 14 | 1); | ata_ident->capabilities2 = (1 << 14 | 1); | ||||
ata_ident->atavalid = ATA_FLAG_64_70 | ATA_FLAG_88; | ata_ident->atavalid = ATA_FLAG_54_58 | ATA_FLAG_64_70; | ||||
ata_ident->obsolete62 = 0x3f; | ata_ident->obsolete62 = 0x3f; | ||||
ata_ident->mwdmamodes = 7; | ata_ident->mwdmamodes = 7; | ||||
if (p->xfermode & ATA_WDMA0) | if (p->xfermode & ATA_WDMA0) | ||||
ata_ident->mwdmamodes |= (1 << ((p->xfermode & 7) + 8)); | ata_ident->mwdmamodes |= (1 << ((p->xfermode & 7) + 8)); | ||||
ata_ident->apiomodes = 3; | ata_ident->apiomodes = 3; | ||||
ata_ident->mwdmamin = 0x0078; | ata_ident->mwdmamin = 0x0078; | ||||
ata_ident->mwdmarec = 0x0078; | ata_ident->mwdmarec = 0x0078; | ||||
ata_ident->pioblind = 0x0078; | ata_ident->pioblind = 0x0078; | ||||
Show All 32 Lines | if (atapi) { | ||||
ata_ident->sectors = sech; | ata_ident->sectors = sech; | ||||
ata_ident->sectors_intr = (0x8000 | 128); | ata_ident->sectors_intr = (0x8000 | 128); | ||||
ata_ident->tcg = 0; | ata_ident->tcg = 0; | ||||
ata_ident->capabilities1 = ATA_SUPPORT_DMA | | ata_ident->capabilities1 = ATA_SUPPORT_DMA | | ||||
ATA_SUPPORT_LBA | ATA_SUPPORT_IORDY; | ATA_SUPPORT_LBA | ATA_SUPPORT_IORDY; | ||||
ata_ident->capabilities2 = (1 << 14); | ata_ident->capabilities2 = (1 << 14); | ||||
ata_ident->atavalid = ATA_FLAG_64_70 | ATA_FLAG_88; | ata_ident->atavalid = ATA_FLAG_54_58 | | ||||
ATA_FLAG_64_70; | |||||
if (p->mult_sectors) | if (p->mult_sectors) | ||||
ata_ident->multi = (ATA_MULTI_VALID | p->mult_sectors); | ata_ident->multi = (ATA_MULTI_VALID | p->mult_sectors); | ||||
if (sectors <= 0x0fffffff) { | if (sectors <= 0x0fffffff) { | ||||
ata_ident->lba_size_1 = sectors; | ata_ident->lba_size_1 = sectors; | ||||
ata_ident->lba_size_2 = (sectors >> 16); | ata_ident->lba_size_2 = (sectors >> 16); | ||||
} else { | } else { | ||||
ata_ident->lba_size_1 = 0xffff; | ata_ident->lba_size_1 = 0xffff; | ||||
ata_ident->lba_size_2 = 0x0fff; | ata_ident->lba_size_2 = 0x0fff; | ||||
▲ Show 20 Lines • Show All 1,460 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
pci_ahci_snapshot_save_queues(struct ahci_port *port, | pci_ahci_snapshot_save_queues(struct ahci_port *port, | ||||
struct vm_snapshot_meta *meta) | struct vm_snapshot_meta *meta) | ||||
{ | { | ||||
int ret; | int ret; | ||||
int idx; | int idx; | ||||
struct ahci_ioreq *ioreq; | struct ahci_ioreq *ioreq; | ||||
SNAPSHOT_ADD_INTERN_ARR(queues_iofhd_indexes, meta); | |||||
SNAPSHOT_ACTIVATE_AUTO_INDEXING(meta, 0); | |||||
STAILQ_FOREACH(ioreq, &port->iofhd, io_flist) { | STAILQ_FOREACH(ioreq, &port->iofhd, io_flist) { | ||||
idx = ((void *) ioreq - (void *) port->ioreq) / sizeof(*ioreq); | idx = ((void *) ioreq - (void *) port->ioreq) / sizeof(*ioreq); | ||||
SNAPSHOT_VAR_OR_LEAVE(idx, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(idx, meta, ret, done); | ||||
} | } | ||||
idx = -1; | idx = -1; | ||||
SNAPSHOT_VAR_OR_LEAVE(idx, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(idx, meta, ret, done); | ||||
SNAPSHOT_DEACTIVATE_AUTO_INDEXING(meta); | |||||
SNAPSHOT_REMOVE_INTERN_ARR(queues_iofhd_indexex, meta); | |||||
SNAPSHOT_ADD_INTERN_ARR(queues_iobhd_indexes, meta); | |||||
SNAPSHOT_ACTIVATE_AUTO_INDEXING(meta, 0); | |||||
TAILQ_FOREACH(ioreq, &port->iobhd, io_blist) { | TAILQ_FOREACH(ioreq, &port->iobhd, io_blist) { | ||||
idx = ((void *) ioreq - (void *) port->ioreq) / sizeof(*ioreq); | idx = ((void *) ioreq - (void *) port->ioreq) / sizeof(*ioreq); | ||||
SNAPSHOT_VAR_OR_LEAVE(idx, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(idx, meta, ret, done); | ||||
/* | /* | ||||
* Snapshot only the busy requests; other requests are | * Snapshot only the busy requests; other requests are | ||||
* not valid. | * not valid. | ||||
*/ | */ | ||||
ret = blockif_snapshot_req(&ioreq->io_req, meta); | ret = blockif_snapshot_req(&ioreq->io_req, meta); | ||||
if (ret != 0) { | if (ret != 0) { | ||||
fprintf(stderr, "%s: failed to snapshot req\r\n", | fprintf(stderr, "%s: failed to snapshot req\r\n", | ||||
__func__); | __func__); | ||||
goto done; | goto done; | ||||
} | } | ||||
} | } | ||||
idx = -1; | idx = -1; | ||||
SNAPSHOT_VAR_OR_LEAVE(idx, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(idx, meta, ret, done); | ||||
SNAPSHOT_DEACTIVATE_AUTO_INDEXING(meta); | |||||
SNAPSHOT_REMOVE_INTERN_ARR(queues_iobhd_indexes, meta); | |||||
done: | done: | ||||
return (ret); | return (ret); | ||||
} | } | ||||
static int | static int | ||||
pci_ahci_snapshot_restore_queues(struct ahci_port *port, | pci_ahci_snapshot_restore_queues(struct ahci_port *port, | ||||
struct vm_snapshot_meta *meta) | struct vm_snapshot_meta *meta) | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | pci_ahci_snapshot(struct vm_snapshot_meta *meta) | ||||
SNAPSHOT_VAR_OR_LEAVE(sc->ccc_ctl, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(sc->ccc_ctl, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(sc->ccc_pts, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(sc->ccc_pts, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(sc->em_loc, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(sc->em_loc, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(sc->em_ctl, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(sc->em_ctl, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(sc->cap2, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(sc->cap2, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(sc->bohc, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(sc->bohc, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(sc->lintr, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(sc->lintr, meta, ret, done); | ||||
SNAPSHOT_ADD_INTERN_ARR(ports, meta); | |||||
for (i = 0; i < MAX_PORTS; i++) { | for (i = 0; i < MAX_PORTS; i++) { | ||||
port = &sc->port[i]; | port = &sc->port[i]; | ||||
SNAPSHOT_SET_INTERN_ARR_INDEX(meta, i); | |||||
if (meta->op == VM_SNAPSHOT_SAVE) | if (meta->op == VM_SNAPSHOT_SAVE) | ||||
bctx = port->bctx; | bctx = port->bctx; | ||||
SNAPSHOT_VAR_OR_LEAVE(bctx, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(bctx, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(port->port, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(port->port, meta, ret, done); | ||||
/* Mostly for restore; save is ensured by the lines above. */ | /* Mostly for restore; save is ensured by the lines above. */ | ||||
if (((bctx == NULL) && (port->bctx != NULL)) || | if (((bctx == NULL) && (port->bctx != NULL)) || | ||||
Show All 9 Lines | for (i = 0; i < MAX_PORTS; i++) { | ||||
if (port->port != i) { | if (port->port != i) { | ||||
fprintf(stderr, "%s: ports not matching: " | fprintf(stderr, "%s: ports not matching: " | ||||
"actual: %d expected: %d\r\n", | "actual: %d expected: %d\r\n", | ||||
__func__, port->port, i); | __func__, port->port, i); | ||||
ret = EINVAL; | ret = EINVAL; | ||||
goto done; | goto done; | ||||
} | } | ||||
SNAPSHOT_ADD_INTERN_ARR(port_cmd_lst_and_rfis, meta); | |||||
SNAPSHOT_ACTIVATE_AUTO_INDEXING(meta, 0); | |||||
SNAPSHOT_GUEST2HOST_ADDR_OR_LEAVE(port->cmd_lst, | SNAPSHOT_GUEST2HOST_ADDR_OR_LEAVE(port->cmd_lst, | ||||
AHCI_CL_SIZE * AHCI_MAX_SLOTS, false, meta, ret, done); | AHCI_CL_SIZE * AHCI_MAX_SLOTS, false, meta, ret, done); | ||||
SNAPSHOT_GUEST2HOST_ADDR_OR_LEAVE(port->rfis, 256, false, meta, | SNAPSHOT_GUEST2HOST_ADDR_OR_LEAVE(port->rfis, 256, false, meta, | ||||
ret, done); | ret, done); | ||||
SNAPSHOT_DEACTIVATE_AUTO_INDEXING(meta); | |||||
SNAPSHOT_REMOVE_INTERN_ARR(port_cmd_lst_and_rfis, meta); | |||||
SNAPSHOT_VAR_OR_LEAVE(port->ata_ident, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(port->ata_ident, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(port->atapi, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(port->atapi, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(port->reset, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(port->reset, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(port->waitforclear, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(port->waitforclear, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(port->mult_sectors, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(port->mult_sectors, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(port->xfermode, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(port->xfermode, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(port->err_cfis, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(port->err_cfis, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(port->sense_key, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(port->sense_key, meta, ret, done); | ||||
Show All 14 Lines | for (i = 0; i < MAX_PORTS; i++) { | ||||
SNAPSHOT_VAR_OR_LEAVE(port->sctl, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(port->sctl, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(port->serr, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(port->serr, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(port->sact, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(port->sact, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(port->ci, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(port->ci, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(port->sntf, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(port->sntf, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(port->fbs, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(port->fbs, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(port->ioqsz, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(port->ioqsz, meta, ret, done); | ||||
SNAPSHOT_CLEAR_INTERN_ARR_INDEX(meta); | |||||
SNAPSHOT_ADD_INTERN_ARR(iorequests, meta); | |||||
for (j = 0; j < port->ioqsz; j++) { | for (j = 0; j < port->ioqsz; j++) { | ||||
ioreq = &port->ioreq[j]; | ioreq = &port->ioreq[j]; | ||||
SNAPSHOT_SET_INTERN_ARR_INDEX(meta, j); | |||||
/* blockif_req snapshot done only for busy requests. */ | /* blockif_req snapshot done only for busy requests. */ | ||||
hdr = (struct ahci_cmd_hdr *)(port->cmd_lst + | hdr = (struct ahci_cmd_hdr *)(port->cmd_lst + | ||||
ioreq->slot * AHCI_CL_SIZE); | ioreq->slot * AHCI_CL_SIZE); | ||||
SNAPSHOT_GUEST2HOST_ADDR_OR_LEAVE(ioreq->cfis, | SNAPSHOT_GUEST2HOST_ADDR_OR_LEAVE(ioreq->cfis, | ||||
0x80 + hdr->prdtl * sizeof(struct ahci_prdt_entry), | 0x80 + hdr->prdtl * sizeof(struct ahci_prdt_entry), | ||||
false, meta, ret, done); | false, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(ioreq->len, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(ioreq->len, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(ioreq->done, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(ioreq->done, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(ioreq->slot, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(ioreq->slot, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(ioreq->more, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(ioreq->more, meta, ret, done); | ||||
SNAPSHOT_VAR_OR_LEAVE(ioreq->readop, meta, ret, done); | SNAPSHOT_VAR_OR_LEAVE(ioreq->readop, meta, ret, done); | ||||
} | } | ||||
SNAPSHOT_CLEAR_INTERN_ARR_INDEX(meta); | |||||
SNAPSHOT_REMOVE_INTERN_ARR(iorequests, meta); | |||||
/* Perform save / restore specific operations. */ | /* Perform save / restore specific operations. */ | ||||
if (meta->op == VM_SNAPSHOT_SAVE) { | if (meta->op == VM_SNAPSHOT_SAVE) { | ||||
ret = pci_ahci_snapshot_save_queues(port, meta); | ret = pci_ahci_snapshot_save_queues(port, meta); | ||||
if (ret != 0) | if (ret != 0) | ||||
goto done; | goto done; | ||||
} else if (meta->op == VM_SNAPSHOT_RESTORE) { | } else if (meta->op == VM_SNAPSHOT_RESTORE) { | ||||
ret = pci_ahci_snapshot_restore_queues(port, meta); | ret = pci_ahci_snapshot_restore_queues(port, meta); | ||||
if (ret != 0) | if (ret != 0) | ||||
goto done; | goto done; | ||||
} else { | } else { | ||||
ret = EINVAL; | ret = EINVAL; | ||||
goto done; | goto done; | ||||
} | } | ||||
SNAPSHOT_ADD_INTERN_ARR(block_context, meta); | |||||
ret = blockif_snapshot(port->bctx, meta); | ret = blockif_snapshot(port->bctx, meta); | ||||
if (ret != 0) { | if (ret != 0) { | ||||
fprintf(stderr, "%s: failed to restore blockif\r\n", | fprintf(stderr, "%s: failed to restore blockif\r\n", | ||||
__func__); | __func__); | ||||
goto done; | goto done; | ||||
} | } | ||||
SNAPSHOT_REMOVE_INTERN_ARR(block_context, meta); | |||||
} | } | ||||
SNAPSHOT_REMOVE_INTERN_ARR(ports, meta); | |||||
done: | done: | ||||
return (ret); | return (ret); | ||||
} | } | ||||
static int | static int | ||||
pci_ahci_pause(struct vmctx *ctx, struct pci_devinst *pi) | pci_ahci_pause(struct vmctx *ctx, struct pci_devinst *pi) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 79 Lines • Show Last 20 Lines |