OSDev Wiki
Advertisement

Общие сведения[]

В 32-разрядных процессорах прямо адресуемый программой объём памяти составляет 4 Гбайта. Процессоры, не имеющие MMU, а также большинство процессоров с MMU для адресации физической памяти используют 32-разрядный адрес, однако некоторые MMU позволяют использовать более широкие адреса; в последнем случае объём физической памяти может превышать 4 Гбайта.

Адреса рассматриваются как числа без знака, поэтому при увеличении адреса свыше 4 Гбайт или уменьшении его ниже нуля происходит свёртка адреса, и он остаётся в пределах 4 Гбайт. Однако, если свёрта происходит при автоматическом изменении адреса (например, при записи содержимого нескольких регистров в стек), результат получается непредсказуемым. Таким образом, программа не должна допускать свёртки адреса в пределах одной команды.

В процессорах M-профиля свёртка адресов команд никогда не происходит, поскольку область адресного пространства со старшими адресами жёстко определена как не допускающая выборку команд для исполнения.

Фирма ARM постоянно меняет терминологию, связанную с доступами к памяти, и одни и те же вещи могут описываться в совершенно разных выражениях для разных версий архитектуры. Приведённое здесь описание упоминает используемые английские термины, но не старается строго им следовать, передавая лишь суть, но не форму.

Выровненные и невыровненные доступы[]

Доступ к памяти называется выровненным, если адрес обращения к памяти кратен размеру обращения. Например, для считывания или записи байта адрес может быть произвольным, для полуслова (два байта) он должен быть кратен двум, для слова (4 байта) — четырём, для двойного слова (8 байтов) — восьми. Если это требование не соблюдается, доступ называется невыровненным.

Возможность выполнения невыровненных доступов зависит от профиля и версии архитектуры. Однако, поскольку невыровненные доступы выполняются медленнее, рекомендуется всегда обеспечивать выравнивание данных, даже если есть гарантия, что невыровненные доступы к ним разрешены.

Выравнивание команд[]

Коды команд набора ARM имеют размер слово, набора Thumb — полуслово, набора Thumb-2 — слово или полуслово. Команды набора ARM всегда должны быть выровнены на границу слова, команды наборов Thumb и Thumb-2, даже когда последние имеют размер слово, — на границу полуслова. При несоблюдении этих требований при попытке выполнить первую невыровненную команду возникнет отказ предвыборки либо прерывание по ошибке использования или серьёзному отказу в зависимости от профиля процессора.

Выравнивание данных[]

Выравнивание данных в M-профиле[]

Процессоры архитектуры ARMv6-M, а также те процессоры архитектуры ARMv8-M, которые не поддерживают так называемое основное расширение (main extension; функционально они подобны архитектуре ARMv6-M), требуют выравнивания данных в памяти размером полуслово и слово по их естественным границам; нарушение этого требования приводит к прерыванию по серьёзному отказу. Данные более крупных размеров всегда обрабатываются несколькими командами, ширина доступа к данным которых не превосходит четырёх байтов, поэтому на них дополнительные ограничения не накладываются.

Процессоры архитектуры ARMv7-M, а также процессоры архитектуры ARMv8-M, имеющие основное расширение (функционально они подобны архитектуре ARMv7-M), допускают для ряда команд выполнение невыровненных доступов к данным в «настоящей» памяти (см. ниже), однако доступы по адресам, относящимся к памяти устройств, всегда должны быть выровненными. Возможностью невыровненного доступа управляет бит UNALIGN_TRP регистра CCR. Невыровненные доступы возможны только в командах LDR, LDRH, LDRHT, LDRSH, LDRSHT, LDRT, STR, STRH, STRHT, STRT и TBH.

Порядок следования байтов[]

В большинстве случаев байты в памяти расположены в порядке «младший-старший» независимо от версии архитектуры и выровненности данных. Однако архитектура поддерживает и порядок «старший-младший»; этот порядок, в частности, популярен в процессорах, используемых в маршрутизаторах и другом сетевом оборудовании.

В зависимости от версии архитектуры и от конкретной реализации порядок байтов может быть либо фиксированным, либо изменяемым программно.

Порядок байтов в M-профиле[]

Байты команд всегда располагаются в памяти в порядке «младший-старший».

В версиях ARMv8-M без основного расширения и ARMv6-M, как правило, порядок следования байтов данных задан жёстко на уровне аппаратуры, однако технически возможны реализации, где порядок определяется в момент сброса по состоянию предназначенного для этого внешнего сигнала (в частности, такая возможность предусмотрена для ядра Cortex-M1). В любом случае, порядок следования байтов программно изменён быть не может.

