Заметки по анатомии многозадачной ОС

Заметки по анатомии многозадачной ОС

Смысл понятия «многозадачный процессор» кар­ди­наль­но и не­сколь­ко раз ви­до­из­ме­нял­ся на про­тя­же­нии по­след­них де­ся­ти­ле­тий. Пусть се­го­дня это по­ка­жет­ся стран­ным, но еще со вре­мен 16-бит­но­го In­tel 8086 вы­ход каж­до­го но­во­го про­цес­со­ра со­про­вож­дал­ся гром­ки­ми заявле­ни­я­ми об эф­фек­тив­ной под­дер­ж­ке мно­го­за­дач­ных сред и мно­го­поль­зо­ва­тель­ских сис­тем. По­про­бу­ем раз­о­брать­ся в ны­неш­ней трак­тов­ке это­го по­ня­тия в кон­тек­с­те ар­хи­тек­ту­ры со­вре­мен­ных про­цес­со­ров.

Три кита многозадачности

Функциональность в современной реализации определяется такими аспектами.

  1. Процессор декларирует наличие и характеристики системных объектов, реализующих аппаратную поддержку ускоренного сохранения и загрузки состояния программно-доступных регистров при переключении задач. Эта информация используется процедурами управления контекстом, входящими в состав ОС.
  2. Операционная система декларирует поддержку для каждого из компонентов программно доступного состояния процессора. Такие компоненты обычно связаны с функциональными расширениями. Например, для работоспособности технологии векторных вычислений AVX512 в многозадачной среде, процессор должен сохранять и восстанавливать содержимое 32 512-битных регистров  ZMM0-ZMM31 при переключении задачи. Эта информация запрашивается приложениями для определения возможности использования расширенных наборов инструкций, наряду с информацией о поддержке данных инструкций процессором.
  3. Процессор реализует механизм, обеспечивающий аппаратную поддержку сохранения состояния исходящей (прерываемой) задачи в оперативной памяти, а также загрузку состояния входящей (прерывающей) задачи за минимальное время.

Трудности роста

В первых реализациях архитектуры AMD64, функциональность многозадачности была су­щест­вен­но умень­ше­на. При­чи­на конечно же не в том, что разработчики посчитали этот аспект не важным. Архитектура, ос­но­ван­ная на ис­поль­зо­ва­нии сегмента состояния задачи или TSS (Task State Segment) впервые появившегося в 16-битном процессоре 80286, несколько устарела. Кроме того, документированная структура TSS и связанная с этим возможность обращения к за­дан­но­му полю по конкретному адресу, нарушала один из базовых паттернов проектирования — инкапсуляцию. Стре­мясь как можно быстрее избавиться от такого «кощунства», архитекторы выбрали самое простое решение: ОС дол­ж­на про­грам­мно выполнять операции по сохранению и восстановлению состояния процессора, например, клас­си­че­ски­ми ин­ст­рук­ци­я­ми MOV или PUSH.

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

Идентификация ресурсов процессора

Результат выполнения функции 0Dh подфункции 0 инструкции CPUID. Регистры EDX:EAX содержат список элементов контекста процессора, EBX содержит требуемый размер области для элементов, сохранение которых поддерживается и включено, ECX содержит полный требуемый размер области для всех поддерживаемых элементов контекста
Рис.1. Результат выполнения функции 0Dh подфункции 0 инструкции CPUID. Регистры EDX:EAX содержат список элементов контекста процессора, EBX содержит требуемый размер области для элементов, сохранение ко­то­рых поддерживается и включено, ECX содержит требуемый размер области для всех элементов контекста

Традиционно, для декларирования функциональности процессора, используется инструкция CPUID. Информация о ресурсах, обеспечивающих аппаратную поддержку многозадачности доступна посредством функции 0Dh. Описание одной из ее подфункций приведено на рис.1. Для более полной информации следует обратиться к документу [1].

Идентификация ресурсов ОС

Каждый бит регистра XCR0 соответствует определенному элементу программно-доступного контекста процессора. Сюда входят Legacy x87 FPU, технологии векторных вычислений SSE128, AVX256/512, регистры, задающие диапазоны и атрибуты для технологий защиты памяти (BNDCSR, BNDREG, PKRU), регистры предикатов (Opmask) для маскирования векторных операндов AVX512
Рис.2. Каждый бит регистра XCR0 соответствует определенному элементу программно-доступного контекста процессора: Legacy x87 FPU, технологии векторных вычислений SSE128, AVX256/512, регистры, задающие ди­а­па­зо­ны и атрибуты для технологий защиты памяти (BNDCSR, BNDREG, PKRU), регистры предикатов (Opmask) для мас­ки­ро­ва­ния векторных операндов AVX512

Коммуникация между процессором и ОС, а также декларирование поддерживаемой функциональности ОС для при­ло­же­ний, осуществляется посредством системного регистра XCR0 (Extended Control Register 0). Пользовательские программы могут прочитать содержимое этого регистра посредством инструкции XGETBV (Extended Get Bit Vector). Запись в регистр может выполнить только привилегированный код ОС, инструкцией XSETBV (Extended Set Bit Vector).

Аппаратная поддержка сохранения и восстановления контекста

Инструкция XSAVE обеспечивает быстрое сохранение выбранных элементов контекста процессора в заданную область памяти. Список сохраняемых объектов находится в регистре XCR0, описанном выше и уточняется содержимым 64-битной маски, передаваемой в регистрах EDX:EAX. Это позволяет выполнить дополнительную оптимизацию, например, избежав сохранения и восстановления элементов, не используемых конкретной процедурой
Рис.3. Инструкция XSAVE обеспечивает быстрое сохранение выбранных элементов контекста процессора в заданную область памяти. Список сохраняемых объектов находится в регистре XCR0, описанном выше и уточняется содержимым 64-битной маски, передаваемой в регистрах EDX:EAX. Это позволяет выполнить дополнительную оптимизацию, например, избежав сохранения и восстановления элементов, не используемых конкретной процедурой

Инструкция XRSTOR обеспечивает быстрое восстановление выбранных элементов контекста процессора из заданной области памяти. Эта инструкция комплиментарна к XSAVE
Рис.4. Инструкция XRSTOR обеспечивает быстрое восстановление выбранных элементов контекста процессора из заданной области памяти. Эта инструкция комплиментарна к XSAVE

Исполнительный механизм, реализующий операции сохранения и восстановления контекста процессора, пред­став­лен инструкциями XSAVE (Save Processor Extended States) и XRSTOR (Restore Processor Extended States).

Что осталось за кадром

Разработчики процессора минимизировали вероятность появления трудноуловимых ошибок, связанных с ис­ка­же­ни­я­ми состояния регистров в многозадачной среде. Выполнение любой инструкции, относящейся к фун­к­ци­о­наль­ным рас­ши­ре­ни­ям (например, SSE или AVX) возможно только в том случае, если для всех элементов процессорного контекста,  которыми оперирует данная инструкция, декларирована поддержка сохранения и восстановления. Иначе, процессор сформирует исключение.

Этот факт необходимо принять к сведению разработчикам UEFI приложений, Legacy-загрузчиков, выполняемых до стар­та операционной системы, а также авторам программ под MS-DOS (если таковые еще остались) желающим при­ме­нять современные функциональные расширения. Даже в том случае, если ваша операционная среда не ис­поль­зу­ет многозадачность и вы не предусматриваете процедуры сохранения и восстановления состояния про­цес­со­ра, ре­сур­сы декларирующие управление процессорным контекстом должны быть инициализированы.