summaryrefslogtreecommitdiffstats
path: root/sys/sparc64
diff options
context:
space:
mode:
authortmm <tmm@FreeBSD.org>2002-03-23 20:42:23 +0000
committertmm <tmm@FreeBSD.org>2002-03-23 20:42:23 +0000
commitb0d3f0a8e860e4c14bc846b086b4c06c7104d838 (patch)
treed12dd0a26681ca3a754e37520159e95480d492ab /sys/sparc64
parent5421e07c01c198e52f7882f475d3febf23457b95 (diff)
downloadFreeBSD-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.h1
-rw-r--r--sys/sparc64/pci/psycho.c8
-rw-r--r--sys/sparc64/pci/psychoreg.h9
-rw-r--r--sys/sparc64/sparc64/iommu.c15
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)
{
OpenPOWER on IntegriCloud