В версиях ARMv8-M с основным расширением и ARMv7-M порядок следования байтов данных, устанавливаемый при сбросе, зависит от реализации; в частности, он может задаваться внешним сигналом. Возможность программного изменения порядка следования байтов данных также определяется реализацией.

Текущий порядок следования байтов данных в памяти отражается состоянием бита ENDIANNESS регистра AIRCR.

Байты данных, доступ к которым осуществляется через PPB (область адресов E0000000—E00FFFFF), всегда располагаются в порядке «младший-старший». Попытка невыровненного доступа, часть которого приходится на адресное пространство PPB, а часть – на другие адреса, приведёт к непредсказуемым последствиям.

Атрибуты памяти[]

Атрибуты памяти позволяют определить, какие доступы в принципе допустимы для данного диапазона адресов и как эти доступы выполняются.

Атрибуты памяти в M-профиле[]

Память в версиях архитектуры  ARMv6-M и ARMv7-M делится на три типа:

  • обычная память (normal);
  • память устройств (device);
  • строго упорядоченная память (strongly-ordered).

В архитектуре ARMv8-M различают только два типа памяти – обычную память и память устройств, причём последняя с точки зрения ARMv7-M является строго упорядоченной.

Помимо типа, память имеет характеристики разделяемости (shareability), кэшируемости (cacheability) и исполняемости. Архитектура ARMv8-M добавляет следующие характеристики: объединяемости (gathering), переупорядочиваемости (reordering) и ранней уведомляемости о записи (early write acknowledgement).

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

Типы памяти[]

Обычная память[]

Обычная память имеет следующие свойства:

  • считывание из одной и той же ячейки может повторяться многократно без побочных эффектов, причём всегда возвращается последнее записанное в эту ячейку значение;
  • считывание из одной ячейки может без побочных эффектов вызывать считывание других смежных ячеек;
  • в одну и ту же ячейку может выполняться многократная запись, не вызывая при этом побочных эффектов, если в промежутках между записями содержимое ячейки не изменяется;
  • могут выполняться невыровненные доступы;
  • перед фактическим доступом к памяти несколько операций доступа могут объединяться в одну.

К данному типу памяти относятся обычные ОЗУ и ПЗУ. Заметим, что доступы на запись к флэш-памяти по тем же адресам, по которым производится её считывание, в обычных условиях вызывают отказ, поскольку для выполнения в неё записи неоходимо предпринимать специальные действия, специфичные для конкретного типа микроконтроллера.

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

Команды группой загрузки и записи (например, POP) могут обращаться к регистрам и к соответствующим им ячейкам обычной памяти в произвольном порядке, т. е. доступы к обычной памяти являются слабо упорядоченными (weakly-ordered).

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

Из обычной памяти может выполняться спекулятивная выборка команд и данных.

Память устройств[]

Доступы к памяти устройств могут вызывать побочные эффекты, а чтение из одной и той же ячейки может каждый раз возвращать разные значения.

Память устройств всегда является некэшируемой. В архитектуре ARMv7-M она может быть разделяемой или неразделяемой, в архитектуре ARMv8-M она формально всегда является разделяемой, что делает её, с точки зрения терминологии, принятой в ARMv7-M, строго упорядоченной памятью.

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

Выполнение команд групповой загрузки или записи может быть прервано, а затем возобновлено, в результате чего могут быть выполнены многократные обращения к одним и тем же ячейкам памяти. По этой причине использовать такие команды для работы с памятью устройств в общем случае нельзя.

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

Спекулятивная выборка из памяти устройств никогда не выполняется, однако из неё может выполняться спекулятивная выборка команд. Чтобы исключить последнюю, выполнение команд из памяти устройств должно быть запрещено. Кроме того, даже при гарантии отсутствия спекулятивной выборки или предвыборки команд архитектура не гарантирует возможность корректного выполнения команд при их выборке из памяти устройств, поэтому запрет выполнения из такой памяти фактически является обязательным.

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

В документации на ARMv7-M указано, что обращения на запись к памяти устройств могут буферизироваться (т. е. не выполняться немедленно, а храниться некоторое время в буфере записи), при этом они могут объединяться при условии соблюдения следующих правил:

  • число доступов остаётся неизменным;
  • порядок доступов остаётся неизменным;
  • размер каждого доступа остаётся неизменным.

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

