Официальный форум СВД Встраиваемые Системы
10 Декабря, 2016, 08:01:02 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.

Войти
 
 
 Сайт СВД ВС  Начало   Помощь Поиск Войти Регистрация  
Страниц: [1]   Вниз
  Печать  
Автор Тема: kernel mode (Ring0) on any CPU  (Прочитано 408 раз)
Артем Кашканов
Пользователь

Сообщений: 11



WWW
« : 22 Июня, 2016, 16:41:32 »

Приветствую!

Имеется задача выполнять инструкции процессора, для которых требуются ring0 или real-memory mode привелегии.

Решение на первый взгляд простое - создаем Interrupt handler, подключаемся к примеру, к int 0x00(systick timer) и творим внутри него все что хотим. Это работает Smiley
Однако данное решение обладает существенным недостатком - все ISR выполняются строго на CPU0 и соответственно результаты выполнения инструкций будут касаться только нулевого процессора.
Таким образом возникает вопрос - как получать ring0 привелении на определенном номере процессора в рантайме?
« Последнее редактирование: 22 Июня, 2016, 16:47:57 от Артем Кашканов » Записан
Андрей Сеньков
Администратор
Опытный пользователь

Сообщений: 262



WWW
« Ответ #1 : 23 Июня, 2016, 16:01:50 »

Добрый день!

как получать ring0 привелении на определенном номере процессора в рантайме?

Думаю, что такой возможности нет.
Записан

Артем Кашканов
Пользователь

Сообщений: 11



WWW
« Ответ #2 : 24 Июня, 2016, 17:09:27 »

А что насчет TraceEvent handler-ов - какие хэндлеры на каком процессоре работают?
Например я вижу, что хэндлер, повешенный на событие _NTO_TRACE_THREAD->_NTO_TRACE_THRUNNING исходя из сравнения информации о cpuid->lapic_id и информации из tracelogger  вроде как выполняется на том же ядре, на котором поток перешел в RUNNING state.

Но хочется именно что быть уверенным в этом. Можете чуть подробнее что-то рассказать об этом механизме?

В чем архитектурное решение иметь только одно ядро для прерываний? Ведь свой lapic есть для каждого процессора - почемУ, например, нельзя запрограммировать свои IDT/GDT для каждого ядра и организовать Interrupt affinity?

Ведь есть еще InterProcessor Interrupts - как его обработчики срабатывают? В syspage же можно повесить свой обработчик для IPI - на каком ядре будет выполняться он?
« Последнее редактирование: 24 Июня, 2016, 17:18:05 от Артем Кашканов » Записан
Владимир Махилёв
Сотрудник СВД ВС
Ветеран

Сообщений: 659



WWW
« Ответ #3 : 24 Июня, 2016, 18:32:24 »

В чем архитектурное решение иметь только одно ядро для прерываний? Ведь свой lapic есть для каждого процессора - почемУ, например, нельзя запрограммировать свои IDT/GDT для каждого ядра и организовать Interrupt affinity?

Для привязки обработки к конкретному ядру можно использовать обработчик прерывания на приоритете потока с помощью InterruptAttachEvent(). Поток-обработчик запускаете на нужном ядре и получаете пульсы.

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

Ведь есть еще InterProcessor Interrupts - как его обработчики срабатывают? В syspage же можно повесить свой обработчик для IPI - на каком ядре будет выполняться он?
На каждом. Плюс каждое ядро будет использовать IPI для обмена с другими ядрами.

Записан

Павел Козлов
Модератор
Пользователь

Сообщений: 96



WWW
« Ответ #4 : 24 Июня, 2016, 20:15:11 »

TraceEvent handler это одна из двух лазеек, которая позволяет выполнить пользовательский код в контексте ядра (в привилегированном режиме). Первая - это обработчик прерываний.
Использовать обработчик TraceEvent можно только с инструментальным ядром. На обработчик TraceEvent действуют те же самые ограничения, что и на обработчик прерывания.
Можно настроить обработчик TraceEvent таким образом, что он будет вызван при сохранении трассы при входе в ядро-QNX для обработки системного вызова и только для  определенного системного вызова.

Подробнее здесь:
http://www.qnx.com/developers/docs/6.5.0/index.jsp?topic=%2Fcom.qnx.doc.neutrino_lib_ref%2Ft%2Ftraceevent.html
и здесь:
http://www.qnx.com/developers/docs/6.5.0/index.jsp?topic=%2Fcom.qnx.doc.instr_en_instr%2Ffiltering.html

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

Цитировать
В чем архитектурное решение иметь только одно ядро для прерываний? Ведь свой lapic есть для каждого процессора - почемУ, например, нельзя запрограммировать свои IDT/GDT для каждого ядра и организовать Interrupt affinity?

QNX настраивает IDT/GDT для каждого ядра. Настройка маршрутизации прерывания по ядрам может быть осуществлена в коде startup. Динамической маршрутизации прерываний, после загрузки QNX,  не предусмотрено.

Цитировать
Ведь есть еще InterProcessor Interrupts - как его обработчики срабатывают? В syspage же можно повесить свой обработчик для IPI - на каком ядре будет выполняться он?

Для x86, генерация и обработка IPI находится в ядре QNX и не изменяется через callout'ы startup.
Записан

Артем Кашканов
Пользователь

Сообщений: 11



WWW
« Ответ #5 : 28 Июня, 2016, 12:27:44 »

