Я считаю, что мое утверждение правильное, до ошибок .
Я не утверждаю, что ошибочное оборудование следует игнорировать, но что его влияние должно сначала оцениваться.
Я быкак напоминание читателю, что, хотя у меня есть взвешенная позиция по этому вопросу, я хотел, чтобы этот ответ был как можно более нейтральным.
Чтобы полностью выполнить эту задачу, я попытался предоставить источников для своих заявлений.
Хотя я делаю доверяю опыту других пользователей, я не могу основывать свою веру на одних воспоминаниях (поскольку они не могут быть проверены) 1 , и я с нетерпением жду, когда кто-тоисправьте мое цитируемое утверждение с помощью доказательств.
Я понимаю, что это непопулярное мнение, я надеюсь, что оно просто не будет считаться абсолютно неправильным.
Прежде всего, как обычно, с компьютерамивсе сводится к стандартам.В то время как Intel документирует поведение MP своих процессоров в руководствах, пошла еще дальше и сделала правильную многопроцессорную спецификацию .
Важность этой спецификации - ее роль в отрасли, эта Это не то, как работают процессоры Intel , это, насколько мне известно, единственный справочник по архитектуре x86 SMP .
AMD и Cyrix выдвинули спецификацию OpenPIC , но цитируют Wikipedia :
Однако с OpenPIC материнская плата x86 не была выпущена. [3]После провала OpenPIC на рынке x86 AMD лицензировала архитектуру Intel APIC для своих процессоров AMD Athlon и более поздних.
В Приложении B4 спецификации MP представлена строка
Если целевой процессор находится в состоянии останова сразу после RESET или INIT , при запуске IPI STARTUP он покидает это состояние и начинает выполнение.В результате для CS: IP устанавливается VV00:0000h
.
. Как отмечено в комментарии, я проанализировал , если , как более сильный * iif ,
К сожалению, цитируемое предложение, как указано, является лишь достаточным условием.Поэтому его нельзя использовать для определения поведения SIPI на работающем процессоре.
Однако Лично я считаю, что это ошибка , цель авторов спецификации - использовать SIPI для пробуждения процессора в wait-for-SIPI гос.
SIPI был специально представлен с появлением интегрированных APIC, наряду с пересмотром INIT IPI, для управления загрузкой AP.
SIPI не влияет на BSP (который никогда не входитсостояние wait-for-SIPI в соответствии с инструкциями Intel) и ясно, что должно не влиять на работающий ЦП.
Полезность SIPI, кроме того, что он не-маскируемым и не требующим включения LAPIC, заключается в том, чтобы избежать запуска из вектора сброса и необходимости наличия флага горячей загрузки для точек доступа.
С точки зрения дизайна не имеет смысла позволять SIPI действовать на работающих процессорах.Процессоры всегда перезапускаются с INIT IPI в качестве первого IPI.
Так что я уверен, что проанализировал цитируемое утверждение как разговорный английский с молчаливым соглашением, что это также необходимое условие .
Я полагаю, что это устанавливает официальное поведение SIPI на работающем процессоре , а именно игнорирование их .
Факт 1: Существует стандартная отраслевая спецификация MP, которой следуют все основные производители x86, хотя, будучи неоднозначной, она намерена установить поведение SIPI.
Страница 98 из Обновление спецификации Pentium , кажется, подтверждает, что, по крайней мере, для Pentium (предположительно для более поздних поколений Intel, которые могут включать AMD, поскольку они купили лицензию на LAPIC у Intel):
Если затем INIT IPI отправляется на остановленный компонент обновления, он будет заблокирован и будет оставаться в ожидании до получения STARTUP IPI.С момента получения STARTUP IPI ЦП будет реагировать на дальнейшие INIT IPlsно будет игнорировать любые IP-адреса при запуске.Он не будет реагировать на будущие IP-адреса STARTUP, пока не произойдет повторное утверждение RESET или INIT (INIT Pin или INIT IPI).
Процессоры Pentium с тактовой частотой 75, 90 и 100 МГц, используемые в качестве основного процессора, никогда не будут реагировать на STARTUP IPI в любое время.Он будет игнорировать STARTUP IPI без каких-либо эффектов.
Для выключения процессоров операционная система должна использовать только INIT IPI, никогда не следует использовать IP-адреса STARTUP после запуска процессоров.
Это не устанавливаетвопрос если есть процессоры, где последующие IPI не игнорируются.
Хотя этот вопрос еще предстоит решить, мы уже превратили его в вопрос "Есть ли глючит Процессоры, которые ...? ".
Это огромный шаг вперед, потому что теперь мы можем видеть, как с этим справляются существующие ОС.
Я не буду обсуждать Windows, хотя я понимаю, что это большое отсутствие, сейчас я не собираюсь копаться в двоичных файлах Windows.
Я могу сделать это позже.
Linux
Linux отправляет два SIPI, и я не вижу обратной связи в этом цикле. Код находится в smpboot.c
, где мы ясно видим, что для num_starts
установлено значение 2
.
Я не буду обсуждать разницу между LAPIC и APIC 82489DX, особенно в том, что последнийне было SIPI 2 .
Однако мы можем видеть, как Linux следует алгоритму Intel, и это не беспокоит второй SIPI.
В цикле, выполненном num_starts
раз, SIPI отправляется целевой AP.
В комментариях было указано, что батут является идемпотентом и что Linux как механизм синхронизации.
Это не соответствует моему опыту, конечно, Linux синхронизирует код между процессорами, но это будет сделано позже при загрузке. после AP работает.
Фактически батут, на котором выполняется первый код C, выполняемый AP, - start_secondary
и не кажется идемпотентным (set_cpu_online
вызывается позжев теле, если это имеет значение).
Наконец, если программисты хотели предотвратить двойной SIPI, они бы как можно раньше применили логику синхронизации, чтобы избежать последующих сложных ситуаций.
Батут доходит до работы с МСП и уязвимостямиисправления, почему кто-то хотел бы сделать это до решения проблемы SIPI-SIPI?
Для меня нет смысла так критически проверять так поздно.
Свободный BSD
Я хотел включить ОС BSD, поскольку известно, что BSD-код очень чистый и надежный.
Мне удалось найти GitHub (неофициальный) репозиторийс исходным кодом Free BSD, и хотя я менее уверен в этом коде, я нашел подпрограмму, которая запускает точку доступа в mp_x86.c
.
Free BSD также использует алгоритм Intel.К моему удивлению, источник также объясняет, почему существует необходимость во втором SIPI: процессор P5 (семейство P54C Pentium?) Проигнорировал первый SIPI из-за ошибки:
/ *
* затем мы выполняем IPI ЗАПУСКА: предыдущий IPI INIT может все еще быть заблокирован
*, (ошибка P5), этот 1-й ЗАПУСК немедленно завершит
*, и ранее запущенный INIT IPI продолжится.ИЛИ
* предыдущий INIT IPI уже запущен.и этот STARTUP IPI будет
* работать.ИЛИ предыдущий INIT IPI был проигнорирован.и этот STARTUP IPI
* будет запущен.
* /
Мне не удалось найти источник этого утверждения, единственная подсказка, которую я имею, - это ошибки AP11Обновление спецификации Pentium найдено в старом ядре Android (т.е. Linux).
Сегодня Linux, похоже, утратил поддержку этих старых глючных LAPIC.
Учитывая подробные комментарии Я не вижу необходимости проверять идемпотентность кода вплоть до гипотетической проверки.
Код BSD четко написан с учетом комментируемых допущений.
Факт 2: Две основные ОС не считают, что ошибки SIPI возникают достаточно часто, чтобы их стоило обрабатывать.
При поиске в Интернете я нашел коммит в симуляторе gem5 с заголовком X86: распознавать только первый IPI запуска после INIT или сброса .
Видимо, сначала они ошиблись, а потом исправили.
Следующим шагом является поиск онлайн-документации.
Сначала я искал в Google Patents и получил много интересных результатов.всплывающее окно (включая способ присвоения идентификаторов APIC), касающееся SIPI. Этот текст я нашел только в патенте Способ и устройство для инициирования выполнения процессора приложений в кластерной многопроцессорной системе :
ЗАПУСК IPI не вызывают какого-либо изменения состояния в целевом процессоре (кроме изменения указателя инструкций) и могут бытьвыдается только один раз после RESET или после получения INIT IPI или подтверждения вывода.
В Википедии указан VIA как единственный другой производитель x86, который все еще присутствует. .
Я попытался посмотретьдля руководств VIA, но кажется, что они не являются общедоступными?
Что касается прошлых производителей, я не смог найти, выпускал ли вообще когда-либо ЦП MP.Например, Cyrix 6x86MX вообще не имел APIC, поэтому они могли быть помещены в систему MP только внешним APIC (который не мог поддерживать SIPI).
Следующим шагом будет просмотреть все ошибок AMD и Intel и посмотреть, есть ли что-то в SIPI.
Однако ошибки - это ошибки, и поэтому вопрос превращается впоиск доказательства несуществования (то есть существуют ли ошибочные LAPIC? ), который трудно найти (просто потому, что ошибки трудно найти и существует множество микроархитектур).
Насколько я понимаю, первая интегрированная APIC (LAPIC, известная сегодня) поставляется с P54C , я проверил ошибки, но ничего не нашел в отношении обработки SIPI.
Однако понимание ошибок в их полных последствиях не тривиально.
Затем я перешел на Pentium Pro Errata (который является следующим Uarch, P6) и обнаружил неправильную обработку SIPI, хотя и не совсем то, что мы ищем:
3АР.INIT_IPI после STARTUP_IPI-STARTUP_IPI последовательность может привести к выполнению
AP в 0 часов **
ПРОБЛЕМА : спецификация MP гласит, что для активации процессора приложения (AP),межпроцессорная последовательность прерываний INIT_IPI, STARTUP_IPI, STARTUP_IPI должна быть отправлена этому процессору.На процессоре Pentium Pro также будет работать последовательность INIT_IPI, STARTUP_IPI.Однако, если последовательность APIT INIT_IPI, STARTUP_IPI, STARTUP_IPI отправляется на точку доступа, в логике APIC может возникнуть внутреннее состояние гонки, которое оставляет процессор в неправильном состоянии.В этом состоянии работа будет корректной, но если в процессор будет отправлен другой INIT_IPI, процессор не остановит выполнение, как ожидалось, а вместо этого начнет выполнение по линейному адресу 0h.Чтобы условие гонки вызвало это неправильное состояние, отношение ядра к шине системы должно быть 5: 2 или больше.
ИМПЛИКАЦИЯ : если система использует отношение частоты ядра к шине 5: 2 или более, и последовательность INIT_IPI, STARTUP_IPI, STARTUP_IPI генерируется на шине APIC для пробужденияAP, а затем через некоторое время другой процессор INIT_IPI отправляется в процессор, этот процессор может попытаться выполнить по линейному адресу 0h и выполнит случайные коды операций.Некоторые операционные системы генерируют эту последовательность при попытке выключить систему, а в многопроцессорной системе могут зависать после перевода процессоров в автономный режим.Эффект виден будетможет быть, ОС не сможет перезапустить систему, если при выходе из операционной системы выбрано «завершение работы и перезапуск» или аналогичный режим.Если операционная система дает пользователю возможность отключить точку доступа с помощью INIT_IPI (корпорация Intel не определила операционные системы, которые в настоящее время имеют такую возможность), этот параметр не следует использовать.
ВОЗМОЖНОЕ РЕШЕНИЕ : код BIOS должен выполнить один STARTUP_IPI, чтобы активировать процессор приложения.Операционные системы, однако, будут выдавать последовательность INIT_IPI, STARTUP_IPI, STARTUP_IPI, как рекомендовано в спецификации MP.Вполне возможно, что код BIOS может содержать обходной путь для этой ошибки в системах с C0 или последующими степенями процессора Pentium Pro.Обходной путь для степпинга B0 процессора Pentium Pro отсутствует.
СОСТОЯНИЕ : Информация о затронутых степпингах приведена в сводной таблице изменений в начале этого раздела.
Эта ошибка AP3 интересна тем, что:
- Это подтверждает, что последовательности INIT-SIPI достаточно для запуска AP.Это было видно из спецификации MP и из кода Free BSD.
- Это может привести к поведению, аналогичному перезапуску.Ошибка создаст INIT IPI (после последовательности INIT-SIPI-SIPI) перезапуск AP в 0h (линейный, предположительно после инициализации).
Если BIOS используетINIT-SIPI-SIPI для использования AP, а затем ОС пытается использовать эту последовательность снова, первый INIT запустит AP.
Однако , это не приведет к предсказуемому поведению, если толькоLAPIC остается в поврежденном состоянии, где любой SIPI будет принят.
Достаточно забавно, в тех же ошибках есть даже ошибка, вызывающая "противоположное поведение": 8AP.AP не отвечают на STARTUP_IPI после INIT # или INIT_IPI в режиме пониженного энергопотребления
Я также проверил ошибки в Pentium II, Pentium II Xeon, Pentium III, Pentium 4 и не нашел ничего нового оSIPIs.
Насколько я понимаю, первым процессором AMD, поддерживающим SMP, был Athlon MP на основе uarch из Palomino.
Я проверил руководство по ревизии для Athlon MP и ничего не нашел, проверил ревизии в этом списке и ничего не нашел.
К сожалению, у меня мало опыта с процессорами не AMD, а не Intel x86.Я не смог найти, какие вторичные производители включали LAPIC.
Факт 3: Трудно найти официальную документацию от не AMD / Intel производителей, а ошибки не легко найти.Ни одна из ошибок не содержит ошибок, связанных с принятием SIPI на работающем процессоре, но присутствуют многочисленные ошибки LAPIC, делающие правдоподобными существование таких ошибок.
Последним этапом будет проверка оборудования.
Хотя этот тест не может исключить наличие другого поведения , по крайней мере это документированный (дрянной) код.
Документированный код хорош тем, что его можно использовать для повторенияэксперимент других исследователей, он может быть исследован на наличие ошибок и является доказательством.
Короче говоря, это научный подход.
Я никогда не видел ЦП, где последующие SIPI перезапускали его, но это не имеет значения, потому что достаточно иметь один неисправный ЦП, чтобы подтвердить наличие ошибки.
IЯ слишком молод, слишком беден и слишком человечен, чтобы провести обширный, безошибочный анализ всех процессоров MP.
Итак, вместо этого я сделал тест и запустил его.
Факт 4: Озеро Виски, Haswell, Kaby Lake и Ivy Bridge игнорируют последующие SIPI.
Приглашаем других людей протестировать процессоры AMD и более старые процессоры.
И снова этоне является доказательством, но важно правильно сформулировать состояние вопроса .
Чем больше у нас данных, тем более точные сведения об ошибке мы получаем.
Тест состоит в начальной загрузке AP и увеличении их счетчика до бесконечного цикла (либо с jmp $
, либо с hlt
, результат тот же).
Между тем BSP будет отправлять SIPI каждые n секунд, где n равно как минимум 2 (но это может быть больше из-за очень неточного механизма синхронизации), и печатать счетчик.
Если счетчик остается на k -1, где k - количество точек доступа, то вторичный SIPI игнорируется.
Есть некоторые технические детали, по которым можно обратиться
Во-первых, загрузчик является устаревшим (не UEFI), и я не хотел читать другой сектор, поэтому я хотел, чтобы он умещался в 512 байт, и поэтому я разделил последовательность загрузки между BSP и точками доступа.
Во-вторых, некоторый код должен выполняться только BSP, но перед входом в защищенный режим (например, настройка режима видео), поэтому я использовал флаг (init
) вместо проверки флага BSP
в регистре IA32_APIC_BASE_MSR
(что будет сделано позже, чтобы отличить точки доступа от BSP).
В-третьих, я взял несколько ярлыков. SIPI загружает процессор на 8000h
, поэтому я прыгнул далеко туда 0000h:7c00h
. Синхронизация выполняется с помощью трюка с портом 80h
, и это очень неточно, но должно быть достаточно. GDT использует пустую запись. Счетчик напечатан на несколько строк ниже верха, чтобы избежать его обрезки каким-либо монитором.
Если цикл изменен для включения INIT IPI, счетчик регулярно увеличивается.
Обратите внимание, что этот код без поддержки.
BITS 16
ORG 7c00h
%define IA32_APIC_BASE_MSR 1bh
%define SVR_REG 0f0h
%define ICRL_REG 0300h
%define ICRH_REG 0310h
xor ax, ax
mov ds, ax
mov ss, ax
xor sp, sp ;This stack ought be enough
cmp BYTE [init], 0
je _get_pm
;Make the trampoline at 8000h
mov BYTE [8000h], 0eah
mov WORD [8001h], 7c00h
mov WORD [8003h], 0000h
mov ax, 0b800h
mov es, ax
mov ax, 0003h
int 10h
mov WORD [es:0000], 0941h
mov BYTE [init], 0
_get_pm:
;Mask interrupts
mov al, 0ffh
out 21h, al
out 0a1h, al
;THIS PART TO BE TESTED
;
;CAN BE REPLACED WITH A cli, SIPIs ARE NOT MASKEABLE
;THE cli REMOVES THE NEED FOR MASKING THE INTERRUPTS AND
;CAN BE PLACED ANYWHERE BEFORE ENTERING PM (BUT LEAVE xor ax, ax
;AS THE FIRST INSTRUCTION)
;Flush pending ones (See Michael Petch's comments)
sti
mov cx, 15
loop $
lgdt [GDT]
mov eax, cr0
or al, 1
mov cr0, eax
sti
mov ax, 10h
mov es, ax
mov ds, ax
mov ss, ax
jmp 08h:DWORD __START32__
__START32__:
BITS 32
mov ecx, IA32_APIC_BASE_MSR
rdmsr
or ax, (1<<11) ;ENABLE LAPIC
mov ecx, IA32_APIC_BASE_MSR
wrmsr
mov ebx, eax
and ebx, 0ffff_f000h ;APIC BASE
or DWORD [ebx+SVR_REG], 100h
test ax, 100h
jnz __BSP__
__AP__:
lock inc BYTE [counter]
jmp $ ;Don't use HLT just in case
__BSP__:
xor edx, edx
mov DWORD [ebx+ICRH_REG], edx
mov DWORD [ebx+ICRL_REG], 000c4500h ;INIT
mov ecx, 10_000
.wait1:
in al, 80h
dec ecx
jnz .wait1
.SIPI_loop:
movzx eax, BYTE [counter]
mov ecx, 100
div ecx
add ax, 0930h
mov WORD [0b8000h + 80*2*5], ax
mov eax, edx
xor edx, edx
mov ecx, 10
div ecx
add ax, 0930h
mov WORD [0b8000h + 80*2*5 + 2], ax
mov eax, edx
xor edx, edx
add ax, 0930h
mov WORD [0b8000h + 80*2*5 + 4], ax
xor edx, edx
mov DWORD [ebx+ICRH_REG], edx
mov DWORD [ebx+ICRL_REG], 000c4608h ;SIPI at 8000h
mov ecx, 2_000_000
.wait2:
in al, 80h
dec ecx
jnz .wait2
jmp .SIPI_loop
GDT dw 17h
dd GDT
dw 0
dd 0000ffffh, 00cf9a00h
dd 0000ffffh, 00cf9200h
counter db 0
init db 1
TIMES 510-($-$$) db 0
dw 0aa55h
Выводы
Никакого однозначного заключения сделать нельзя, вопрос все еще открыт.
Читателю был представлен список фактов.
Предполагаемое поведение - игнорировать последующие SIPI, необходимость в двух SIPI связана с «ошибкой P5».
Linux и Free BSD, похоже, не возражают против ошибочной обработки SIPI.
Другие производители, по-видимому, не предоставляют никакой документации по своим LAPIC, если они производят их самостоятельно.
Последние аппаратные средства Intel игнорируют последующие SIPI.
1 С должным уважением ко всем вовлеченным людям и без ущерба для доверия. Я делаю полагаю, что там есть ошибочные ЦП, но есть также и программное обеспечение с ошибками и память с ошибками. Как я не доверяю своим старым воспоминаниям Я думаю, что я все еще в пределах почтительного разговора, чтобы попросить других не доверять своим смутным.
2 Возможно, потому что MP в те дни был сделан с обычными процессорами, упакованными вместе, и утверждение их INIT#
с внешним чипом (APIC) было единственным способом запустить их (наряду с настройкой вектор теплого сброса). Однако в те годы я был слишком молод, чтобы иметь компьютер.
Согласно моему тестированию, SIPI игнорируются, когда они не находятся в состоянии wait-for-SIPI .
Я тестировал Whisky-lake 8565U , конечно, тест на реальном оборудовании не является доказательством.
Я уверен, что все процессоры Intel начиная с Pentium 4 также ведут себя одинаково, но это всего лишь мой взгляд .
В этом ответе я исключительно хочу представить результат теста. Каждый сделает свои выводы.