这是"不应该发生"崩溃AMD Fusion CPU的错误吗?

Bra*_*ger 68 crash x86 assembly windbg amd-processor

我的公司已经开始让许多客户打电话,因为我们的程序因其系统上的访问冲突而崩溃.

崩溃发生在SQLite 3.6.23.1中,我们将其作为应用程序的一部分提供.(我们提供自定义构建,以便使用与应用程序其余部分相同的VC++库,但这是SQLite代码库存.)

pcache1Fetch执行时发生崩溃call 00000000,如WinDbg调用堆栈所示:

0b50e5c4 719f9fad 06fe35f0 00000000 000079ad 0x0
0b50e5d8 719f9216 058d1628 000079ad 00000001 SQLite_Interop!pcache1Fetch+0x2d [sqlite3.c @ 31530]
0b50e5f4 719fd581 000079ad 00000001 0b50e63c SQLite_Interop!sqlite3PcacheFetch+0x76 [sqlite3.c @ 30651]
0b50e61c 719fff0c 000079ad 0b50e63c 00000000 SQLite_Interop!sqlite3PagerAcquire+0x51 [sqlite3.c @ 36026]
0b50e644 71a029ba 0b50e65c 00000001 00000e00 SQLite_Interop!getAndInitPage+0x1c [sqlite3.c @ 40158]
0b50e65c 71a030f8 000079ad 0aecd680 071ce030 SQLite_Interop!moveToChild+0x2a [sqlite3.c @ 42555]
0b50e690 71a0c637 0aecd6f0 00000000 0001edbe SQLite_Interop!sqlite3BtreeMovetoUnpacked+0x378 [sqlite3.c @ 43016]
0b50e6b8 71a109ed 06fd53e0 00000000 071ce030 SQLite_Interop!sqlite3VdbeCursorMoveto+0x27 [sqlite3.c @ 50624]
0b50e824 71a0db76 071ce030 0b50e880 071ce030 SQLite_Interop!sqlite3VdbeExec+0x14fd [sqlite3.c @ 55409]
0b50e850 71a0dcb5 0b50e880 21f9b4c0 00402540 SQLite_Interop!sqlite3Step+0x116 [sqlite3.c @ 51744]
0b50e870 00629a30 071ce030 76897ff4 70f24970 SQLite_Interop!sqlite3_step+0x75 [sqlite3.c @ 51806]
Run Code Online (Sandbox Code Playgroud)

相关的C代码行是:

if( createFlag==1 ) sqlite3BeginBenignMalloc();
Run Code Online (Sandbox Code Playgroud)

编译器内联sqlite3BeginBenignMalloc,定义为:

typedef struct BenignMallocHooks BenignMallocHooks;
static SQLITE_WSD struct BenignMallocHooks {
  void (*xBenignBegin)(void);
  void (*xBenignEnd)(void);
} sqlite3Hooks = { 0, 0 };

# define wsdHooksInit
# define wsdHooks sqlite3Hooks

SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void){
  wsdHooksInit;
  if( wsdHooks.xBenignBegin ){
    wsdHooks.xBenignBegin();
  }
}
Run Code Online (Sandbox Code Playgroud)

这个程序集是:

719f9f99    mov     esi,dword ptr [esp+1Ch]
719f9f9d    cmp     esi,1
719f9fa0    jne     SQLite_Interop!pcache1Fetch+0x2d (719f9fad)
719f9fa2    mov     eax,dword ptr [SQLite_Interop!sqlite3Hooks (71a7813c)]
719f9fa7    test    eax,eax
719f9fa9    je      SQLite_Interop!pcache1Fetch+0x2d (719f9fad)
719f9fab    call    eax ; *** CRASH HERE ***
719f9fad    mov     ebx,dword ptr [esp+14h]
Run Code Online (Sandbox Code Playgroud)

寄存器是:

eax=00000000 ebx=00000001 ecx=000013f0 edx=fffffffe esi=00000001 edi=00000000
eip=00000000 esp=0b50e5c8 ebp=000079ad iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010202
Run Code Online (Sandbox Code Playgroud)

如果eax为0(它是),零标志应设置为test eax, eax,但它不为零.因为没有设置零标志,je不会跳转,然后应用程序崩溃尝试执行call eax (00000000).