Документация на ARMv8-M предусматривает разную степень упорядоченности доступов к памяти устройств, используя для этого три новых характеристики: объединяемость (G/nG), переупорядочиваемость (R/nR) и ранняя уведомляемость о записи (E/nE). Допустимы четыре сочетания этих характеристик:

  • nGnRnE – самый строгий порядок доступа;
  • nGnRE – менее строгий порядок;
  • nGRE – ещё менее строгий порядок;
  • GRE – самый нестрогий порядок.

Строго упорядоченная память[]

Строго упорядоченная память определена в архитектуре ARMv7-M и отличается от памяти устройств лишь тем, что всегда является разделяемой. Поскольку в ARMv8-M память устройств всегда является разделяемой, она соответствует строго упорядоченной памяти в терминологии ARMv7-M.

Характеристики памяти[]

Кэшируемость[]

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

Кэшируемой может быть только обычная память; память устройств и строго упорядоченная память кэшироваться не могут.

Разделяемость[]

В архитектуре ARMv7-M разделяемость подразумевает наличие нескольких инициаторов, имеющих доступ к данной памяти, а неразделяемость – наличие только одного инициатора.

В архитектуре ARMv8-M разделяемость не связана с числом инициаторов. Если область памяти определена как разделяемая, это означает, что аппаратура гарантирует согласованность доступов нескольких инициаторов (процессоров) к одним и тем же ячейкам памяти. Если область определена как неразделяемая, но доступ к ней может осуществляться несколькими инициаторами, аппаратура не даёт гарантий согласованности. Для её обеспечения программист должен использовать барьеры, а также самостоятельно выполнять необходимые операции обслуживания кэша.

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

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

В архитектуре ARMv8-M дополнительно появились понятия внешней и внутренней разделяемости (outer/inner shareability), что, в свою очередь, вытекает из возможности наличия нескольких доменов разделяемости, причём внутренние домены могут быть вложены во внешний домен. Любое устройство может быть членом только одного внутреннего и одного внешнего доменов. Для всех устройств одного внутреннего домена гарантируется согласованность доступов, которые являются внутренне разделяемыми, а для всех устройств одного внешнего домена – доступов, которые являются внешне разделяемыми.

Строго упорядоченная память (этот термин применяется только в архитектурах ARMv6-M и ARMv7-M) всегда является разделяемой. Память устройств в ARMv6-M и ARMv7-M может быть разделяемой или неразделяемой (последнее понимается как наличие только одного инициатора, способного обращаться к данной части адресного пространства), в ARMv8-M она всегда разделяемая. Обычная некэшируемая память является разделяемой, кэшируемая может быть как разделяемой, так и неразделяемой.

Исполняемость[]

Исполняемость определяет, может ли содержимое ячеек данной области адресного пространства считываться в рамках выборки команд.

Объединяемость[]

Характеристика объединяемости (gathering, G или nG) введена в архитектуре ARMv8-M и применяется для памяти устройств.

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

Доступы к области памяти с характеристикой G могут выполняться идентично областям с характеристикой nG, поскольку последняя определяет более строгий порядок доступов. Однако, если для области задана характеристика nG, доступ к ней не может выполняться, как если бы была задана характеристика G.

Объединение доступов к области с характеристикой G не выполняется, если эти доступы разделены барьером памяти или если они формируются операциями чтения с захватом или записи с освобождением (командами типа LDA и STL).

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

Переупорядочиваемость[]

Характеристика переупорядочиваемости (reordering, R или nR) введена в архитектуре ARMv8-M и имеет смысл только при доступах к периферийным устройствам. Когда указано, что некоторая область памяти является непереупорядочиваемой (nR), все обращения к периферийным устройствам в такой области выполняются в порядке, явно определяемом программой. При характеристике R порядок фактических доступов не гарантируется, поэтому для в случаях, когда его необходимо соблюдать, программа должна использовать барьеры.

Доступы к области памяти с характеристикой R могут выполняться идентично областям с характеристикой nR, поскольку последняя определяет более строгий порядок доступов. Однако, если для области задана характеристика nR, доступ к ней не может выполняться, как если бы была задана характеристика R.

Наличие характеристики nR не накладывает дополнительных требований на взаимное упорядочивание доступов:

  • между доступами к области с характеристикой nR и к области с характеристикой R;
  • между доступами к области с характеристикой nR и к области обычной памяти;
  • между доступами к разным периферийным устройствам в области с характеристикой nR.

Размер области памяти, отводимой одному периферийному устройству, определяется реализацией.

Ранняя уведомляемость о записи[]

Характеристика ранней уведомляемости о записи (early write acknowledgement, E или nE) определяет, должен ли инициатор доступа на запись получать уведомление о завершении этого доступа только от целевого устройства (nE), или же это уведомление может быть выдано неким промежуточным узлом (E).

