Одноуровневая память
Указатели и теги
После роста производительности, самое большое достоинство одноуровневой памяти — всеобъемлющая возможность совместного доступа. Впрочем, это и самый большой ее недостаток. Если каждый пользователь системы имеет доступ к большому единому адресному пространству, требуются гарантии от несанкционированного доступа к тем объектам или информации, на которые у этих пользователей нет прав. В "Объекты" мы говорили, что такая защита осуществляется в AS/400 указателями. Давай те теперь рассмотрим указатели и их функции более подробно.
Итак, доступ к объекту MI обеспечивается путем разрешения указателя. Указатели имеют длину 16 байт (128 бит). Разрешенный системный указатель содержит возможность прямой адресации системного объекта, то есть в нем находится 64-разрядный виртуальный адрес. Указатели других типов (пространства, данных, команд и процедур) также содержат виртуальные адреса.
Указатели находятся в ассоциированном пространстве системного объекта. В этом же пространстве содержатся данные, к которым имеет доступ и которые может изменить программа MI. Доступ и модификация данных в ассоциированном пространстве законны; изменение указателя — нет. Если бы программа MI могла изменять содержимое указателя, то была бы нарушена защита. Адрес в указателе мог бы быть изменен так, чтобы указывать на еще какойнибудь объект или структуру, доступ к которой запрещен. Конечно, все это касается пользовательских программ, в которых команды MI заданы непосредственно; и не имеет отношение к программам на ЯВУ, таких как RPG или Cobol.
Когда разрабатывалась структура указателя, способами защиты были избраны устранение ассемблера MI, перевод некоторых команд в разряд привилегированных и удаление из указателей полномочий. Как говорилось в "Защита от несанкционированного доступа" , все эти усиления уровней защиты привносились в AS/400 с течением времени. Но даже такая степень защищенности не дает стопроцентной уверенности в том, что содержимое указателя не подвергнется несанкционированным изменениям.
В "Объекты" отмечалось, что ассоциированное пространство, содержащее указатели, занимает отдельный сегмент системного объекта. Первоначально в System/38 мы хотели использовать два сегмента: один — для данных, а второй —для указателей. Но такой подход снижал производительность системы. При использовании объекта было необходимо считывать с диска страницы, как сегмента данных, так и сегмента указателей, что повышало накладные расходы. Кроме того, два сегмента требовали некоторого увеличения размеров памяти. Единственным плюсом ассоциированного сегмента указателей была надежда, что он может защитить указатели от модификации пользователями. Но оказалось, что это не так.
Скоро выяснилось, что мы не можем защитить ассоциированный сегмент указателей от изменений. При той степени защиты, которая планировались для System/38 (уровень 30), пользователь, имевший право доступа к объекту, мог работать с его содержимым с помощью ассемблера MI. Помещение указателей в отдельную часть объекта не предоставляло дополнительной защиты. Пришлось искать другое решение.
Аппаратная защита указателей
Мы понимали, что необходима некоторая форма аппаратной защиты памяти для указателей. Многие из больших систем того времени, такие как System/370, использовали для защиты памяти специальные аппаратные разряды, разрешавшие или запрещавшие пользователю доступ к некоторому блоку байтов памяти. Биты защиты обычно помещались в отдельном аппаратном массиве памяти, где пользователь не мог до них добраться. При каждом обращении к памяти этот массив проверялся, чтобы определить, имеет ли пользователь право на доступ к данному блоку памяти. Обычно такая защита устанавливалась на физический блок памяти размером в одну страницу.
Первоначально использовать в аппаратуре System/38 такой тип защиты памяти не планировалось: никто не думал, что он понадобится, ведь защита проектируемой системы выполнялась на уровне объектов. Однако, когда стало понятно, что некая форма аппаратной защиты все же нужна, мы рассмотрели возможность защиты блока размером в одну страницу. Но, вопервых, это было дорого, а, кроме того, такой подход не вполне соответствовал планам разработчиков. В идеале, нам виделась защита для каждых 16 байтов памяти, так как указатель занимает именно столько. Но чтобы сделать систему производительной, хотелось иметь возможность размещать указатели где угодно, но тогда отдельный аппаратный массив разрядов защиты для каждых 16 байтов памяти становился неприемлем по стоимости. Наконец, нашлось решение: использовать для защиты памяти дополнительные разряды, предназначенные для кода коррекции ошибок ECC (error correcting code).
Иногда, в памяти компьютера возникают ошибки изза перепадов напряжения в электросети или по другим причинам. Для защиты от ошибок в большинстве памятей используются коды обнаружения ошибок и коды исправления ошибок. Действуют они так: к каждому слову памяти добавляются дополнительные разряды. Слово памяти содержит столько разрядов, сколько может быть считано за одну операцию. При считывании данных из памяти эти дополнительные разряды проверяются, что бы определить, не произошла ли ошибка.
Простейшая форма обнаружения ошибок — добавление к слову памяти одного разряда четности. Его значение выбирается так, чтобы число разрядов 1 в слове памяти, включая разряд четности, всегда было четным. Если в памяти происходит ошибка, вызывающая изменение значения любого из битов с 1 на 0 или наоборот, то она будет обнаружена, когда при следующем считывании слова окажется, что число разрядов 1 нечетно. Четность позволяет определить одиночную ошибку, но не говорит, в каком разряде она произошла. С помощью такого механизма, обычно применяемого на ПК, можно определить нечетное число ошибок в слове памяти. Но если число ошибок четное, он не поможет.
Большинство компьютеров, используемых для коммерческих задач, в частности AS/400, как для обнаружения, так и для исправления ошибок применяют дополнительные разряды кодов коррекции. Эти дополнительные разряды могут определять все однократные и многократные ошибки, и даже указать, в каком именно разряде они произошли. Таким образом, аппаратура может исправить ошибку и продолжить работу. Значение коррекции ошибок очевидно для каждого, кому приходилось видеть на экране ПК сообщение "memory parity error". С таким сломанным ПК ничего нельзя сделать до тех пор, пока неисправный модуль памяти не заменен. По этой причине многие старшие модели современных ПК используют памяти ECC.
Оригинальная аппаратура System/38 имела 32разрядное (4байтовое) слово памяти. ECC требовал дополнительных 7 разрядов, то есть для каждого слова памяти было нужно 39 разрядов. Технология тогда позволяла увеличивать размер слова только приращениями по 8 разрядов, то есть, фактически, слово памяти имело размер 40 разрядов. Для каждого 4-байтового слова памяти предусматривался дополнительный разряд, который и должен был осуществлять функции защиты памяти. Мы назвали его разрядом тега.
Указатель занимает 16 байтов памяти. Мы решили всегда помещать указатели на 16-байтовые границы (все четыре младшие разряда адреса памяти равны 0). Такую конфигурацию обычно обозначают термином четверное слово (quadword), или, иначе говоря, 16-байтовое поле, выровненное на 16-байтовую границу. Есть и двойные слова, а кроме того, слова, выровненные на 8-ми и 4-байтовые границы. Обычно, под термином слово понимается 4 байта.
Указатель в оригинальной System/38 занимал четыре последовательных 4-байтовых слова памяти, каждое со своим разрядом тега. Мы решили, что для каждого слова памяти этот разряд будет равен 1, если слово содержит любую из четырех частей указателя; и 0 — если не содержит. Для самого указателя нужен только один разряд, так что если все четыре разряда в четырех последовательных словах памяти установлены в 1, то значение логического тега указателя равно 1. Если любой из четырех разрядов был равен 0, то и логический тег указателя равнялся 0.
Последующие версии AS/400 имеют 64-разрядное (8-байтовое) слово памяти. Такое слово требует 8 разрядов ЕСС; так что с учетом разряда тега, слова памяти AS/400 упакованы по 73 разряда. Мы попрежнему размещаем указатели на 16-байтовых границах, и у каждого указателя есть один логический разряд тега. Если в AS/400 с 64-разрядным словом, два разряда тега в двух последовательных словах, содержащих указатель, оба равны 1, то и логический тег указателя равен 1. Если же любой из разрядов равен нулю, то и указатель имеет логический тег 0. Чтобы оставаться в рамках принятой терминологии, мы называем 64-разрядное слово памяти двойным словом.
Всякий раз, когда в AS/400 происходит запись в память, аппаратура управления памятью строит ЕСС и сохраняет его вместе со словом памяти. В процессе операции записи эта аппаратура также отключает разряд тега в слове памяти (устанавливает его в 0). Так что в результате выполнения любой стандартной команды записи в память, разряды тега записанных слов всегда будут сброшены в 0.
Режим активных тегов
В "Технология PowerPC" мы говорили о расширениях архитектуры PowerPC. Одно из таких расширений — режим активных тегов. Когда процессор PowerPC работает в данном режиме, доступны дополнительные команды, которых нет в режиме неактивных тегов. Всего для AS/400 было добавлено 25 команд, доступных только в режиме активных тегов. Сюда входят команды множественной загрузки и сохранения четверных слов в регистрах, а также команды, обратные им. Есть также команды десятичной арифметики, системные функции вызова/возврата и команды выделения для проверки значений разрядов в управляющих регистрах. Шесть новых команд поддерживают теги.
Некоторые из этих специальных теговых команд используются для установки или проверки значений разрядов тега. Одна из них, команда "Сохранить четверное слово" ("stq"), сохраняет в памяти 16 байтов данных из двух 64разрядных регистров и включает два разряда тега. Другая —"Загрузить четверное слово" ("lq"), загружает 16 байтов памяти в два 64разрядных регистра и устанавливает разряд в регистре управления в 1, если оба теговых разряда в считанных словах равны 1 (в противном случае этот разряд устанавливается в 0). Еще одна команда позволяет считывать теги из памяти в специальный регистр процессора. Использование этой команды будет рассмотрено в следующем разделе.
Теговые команды используются только в SLIC; они не генерируются транслятором для программ MI. Это означает, что любое сохранение в памяти, сгенерированное для программы MI, всегда использует стандартные команды и отключает разряды тега. Когда в процессе разрешения создается указатель, SLIC строит его в двух 64-разрядных регистрах и использует команду "stq" для включения теговых регистров в памяти. При всякой попытке использовать указатель программой MI, SLIC загружает его содержимое командой "lq" в регистры и затем проверяет, установлены ли разряды тега. Если разряды тега сброшены, значит, ктото изменил указатель, и он теперь неверен.
Разряды тега AS/400 не предотвращают изменения указателей, а лишь определяют, производились ли эти изменения. Такой подход отличается от большинства схем защиты памяти. Обычно, защита памяти не допускает изменений, и такая защита на уровне страниц в AS/400 имеется. Однако указатели распознают лишь уже произошедшие модификации, что по сравнению с ранними версиями системы сокращает объем аппаратуры, но попрежнему обеспечивает нужный уровень защиты.
Указатели нельзя подделать. Теги гарантируют, что указатель создан ОС (SLIC), и что он не изменялся чем-либо, кроме SLIC. Недобросовестный пользователь, попытавшись создать, скопировать или изменить указатель, не сможет включить разряды тега и получит в результате бесполезные 16 байт. Именно поэтому AS/400 всегда работает в режиме активных тегов, несмотря на то, что процессоры PowerPC, используемые в ней, могут действовать и в режиме неактивных тегов.
Указатели и теги на диске
Разработчики System/38 столкнулись с и другой проблемой. Допустим, потребуется переместить страницу из памяти на диск. В памяти есть дополнительные разряды для ЕСС и тегов, а на диске нет. Там используется другая форма кода коррекции ошибок, называемая циклическим избыточным контролем CRC (cyclic redundancy check), который не добавляет дополнительных разрядов к каждому слову памяти. Значит, нужен способ сохранения разрядов тега вместе с указателями при перемещении страницы, содержащей указатели, на диск. Короче говоря, нужно найти дополнительное место на диске.
Магнитный диск представляет собой набор плоскостей, имеющих по две поверхности для записи. Поверхность каждого диска разделена на концентрические окружности, называемые дорожками. В свою очередь, дорожки разделены на сектора, которые и содержат информацию. Размер сектора для System/38 и AS/400 равен 520 байтам. Каждый сектор содержит 8-байтовый заголовок сектора и область данных в 512 байт. Размер сектора был выбран так, чтобы 512-байтовая страница System/38 умещалась в него.
В System/38 было определено несколько специальных команд IMPI для работы с тегами. Одна из таких команд— "Извлечь теги" — использовалась для сбора тегов со страницы памяти. При записи страницы на диск, теги также записывались на диск. Другая команда IMPI — "Вставить теги"— применялась для помещения тегов обратно в память после считывания страницы с диска.
Многие ISV и пользователи, знавшие о разрядах тега System/38, считали, что они хранятся на диске в 8байтовых заголовках секторов. Но это не так. Информация на самой странице сохранялась в 512байтной области данных сектора. Заголовок сектора содержал информацию о странице, но наиболее важной его задачей было хранение виртуального адреса страницы. Этот адрес нужен был для восстановления. Даже в случае потери таблицы в памяти, связывавшей виртуальные адреса с местами на диске, она могла быть восстановлена: достаточно считать заголовки каждого сектора и определить, с каким виртуальным адресом этот сектор связан. Так что большая часть пространства в заголовке сектора была занята виртуальным адресом страницы, места для тегов не оставалось.
Это подтверждает простой расчет. Одна страница может содержать 32 указателя (16 байтов ґ32 = 512), что означает 32 бита тегов на страницу. Виртуальный адрес в System/38 занимал 48 разрядов, но для идентификации страницы использовались не все из них. Младшие 9 разрядов виртуального адреса задавали байт на 512-байтной странице (29=512). Следовательно, для уникальной идентификации страницы нужно хранить только 39 старших разрядов виртуального адреса (48–9=39). Однако даже без разрядов состояния потребовался бы минимум 71 разряд для хранения виртуального адреса страницы и всех битов тега (39+32=71), в заголовке же сектора было только 64 разряда. Хранить биты тега в заголовках секторов оказалось невозможно.
Разработчики System/38, проявив недюжинную смекалку, нашли для тегов место внутри страницы. Дело в том, что некоторое пространство в указателе не используется. Если на странице есть хотя бы один указатель, то есть и некоторое неиспользуемое пространство, в котором можно хранить биты тега. Если указателей на странице нет, то все биты тега для нее равны 0, поэтому и хранить их незачем. Заголовок сектора в System/38 содержал информацию о том, есть ли на странице теги, и если есть, то где именно.
До появления RISC-процессоров мы продолжали использовать на AS/400 и размер страницы, равный 512 байтам, и только что описанный метод хранения битов тега. Но уже несколько лет нас мучило желание увеличить размер страницы.
Размер страницы в 512 байт был выбран для System/38 по причине ограниченности размеров основной памяти5Перед объявлением System/38 в Рочестер приехал "эксперт" из IBM, который заявил, что планируемые нами размеры памяти слишком велики. Несмотря на протесты тех из нас, кто хорошо разбирался в теме дискуссии, размер памяти пришлось сократить. В результате оригинальная Model 5 работала плохо, так как была ограничена 2 мегабайтами памяти. А ведь при увеличении размера памяти производительность росла. Когда тот же самый "эксперт" вернулся, чтобы помочь нам с AS/400, мы вышвырнули его вон.. Но для увеличенной памяти AS/400 512-байтовая страница была слишком мала, страниц получалось слишком много, и таблицы страниц достигали гигантских размеров. Кроме того, уже многие годы мы "упаковывали" маленькие страницы в "логические" страницы большего размера для сокращения объема дисковых операций. Для новых процессоров было решено увеличить размер страницы до 4 КБ (4 096 байтов).
В новых моделях был сохранен размер сектора на диске в 520 байт. Четырехкилобайтовая страница теперь хранится в восьми последовательных секторах. При наличии восьми 8-байтовых заголовков на каждой странице в 4 КБ больше чем достаточно места для хранения 256 теговых битов.
Для извлечения тегов из памяти к архитектуре процессора PowerPC был добавлен специальный регистр тегов. Когда процессор выполняет специальную теговую команду, "Множественная загрузка двойных слов" ("lmd"), в 16 регистров может быть считано из памяти до 16 двойных слов (восемь четверных слов). При выполнении команды в регистре тега сохраняется восемь теговых регистров четверных слов памяти. Обратите внимание, что в регистре тега сохраняются 8 логических битов тега, а не 16 физических, как в памяти. Вспомним, что четверное слово это два 64-разрядных (8-байтовых) слова памяти; следовательно, в четверном слове два физических бита тега, так что в восьми четверных словах — 16 физических битов тега. С помощью команды "lmd" биты тегов страницы могут быть собраны для последующей записи на диске вместе с данными. Эта команда также доступна только в режиме активных тегов.