更新:eax此处应始终为0,因为sqlite3Hooks.xBenignBegin未在我们的代码构建中设置.我可以使用SQLITE_OMIT_BUILTIN_TESTdefined 重建SQLite ,这将#define sqlite3BeginBenignMalloc()在代码中打开并完全省略此代码路径.这可能会解决问题,但它并不像是"真正的"修复; 什么会阻止它在其他代码路径中发生?

到目前为止,共同的因素是所有客户都运行"Windows 7家庭高级版64位(6.1,Build 7601)Service Pack 1"并具有以下CPU之一(根据DxDiag):

  • AMD A6-3400M APU配Radeon(tm)高清显卡(4个CPU),~1.4GHz
  • AMD A8-3500M APU配Radeon(tm)高清显卡(4个CPU),约1.5GHz
  • AMD A8-3850 APU配Radeon(tm)高清显卡(4个CPU),约2.9GHz

根据维基百科的AMD Fusion文章,这些都是基于K10核心的"Llano"型号AMD Fusion芯片,并于2011年6月发布,这是我们刚开始收到报告的时候.

最常见的客户系统是东芝Satellite L775D,但我们也有HP Pavilion dv6&dv7和Gateway系统的崩溃报告.

这次崩溃是由CPU错误引起的(参见AMD家族12h处理器的勘误表),还是有其他可能的解释我忽略了?(根据Raymond的说法,它可能会超频,但奇怪的是这个特定的CPU型号会受到影响,如果是这样的话.)

老实说,它似乎不太可能是CPU或操作系统错误,因为客户没有在其他应用程序中获得蓝屏或崩溃.必须有其他更可能的解释 - 但是什么?

8月15日更新:我已经购买了配备AMD A6-3400M处理器的东芝L745D笔记本电脑,可以在运行程序时始终如一地重现故障.崩溃总是在同一条指令上; .time报告在崩溃前的1m30到7m之间的任何地方.我在原帖中忽略的一个事实(可能与问题相关)是应用程序是多线程的,并且具有高CPU和I/O使用率.该应用程序默认生成四个工作线程,并发布80 +%的CPU使用率(对于I/O以及SQLite代码中的互斥锁有一些阻塞),直到崩溃为止.我修改了应用程序只使用两个线程,它仍然崩溃(虽然它需要更长的时间).我现在只用一个线程运行测试,它还没有崩溃.

另请注意,它似乎不是纯粹的CPU负载问题; 我可以在系统上运行Prime95而没有错误,它会将CPU温度提升到> 70°C,而我的应用程序在运行时几乎不会达到50°C以上的温度.

8月16日更新:稍微扰乱说明会使问题"消失".对于eaxmple,替换内存load(mov eax,dword ptr [SQLite_Interop!sqlite3Hooks (71a7813c)])可以xor eax, eax防止崩溃.修改原始C代码以向if( createFlag==1 )语句添加额外的检查会更改已编译代码中各种跳转的相对偏移(以及test eax, eaxcall eax语句的位置),并且似乎也可以防止出现此问题.

到目前为止我发现的最奇怪的结果是将jneat 719f9fa0改为两条nop指令(这样控制总是落到test eax, eax指令上,无论createFlag/ 的值esi是什么)都允许程序运行而不会崩溃.

Bra*_*ger 27

我在Microsoft Build会议上与一位AMD工程师谈到了这个错误,并向他展示了我的责任.他今天早上给我发了电子邮件:

我们调查并发现这是由于Llano APU家族中已知的勘误表.它可以通过BIOS更新来修复,具体取决于OEM - 如果可能,请将其推荐给您的客户(即使您有解决方法).

如果您有兴趣,家庭12h修订指南中的勘误表是665(参见第45页):http: //support.amd.com/TechDocs/44739_12h_Rev_Gd.pdf#page=45

以下是该错误的描述:

665整数除法可能导致不可预测的行为

描述

在高度具体和详细的​​内部时序条件下,处理器内核可以中止推测DIV或IDIV整数除法指令(由于推测执行被重定向,例如由于错误预测的分支)但可能挂起或过早地完成第一次指导非投机路径.

对系统的潜在影响

不可预测的系统行为,通常会导致系统挂起.

建议的解决方法

BIOS应该设置MSRC001_1029 [31].

此解决方法更改了AMD系列10h和12h处理器软件优化指南中指定的DIV/IDIV指令延迟,订单#40546.应用此解决方法后,AMD系列12h处理器的DIV/IDIV延迟类似于DIV/IDIV延迟用于AMD系列10h处理器.

修复计划

没有

  • 它很有趣如何划分指令总是被看到在x86上被窃听... (5认同)