Прерывание инструкции по сборке во время ее работы

Когда прерывание поступает в ЦП, оно обрабатывается путем сохранения текущего местоположения адреса перед переходом в обработчик, если оно подтверждено. В противном случае игнорируется.

Интересно, не прерывается ли вызов инструкции сборки.

Например,

mvi a, 03h ; put 3 value into acc. in 8080 assembly

Может быть прервана однострочная инструкция? А если нет, то атомарно ??

Всегда ли есть гарантия, что "однострочная инструкция по сборке" всегда атомарна ??

Что, если нет ключевого слова lock, т.е. в сборке 8080, как тогда обеспечивается атомарность?

Например, что, если требуется оперировать 64-битной суммой, но нет способа сделать это с помощью «однострочной инструкции», и при работе над суммой возникает прерывание. Как это можно предотвратить на уровне сборки ??

Для меня концепция начинает сводиться к одному.


person snr    schedule 15.03.2019    source источник
comment
Разработчик микросхемы позаботился о том, чтобы она была атомарной, так и должно быть. Обработчик прерывания никогда не должен искажать состояние процессора, чтобы операция с несколькими инструкциями работала неправильно. На 8080 это не так сложно сделать, просто сохранив и восстановив регистры. Сама логика прерывания уже сохраняет регистр IP, RET восстанавливает его. Почти каждый обработчик прерывания начинается с PUSH PSW, чтобы сохранить флаги и регистры аккумулятора.   -  person Hans Passant    schedule 15.03.2019
comment
Сомневаюсь, что это сделано для 8080. Однако теоретически возможно, что уже выполняющаяся инструкция будет прервана прерыванием. Я работал над разными RISC-процессорами (для FPGA). В одном проекте инструкции могут даже быть прерваны таким образом, что регистр, в который производится запись, имеет несогласованное значение, если это произойдет. В этом дизайне адрес возврата будет адресом инструкции, которая была прервана, поэтому в этом случае вся инструкция будет повторена. Так что, по крайней мере, существуют конструкции, позволяющие прерывать инструкции.   -  person Martin Rosenau    schedule 15.03.2019


Ответы (2)


Да, все "нормальные" ISA, включая 8080 и x86, гарантируют, что инструкции являются атомарными по отношению к прерываниям на одном и том же ядре. Либо инструкция полностью выполнена, и все ее архитектурные эффекты видны (в обработчике прерывания) , или ни одного из них. Любые отклонения от этого правила обычно тщательно документируются.


Например, Руководство Intel x86, том 3 (~ 1000 страниц в формате PDF) действительно подчеркивает следующее:

6.6 ПЕРЕЗАПУСК ПРОГРАММЫ ИЛИ ЗАДАЧИ
Чтобы разрешить перезапуск программы или задачи после обработки исключения или прерывания, все исключения (кроме прерываний) гарантированно сообщают об исключениях на границе инструкции. Все прерывания гарантированно выполняются на границе инструкции.

Старый абзац в В руководстве Intel том.1 говорится об одноядерных системах, использующих cmpxchg без lock префикса для атомарного чтения-изменения-записи (в отношении другого программного обеспечения, а не доступа к аппаратному DMA).

Инструкция CMPXCHG обычно используется для тестирования и изменения семафоров. Он проверяет, свободен ли семафор. Если семафор свободен, он помечается как выделенный; в противном случае он получает идентификатор текущего владельца. Все это выполняется за одну непрерывную операцию [потому что это одна инструкция]. В однопроцессорной системе инструкция CMPXCHG устраняет необходимость переключения на уровень защиты 0 (для отключения прерываний) перед выполнением нескольких инструкций для проверки и изменения семафора.

Для многопроцессорных систем CMPXCHG можно комбинировать с префиксом LOCK для атомарного выполнения операции сравнения и обмена. (См. «Заблокированные атомарные операции» в главе 8 «Управление несколькими процессорами» Руководства разработчика программного обеспечения для архитектур Intel® 64 и IA-32, том 3A, для получения дополнительной информации об атомарных операциях.)

