diff options
author | tmm <tmm@FreeBSD.org> | 2002-03-23 20:42:23 +0000 |
---|---|---|
committer | tmm <tmm@FreeBSD.org> | 2002-03-23 20:42:23 +0000 |
commit | b0d3f0a8e860e4c14bc846b086b4c06c7104d838 (patch) | |
tree | d12dd0a26681ca3a754e37520159e95480d492ab /sys/sparc64 | |
parent | 5421e07c01c198e52f7882f475d3febf23457b95 (diff) | |
download | FreeBSD-src-b0d3f0a8e860e4c14bc846b086b4c06c7104d838.zip FreeBSD-src-b0d3f0a8e860e4c14bc846b086b4c06c7104d838.tar.gz |
Add code to print the fault virtual address for uncorrectable DMA errors
caused by IOMMU misses to aid debugging. This will only work on
UltraSPARC-IIi and IIe.
Diffstat (limited to 'sys/sparc64')
-rw-r--r-- | sys/sparc64/include/iommuvar.h | 1 | ||||
-rw-r--r-- | sys/sparc64/pci/psycho.c | 8 | ||||
-rw-r--r-- | sys/sparc64/pci/psychoreg.h | 9 | ||||
-rw-r--r-- | sys/sparc64/sparc64/iommu.c | 15 |
4 files changed, 33 insertions, 0 deletions
diff --git a/sys/sparc64/include/iommuvar.h b/sys/sparc64/include/iommuvar.h index 148d0417..9fbde6f 100644 --- a/sys/sparc64/include/iommuvar.h +++ b/sys/sparc64/include/iommuvar.h @@ -80,6 +80,7 @@ void iommu_init(char *, struct iommu_state *, int, u_int32_t); void iommu_reset(struct iommu_state *); void iommu_enter(struct iommu_state *, vm_offset_t, vm_offset_t, int); void iommu_remove(struct iommu_state *, vm_offset_t, size_t); +void iommu_decode_fault(struct iommu_state *, vm_offset_t); int iommu_dvmamap_create(bus_dma_tag_t, struct iommu_state *, int, bus_dmamap_t *); diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c index 249f489..ff1ba03 100644 --- a/sys/sparc64/pci/psycho.c +++ b/sys/sparc64/pci/psycho.c @@ -710,6 +710,14 @@ psycho_ue(void *arg) afar = PSYCHO_READ8(sc, PSR_UE_AFA); afsr = PSYCHO_READ8(sc, PSR_UE_AFS); + /* + * On the UltraSPARC-IIi/IIe, IOMMU misses/protection faults cause + * the AFAR to be set to the physical address of the TTE entry that + * was invalid/write protected. Call into the iommu code to have + * them decoded to virtual IO addresses. + */ + if ((afsr & UEAFSR_P_DTE) != 0) + iommu_decode_fault(sc->sc_is, afar); /* It's uncorrectable. Dump the regs and panic. */ panic("%s: uncorrectable DMA error AFAR %#lx AFSR %#lx\n", device_get_name(sc->sc_dev), (u_long)afar, (u_long)afsr); diff --git a/sys/sparc64/pci/psychoreg.h b/sys/sparc64/pci/psychoreg.h index 9de6272..7de9c62 100644 --- a/sys/sparc64/pci/psychoreg.h +++ b/sys/sparc64/pci/psychoreg.h @@ -231,6 +231,15 @@ #define PCICTL_4ENABLE 0x000000000000000f /* enable 4 PCI slots */ #define PCICTL_6ENABLE 0x000000000000003f /* enable 6 PCI slots */ +/* Uncorrectable error asynchronous fault status registers */ +#define UEAFSR_BLK (1UL << 22) /* pri. error caused by read */ +#define UEAFSR_P_DTE (1UL << 56) /* pri. DMA translation error */ +#define UEAFSR_S_DTE (1UL << 57) /* sec. DMA translation error */ +#define UEAFSR_S_DWR (1UL << 58) /* sec. error during write */ +#define UEAFSR_S_DRD (1UL << 59) /* sec. error during read */ +#define UEAFSR_P_DWR (1UL << 61) /* pri. error during write */ +#define UEAFSR_P_DRD (1UL << 62) /* pri. error during read */ + /* * these are the PROM structures we grovel */ diff --git a/sys/sparc64/sparc64/iommu.c b/sys/sparc64/sparc64/iommu.c index 8ce4424..3e70bdb 100644 --- a/sys/sparc64/sparc64/iommu.c +++ b/sys/sparc64/sparc64/iommu.c @@ -385,6 +385,21 @@ iommu_remove(struct iommu_state *is, vm_offset_t va, vm_size_t len) } } +void +iommu_decode_fault(struct iommu_state *is, vm_offset_t phys) +{ + bus_addr_t va; + long idx; + + idx = phys - is->is_ptsb; + if (phys < is->is_ptsb || + idx > (PAGE_SIZE << is->is_tsbsize)) + return; + va = is->is_dvmabase + + (((bus_addr_t)idx >> IOTTE_SHIFT) << IO_PAGE_SHIFT); + printf("IOMMU fault virtual address %#lx\n", (u_long)va); +} + static int iommu_strbuf_flush_done(struct iommu_state *is) { |