Что происходит с начальным IPI, отправленным активной точке доступа, которая не находится в состоянии ожидания для SIPI - PullRequest
3 голосов
/ 30 мая 2019

В предыдущем ответе Stackoverflow Маргарет Блум говорит:

Пробуждение точек доступа

Это достигается путем включения INIT-Последовательность SIPI-SIPI (ISS) для всех точек доступа.

BSP, который отправит последовательность ISS, используя в качестве пункта назначения сокращенное обозначение Все, кроме себя, тем самым нацеливаясь на все точки доступа.

SIPI (межпроцессное прерывание запуска) игнорируется всеми процессорами, которые активизируются к моменту его получения, поэтому второй SIPI игнорируется , если первого достаточно для пробуждения целевых процессоров.Это рекомендовано Intel по соображениям совместимости.

Я много лет занимался многократной обработкой кода, и мое наблюдение за аппаратным обеспечением заключалось в том, что на некоторых процессорах он выглядит иначе, чем заявлено.Я почти уверен, что наблюдал за изменением указателя инструкций для процессоров приложений (AP) при получении IPI запуска, даже когда он был активен (не в IP-интерфейсе ожидания для запуска).

Есть лилюбая документация Intel, в которой говорится, что AP будет делать при получении стартового IPI, когда он не находится в состоянии ожидания для запуска IPI, или документально описывается поведение как неопределенное?Я не могу найти окончательный ответ в Руководствах по программной документации Intel или в дополнительном документе Intel Минимальный загрузчик для архитектуры Intel® .

Обычно я пишу код инициализации для инициализации и запуска AP, предполагая, что AP может получить SIPI и сбросить указатель инструкций, находясь в состоянии active (не в состоянии ожидания запуска).- состояние IPI).

Я пытаюсь определить точность заявления Маргарет Блум о том, что второй StartI IPI будет игнорироваться AP, который был предварительно активирован.

Ответы [ 2 ]

3 голосов
/ 02 июня 2019

Я считаю, что мое утверждение правильное, до ошибок .

Я не утверждаю, что ошибочное оборудование следует игнорировать, но что его влияние должно сначала оцениваться.
Я быкак напоминание читателю, что, хотя у меня есть взвешенная позиция по этому вопросу, я хотел, чтобы этот ответ был как можно более нейтральным.
Чтобы полностью выполнить эту задачу, я попытался предоставить источников для своих заявлений.

Хотя я делаю доверяю опыту других пользователей, я не могу основывать свою веру на одних воспоминаниях (поскольку они не могут быть проверены) 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 интересна тем, что:

  1. Это подтверждает, что последовательности INIT-SIPI достаточно для запуска AP.Это было видно из спецификации MP и из кода Free BSD.
  2. Это может привести к поведению, аналогичному перезапуску.Ошибка создаст 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 также ведут себя одинаково, но это всего лишь мой взгляд .
В этом ответе я исключительно хочу представить результат теста. Каждый сделает свои выводы.

3 голосов
/ 01 июня 2019

Короткий ответ

  • Некоторые процессоры перезагружаются на втором SIPI
  • Я не знаю, какие процессоры перезапускаются на втором SIPI, потому что яслишком долго защищался от этого
  • Я не проверял, но я не думаю, что в документации Intel указано поведение для случая «SIPI получен при запуске процессора»
  • Если документация Intel делаетукажите поведение процессоров Intel, тогда это не означает, что процессоры других производителей (AMD, VIA, SiS, Cyrix, ...) ведут себя так же, как процессоры Intel.Руководство Intel только «гарантировано» (исключая ошибки / обновления спецификаций) для применения к процессорам Intel.

Более длинный ответ

Когда я впервые начал внедрятьПоддержка процессора (более 10 лет назад) Я следовал процедуре запуска Intel (из спецификации Intel MultiPcessor, с задержками между INIT, SIPI и SIPI), и после запуска точки доступа он увеличил счетчик number_of_CPU_running (например, с * 1020).*).

Я обнаружил, что некоторые процессоры перезагружаются при получении второго SIPI;и на некоторых компьютерах счетчик number_of_CPU_running будет увеличен вдвое (например, с процессорами BSP и 3 AP, счетчик number_of_CPU_running может в итоге получить 7, а не 4).

