--- sys/dev/disk/nata/ata-all.h +++ sys/dev/disk/nata/ata-all.h @@ -236,7 +236,9 @@ #define ATA_AHCI_CL_OFFSET 0 #define ATA_AHCI_FB_OFFSET 1024 #define ATA_AHCI_CT_OFFSET 1024+256 #define ATA_AHCI_CT_SG_OFFSET 128 -#define ATA_AHCI_CT_SIZE 256 +/* must equal sizeof(struct ata_ahci_cmd_tab) = 128 + 64*16 = 1152. + * tag is currently hardcoded 0; any per-tag dispatch must also size the + * work area (MAXWSPCSZ) for the number of supported tags. */ +#define ATA_AHCI_CT_SIZE 1152 struct ata_ahci_dma_prd { u_int64_t dba; --- sys/dev/disk/nata/chipsets/ata-ahci.c +++ sys/dev/disk/nata/chipsets/ata-ahci.c @@ -531,13 +531,14 @@ ata_ahci_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) struct ata_ahci_dma_prd *prd = args->dmatab; int i; + /* assert the bound BEFORE writing the table */ + KASSERT(nsegs <= ATA_AHCI_DMA_ENTRIES, ("too many DMA segment entries\n")); if (!(args->error = error)) { for (i = 0; i < nsegs; i++) { prd[i].dba = htole64(segs[i].ds_addr); prd[i].dbc = htole32((segs[i].ds_len - 1) & ATA_AHCI_PRD_MASK); } } - KASSERT(nsegs <= ATA_AHCI_DMA_ENTRIES, ("too many DMA segment entries\n")); args->nsegs = nsegs; } @@ -575,3 +586,7 @@ ata_ahci_setup_fis(struct ata_ahci_cmd_tab *ctp, struct ata_request *request) } return ata_request2fis_h2d(request, &ctp->cfis[0]); } + +/* keep the cmd-table stride honest against the struct it indexes */ +_Static_assert(ATA_AHCI_CT_SIZE == sizeof(struct ata_ahci_cmd_tab), + ("ATA_AHCI_CT_SIZE must equal sizeof(struct ata_ahci_cmd_tab)"));