Записки разработчика Intel System Studio: отладка Linux-ядра Android с помощью Intel JTAG Debugger и MinnowBoard MAX

от автора

Инструменты отладки нужны каждому разработчику. Однако, не существует универсальных решений, подходящих и тем, кто создаёт приложения пользовательского уровня, и тем, кто пишет низкоуровневые программы, вроде драйверов оборудования. Чем ближе к «железу» — тем больше хардкора в отладке и тестировании.

Из этого материала вы узнаете о том, как отлаживать код и анализировать исключения на уровне ядра Linux ОС Android в системах, основанных на архитектуре Intel. А именно, мы рассмотрим отладочный инструмент JTAG Debugger, который является частью пакета Intel System Studio Ultimate Edition. Мы расскажем о стандарте JTAG, о вышеупомянутом JTAG-отладчике Intel, об обработке исключений. В качестве примера мы будем использовать мини-компьютер MinnowBoard MAX с Intel Atom на борту.

Обзор JTAG

JTAG (произносится как «джей-таг», «jay-tag») – это сокращение от Joint Test Action Group. Обычно, когда говорят «JTAG», подразумевают стандарт IEEE 1149.1-1990 (IEEE Standard Test Access Port and Boundary-Scan Architecture). Этот стандарт устанавливает правила отладки и тестирования однокристальных систем (SoC, System on Chip) и программного обеспечения микропроцессоров (Microprocessor Software).

При JTAG-отладке используется набор инструментов, состоящий из трёх частей: программный JTAG-отладчик, установленный на главном компьютере, аппаратный JTAG-адаптер (датчик) и внутрисхемный отладчик (OCD, On Chip Debug), которым оснащена тестируемая микросхема.

Программный JTAG-отладчик

JTAG-отладчик – это программный инструмент, установленный на главном компьютере. Он получает данные и сведения об адресах от JTAG-адаптера и отображает их в пользовательском интерфейсе. Разработчик, в свою очередь, может отправлять команды JTAG-адаптеру, который подключен к основному компьютеру по USB или с помощью другого интерфейса.

Пользуясь этим инструментом, можно контролировать выполнение программы и отлаживать её на уровне исходного кода. Подобное реализуется благодаря файлам символов, которые соответствуют двоичным образам, загружаемым на целевые системы. Эти средства дают разработчику следующие возможности: запуск (run) и остановка (stop) исполнения кода, выполнение в ходе отладки шага с обходом (step over) и шага с заходом (step into), указание точек останова (breakpoints), доступ к памяти.

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

Intel JTAG Debugger (известный как XDB), входит в состав Intel System Studio Ultimate Edition. XDB – это тот самый программный инструмент JTAG-отладки, который должен быть установлен на главном компьютере.

Аппаратный JTAG-адаптер

JTAG-адаптер – это устройство, которое преобразует JTAG-сигналы в формат, подходящий для передачи компьютеру. Для сопряжения адаптеров и ПК используются такие интерфейсы, как USB, параллельный порт, RS-232, Ethernet. USB – самый популярный среди них. Именно он применяется для связи многих JTAG-адаптеров с компьютерами. Стандартом предусмотрено минимальное число JTAG-контактов для подключения целевых устройств к JTAG-адаптерам, однако, на практике применяются самые разные интерфейсы. Например, это 10- и 20-контактные разъемы для ARM, 14-контактный для ST, 16-контактный для OCDS.

В связке из отладчика Intel JTAG и MinnowBoard MAX, о которой идёт речь в этом материале, используется 60-контактный разъем для подключения целевого устройства. В качестве JTAG-адаптера для MinnowBoard MAX применяется Intel ITP-XDP3. Отладчик Intel JTAG совместим и с JTAG-адаптерами других производителей. Например – с Macraigor Systems usb2Demon и OpenOCD.

Внутрисхемный отладчик (целевой микрочип)

Главные компоненты внутрисхемного отладчика – это TAP (Test Access Point, тестовый порт) и TDI (Test Data In, вход тестовых данных)/TDP (Test Data Out, выход тестовых данных). Используя TAP можно сбрасывать, читать и записывать состояние регистров, пользоваться инструкцией BYPASS. Основная технология, которая применяется в JTAG – это так называемое граничное сканирование (Boundary Scan) с использованием сигнальных линий TDI/TDO.


Конфигурация из JTAG-адаптера и целевой системы. Здесь же показана плата расширения, которая используется для соединения Intel ITP-XDP3 и MinnowBoard MAX

Обзор исключений в архитектуре Intel