(Подробнее о префиксе lock и его реализации по сравнению с неблокированным add [mem], 1 см. Может ли num ++ быть атомарным вместо int num?)

Как указывает Intel в первом абзаце, один из способов добиться атомарности нескольких инструкций - отключить прерывания, а затем снова включить их, когда вы закончите. Это лучше, чем использование мьютекса для защиты более крупного целое число, особенно если вы говорите о данных, совместно используемых основной программой и обработчиком прерывания. Если прерывание происходит, когда основная программа удерживает блокировку, она не может ждать снятия блокировки; этого никогда не случится.

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

В любом случае, отключение прерываний - это то, как вы можете атомарно что-то делать с 64-битным целым числом на 8080.


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

например rep-строковые инструкции x86, такие как rep movsb (одинарная инструкция memcpy произвольного размера), архитектурно эквивалентны повторению базовой инструкции (movsb) RCX раз, каждый раз уменьшая RCX и увеличивая или уменьшая входные указатели (RSI и RDI). Прерывание, поступающее во время копирования, может установить RCX starting_value - byte_copied и (если RCX тогда ненулевое) оставить RIP, указывающий на инструкцию, поэтому при возобновлении после прерывания rep movsb снова запустится и выполнит остальную часть копирования.

Другие примеры x86 включают сборочные нагрузки SIMD (AVX2 / AVX512) и хранилища разброса (AVX512). Например. vpgatherdd ymm0, [rdi + ymm1*4], ymm2 выполняет до 8 32-битных загрузок, в соответствии с которыми установлены элементы ymm2 . И результаты объединяются в ymm0.

В обычном случае (без прерываний, ошибок страниц или других синхронных исключений во время сбора) вы получаете данные в регистр назначения, а регистр маски обнуляется. Таким образом, регистр маски дает ЦП место для хранения прогресса.

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


Некоторые другие долго выполняющиеся инструкции (например, wbinvd, который очищает все кеши данных во всех ядрах) не являются архитектурно прерываемыми или даже микро архитектурно прерываемыми (чтобы отменить частичную работу и перейти к обработке прерывание). Он имеет привилегии, поэтому пользовательское пространство не может выполнить его как атаку отказа в обслуживании, вызывающую высокую задержку прерывания.


Связанный пример документирования забавного поведения - это когда x86 popad выходит за пределы стека (ограничение сегмента). Это исключение (не внешнее прерывание), задокументированное ранее в руководстве тома 3, в разделе 6.5 ИСКЛЮЧИТЕЛЬНЫЕ КЛАССИФИКАЦИИ (например, отказ / прерывание / прерывание, более подробную информацию см. В PDF).

ПРИМЕЧАНИЕ. Одно подмножество исключений, которое обычно регистрируется как сбой, не подлежит перезапуску. Такие исключения приводят к потере некоторого состояния процессора. Например, выполнение инструкции POPAD при пересечении кадра стека конец сегмента стека вызывает сообщение об ошибке. В этой ситуации обработчик исключений видит, что указатель инструкции (CS: EIP) был восстановлен, как если бы инструкция POPAD не была выполнена. Однако внутреннее состояние процессора (регистры общего назначения) будет изменено. Такие случаи считаются ошибками программирования. Приложение, вызывающее этот класс исключений, должно быть прекращено операционной системой.

Обратите внимание, что это происходит только в том случае, если popad сам вызывает исключение, не по какой-либо другой причине. Внешнее прерывание не может разделять popad так, как это может быть rep movsb или vpgatherdd

(Я предполагаю, что для целей popad сбоев он эффективно работает итеративно, вытаскивая по одному регистру за раз и логически изменяя RSP / ESP / SP, а также целевой регистр. Вместо проверки всего региона он будет загружаться для ограничения сегмента перед начиная, потому что это потребует дополнительного добавления, я думаю.)