Данная характеристика рассматривается как подсказка и поэтому может игнорироваться: доступы к области с характеристикой E могут выполняться, как если бы была задана характеристика nE, и наоборот. Фирма ARM, однако, настоятельно рекомендует не игнорировать эту характеристику в любой конкретной реализации.

Права доступа к памяти[]

Права доступа в M-профиле[]

При обращении к памяти процессор может находиться в привилегированном или непривилегированном состоянии (последнее поддерживается не всеми реализациями). Различают три вида доступов:

  • выборка команд;
  • чтение данных;
  • запись данных.

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

При попытке выполнить доступ с нарушением требуемых прав возникает прерывание.

Атомарность доступов к памяти[]

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

В архитектуре ARM различают атомарность для одной и нескольких копий данных (single- и multi-copy atomicity).

Атомарность в M-профиле[]

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

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

Атомарными для одной копии являются любые байтовые доступы, а также выровненные доступы к полусловам и словам данных.

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

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

Операции заполнения и записи строк кэша не сказываются на атомарности явно заданных доступов к памяти.

Операция записи является атомарной для нескольких копий, если соблюдаются оба следующих условия:

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

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

Монопольный доступ к памяти[]

Монопольный доступ в M-профиле[]

Процессоры архитектуры ARMv6-M монопольный доступ к памяти не поддерживают. В многопроцессорных микроконтроллерах, содержащих ядра этой архитектуры, для межпроцессорной синхронизации предусматриваются специальные средства, специфичные для конкретного микроконтроллера и не относящиеся к архитектуре ARM.

Монопольный доступ к памяти в архитектуре ARMv7-M обеспечивается командами типа LDREX и STREX.

Архитектура ARMv8-M (с основным расширением) дополнительно предусматривает команды типа LDA и STA.

Порядок доступов к памяти[]

Порядок доступов к памяти зависит от её типа и атрибутов и определяет:

  • когда побочные эффекты, если таковые имеются, гарантированно проявят себя;
  • каковы требования к согласованности содержимого памяти.

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

Порядок доступов в M-профиле[]

Различают явные и неявные доступы. К первым относятся доступы к данным, заданным в выполняемых командах, ко вторым – выборка команд, а также загрузка строк кэша и запись их в память. Если прямо не указано иное, требования к порядку доступов относятся только к явным доступам.

В архитектуре ARMv8-M доступы для выборки команд и доступы к данным считаются исходящими от разных инициаторов.

Наблюдаемость доступов к памяти[]

Запись в ячейку памяти является наблюдаемой некоторым наблюдателем, когда:

  • последующее считывание этой же ячейки данным наблюдателем вернёт значение, записанное либо данным наблюдаемым обращением на запись, либо обращением на запись в эту же ячейку, выполненным любым другим наблюдателем позже данного наблюдаемого обращения в согласованном порядке доступов;
  • последующая запись в эту ячейку данным наблюдателем имеет место в согласованном порядке доступов после данного наблюдаемого обращения на запись.

Запись считается глобально наблюдаемой в домене разделяемой памяти, когда:

  • последующее считывание этой же ячейки любым наблюдателем в данном домене вернёт значение, записанное либо данным глобально наблюдаемым обращением на запись, либо обращением на запись в эту же ячейку со стороны любого наблюдателя, выполненным позже данного глобально наблюдаемого обращения в согласованном порядке доступов;
  • последующая запись в эту ячейку любым наблюдателем данного домена имеет место в согласованном порядке доступов после данного глобально наблюдаемого обращения.

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

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

Дополнительно для строго упорядоченной памяти (ARMv6-M или ARMv7-M) либо памяти устройств с характеристиками nGnRnE (ARMv8-M) чтение или запись в регистр периферийного устройства считается наблюдаемым и глобально наблюдаемым, когда:

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

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

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

Завершённость доступов к памяти[]

Чтение или запись в пределах домена разделяемости считаются завершёнными, когда соблюдаются оба следующих условия:

  • это чтение или запись глобально наблюдаемо в пределах данного домена;
  • все выборки команд наблюдателями, входящими в данный домен, наблюдают данное чтение или запись.

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

Завершённость доступа к памяти устройств или строго упорядоченной памяти (ARMv6-M и ARMv7-M) либо к памяти устройств с характеристиками, отличающимися от nGnRnE (ARMv8-M), не гарантирует, что побочные эффекты, связанные с данным доступом, уже наблюдаемы всеми наблюдателями. Способ гарантировать эту наблюдаемость определяется реализацией; например, это может быть некий регистр, завершение считывания которого даёт гарантию, что эффекты, вызываемые ранее выполненными обращениями к этому же устройству, стали глобально наблюдаемыми.