Исключение (exception) – это синхронное событие, которое генерируется, когда процессор, при выполнении инструкций, обнаруживает одно или несколько предопределенных условий. Архитектура IA-32 предусматривает три класса исключений: отказ (fault), ловушка (trap) и авария (abort). Обычно при возникновении отказов и ловушек возможно продолжение прерванной работы, в то время как при авариях – нет. Когда возникает исключение, оно обрабатывается так же, как обрабатываются прерывания. Это означает, что после остановки и сохранения текущего процесса, система переключается на обработчик исключения, а после того, как обработчик завершил работу, возвращается к исполняемой ранее задаче.

Исключения и прерывания защищенного режима

Вектор Сокращённое наименование Описание Тип Код ошибки Источник
0 #DE Ошибка деления Отказ Нет Инструкции DIV и IDIV
1 #DB Зарезервировано Отказ / ловушка Нет Только для использования Intel
2 Прерывание NMI Прерывание Нет Внешнее немаскируемое прерывание
3 #BP Точка останова Ловушка Нет Инструкция INT 3
4 #OF Переполнение Ловушка Нет Инструкция INT0
5 #BR Выход за границы диапазона Отказ Нет Инструкция BOUND
6 #UD Неправильный (неопределенный) код операции Отказ Нет Инструкция UD2 или зарезервированный код операции
7 #NM Устройство недоступно (Нет математического сопроцессора) Отказ Нет Инструкции вычислений с плавающей точкой или инструкции WAIT/FWAIT
8 #DF Двойной отказ Авария Да (ноль) Любая инструкция, которая может сгенерировать исключение, NMI или INTR
9 Выход за пределы сегмента сопроцессора (зарезервировано) Отказ Нет Инструкция, выполняющая вычисления с плавающей точкой
10 #TS Неверный TSS Отказ Да Переключение задач или доступ к TSS
11 #NP Сегмент отсутствует Отказ Да Загрузка сегментных регистров или доступ к системным сегментам
12 #SS Отказ сегмента стека Отказ Да Операции со стеком и загрузка регистра SS
13 #GP Общая ошибка защиты Отказ Да Ошибки, связанные с памятью, проверками защиты
14 #PF Отказ страницы Отказ Да Работа с памятью
15 Зарезервировано Intel, не предназначено для использования Нет
16 #MF Ошибка вычислений с плавающей точкой x87 FPU (Ошибка вычислений) Отказ Нет Вычисления с плавающей точкой на x87 FPU или инструкции WAIT/FWAIT
17 #AC Ошибка проверки выравнивания Отказ Да (ноль) Работа с данными в памяти
18 #MC Аппаратная ошибка Авария Нет Коды ошибок (если они есть) и их источник зависят от аппаратного обеспечения
19 #XM Исключения вычислений с плавающей точкой SIMD Отказ Нет Инструкции вычислений с плавающей точкой SSE, SSE2, SSE3
20 #VE Исключение виртуализации Отказ Нет EPT-нарушения
21 – 31 Зарезервировано Intel, не предназначено для использования
32 – 255 Прерывания, заданные разработчиком (не зарезервированы) Прерывание Внешние прерывания или инструкции INT n.

Подготовка MinnowBoard MAX и Intel ITP-XDP3 к подключению к главному компьютеру по USB

Для начала надо установить на MinnowBoard MAX ОС Android. Для того чтобы это сделать, обратитесь к материалу «Статья разработчика Intel System Studio: настройка, сборка и профилировка Linux-ядра Android с помощью VTune». Он содержит инструкцию по сборке, установке и настройке Android на MinnowBoard MAX.

После установки ОС подключим MinnowBoard MAX к JTAG-адаптеру Intel ITP-XDP3 с помощью платы расширения. JTAG-адаптер присоединим к ПК по USB. На главном компьютере должна быть установлена Intel System Studio Ultimate Edition, в состав которой входит USB-драйвер для Intel ITP-XDP3.


MinnowBoard MAX подключён к JTAG-адаптеру Intel ITP-XDP3, который, в свою очередь, подключён к хост-компьютеру с установленным на нём JTAG-отладчиком от Intel (XDB)

Использование JTAG-отладчика Intel (XDB) для отладки ядра Android на MinnowBoard MAX

Рассмотрим пошаговую процедуру использования XDB в деле отладки Linux-ядра ОС Android.

1. Запустим JTAG-отладчик Intel. Для этого нужно перейти в папку, где он установлен, и запустить пакетный файл (например – start_xdb_legacy_products.bat).

2. Подключимся к целевому устройству. Для этого нужно, в интерфейсе JTAG-отладчика, выполнить команду File > Connect и выбрать, во-первых, аппаратный JTAG- адаптер. В нашем случае это Intel ITP-XPD3. Во-вторых – надо указать целевую платформу. Нас интересует Intel Atom Processor E38xx, Z3680, X37xx – 2 cores (ValleyView).


