On 02/26/2015 05:02 PM, Paolo Bonzini wrote:
On 26/02/2015 22:31, Jordan Hargrave wrote:
My OS initializes DMAR page tables and then enables the IOMMU translation.
Then OS initializes AHCI driver. Writes VIRTUAL DMA to FIS registers.
eg. FIS DMA address is 0x10000 (maps to some hardware physical address
via iommu)
The OS writes 0x00 PORT_FIS_ADDR_HI -> qemu calls map_page (0x00 << 32)
| 0x7fae0000... 0x7fae0000 is stale, and is not in the IOMMU page map.
Causes a non-recoverable IOMMU fault.
That's a bug in QEMU. map_page must be skipped unless PORT_CMD_FIS_ON
is set in pr->cmd (also, QEMU is never resetting PORT_CMD_FIS_ON when
PORT_CMD_FIS_RX goes down).
Paolo
map_page must be skipped *if* PORT_CMD_FIS_ON is set -- or rather, that
produces undefined behavior in the AHCI spec. We can only set these
fields when the FIS Receive Engine is off. We can only modify the CLB if
PxCMD.ST is off.
We also never actually reset PORT_CMD_FIS_RX or PORT_CMD_FIS_ON
ourselves, so the status bit will get reset when the user writes zeroes
to those bits when writing PxCMD. (We always clear PORT_CMD_FIS_ON and
PORT_CMD_LIST_ON both upon any write to PxCMD, then re-add these flags
if we see the user has written PORT_CMD_START or PORT_CMD_FIS_RX.)
So I think I can fix this just by delaying the CLB and FB mappings to
the PORT_CMD_LIST_ON and PORT_CMD_FIS_ON events. I'll send a patch.