Неисправные ЦП возвращаются в состояние вывода из эксплуатации по прерываниям.

Такие процессоры, как современные x86 с выполнением вне очереди и разделением сложных инструкций на несколько мопов, по-прежнему гарантируют, что это так. Когда приходит прерывание, ЦП должен выбрать точку между двумя инструкциями, которые он выполняет, в качестве места, где архитектурно происходит прерывание. Он должен отменить любую работу, которая уже была сделана по декодированию или началу выполнения любых последующих инструкций. Предполагая, что прерывание вернется, они будут повторно извлечены и снова начнут выполнение.

См. Когда происходит прерывание, что происходит с инструкциями в процессе разработки?.

Как говорит Энди Глю, текущие процессоры не переименовывают уровень привилегий, поэтому то, что происходит логически (обработчик прерываний / исключений выполняется после завершения предыдущих инструкций), соответствует тому, что на самом деле происходит.

Однако забавный факт: прерывания x86 не полностью сериализуются, по крайней мере, не гарантируется на бумаге. (В терминологии x86 такие инструкции, как cpuid и iret, определены как сериализация; истощите внутреннюю часть OoO и буфер хранения и все остальное, что может иметь значение. Это очень сильный барьер, и многие другие вещи не являются < / em>, например mfence.)

На практике (поскольку процессоры на практике не переименовывают уровень привилегий), не будет никаких старых инструкций / операций пользовательского пространства в вышедшей из строя серверной части, которые все еще работают, когда запускается обработчик прерывания.

Асинхронные (внешние) прерывания также могут истощать буфер хранилища, в зависимости от того, как мы интерпретируем формулировку Intel SDM vol.3 11.10: * содержимое буфера хранилища всегда выгружаются в память в следующих ситуациях: "..." Когда исключение или прерывание сгенерировано ". Очевидно, что это применимо к исключениям (когда ядро ​​ЦП само генерирует прерывание), а также может означает перед обслуживанием прерывания.

(Сохранение данных из устаревших инструкций хранилища не является умозрительным; это определенно произойдет, и ЦП уже сбросил состояние, в которое он должен был бы иметь возможность откатиться до этой инструкции сохранения. Таким образом, большое хранилище буфер, заполненный разрозненными хранилищами промахов кэша, может снизить задержку прерывания. Либо из-за ожидания его истощения до того, как какие-либо инструкции обработчика прерываний могут быть запущены вообще, либо, по крайней мере, до того, как любая _22 _ / _ 23_ или locked инструкция в ISR может произойти, если она превратится из того, что буфер хранилища не истощен.)