С тех пор, как я использовалсинхронизация памяти, чтобы избежать проблемы.В частности, передающий ЦП устанавливает переменную (state = 0) перед попыткой запустить принимающий ЦП, если / когда принимающий ЦП запускает, он меняет переменную (state = 1) и ожидает повторного изменения переменной, и когдаотправляющий ЦП видит, что переменная была изменена (получая ЦП), он меняет переменную (state = 2), чтобы позволить продолжающемуся ЦПУ получения.

Кроме того;для повышения производительности во время задержки после отправки первого SIPI отправляющий ЦП отслеживает эту переменную, а если принимающий ЦП изменяет переменную, он отменяет задержку и вообще не отправляет второй IPI.Я также значительно увеличиваю последнюю задержку, потому что она истекает только в случае сбоя (и вы не хотите предполагать, что ЦП не запустился, когда запустился слишком поздно, и в итоге ЦП выполняет функцию «кто знает что» в качестве ОСизменяет содержимое памяти и т. д. позже).

Другими словами, я в основном игнорирую процедуру Intel «Запуск процессора приложений» (например, из раздела B.4 Спецификации многопроцессорных систем Intel) и мой код для отправляющего ЦП.делает:

    set synchronization variable (state = 0)
    send INIT IPI
    wait 10 milliseconds
    send SIPI IPI
    calculate time-out value ("now + 200 microseconds")
    while time-out hasn't expired {
        if the synchronization variable was changed jump to the "CPU_started" code
    }
    send a second SIPI IPI
    calculate time-out value ("now + 500 milliseconds")
    while time-out hasn't expired {
        if the synchronization variable was changed jump to the "CPU_started" code
    }
    do "CPU failed to start" error handling and return

CPU_started:
    set synchronization variable (state = 2) to let the started CPU know it can continue

Мой код для принимающего ЦП делает это:

    get info from trampoline (address of stack this CPU needs to use, etc), because sending CPU may change the info after it knows this CPU started
    set synchronization variable (state = 1)
    while synchronization variable remains unchanged (state == 1) {
        pause (can't continue until sending CPU knows this CPU started)
    }
    initialize the CPU (setup protected mode or long mode, etc) and enter the kernel

Примечание 1: В зависимости от окружающего кода (например, если переменная синхронизации находится в батуте и ОСвскоре перерабатывает батут для запуска других процессоров);отправляющему ЦП, возможно, придется подождать, пока принимающий ЦП не изменит переменную синхронизации в последний раз (чтобы ЦП-отправитель знал, что безопасно перезапустить / сбросить переменную синхронизации).

Примечание 2: ЦП "«почти всегда» начинается с первого SIPI, и разумно предположить, что второй SIPI существует только в случае, если первый SIPI потерян / поврежден, и разумно предположить, что задержка в 200 микросекунд является консервативным худшим случаем.По этим причинам мой подход «отменить время ожидания и пропустить второй SIPI», вероятно, уменьшит пару задержек в 200 миллисекунд в 4 раза (например, 100 мкс вместо 400 мкс).10-миллисекундная задержка (между INIT IPI и первым SIPI) может быть амортизирована (например, отправить INIT на N ЦП, затем задержать на 10 миллисекунд, а затем выполнить оставшиеся операции для каждого из N ЦП по одному за раз);и вы можете «заснежить» запуск CPU AP (например, используйте BSP для запуска группы из N процессоров, затем используйте 1+N CPU параллельно для запуска (1+N)*M CPU, затем используйте 1+N*M CPU для запуска (1+N*M)*L CPU,и т. д. Другими словами, запуск 255 процессоров по методу Intel увеличивает время задержки до 2,64 секунды, но с помощью достаточно продвинутого кода это можно уменьшить до менее чем 0,05 секунды.

Примечание 3: Подход «широковещательный INIT-SIPI-SIPI» не работает и никогда не должен использоваться ОС (потому что он затрудняет обнаружение «CPU не удалось запустить», потому что он может запускать неисправные CPU, и потому чтоон может запускать процессоры, которые были отключены по другим причинам - например, гиперпоточность отключена пользователем в настройках прошивки).К сожалению, в руководстве Intel есть пример кода, который описывает подход «широковещательный INIT-SIPI-SIPI», который предназначен для разработчиков микропрограмм (где подход «широковещательный INIT-SIPI-SIPI» имеет смысл и безопасен), и новички видят этот примери (неправильно) предположить, что ОС может использовать этот подход.

...