Цитировать
Использовать обработчик TraceEvent можно только с инструментальным ядром
Насколько я понимаю procnto-smp и procnto-smp-instr можно заменять друг на друга в рантайме (или нет?) ? Мне эта информация попадалась вскольз во время прочтения документации. Есть четкое описание этой операции, дабы ее можно было реализовать в виде небольшой root-утилитки?

Цитировать
Если установить для потока runmask на определённое процессорное ядро, то  можно исключить миграцию потока по различным ядрам.
Так и делаю, работает отлично, но execution time в 1 мс с использованием TraceEvent handler несколько удручает. хотя и терпимо

Кстати есть возможность настроить TraceEvent handler таким образом, чтобы программу его использующую можно было с помощью tracelogger профилировать? например сейчас я использую
Код:
TraceEvent(_NTO_TRACE_ADDEVENT, _NTO_TRACE_THREAD, _NTO_TRACE_THNANOSLEEP);//добавили event
TraceEvent(_NTO_TRACE_SETEVENTPID, _NTO_TRACE_THREAD, _NTO_TRACE_THNANOSLEEP, getpid());//включили фильтрацию
TraceEvent(_NTO_TRACE_ADDEVENTHANDLER, _NTO_TRACE_THREAD, _NTO_TRACE_THNANOSLEEP, thread_run_eh, data);//подключили обработчик
nanosleep(&time, NULL);//<===TraceEvent handled here
TraceEvent(_NTO_TRACE_DELEVENTHANDLER, _NTO_TRACE_THREAD, _NTO_TRACE_THNANOSLEEP);//отключили обработчик
Но запуск программы с таким кодом под tracelogger дает пустой .kev-файл на выходе.
Я знаю что можно сделать зависимое управление через ключ -d1 и команды START/STOP, меня интересует независимый метод.

UPD:  Описанный ваше код справляется с этой задачей проблема была в различных значениях TSC-регистров на разных CPU(изменил пока тестил) и парсеры некорретно ее обрабатывали.

Цитировать
Динамической маршрутизации прерываний, после загрузки QNX,  не предусмотрено
Что случится, если такую возможность предусмотреть? Ведь под ring0 выполняться получается, адреса все есть. Что сломается в системе, если я начну в TraceEvent handler-e изменять привязку интераптов на ядра? и как этого избежать. (пусть даже чисто теоретически).

Цитировать
Для x86, генерация и обработка IPI находится в ядре QNX и не изменяется через callout'ы startup.
На каких архитектурах это в принципе возможно? Вот по этой ссылке в Wiki не шибко подробно упоминаются smp-возможности системы на этапе startup. Судя по вашему категоричному комментарию эту ссылку читать мне не имеет смысла.
« Последнее редактирование: 28 Июня, 2016, 16:19:28 от Артем Кашканов » Записан
Владимир Махилёв
Сотрудник СВД ВС
Ветеран

Сообщений: 659



WWW
« Ответ #6 : 28 Июня, 2016, 17:54:54 »

Насколько я понимаю procnto-smp и procnto-smp-instr можно заменять друг на друга в рантайме (или нет?) ? Мне эта информация попадалась вскольз во время прочтения документации. Есть четкое описание этой операции, дабы ее можно было реализовать в виде небольшой root-утилитки?

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

Что случится, если такую возможность предусмотреть? Ведь под ring0 выполняться получается, адреса все есть. Что сломается в системе, если я начну в TraceEvent handler-e изменять привязку интераптов на ядра? и как этого избежать. (пусть даже чисто теоретически).

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

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

IPI для x86 находится в ядре.
Для других архитектур IPI вынесены в startup в виде callout'ов. Посмотрите на код startup любого BSP для архитектур ARM, MIPS, PowerPC.
И, в любом случае, идея залезать со своим кодом в IPI крайне сомнительная.


Записан

Артем Кашканов
Пользователь

Сообщений: 11



WWW
« Ответ #7 : 13 Июля, 2016, 14:53:45 »

Цитировать
На практике в динамической маршрутизации прерываний необходимости еще не возникало, достаточно единожды настроить её в startup.
А есть какие-то более полные материалы по этому вопросу? Ибо описание add_interrupt() и add_interrupt_array() очень скудное (можно сказать его в принципе нет), а описание структуры startup_intrinfo не дает ответа как его привязать к определенному процессору.
Записан
Владимир Махилёв
Сотрудник СВД ВС
Ветеран

Сообщений: 659



WWW
« Ответ #8 : 14 Июля, 2016, 12:40:28 »

Ожидать подробной документации кода startup не стоит. Это системный код, он достаточно компактный и само-говорящий.
Из документации будет полезна спецификация на сам контроллер прерываний.

Вам нужно для начала выяснить как в принципе направлять прерывания на x86 и APIC на нужные ядра.
Затем, вам потребуется доработать код в startup который инициализирует контроллер прерываний APIC. Обратите внимание на поле cpu_mask.

Записан

Страниц: [1]   Вверх
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP © 2002-2016 СВД Встраиваемые Системы.
При использовании материалов сайта ссылка на forum.kpda.ru обязательна.

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines | © Aiwan. Kolobok smiles | Sitemap
Valid XHTML 1.0! Valid CSS!
Сайт СВД ВС

В последний раз google посещал эту страницу 13 Ноября, 2016, 19:05:44