Требования к упорядочиванию доступов к памяти[]

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

В архитектурах ARMv6-M и ARMv7-M доступы к памяти устройств или к строго упорядоченной памяти являются глобально наблюдаемыми в концептуальном порядке. В архитектуре ARMv8-M это ограничение ослаблено: доступы обязаны быть глобально наблюдаемыми в концептуальном порядке лишь в случае, если они относятся к одному и тому же периферийному устройству (т. е. участку адресного пространства, размер которого определяется реализацией и предназначен для одного устройства), относящемуся к памяти устройств с характеристикой nR. Таким образом, если программе, выполняемой на процессоре архитектуры ARMv8-M, требуется обеспечить упорядоченность доступов к нескольким устройствам, она должна использовать барьеры.

Доступы, связанные с выборкой команд, могут наблюдаться в произвольном порядке, если только они не разделены событиями синхронизации контекста. К таким событиям относятся:

  • выполнение команды ISB;
  • вход в обработчик прерывания;
  • выход из обработчика прерывания;
  • выход из режима отладки.

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

Барьеры памяти[]

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

Изначально было определено три типа барьеров, обозначаемых в соответствии с мнемониками команд DMB, DSB и ISB. Позднее они были дополнены ещё тремя барьерами – CSDB, PSSBB и SSBB. Три новых барьера связаны с введением в архитектуру поддержки спекулятивного выполнения команд.

Барьер использования спекулятивных данных (CSDB)[]

Этот вид барьера (consumption of speculative data barrier) задаётся командой CSDB. Он запрещает командам, выполняемым после барьера, формировать любую часть данных, производных от спекулятивно выполняемой команды загрузки, предшествующей барьеру.

Барьер данных (DMB)[]

Этот вид барьера (data memory barrier) задаётся командой DMB. Он обеспечивает завершение в требуемом домене разделяемости (в частности, во всей вычислительной системе) всех явных обращений к памяти, инициированных до выполнения команды DMB, перед тем, как будет начато выполнение любых явных обращений к памяти после этой команды.

Команда DMB позволяет определить домен разделяемости, в рамках которого необходимо установить барьер, и типы доступа, на которые он распространяется. В процессорах M-профиля барьер всегда относится ко всей вычислительной системе сразу (т. е. ко всем доменам разделяемости, если их несколько) и ко всем видам доступа, т. е. соответствующие биты кода команды игнорируются. Процессоры профилей A и R могут поддерживать более тонкую настройку барьера.

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

Барьер синхронизации данных (DSB)[]

Этот вид барьера (data synchronization barrier) задаётся командой DSB. Он блокирует выполнение любых команд, расположенных после барьера, до тех пор, пока выполнение команды DSB не будет завершено. Её выполнение завершается при одновременном соблюдении всех следующих условий:

  • в пределах заданного домена должны быть завершены все явные доступы, инициированные до выполнения DSB;
  • если DSB запрашивает барьер для операций чтения и записи, в пределах домена должны быть завершены все операции обслуживания кэшей и предсказателя ветвлений, инициированные процессором, выполняющим команду DSB;
  • должны быть завершены все явные обращения к средствам управления вычислительной системой (например, к пространству управления системой процессора M-профиля), которые были инициированы данным процессором до команды DSB и которые влияют на контекст выполнения.

Барьер синхронизации команд (ISB)[]

Этот вид барьера (instruction synchronization barrier) задаваётся командой ISB. Он обеспечивает очистку конвейера процессора и повторную выборку команд, следующих в программе после ISB, из кэша или из памяти.

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

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

Совместное использование ISB и DSB или DMB гарантирует выполнение обновлённых команд в случае их динамической модификации в памяти.

Барьер обхода физической спекулятивной записи (PSSBB)[]

Этот вид барьера (physical speculative store bypass barrier) задаётся командой PSSBB. Он блокирует спекулятивную загрузку:

  • более старых данных, чем в самой последней записи по тому же физическому адресу, появляющейся в программе перед загрузкой;
  • данных, записываемых по тому же физическому адресу после загрузки.

Барьер обхода спекулятивной записи (SSBB)[]

Этот вид барьера (speculative store bypass barrier) задаётся командой SSBB. Он блокирует спекулятивную загрузку:

  • более старых данных, чем в самой последней записи по тому же виртуальному адресу, появляющейся в программе перед загрузкой;
  • данных, записываемых по тому же виртуальному адресу после загрузки.
Advertisement