Это" не должно произойти " сбой ошибки процессора AMD Fusion?
моя компания начала иметь ряд клиентов позвонить, потому что наша программа сбой с нарушением прав доступа на их системах.
сбой происходит в 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]
соответствующая строка кода C:
if( createFlag==1 ) sqlite3BeginBenignMalloc();
компилятор inlines 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();
}
}
и сборка для этого:
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]
регистры являются:
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
если eax
равно 0 (что и есть), нулевой флаг должен быть установлен test eax, eax
, но это не ноль. Потому что нулевой флаг не установлен,je
не прыгает, а затем приложение аварийно завершает работу, пытаясь выполнить call eax (00000000)
.
обновление:eax
здесь всегда должно быть 0, потому что sqlite3Hooks.xBenignBegin
не установлен в нашей сборке кода. Я мог бы перестроить SQLite с SQLITE_OMIT_BUILTIN_TEST
определено, что бы повернуть на #define sqlite3BeginBenignMalloc()
в коде и полностью опустить этот путь кода. Это может решить проблему, но это не похоже на "реальное" исправление; что остановит его в каком-то другом пути кода?
до сих пор общим фактором является то, что все клиенты работают под управлением "Windows 7 Home Premium 64-бит (6.1, сборка 7601) пакет обновления 1" и имеют один из следующих процессоров (в соответствии с DxDiag):
- AMD A6-3400M APU с графикой Radeon (tm) HD (4 процессора), ~1,4 ГГц
- AMD A8-3500M APU с графикой Radeon (tm) HD (4 процессора), ~1,5 ГГц
- AMD A8-3850 APU с графикой Radeon (tm) HD (4 процессора), ~2,9 ГГц
согласно Википедии AMD Fusion article, эти все обломоки сплавливания АМД модели" Ллано " основанные на К10 ядро и были выпущены в июне 2011 года, когда мы начали получать отчеты.
наиболее распространенной системой клиентов является Toshiba Satellite L775D, но у нас также есть отчеты о сбоях от HP Pavilion dv6 & dv7 и Gateway systems.
может ли этот сбой быть вызван ошибкой процессора (см. ошибки для процессоров семейства AMD 12h), или есть какое-то другое возможное объяснение, которое я пропускаю? (По словам Раймонда, это может быть разгон, но странно, что именно эта конкретная модель процессора влияет, если это так.)
честно говоря, это не кажется возможным, что это действительно Ошибка процессора или ОС, потому что клиенты не получают bluescreens или сбои в других приложениях. Должно быть другое, более вероятное объяснение, но какое?
Обновление 15 Августа: я приобрел ноутбук Toshiba L745D с процессором AMD A6-3400M и могу последовательно воспроизводить сбой, когда запуск программы. Сбой всегда происходит по одной и той же инструкции; .time
отчеты в любом месте от 1m30s до 7m времени пользователя до аварии. Один факт (который может иметь отношение к проблеме), который я забыл упомянуть в исходном сообщении, заключается в том, что приложение является многопоточным и имеет как высокий процессор, так и использование ввода-вывода. Приложение порождает четыре рабочих потока по умолчанию и публикует 80+% использования ЦП (есть некоторые блокировки для ввода-вывода, а также для мьютексов в коде SQLite), пока он не выйдет из строя. Я изменил приложение использует только два потока, и оно все равно разбилось (хотя это заняло больше времени). Теперь я запускаю тест только с одним потоком, и он еще не разбился.
обратите внимание также, что это не кажется чисто проблема загрузки процессора; я могу запустить Prime95 без ошибок в системе, и это повысит температуру процессора до >70°C, в то время как мое приложение едва получает температуру выше 50°C во время его работы.
Обновление 16 Августа: возмущающих инструкции слегка заставляют проблему "уйти". Для eaxmple, замена нагрузки памяти (mov eax,dword ptr [SQLite_Interop!sqlite3Hooks (71a7813c)]
) С xor eax, eax
предотвращает аварии. Изменение исходного кода C для добавления дополнительной проверки в if( createFlag==1 )
оператор изменяет относительные смещения различных переходов в скомпилированном коде (а также расположение test eax, eax
и call eax
заявления), а также кажется, чтобы предотвратить проблему.
самый странный результат, который я нашел до сих пор, это изменение jne
at 719f9fa0
to два nop
инструкций (контроля всегда находится в test eax, eax
инструкция, независимо от того, что значение createFlag
/esi
is) позволяет программе работать без сбоев.
3 ответа:
Я поговорил с инженером AMD на конференции Microsoft Build об этой ошибке и показал ему мой упрек. Он написал мне сегодня утром:
мы исследовали и обнаружили, что это связано с известными ошибками в семья Ллано АПУ. Это можно исправить с помощью обновления BIOS в зависимости от OEM-если возможно пожалуйста порекомендуйте его к вашим клиентам (даже если у вас есть обходной путь).
в случае, если вы заинтересованы, ошибки 665 в семье 12h Руководство по пересмотру (см. стр. 45): http://support.amd.com/TechDocs/44739_12h_Rev_Gd.pdf#page=45
Вот описание этой ошибки:
665 Целочисленное Деление Инструкция Может Вызвать Непредсказуемое Поведение
описание
при очень специфическом и детальном наборе внутренних условий синхронизации процессорное ядро может прервать спекулятивную инструкцию div или idiv integer divide (из-за спекулятивного выполнения перенаправляется, например, из-за неверно предсказанной ветви), но может зависнуть или преждевременно завершить первую инструкцию не спекулятивного пути.
потенциальное влияние на систему
непредсказуемое поведение системы, обычно приводящее к зависанию системы.
Предложенный Обходной Путь
BIOS должен установить MSRC001_1029[31].
этот обходной путь изменяет задержку инструкции DIV / IDIV, указанную в Руководство По Оптимизации Программного Обеспечения для процессоров семейства AMD 10h и 12h, приказ № 40546. С этот метод применяется, задержка див/исключением idiv для процессоров AMD семейства 12ч похожи на латентность див/исключением idiv для процессоров AMD семейства 10h.
Исправить Запланировано
нет
я немного обеспокоен тем, что код, сгенерированный дляневажно: эти инструкции предназначены дляif (wsdHooks.xBenignBegin)
не очень общие. Он предполагает, что единственным истинным значением является1
в то время как это действительно должно быть тестирование для любой ненулевое значение. Тем не менее, MSVC иногда сбивает с толку таким образом. Это, наверное, ничего.C
код не представил.учитывая, что eflag
Z
бит ясен иEAX
равно нулю, код не попал сюда, выполнив инструкция719f9fa7 test eax,eax
должен быть прыжок откуда-то еще к следующей инструкции (
719f9fa9 je SQLite_Interop!pcache1Fetch+0x2d
) или даже инструкция.еще одна сложность заключается в том, что в семействе x86 он является общим для недопустимой цели перехода (например, второй байт
JE
инструкция), Чтобы выполнить невозмутимый (без ошибок) для довольно большого количества инструкций, часто в конечном итоге возвращаясь к правильному выравниванию инструкций. Сказал по-другому, вы можете не смотреть для перехода к началу любой из этих инструкций: переход может быть в середине их байтов, что приводит к выполнению ничем не примечательных операций, таких какadd [al+ebp],al
, которые, как правило, не замечают.Я предсказываю, что точка останова в
test
инструкция не будет нажата для исключения. Единственный способ найти такие причины - либо быть очень удачливым, либо подозревать все и доказывать их невиновность один за другим.
прежде чем рассматривать возможность ошибки процессора, попробуйте исключить более вероятные причины
другой путь кода к инструкции вызова. Используйте
uf
команда для разборки функции и поиска других переходов / ветвей к инструкции вызовапереход / вызов в 0 из функции hook.
dps SQLite_Interop!sqlite3Hooks l 2
и убедитесь, что он показывает нули.