Выбор аппаратного JTAG-адаптера и целевой платформы в XDB

3. Загрузим файлы символов и укажем директорию файлов исходного кода. Для этого нужно выполнить в JTAG-отладчике Intel команду File > Load / Unload Symbol и указать файлы символов. Для файлов исходного кода нужно выполнить команду Options > Source Directories и указать правила сопоставления файлов исходного кода и файлов символов, а так же соответствующие директории. Правила позволяют настроить соответствие путей в файле символов, которые записываются во время компиляции, и текущих мест расположения файлов исходного кода.

4. Найдём entry-файл, в котором имеется обработчик исключений. Воспользуемся командой меню JTAG-отладчика Intel View > Source files и откроем файл entry_64.S.


Поиск файла entry_64.S

5. Установим точку останова на точке входа исключения. Для этого найдём строку ENTRY(error_entry), которая является точкой входа исключения с кодом ошибки в регистре RAX. Каждый обработчик исключения определён как макрос zeroentry или errorentry. Таким образом, можно установить точку останова в error_entry или в каком-то конкретном обработчике. В данном материале мы используем для тестирования «zeroentry invalid_op do_invalid_op».

ENTRY(error_entry) 	XCPT_FRAME 	CFI_ADJUST_CFA_OFFSET 15*8 	/* oldrax contains error code */ 	cld 	movq_cfi rdi, RDI+8 	movq_cfi rsi, RSI+8 	movq_cfi rdx, RDX+8 	movq_cfi rcx, RCX+8 	movq_cfi rax, RAX+8 	movq_cfi  r8,  R8+8 	movq_cfi  r9,  R9+8 	movq_cfi r10, R10+8 	movq_cfi r11, R11+8 	movq_cfi rbx, RBX+8 	movq_cfi rbp, RBP+8 	movq_cfi r12, R12+8 	movq_cfi r13, R13+8 	movq_cfi r14, R14+8 	movq_cfi r15, R15+8 	xorl %ebx,%ebx 	testl $3,CS+8(%rsp) 	je error_kernelspace error_swapgs: 	SWAPGS error_sti: 	TRACE_IRQS_OFF 	ret <....> zeroentry divide_error do_divide_error zeroentry overflow do_overflow zeroentry bounds do_bounds zeroentry invalid_op do_invalid_op zeroentry device_not_available do_device_not_available paranoiderrorentry double_fault do_double_fault zeroentry coprocessor_segment_overrun do_coprocessor_segment_overrun errorentry invalid_TSS do_invalid_TSS errorentry segment_not_present do_segment_not_present zeroentry spurious_interrupt_bug do_spurious_interrupt_bug zeroentry coprocessor_error do_coprocessor_error errorentry alignment_check do_alignment_check zeroentry simd_coprocessor_error do_simd_coprocessor_error

Теперь, в качестве примера, вызовем исключение, и проверим, сработал ли обработчик, на котором мы установили точку останова. Установим точку останова на «zeroentry invalid_op do_invalid_op» и вызовем блок кода BUG(), который выполняет инструкцию ud2, вызывающую отказ (fault) «Неправильный код операции».

#define BUG()							\ do {								\ 	asm volatile("ud2");					\ 	unreachable();						\ } while (0)

Вызов BUG()

Макрос BUG() надо добавить в собственный тестовый код уровня ядра для того, чтобы было вызвано исключение. В данном примере мы добавили его в keyboard.c для того, чтобы исключение вызывалось при появлении особых последовательностей символов, вводимых с клавиатуры.


Результат вызова макроса BUG()


Результат вызова макроса BUG(), увеличенный фрагмент копии экрана

Остановка на точке останова Invalid_op

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


Точка останова в обработчике исключения «Неправильный код операции»


Точка останова в обработчике исключения «Неправильный код операции», увеличенный фрагмент копии экрана

Заключение

Некоторые исключения – это критические ошибки аппаратного и программного обеспечения системы. Поэтому очень важно знать – как, почему и где они происходят. Используя JTAG-отладчик Intel, такие ошибки легко обнаружить и добраться до причины их возникновения. Всё это возможно потому, что данный отладчик предоставляет разработчику мощные возможности. Среди них – лёгкий доступ к скомпилированному и исходному коду, просмотр стека вызовов и регистров.

Полезные ссылки

Intel 64 and IA-32 Architectures Software Developer’s Manual
JTAG Tutorial: IEE 1149.x and Software Debug

ссылка на оригинал статьи http://habrahabr.ru/post/266701/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *