Commit 38c2c791 authored by Eric Anholt's avatar Eric Anholt

drm/v3d: Fix and extend MMU error handling.

We were setting the wrong flags to enable PTI errors, so we were
seeing reads to invalid PTEs show up as write errors.  Also, we
weren't turning on the interrupts.  The AXI IDs we were dumping
included the outstanding write number and so they looked basically
random.  And the VIO_ADDR decoding was based on the MMU VA_WIDTH for
the first platform I worked on and was wrong on others.  In short,
this was a thorough mess from early HW enabling.

Tested on V3D 4.1 and 4.2 with intentional L2T, CLE, PTB, and TLB
faults.
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
Link: https://patchwork.freedesktop.org/patch/msgid/20190419001014.23579-4-eric@anholt.netReviewed-by: default avatarPaul Kocialkowski <paul.kocialkowski@bootlin.com>
parent 1ba9d7cb
...@@ -261,6 +261,7 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) ...@@ -261,6 +261,7 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO); mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO);
dev->coherent_dma_mask = dev->coherent_dma_mask =
DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH)); DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH));
v3d->va_width = 30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_VA_WIDTH);
ident1 = V3D_READ(V3D_HUB_IDENT1); ident1 = V3D_READ(V3D_HUB_IDENT1);
v3d->ver = (V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_TVER) * 10 + v3d->ver = (V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_TVER) * 10 +
......
...@@ -57,6 +57,8 @@ struct v3d_dev { ...@@ -57,6 +57,8 @@ struct v3d_dev {
*/ */
void *mmu_scratch; void *mmu_scratch;
dma_addr_t mmu_scratch_paddr; dma_addr_t mmu_scratch_paddr;
/* virtual address bits from V3D to the MMU. */
int va_width;
/* Number of V3D cores. */ /* Number of V3D cores. */
u32 cores; u32 cores;
......
...@@ -162,10 +162,33 @@ v3d_hub_irq(int irq, void *arg) ...@@ -162,10 +162,33 @@ v3d_hub_irq(int irq, void *arg)
V3D_HUB_INT_MMU_PTI | V3D_HUB_INT_MMU_PTI |
V3D_HUB_INT_MMU_CAP)) { V3D_HUB_INT_MMU_CAP)) {
u32 axi_id = V3D_READ(V3D_MMU_VIO_ID); u32 axi_id = V3D_READ(V3D_MMU_VIO_ID);
u64 vio_addr = (u64)V3D_READ(V3D_MMU_VIO_ADDR) << 8; u64 vio_addr = ((u64)V3D_READ(V3D_MMU_VIO_ADDR) <<
(v3d->va_width - 32));
static const char *const v3d41_axi_ids[] = {
"L2T",
"PTB",
"PSE",
"TLB",
"CLE",
"TFU",
"MMU",
"GMP",
};
const char *client = "?";
V3D_WRITE(V3D_MMU_CTL,
V3D_READ(V3D_MMU_CTL) & (V3D_MMU_CTL_CAP_EXCEEDED |
V3D_MMU_CTL_PT_INVALID |
V3D_MMU_CTL_WRITE_VIOLATION));
if (v3d->ver >= 41) {
axi_id = axi_id >> 5;
if (axi_id < ARRAY_SIZE(v3d41_axi_ids))
client = v3d41_axi_ids[axi_id];
}
dev_err(v3d->dev, "MMU error from client %d at 0x%08llx%s%s%s\n", dev_err(v3d->dev, "MMU error from client %s (%d) at 0x%llx%s%s%s\n",
axi_id, (long long)vio_addr, client, axi_id, (long long)vio_addr,
((intsts & V3D_HUB_INT_MMU_WRV) ? ((intsts & V3D_HUB_INT_MMU_WRV) ?
", write violation" : ""), ", write violation" : ""),
((intsts & V3D_HUB_INT_MMU_PTI) ? ((intsts & V3D_HUB_INT_MMU_PTI) ?
......
...@@ -69,10 +69,13 @@ int v3d_mmu_set_page_table(struct v3d_dev *v3d) ...@@ -69,10 +69,13 @@ int v3d_mmu_set_page_table(struct v3d_dev *v3d)
V3D_WRITE(V3D_MMU_PT_PA_BASE, v3d->pt_paddr >> V3D_MMU_PAGE_SHIFT); V3D_WRITE(V3D_MMU_PT_PA_BASE, v3d->pt_paddr >> V3D_MMU_PAGE_SHIFT);
V3D_WRITE(V3D_MMU_CTL, V3D_WRITE(V3D_MMU_CTL,
V3D_MMU_CTL_ENABLE | V3D_MMU_CTL_ENABLE |
V3D_MMU_CTL_PT_INVALID | V3D_MMU_CTL_PT_INVALID_ENABLE |
V3D_MMU_CTL_PT_INVALID_ABORT | V3D_MMU_CTL_PT_INVALID_ABORT |
V3D_MMU_CTL_PT_INVALID_INT |
V3D_MMU_CTL_WRITE_VIOLATION_ABORT | V3D_MMU_CTL_WRITE_VIOLATION_ABORT |
V3D_MMU_CTL_CAP_EXCEEDED_ABORT); V3D_MMU_CTL_WRITE_VIOLATION_INT |
V3D_MMU_CTL_CAP_EXCEEDED_ABORT |
V3D_MMU_CTL_CAP_EXCEEDED_INT);
V3D_WRITE(V3D_MMU_ILLEGAL_ADDR, V3D_WRITE(V3D_MMU_ILLEGAL_ADDR,
(v3d->mmu_scratch_paddr >> V3D_MMU_PAGE_SHIFT) | (v3d->mmu_scratch_paddr >> V3D_MMU_PAGE_SHIFT) |
V3D_MMU_ILLEGAL_ADDR_ENABLE); V3D_MMU_ILLEGAL_ADDR_ENABLE);
......
...@@ -152,7 +152,8 @@ ...@@ -152,7 +152,8 @@
# define V3D_MMU_CTL_PT_INVALID_ABORT BIT(19) # define V3D_MMU_CTL_PT_INVALID_ABORT BIT(19)
# define V3D_MMU_CTL_PT_INVALID_INT BIT(18) # define V3D_MMU_CTL_PT_INVALID_INT BIT(18)
# define V3D_MMU_CTL_PT_INVALID_EXCEPTION BIT(17) # define V3D_MMU_CTL_PT_INVALID_EXCEPTION BIT(17)
# define V3D_MMU_CTL_WRITE_VIOLATION BIT(16) # define V3D_MMU_CTL_PT_INVALID_ENABLE BIT(16)
# define V3D_MMU_CTL_WRITE_VIOLATION BIT(12)
# define V3D_MMU_CTL_WRITE_VIOLATION_ABORT BIT(11) # define V3D_MMU_CTL_WRITE_VIOLATION_ABORT BIT(11)
# define V3D_MMU_CTL_WRITE_VIOLATION_INT BIT(10) # define V3D_MMU_CTL_WRITE_VIOLATION_INT BIT(10)
# define V3D_MMU_CTL_WRITE_VIOLATION_EXCEPTION BIT(9) # define V3D_MMU_CTL_WRITE_VIOLATION_EXCEPTION BIT(9)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment