.
Для системных интеграторов и производителей устройств важно взаимодействие с драйверами устройств и системным ПО. Это особенно важно, если нужно реализовать поддержку какого-либо дополнительного устройства или осуществить портирование без потери производительности.
В следующих главах мы рассмотрим решения для отладки на основе стандарта IEEE 1149.1 (JTAG). Мы обратим внимание на архитектурные различия между ARM* и Intel®, способные повлиять на отладку на уровне системы.
1.1Отладка JTAG
Для отладки системного ПО уровня ОС и драйверов устройств наиболее распространенным методом является использование интерфейса JTAG. Стандарт JTAG IEEE 1149.1 определяет стандартный тестовый порт доступа и архитектуру граничного сканирования для портов тестового доступа, применяемых для тестирования печатных плат. Этот стандарт часто называют просто интерфейсом отладки JTAG. Из стандарта тестирования печатных плат он превратился в ставший стандартом де-факто интерфейс для отладки платформ независимо от ОС и на уровне ОС.
Дополнительные сведения о JTAG и его использовании в отладке современного ПО см. в статье Рэнди Джонсона и Стюарта Кристи "JTAG 101; IEEE 1149.x and Software Debug".
С точки зрения производителей устройств, разработчиков приложений и драйверов, понимание взаимодействия между драйверами и программными компонентами в различных подсистемах микросхем и устройств важно для определения стабильности платформы. С точки зрения проверки микросхем низкоуровневый комплект ПО обеспечивает тестовую среду, позволяющую сымитировать факторы нагрузки, которым платформа будет подвергаться при ее реальном использовании. Для работы с современными системами требуется понимать, как работают все их компоненты вместе в реальной обстановке; положительных результатов тестирования отдельных компонентов недостаточно. Именно на этом уровне и используется отладка на базе JTAG. Благодаря связи JTAG с аппаратным уровнем можно экспортировать сведения о состоянии в ОС Android на целевом устройстве.
Для отладки драйверов устройств особенно важно знать и точное состояние периферийного устройства в наборе микросхем, и взаимодействие драйвера устройства с уровнем ОС и остальным ПО.
Если рассматривать Android с точки зрения отладки системы, если изучить драйверы устройств и ядро ОС, то видно, что это просто специализированная разновидность Linux. С ней можно работать как с любой разновидностью Linux с ядром версии 2.6.3x или более поздней.
Процессор Intel® Atom™ Z2460 поддерживает граничное сканирование IEEE-1149.1 и IEEE-1149.7 (JTAG), интерфейс параллельной трассировки MPI PTI, а также трассировку инструкций на базе Branch Trace Storage (BTS), Last Branch Record (LBR) и Architectural Event Trace (AET) с помощью порта Intel XDP, совместимого с JTAG.
Различные поставщики JTAG предлагают решения для отладки систем с поддержкой Android, в том числе следующие:
• Wind River (http://www.windriver.com/products/JTAG-debugging/)
• Lauterbach (http://www.lauterbach.com)
• Intel (http://software.intel.com - могут действовать ограничения доступа)
1.2. Отладка ОС Android
Отладка платформ Android осложняется тем, что обычно система Android стремится перейти в состояние простоя и сна для оптимизации расхода электроэнергии. Таким образом, отладка режима пониженного потребления электроэнергии становится непростой задачей.
• Можно поддерживать функциональность JTAG в некоторых состояниях пониженного потребления электроэнергии.
• Там, где это невозможно, следует запускать JTAG сразу же после включения питания набора микросхем, отвечающего за работу JTAG.
Многие проблемы уровня ОС на платформах такого типа обычно связаны и изменениями режима электропитания и последовательностями засыпания и пробуждения устройств.
Системный отладчик на основе агента отладки или интерфейса JTAG очень полезен для решения ряда важных задач разработки ОС.
С помощью отладчика можно проверить процесс загрузки, выявлять и исправлять неполадки стабильности, такие как ошибки времени выполнения, сбои сегментации или неверный запуск служб при загрузке.
Также отладчик дает возможность выявлять и устранять ошибки конфигурации ОС благодаря доступу к таблицам страниц, таблицам дескрипторов и дереву инструкций. Трассировка инструкций в сочетании с доступом к таблице памяти может быть полезно для выявления причин переполнения стека, утечки памяти и даже случаев повреждения данных.
На рис. 1 показано преобразование таблицы страниц из физических в виртуальные адреса памяти. Для платформы x86 характерна высокая гибкость в определении глубины таблиц преобразования и точность адресации блоков памяти. Такое удобство доступа и представления памяти играет важную роль для разработки системы на уровне ОС.
Рис. 1. Преобразование логического адреса в линейный
Для преобразования логического адреса в линейный адрес процессор выполняет следующие действия:
- С помощью смещения в селекторе сегмента находит дескриптор сегмента в таблице GDT или LDT и считывает его в процессор. (Этот шаг требуется только в случае загрузки нового селектора сегмента в сегментный регистр.)
- Проверяет дескриптор сегмента, чтобы выяснить наличие прав доступа и диапазон сегмента и убедиться, что сегмент доступен и смещение находится в пределах сегмента.
- Добавляет базовый адрес сегмента из дескриптора сегмента к смещению для получения линейного адреса.
- Если страничное преобразование не используется, процессор непосредственно сопоставляет линейный адрес физическому (то есть линейный адрес выводится на шину адреса процессора). Если линейное адресное пространство разбито на страницы, в процесс преобразования линейного адреса в физический добавляется второй уровень.
В защищенном режиме архитектура Intel позволяет либо непосредственно сопоставить линейное адресное пространство большому объему физической памяти (например, в 4 ГБ ОЗУ), либо косвенно (с помощью страничной адресации) сопоставить его меньшему объему физической памяти и дискового пространства. Последний метод сопоставления линейного адресного пространства часто называют виртуальной памятью или виртуальной памятью со страничным преобразованием адресов по требованию.
При использовании страничного преобразования процессор делит линейное адресное пространство на страницы фиксированного размера (обычно 4 Кб), которые сопоставляются физической памяти и/или дисковому пространству. Когда программа (или задача) ссылается на логический адрес в памяти, процессор преобразует этот адрес в линейный адрес, а затем с помощью механизма страничной адресации преобразует линейный адрес в соответствующий физический адрес. Если страница, содержащая линейный адрес, не загружена в настоящий момент в физическую память, процессор генерирует исключение по отсутствию страницы (#PF). В этом случае обработчик исключений обычно дает указание операционной системе или исполняемой программе загрузить эту страницу из дискового хранилища в физическую память (в процессе операции другая страница может быть записана из физической памяти на диск). После загрузки страницы в физическую память значение, возвращенное обработчиком исключений, инициирует повторный запуск инструкции, в результате которой было сгенерировано исключение. При сопоставлении линейных адресов физическому адресному пространству и при генерации исключений по отсутствию страницы (если это необходимо) процессор использует информацию из каталогов страниц и таблиц страниц, сохраненных в памяти.
Страничное преобразование отличается от сегментации тем, что страницы имеют одинаковый размер. Размер сегментов обычно совпадает с размером содержащихся в них фрагментов кода или структур данных, тогда как размер страниц фиксирован. Если для преобразования адресов используется только сегментация, структура данных, загруженная в память, будет находиться в памяти целиком. Если используется страничное преобразование, структура данных может быть частично загружена в память, а частично оставаться на диске.
Чтобы уменьшить число тактов шинного обмена, необходимых для преобразования адреса, последние использованные записи каталога страниц и таблицы страниц загружаются в кэш-память процессора в компоненты, называемые буферами быстрого преобразования адресов (TLB). Буферы TLB обеспечивают выполнение большинства запросов чтения в текущем каталоге страниц и таблицах страниц без расходования тактов шинного обмена. Дополнительные такты шинного обмена требуются только тогда, когда в буферах TLB не содержится запись таблицы страниц; обычно это происходит в том случае, если страница не использовалась долгое время.
Таковы два основных различия в разработке и настройке пакета программ ОС Android в архитектуре Intel и в других архитектурах. Модель адресации селектора с базой и смещением в сочетании с локальной и глобальной таблицами дескрипторов (LDT и GDT) обеспечивает глубокое многоуровневое преобразование адресов физической памяти в виртуальную память с изменяемой точностью адресации блоков памяти. Это очень удобно для нестандартной конфигурации памяти в сегментированной среде с защищенными изолированными областями памяти. Но при неправильном использовании в этом случае замедляется доступ к памяти. Таким образом, важно иметь хорошее представление преобразования страниц памяти.
Еще одно различие между архитектурами заключается в обработке системных прерываний. Например, в ARM существует готовый набор аппаратных прерываний в зарезервированном адресном пространстве с 0x0 по 0x20. Эти расположения содержат инструкции переходов к обработчику прерываний. В архитектуре Intel используется выделенный контроллер аппаратных прерываний. Аппаратные прерывания недоступны напрямую в адресном пространстве памяти процессора, но обрабатываются путем доступа к контроллеру прерываний Intel 8529. Преимущество такого подхода состоит в том, что обработчик прерываний поддерживает прямую обработку прерываний ввода-вывода для подключенных устройств. В архитектурах без выделенного контроллера прерываний для решения этой задачи обычно применяется перегрузка прерывания IRQ более сложным обработчиком.
2.1.Отладка драйверов устройств
Отладчик JTAG уровня ОС должен обеспечивать наглядное представление потоков ядра и активных модулей ядра, а также других данных, экспортированных ядром. Для отладки динамически загружаемых служб и драйверов можно использовать исправление ядра или модуль ядра, экспортирующий расположение метода инициализации драйвера и метода деструкции в памяти.
Для отладки конфигурации системы и драйверов устройств важно иметь возможность прямого доступа и проверки содержимого регистров конфигурации устройств. Эти регистры и их содержимое можно просто отобразить в виде списка шестнадцатеричных значений, либо можно представить их в виде битовых полей, как показано на рис. 2. Побитовое наглядное представление позволяет лучше понять процесс изменения состояния устройства в ходе отладки, когда соответствующий драйвер устройства взаимодействует с ним.
Рис. 2. Регистры устройства в окне битовых полей
Анализ кода после распаковки сжатого ядра Android zImage в память осуществляется путем высвобождения управления выполнением в отладчике до достижения start_kernel. При этом предполагается, что был загружен файл vmlinux, содержащий символьную информацию ядра. На этом этапе можно использовать программные точки останова. До этого момента в процессе загрузки следует использовать только аппаратные точки останова на базе регистров (чтобы избежать ситуации, когда отладчик попытается записать инструкции точек останова в память, которая еще не инициализирована). Затем ОС успешно загружается после достижения цикла бездействия mwait_idle.
Кроме того, если решение для отладки предоставляет доступ к трассировке инструкций на базе Last Branch Storage (LBR), эта возможность в сочетании со всеми обычными функциями управления выполнением в отладчике JTAG позволяет принудительно останавливать выполнение при исключениях и анализировать поток событий исключения в обратной последовательности, что позволяет определять причину неполадок при выполнении.
Записи Last Branch Record можно использовать для трассировки выполнения кода начиная с нужной точки сброса. Поскольку данные о прерывании выполнения кода сохраняются в этих записях MSR, отладчики могут реконструировать выполненный код, считав адреса To и From, получив доступ к памяти между этими двумя адресами и выполнив дизассемблирование кода. Дизассемблированный код обычно отображается в графическом пользовательском интерфейсе трассировки в интерфейсе отладчика. Это может помочь выяснить, какой код выполнялся перед прерыванием SMI (System Management Interrupt) или другим исключением, если в месте прерывания настроена точка останова.
2.2.Аппаратные точки останова
Как и в ARM, процессоры Intel поддерживают инструкции программных точек останова, а также аппаратные точки останова для данных и кода. В архитектуре ARM обычно имеется набор выделенных регистров для точек останова и точек наблюдения. В стандартной реализации поддерживается по 2 регистра каждого из этих типов. Когда эти регистры содержат значения, процессор проверяет данные доступа, чтобы задать адрес в памяти для регистра счетчика программы или доступ к памяти на чтение или запись. При осуществлении доступа выполнение останавливается. Такое поведение отличается от программных точек останова: их выполнение останавливается при получении инструкции точки останова. Поскольку инструкция точки останова заменяет инструкцию сборки, которая должна находиться в заданном адресе памяти, выполнение останавливается до момента, в котором была бы выполнена инструкция.
Реализация аппаратных точек останова в архитектурах Intel и ARM очень похожа, но у Intel чуть выше гибкость.
На всех ядрах процессоров Intel Atom имеется 4 регистра DR, где хранятся адреса, сравниваемые с полученными адресами шины памяти до (иногда после) выборки памяти.
Можно использовать все четыре этих регистра, чтобы предоставлять адреса, переключающие любое из следующих событий управления отладкой:
- 00 — прерывание при выполнении инструкции
- 01 — прерывание только при записи данных
- 10 — не задано ЛИБО (если архитектура допускает) прерывание при чтении или записи ввода-вывода
- 11 — прерывание при чтении или записи данных, но не при выборке инструкций
Таким образом, все 4 аппаратные точки останова могут служить как точками останова, так и точками наблюдения. Точки наблюдения могут работать в режиме только записи либо чтения и записи (или ввода-вывода).
2.3. Отладка для разных платформ: Intel® Atom™ и ARM
Многие разработчики, работающие с Intel Atom, могут обладать опытом разработки главным образом для RISC-процессоров с фиксированной длиной инструкций. Такая архитектура используется в процессорах MIPS и ARM. Модель перекрестной отладки для архитектур Intel Atom и ARM не имеет существенных отличий. Многие принципиальные методы и проблемы отладки совпадают.
Впрочем, разработка на ПК с архитектурой Intel для устройств с Intel Atom имеет два существенных преимущества, особенно если встроенная операционная система является производной от одной из массовых стандартных ОС, таких как Linux или Windows. Первое преимущество заключается в наличии огромного количества средств тестирования, анализа потребляемого электропитания и отладки для разработчиков, работающих с архитектурой Intel. Второе преимущество заключается в возможности локальной отладки функциональной правильности и многопоточности приложений. Это преимущество будет описано ниже.
Между процессорами Intel Atom и ARM существует ряд различий, о которых должны знать разработчики. Эти различия описываются в следующих главах.
2.4.Инструкции различной длины
В наборах инструкций IA-32 и Intel 64 используются инструкции разной длины. На отладчик это влияет следующим образом: отладчик не может просто исследовать код с фиксированными 32-разрядными интервалами. Необходимо интерпретировать и дизассемблировать машинные инструкции приложения на основе контекста этих инструкций. Расположение следующей инструкции зависит от расположения, размера и правильного декодирования предыдущей инструкции. В архитектуре АРМ, напротив, отладчику достаточно следить за последовательностью кода, переключающую из режима ARM в режим Thumb или в расширенный режим Thumb и обратно. В пределах одного режима все инструкции и адреса памяти имеют размер либо 32, либо 16 разрядов. Разработчики микропрограмм и драйверов устройств, которым требуется точно адресовать вызовы к определенным регистрам устройства и использовать окно памяти отладчика, должны понимать возможное влияние инструкций различной длины.
2.5. Аппаратные прерывания
Еще одна разница в архитектуре может оказаться важной при отладке системного кода, отвечающего за обработку аппаратных прерываний. В архитектуре ARM векторы исключений:
- 0 — сброс
- 1 — отмена
- 2 — отмена данных
- 3 — отмена упреждающей выборки
- 4 — неопределенная инструкция
- 5 — прерывание (IRQ)
- 6 — быстрое прерывание (FIRQ)
назначаются адресам с 0x0 по 0x20. Эта область памяти защищена, в ней невозможно перераспределение. Обычно все векторные расположения с 0x0 по 0x20 содержат переходы к адресу памяти, где находится настоящий код обработчика исключений. Применительно к вектору сброса это означает, что 0x0 является переходом к расположению кода загрузки микропрограммы или платформы. Из-за такого подхода реализация аппаратных прерываний и обработчиков сигналов ОС в архитектуре ARM является менее гибкой, но с более высоким уровнем стандартизации. «Поймать» прерывание отладчиком очень просто: достаточно установить аппаратную точку останова в расположении вектора в диапазоне адресов с 0x0 по 0x20.
В архитектуре Intel используется выделенный контроллер аппаратных прерываний. Прерывания
- 0 — системный таймер
- 1 — клавиатура
- 2 — каскадный второй контроллер прерывания
- 3 — последовательный интерфейс COM2
- 4 — последовательный интерфейс COM1
- 5 — параллельный интерфейс LPT
- 6 — контроллер дисковода для гибких дисков
- 7 — доступное прерывание
- 8 — часы CMOS реального времени
- 9 — звуковой адаптер
- 10 — сетевой адаптер
- 11 — доступное прерывание
- 12 — доступное прерывание
- 13 — числовой процессор
- 14 — интерфейс жесткого диска IDE
- 15 — интерфейс жесткого диска IDE
— недоступны напрямую в адресном пространстве памяти процессора, но обрабатываются путем доступа к контроллеру прерываний Intel 8259. В списке прерываний видно, что контроллер поддерживает прямую обработку аппаратных прерываний ввода-вывода подключенных устройств, которые обрабатываются посредством прерываний IRQ или быстрых прерываний на платформе ARM. Эта возможность упрощает реализацию правильной обработки прерываний в архитектуре Intel на уровне ОС, особенно для ввода-вывода устройств. Сопоставление программных исключений, таких как отмены или сбои сегментации, также обрабатываются более гибко в архитектуре Intel; оно осуществляется портом контроллера прерываний, адресация к которому осуществляется через таблицу дескрипторов прерываний (IDT). Сопоставление IDT аппаратным прерываниям определяется системными программами. Кроме того, невозможно с легкостью получать такие исключения при отладке, не учитывающей системные программы. В архитектуре Intel для отладки программных событий, переключающих аппаратные прерывания, требуется определенное знание уровня ОС. Необходимо знать, каким образом сигналы ОС этих исключений соотносятся с контроллером прерываний. Даже в отладчике системного уровня сопоставленная в памяти таблица сигналов из ОС будет перехватывать исключения на уровне ОС, а не на аппаратном уровне.
2.6.Одношаговые инструкции
В архитектуре ARM нет явных одношаговых инструкций. В архитектуре Intel одношаговые переходы уровня сборки часто реализуются в отладчике напрямую с помощью таких инструкций. В ARM однократный переход инструкции реализуется в виде команды «Выполнять до прерывания». Отладчик должен проверить код, чтобы убедиться в том, что учитываются все пути кода (особенно при отступлении от инструкции ветви). С точки зрения реализации отладчика, при этом возникают некоторые издержки, но их объем незначителен, поскольку реализация «Выполнять до прерывания» все равно будет требоваться для переходов в высокоуровневом языке. Разработчики ПО должны учитывать это различие, поскольку оно может вызвать слегка иное поведение переходов.
2.7.Сопоставление виртуальной памяти
Реализация таблицы дескрипторов и преобразования страниц для сопоставления виртуальной памяти очень похожи, по крайней мере по принципу работы. В архитектуре Intel глобальная и локальная таблицы дескрипторов (GDT и LDT) позволяют управлять уровнем вложенности страниц памяти в виртуальном адресном пространстве. На рис. 3 представлено преобразование линейного адреса в физический в архитектуре Intel.
Рис. 3. Преобразование страниц в архитектуре Intel®
В архитектуре ARM таблицы страниц первого и второго уровней определяют более прямой поиск страниц виртуальной памяти глубиной не более одного или двух уровней. На рис. 4 показано преобразование линейного адреса в физический адрес.
Рис. 4. Преобразование страниц в архитектуре ARM
В архитектуре Intel поддерживаются различные уровни таблиц дескрипторов, таблиц страниц, доступ к 32-разрядному адресному пространству в реальном режиме и 64-разрядная адресация в защищенном режиме, зависимая от модели селектора «база : смещение». В различных режимах ARM модель «база : смещение» не используется. В архитектуре Intel можно явным образом задать более глубокий поиск таблиц страниц. В ARM заданный набор — две таблицы. В архитектуре Intel таблицы дескрипторов могут маскировать вложенные таблицы, поэтому фактическая глубина таблицы страницы может вдвое или втрое превышать глубину в архитектуре ARM.
Механизм преобразования страниц Intel обеспечивает более высокую гибкость в работе с памятью системы и механизмов, используемых уровнем ОС для выделения определенных блоков памяти, таких как защищенных блоков для выполнения приложений. Но при этом разработчикам становится сложнее получить полную картину виртуализации памяти и устранить утечки памяти и нарушения доступа к памяти (сбои сегментации). Такая проблема была бы менее важна для полнофункциональных ОС с большим объемом памяти. Операционные системы реального времени, более зависимые от правильной работы с памятью, более уязвимы для таких неполадок.
3 Технология гиперпоточности Intel®
С точки зрения отладки, нет разницы между физическим ядром процессора и логическим ядром, реализованным при помощи технологии гиперпоточности Intel. Включение гиперпоточности происходит в процессе инициализации платформы в BIOS. Поэтому с точки зрения приложения нет сколько-нибудь заметной разницы между физическими и логическими ядрами. Эта технология обеспечивает одновременное выполнение нескольких потоков, поэтому отладка работает в точности так же, как на системах с несколькими физическими ядрами.
4 Компоненты микросхемы ЦП и взаимодействие между ядрамиMulti-Core
Из-за взаимодействия десятков программных и аппаратных компонентов внутри одной микросхемы существенно усложняется поиск причин неполадок при отладке. Взаимодействие между различными программными компонентами часто зависит от времени. При отладке кода со взаимодействием между компонентами обычно невозможно просто пошагово выполнять один определенный компонент. Традиционная отладка с помощью printf также неэффективна в данном случае, поскольку изменения при отладке могут отрицательно повлиять на временные параметры и привести к еще более серьезным проблемам, действуя наподобие физического принципа неопределенности Гейзенберга (согласно этому принципу, в частности, любые попытки измерения скорости и положения частицы сами по себе вносят возмущения в движение частицы и непредсказуемо меняют ее скорость, т. е. наблюдение характеристик меняет эти характеристики).
4.1.Отладка трассировки событий
Существует множество программных средств статического анализа и основанных на них технологий трассировки событий, которые помогают решить эту задачу. Они имеют общий принцип работы, состоящий в использовании буферной памяти DRAM небольшого размера — в эту память загружаются данные события во время их создания, а затем используется какой-либо механизм протоколирования, записывающий результат трассировки в файл журнала. Мониторинг трассировки данных может выполняться в режиме реального времени при непосредственном взаимодействии с API протоколирования данных трассировки или в автономном режиме с использованием различных средств просмотра трассировки для анализа сложных взаимосвязей между программными компонентами. Наиболее распространены три таких программных средства — LTTng*, Ftrace* и SVEN*.
Далее приведена таблица сравнения этих трех средств, предназначенных в основном для операционных систем типа Linux* и поэтому совместимых с Android*.
Рис. 5. Различные решения для трассировки событий
Дополнительные сведения см. на соответствующих веб-сайтах:
- LTTng* Project: https://lttng.org/
- Ftrace*: http://elinux.org/Ftrace