Связанный: Sandpile (https://www.sandpile.org/x86/coherent.htm) есть таблица сериализуемых вещей. Прерываний и исключений нет. Но опять же, это не означает, что они не истощают буфер хранилища. Это можно проверить с помощью эксперимента: ищите переупорядочение StoreLoad между хранилищем в пользовательском пространстве и загрузкой (другой общей переменной) в ISR, как это наблюдается другим ядром.

Часть этого раздела на самом деле не относится к этому ответу и должна быть перемещена в другое место. Это здесь, потому что обсуждение в комментариях к Что происходит с ожидаемой семантикой памяти (например, чтение после записи), когда поток запланировано на другом ядре ЦП? назвал это источником, вероятно, неверного утверждения о том, что прерывания не истощают буфер хранилища, что я написал после неверной интерпретации «не сериализации».

person Peter Cordes    schedule 15.03.2019
comment
Sandpile не перечисляет аппаратные прерывания как сериализуемые, вероятно, потому, что они не являются инструкциями. Я думаю, что этот список представляет собой список инструкций по сериализации, а не сериализацию событий. Но документ? поле говорит нет для прерываний и исключений, что я не уверен, что это означает. - person Hadi Brais; 11.02.2020
comment
В руководстве Intel V2 упоминается, что инструкции INT в основном имеют те же свойства сериализации, что и LFENCE. Однако в руководстве AMD об этом не говорится (AFAICT). Кроме того, в руководствах Intel и AMD упоминается, что исключения и прерывания истощают буфер хранилища и буферы WC. Это предполагает, что термин «прерывания» в данном контексте относится к аппаратным прерываниям, а термин «исключения» относится к исключениям программных ошибок и исключениям машинной проверки (см. Раздел 6.4 тома 3). Мне кажется, что исключения и прерывания полностью сериализуются. - person Hadi Brais; 11.02.2020
comment
Я не хочу сейчас читать всю статью 2008 года, можете ли вы указать, где именно говорится, что прерывания на x86 сериализуются? И, надеюсь, термины прерывания и сериализация хорошо определены в статье, поэтому нам не нужно гадать. И также, надеюсь, они дадут ссылку на Intel (авторы не из Intel). Они использовали симулятор Simics, который является академическим симулятором, а это означает, что их результаты не обязательно показывают, как работают настоящие процессоры. - person Hadi Brais; 11.02.2020
comment
@HadiBrais: Эта газета - отвлекающий маневр; они говорят только о сериализации OoO exec, а не о памяти. Я смотрел раздел 3.2, где говорится о том, что процессоры не переименовывают CS, поэтому syscall сериализуется. И косвенно то же самое и с прерываниями (по крайней мере, если они взяты из пользовательского пространства), хотя они даже не упоминают об этом. Я собираюсь удалить этот раздел из этого ответа; после второго взгляда это слишком отдаленно связано. (Кстати, я обновил ссылку на его версию в более удобном формате. ftp.cs.wisc.edu/sohi/papers/2008/hpca2008-serial.pdf.) - person Peter Cordes; 11.02.2020

Я не уверен, что 8080 был разработан для использования в многопроцессорных системах с общей оперативной памятью, что, однако, не обязательно означает невозможность или отсутствие таких систем. Префикс блокировки 8086 предназначен для таких систем, чтобы гарантировать, что только один процессор может иметь монопольный доступ к памяти при выполнении последовательности чтения из памяти, изменения значения, записи в память (RMW). Префикс блокировки не предназначен для защиты инструкции или нескольких инструкций от вытеснения обработчиком прерывания.

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

Действительно, вы не можете выполнить 64-битное сложение с помощью одной инструкции 8080, поэтому эта операция может быть прервана ISR.

Если вам вообще не нужно такое приоритетное прерывание, вы можете защитить свой 64-битный адд с помощью инструкций по отключению и включению прерывания (DI и EI).

Если вы хотите, чтобы ISR вытесняла 64-битную, но не нарушая регистры, которые использует 64-битное добавление, ISR должна сохранять и восстанавливать эти регистры, например, используя инструкции PUSH и POP.

Найдите руководство по 8080 для подробного описания обработки прерываний (например, здесь) .

person Alexey Frunze    schedule 15.03.2019
comment
На 8086 lock (и xchg с памятью) существуют для атомарности по отношению к другим устройствам, не связанным с процессором, в системе, например DMA читает. И для использования с отображаемым в память вводом-выводом, я думаю, там, где, возможно, было важно, чтобы ЦП поддерживал сигнал #LOCK при выполнении чтения + записи. Я думаю, что самые ранние системы SMP x86 были 386. (А раньше с чем-то вроде современной модели памяти было 486; я думаю, что я читал, что у 386 не было некоторых текущих гарантий.) - person Peter Cordes; 15.03.2019
comment
@PeterCordes Возможно, ты прав в отношении другие устройства доступа к памяти. Я сосредоточился только на процессорах. - person Alexey Frunze; 15.03.2019
comment
Ну, это то, для чего он в основном используется на современной x86, но вы буквально говорите префикс блокировки 8086, а не префикс блокировки x86. Такого варианта использования не существует в 8086 (и интересно, что он существовал до систем SMP.) - person Peter Cordes; 15.03.2019
comment
@PeterCordes А, да, x86 лучше, чем 8086. - person Alexey Frunze; 15.03.2019