radeon_hd: AtomBIOS loop failure detection now time based

* If the same call is made for 5 seconds straight, fail.
* Resolves random AtomBIOS failures.
* AtomBIOS failures now represent *real* bugs :)
This commit is contained in:
Alexander von Gluck IV
2012-03-14 06:20:14 -05:00
parent a9c45d3774
commit 32ef94aa91
@@ -36,10 +36,10 @@
/* AtomBIOS loop detection /* AtomBIOS loop detection
* Number of repeat AtomBIOS jmp operations * Number of seconds of identical jmp operations
* before bailing due to stuck in a loop * before detecting a fault.
*/ */
#define ATOM_OP_JMP_TIMEOUT 512 #define ATOM_OP_JMP_TIMEOUT 5
// *** Tracing // *** Tracing
#undef TRACE #undef TRACE
@@ -77,8 +77,9 @@ typedef struct {
uint32 *ps, *ws; uint32 *ps, *ws;
int ps_shift; int ps_shift;
uint16 start; uint16 start;
uint16 last_jump; uint16 lastJump;
uint16 last_jump_count; uint32 lastJumpCount;
bigtime_t jumpStart;
bool abort; bool abort;
} atom_exec_context; } atom_exec_context;
@@ -541,7 +542,7 @@ atom_op_calltable(atom_exec_context *ctx, int *ptr, int arg)
if (idx < ATOM_TABLE_NAMES_CNT) { if (idx < ATOM_TABLE_NAMES_CNT) {
TRACE("%s: table: %s (%d)\n", __func__, atom_table_names[idx], idx); TRACE("%s: table: %s (%d)\n", __func__, atom_table_names[idx], idx);
} else { } else {
TRACE("%s: table: unknown (%d)\n", __func__, idx); ERROR("%s: table: unknown (%d)\n", __func__, idx);
} }
if (U16(ctx->ctx->cmd_table + 4 + 2 * idx)) { if (U16(ctx->ctx->cmd_table + 4 + 2 * idx)) {
@@ -659,17 +660,20 @@ atom_op_jump(atom_exec_context *ctx, int *ptr, int arg)
execute? "yes" : "no", target); execute? "yes" : "no", target);
if (execute) { if (execute) {
if (ctx->last_jump == (ctx->start + target)) { // Time based jmp timeout
if (ctx->last_jump_count > ATOM_OP_JMP_TIMEOUT) { if (ctx->lastJump == (ctx->start + target)) {
ERROR("%s: Error: AtomBIOS stuck in loop for more then %d" bigtime_t loopDuration = system_time() - ctx->jumpStart;
" jumps... abort!\n", __func__, ATOM_OP_JMP_TIMEOUT); if (loopDuration > ATOM_OP_JMP_TIMEOUT * 1000000) {
ERROR("%s: Error: AtomBIOS stuck in loop for more then %d "
"seconds. (%" B_PRIu32 " identical jmp op's)\n", __func__,
ATOM_OP_JMP_TIMEOUT, ctx->lastJumpCount);
ctx->abort = true; ctx->abort = true;
} else
ctx->lastJumpCount++;
} else { } else {
ctx->last_jump_count++; ctx->jumpStart = system_time();
} ctx->lastJump = ctx->start + target;
} else { ctx->lastJumpCount = 1;
ctx->last_jump = ctx->start + target;
ctx->last_jump_count = 1;
} }
*ptr = ctx->start + target; *ptr = ctx->start + target;
} }
@@ -1137,8 +1141,10 @@ atom_execute_table_locked(atom_context *ctx, int index, uint32 * params)
unsigned char op; unsigned char op;
atom_exec_context ectx; atom_exec_context ectx;
if (!base) if (!base) {
ERROR("%s: BUG: Table called doesn't exist in AtomBIOS!\n", __func__);
return B_ERROR; return B_ERROR;
}
len = CU16(base + ATOM_CT_SIZE_PTR); len = CU16(base + ATOM_CT_SIZE_PTR);
ws = CU8(base + ATOM_CT_WS_PTR); ws = CU8(base + ATOM_CT_WS_PTR);
@@ -1150,8 +1156,9 @@ atom_execute_table_locked(atom_context *ctx, int index, uint32 * params)
ectx.start = base; ectx.start = base;
ectx.ps = params; ectx.ps = params;
ectx.abort = false; ectx.abort = false;
ectx.last_jump = 0; ectx.lastJump = 0;
ectx.last_jump_count = 0; ectx.lastJumpCount = 0;
ectx.jumpStart = 0;
if (ws) if (ws)
ectx.ws = (uint32*)malloc(4 * ws); ectx.ws = (uint32*)malloc(4 * ws);
else else