//
long nop
long ret
+//
+// Trap handler.
+// Requires at least 4 GPRs and 32 bytes of l[] memory to temporarily save GPRs.
+// Low 32 bytes of l[] memory shouldn't be used if resumeability is required.
+//
+// Trap info:
+// 0x000: mutex
+// 0x004: PC
+// 0x008: trapstat
+// 0x00c: warperr
+// 0x010: tidx
+// 0x014: tidy
+// 0x018: tidz
+// 0x01c: ctaidx
+// 0x020: ctaidy
+// 0x024: ctaidz
+// 0x030: $r0q
+// 0x130: $flags
+// 0x140: s[]
+//
+st b128 wb l[0x00] $r0q
+// check state of the warp and continue if it didn't cause the trap
+long mov b32 $r1 $trapstat
+long mov b32 $r3 $warperr
+mov $r2 $flags mask 0xffff
+and b32 0 $c $r1 $r3
+e $c bra #end_cont
+// spill control flow stack to l[]
+long mov b32 $r3 16
+spill_cfstack:
+preret #end_exit
+sub b32 $r3 $c $r3 0x1
+lg $c bra #spill_cfstack
+// retrieve pointer to trap info
+mov b32 $r0 c0[0x1900]
+mov b32 $r1 c0[0x1904]
+// we only let a single faulting thread store its state
+mov b32 $r3 0x1
+exch b32 $r3 g[$r0d] $r3
+joinat #end_exit
+set $p0 0x1 eq u32 $r3 0x1
+join $p0 nop
+// store $c and $p registers
+st b32 wb g[$r0d+0x130] $r2
+// store $trapstat and $warperr
+long mov b32 $r2 $trapstat
+long mov b32 $r3 $warperr
+st b64 wb g[$r0d+0x8] $r2d
+// store registers
+st b128 wb g[$r0d+0x40] $r4q
+st b128 wb g[$r0d+0x50] $r8q
+st b128 wb g[$r0d+0x60] $r12q
+st b128 wb g[$r0d+0x70] $r16q
+st b128 wb g[$r0d+0x80] $r20q
+st b128 wb g[$r0d+0x90] $r24q
+st b128 wb g[$r0d+0xa0] $r28q
+st b128 wb g[$r0d+0xb0] $r32q
+st b128 wb g[$r0d+0xc0] $r36q
+st b128 wb g[$r0d+0xd0] $r40q
+st b128 wb g[$r0d+0xe0] $r44q
+st b128 wb g[$r0d+0xf0] $r48q
+st b128 wb g[$r0d+0x100] $r52q
+st b128 wb g[$r0d+0x110] $r56q
+st b128 wb g[$r0d+0x120] $r60q
+ld b64 $r2d cs l[0x0]
+st b64 wb g[$r0d+0x30] $r2d
+ld b64 $r2d cs l[0x8]
+st b64 wb g[$r0d+0x38] $r2d
+// store thread id
+long mov b32 $r2 $tidx
+long mov b32 $r3 $tidy
+st b64 wb g[$r0d+0x10] $r2d
+long mov b32 $r2 $tidz
+long mov b32 $r3 $ctaidx
+st b64 wb g[$r0d+0x18] $r2d
+long mov b32 $r2 $ctaidy
+long mov b32 $r3 $ctaidz
+st b64 wb g[$r0d+0x20] $r2d
+// store shared memory (in reverse order so $r0d is base again at the end)
+long mov b32 $r3 $smemsz
+sub b32 $r3 $c $r3 0x4
+s $c bra #shared_done
+add b32 $r0 $c $r0 $r3
+add b32 $r1 $r1 0x0 $c
+shared_loop:
+long ld b32 $r2 s[$r3]
+long st b32 wb g[$r0d+0x140] $r2
+sub b32 $r0 $c $r0 0x4
+sub b32 $r1 $r1 0x0 $c
+sub b32 $r3 $c $r3 0x4
+lg $c bra #shared_loop
+shared_done:
+// search the stack for trap entry to retrieve PC
+mov b32 $r0 c0[0x1908]
+mov b32 $r1 c0[0x190c]
+membar sys
+// invalidate caches so we can read stack entries via g[]
+cctl ivall 0 l[0]
+cctl ivall 0 g[$r0d]
+// get offsets
+mov b32 $r2 $physid
+ext u32 $r3 $r2 0x0814 // MP id
+ext u32 $r2 $r2 0x0608 // warp id
+mul $r2 u32 $r2 u32 c0[0x1914] // warp offset
+mul $r3 u32 $r3 u32 c0[0x1910] // MP offset
+add b32 $r2 $r2 $r3 // MP + warp offset
+add b32 $r0 $c $r0 $r2
+add b32 $r1 $r1 0x0 $c
+search_cstack:
+mov b32 $r3 c0[0x1918] // cstack size
+ld u8 $r2 cv g[$r0d+0x8]
+set $p0 0x1 eq u32 $r2 0xa
+$p0 bra #entry_found
+add b32 $r0 $c $r0 0x10
+add b32 $r1 $r1 0x0 $c
+sub b32 $r3 $c $r3 0x10
+lg $c bra #search_cstack
+bra #end_exit
+entry_found:
+// load PC (may be unaligned and spread out)
+ld b32 $r2 cv g[$r0d]
+mov b32 $r0 c0[0x1900]
+mov b32 $r1 c0[0x1904]
+st b32 wb g[$r0d+0x4] $r2
+join nop
+// invalidate caches and exit
+end_exit:
+cctl ivall 0 g[0]
+bpt pause 0x0
+rtt terminate
+end_cont:
+bpt pause 0x0
+mov $flags $r2 mask 0xffff
+ld b128 $r0q cs l[0x00]
+rtt
0x9000000000001de7ULL,
0x4000000000001de4ULL,
0x9000000000001de7ULL,
+ 0xc800000003f01cc5ULL,
+ 0x2c00000100005c04ULL,
+ 0x2c0000010800dc04ULL,
+ 0x3000c3fffff09c04ULL,
+ 0x680100000c1fdc03ULL,
+ 0x4000000a60001c47ULL,
+ 0x180000004000dde2ULL,
+ 0x78000009c0000007ULL,
+ 0x0c0000000430dd02ULL,
+ 0x4003ffffa0001ca7ULL,
+ 0x2800406400001de4ULL,
+ 0x2800406410005de4ULL,
+ 0x180000000400dde2ULL,
+ 0x547e18000000dd05ULL,
+ 0x60000008e0000007ULL,
+ 0x190ec0000431dc03ULL,
+ 0x40000000000001f4ULL,
+ 0x94000004c0009c85ULL,
+ 0x2c00000100009c04ULL,
+ 0x2c0000010800dc04ULL,
+ 0x9400000020009ca5ULL,
+ 0x9400000100011cc5ULL,
+ 0x9400000140021cc5ULL,
+ 0x9400000180031cc5ULL,
+ 0x94000001c0041cc5ULL,
+ 0x9400000200051cc5ULL,
+ 0x9400000240061cc5ULL,
+ 0x9400000280071cc5ULL,
+ 0x94000002c0081cc5ULL,
+ 0x9400000300091cc5ULL,
+ 0x94000003400a1cc5ULL,
+ 0x94000003800b1cc5ULL,
+ 0x94000003c00c1cc5ULL,
+ 0x94000004000d1cc5ULL,
+ 0x94000004400e1cc5ULL,
+ 0x94000004800f1cc5ULL,
+ 0xc000000003f09ea5ULL,
+ 0x94000000c0009ca5ULL,
+ 0xc000000023f09ea5ULL,
+ 0x94000000e0009ca5ULL,
+ 0x2c00000084009c04ULL,
+ 0x2c0000008800dc04ULL,
+ 0x9400000040009ca5ULL,
+ 0x2c0000008c009c04ULL,
+ 0x2c0000009400dc04ULL,
+ 0x9400000060009ca5ULL,
+ 0x2c00000098009c04ULL,
+ 0x2c0000009c00dc04ULL,
+ 0x9400000080009ca5ULL,
+ 0x2c000000c800dc04ULL,
+ 0x0c0000001030dd02ULL,
+ 0x4000000100001ea7ULL,
+ 0x480100000c001c03ULL,
+ 0x0800000000105c42ULL,
+ 0xc100000000309c85ULL,
+ 0x9400000500009c85ULL,
+ 0x0c00000010001d02ULL,
+ 0x0800000000105d42ULL,
+ 0x0c0000001030dd02ULL,
+ 0x4003ffff40001ca7ULL,
+ 0x2800406420001de4ULL,
+ 0x2800406430005de4ULL,
+ 0xe000000000001c45ULL,
+ 0xd000000003ffdcc5ULL,
+ 0x9c000000000fdcc5ULL,
+ 0x2c0000000c009c04ULL,
+ 0x7000c0205020dc03ULL,
+ 0x7000c01820209c03ULL,
+ 0x5000406450209c03ULL,
+ 0x500040644030dc03ULL,
+ 0x480000000c209c03ULL,
+ 0x4801000008001c03ULL,
+ 0x0800000000105c42ULL,
+ 0x280040646000dde4ULL,
+ 0x8400000020009f05ULL,
+ 0x190ec0002821dc03ULL,
+ 0x40000000800001e7ULL,
+ 0x0c00000040001c02ULL,
+ 0x0800000000105c42ULL,
+ 0x0c0000004030dd02ULL,
+ 0x00029dff0ffc5cbfULL,
+ 0x8400000000009f85ULL,
+ 0x2800406400001de4ULL,
+ 0x2800406410005de4ULL,
+ 0x9400000010009c85ULL,
+ 0x4000000000001df4ULL,
+ 0x9800000003ffdcc5ULL,
+ 0xd000000000008007ULL,
+ 0xa000000000004007ULL,
+ 0xd000000000008007ULL,
+ 0x3400c3fffc201c04ULL,
+ 0xc000000003f01ec5ULL,
+ 0xa000000000000007ULL
};
static const uint16_t nve4_builtin_offsets[NVC0_BUILTIN_COUNT] =
PUSH_DATA (push, 1);
PUSH_DATA (push, 3); /* 7 */
PUSH_DATA (push, 1);
+
+#ifdef DEBUG
+ BEGIN_NVC0(push, NVE4_COMPUTE(UPLOAD_ADDRESS_HIGH), 2);
+ PUSH_DATAh(push, screen->parm->offset + NVE4_CP_INPUT_TRAP_INFO_PTR);
+ PUSH_DATA (push, screen->parm->offset + NVE4_CP_INPUT_TRAP_INFO_PTR);
+ BEGIN_NVC0(push, NVE4_COMPUTE(UPLOAD_SIZE), 2);
+ PUSH_DATA (push, 28);
+ PUSH_DATA (push, NVE4_COMPUTE_UPLOAD_UNK0184_UNKVAL);
+ BEGIN_1IC0(push, NVE4_COMPUTE(UPLOAD_EXEC), 8);
+ PUSH_DATA (push, NVE4_COMPUTE_UPLOAD_EXEC_UNKVAL_DATA);
+ PUSH_DATA (push, screen->parm->offset + NVE4_CP_PARAM_TRAP_INFO);
+ PUSH_DATAh(push, screen->parm->offset + NVE4_CP_PARAM_TRAP_INFO);
+ PUSH_DATA (push, screen->tls->offset);
+ PUSH_DATAh(push, screen->tls->offset);
+ PUSH_DATA (push, screen->tls->size / 2); /* MP TEMP block size */
+ PUSH_DATA (push, screen->tls->size / 2 / 64); /* warp TEMP block size */
+ PUSH_DATA (push, 0); /* warp cfstack size */
+#endif
+
BEGIN_NVC0(push, NVE4_COMPUTE(FLUSH), 1);
PUSH_DATA (push, NVE4_COMPUTE_FLUSH_CB);
}
}
+static void
+nve4_compute_trap_info(struct nvc0_context *nvc0)
+{
+ struct nvc0_screen *screen = nvc0->screen;
+ struct nouveau_bo *bo = screen->parm;
+ int ret, i;
+ volatile struct nve4_mp_trap_info *info;
+ uint8_t *map;
+
+ ret = nouveau_bo_map(bo, NOUVEAU_BO_RDWR, nvc0->base.client);
+ if (ret)
+ return;
+ map = (uint8_t *)bo->map;
+ info = (volatile struct nve4_mp_trap_info *)(map + NVE4_CP_PARAM_TRAP_INFO);
+
+ if (info->lock) {
+ debug_printf("trapstat = %08x\n", info->trapstat);
+ debug_printf("warperr = %08x\n", info->warperr);
+ debug_printf("PC = %x\n", info->pc);
+ debug_printf("tid = %u %u %u\n",
+ info->tid[0], info->tid[1], info->tid[2]);
+ debug_printf("ctaid = %u %u %u\n",
+ info->ctaid[0], info->ctaid[1], info->ctaid[2]);
+ for (i = 0; i <= 63; ++i)
+ debug_printf("$r%i = %08x\n", i, info->r[i]);
+ for (i = 0; i <= 6; ++i)
+ debug_printf("$p%i = %i\n", i, (info->flags >> i) & 1);
+ debug_printf("$c = %x\n", info->flags >> 12);
+ }
+ info->lock = 0;
+}
/* Input space is implemented as c0[], to which we bind the screen->parm bo.
*/
-#define NVE4_CP_INPUT_USER 0x0000
-#define NVE4_CP_INPUT_USER_LIMIT 0x1000
-#define NVE4_CP_INPUT_GRID_INFO(i) (0x1000 + (i) * 4)
-#define NVE4_CP_INPUT_NTID(i) (0x1000 + (i) * 4)
-#define NVE4_CP_INPUT_NCTAID(i) (0x100c + (i) * 4)
-#define NVE4_CP_INPUT_GRIDID 0x1018
-#define NVE4_CP_INPUT_TEX(i) (0x1040 + (i) * 4)
-#define NVE4_CP_INPUT_TEX_STRIDE 4
-#define NVE4_CP_INPUT_TEX_MAX 32
-#define NVE4_CP_INPUT_MS_OFFSETS 0x10c0
-#define NVE4_CP_INPUT_SUF_STRIDE 64
-#define NVE4_CP_INPUT_SUF(i) (0x1100 + (i) * NVE4_CP_INPUT_SUF_STRIDE)
-#define NVE4_CP_INPUT_SUF_MAX 32
-#define NVE4_CP_INPUT_SIZE 0x1900
-#define NVE4_CP_PARAM_SIZE 0x2000
+#define NVE4_CP_INPUT_USER 0x0000
+#define NVE4_CP_INPUT_USER_LIMIT 0x1000
+#define NVE4_CP_INPUT_GRID_INFO(i) (0x1000 + (i) * 4)
+#define NVE4_CP_INPUT_NTID(i) (0x1000 + (i) * 4)
+#define NVE4_CP_INPUT_NCTAID(i) (0x100c + (i) * 4)
+#define NVE4_CP_INPUT_GRIDID 0x1018
+#define NVE4_CP_INPUT_TEX(i) (0x1040 + (i) * 4)
+#define NVE4_CP_INPUT_TEX_STRIDE 4
+#define NVE4_CP_INPUT_TEX_MAX 32
+#define NVE4_CP_INPUT_MS_OFFSETS 0x10c0
+#define NVE4_CP_INPUT_SUF_STRIDE 64
+#define NVE4_CP_INPUT_SUF(i) (0x1100 + (i) * NVE4_CP_INPUT_SUF_STRIDE)
+#define NVE4_CP_INPUT_SUF_MAX 32
+#define NVE4_CP_INPUT_TRAP_INFO_PTR 0x1900
+#define NVE4_CP_INPUT_TEMP_PTR 0x1908
+#define NVE4_CP_INPUT_MP_TEMP_SIZE 0x1910
+#define NVE4_CP_INPUT_WARP_TEMP_SIZE 0x1914
+#define NVE4_CP_INPUT_CSTACK_SIZE 0x1918
+#define NVE4_CP_INPUT_SIZE 0x1a00
+#define NVE4_CP_PARAM_TRAP_INFO 0x2000
+#define NVE4_CP_PARAM_TRAP_INFO_SZ (1 << 16)
+#define NVE4_CP_PARAM_SIZE (NVE4_CP_PARAM_TRAP_INFO + (1 << 16))
struct nve4_cp_launch_desc
{
}
}
+struct nve4_mp_trap_info {
+ u32 lock;
+ u32 pc;
+ u32 trapstat;
+ u32 warperr;
+ u32 tid[3];
+ u32 ctaid[3];
+ u32 pad028[2];
+ u32 r[64];
+ u32 flags;
+ u32 pad134[3];
+ u32 s[0x3000];
+};
+
#endif /* NVE4_COMPUTE_H */