Перейти к содержанию

SVC и SVCall

Задача в RTOS работает с ограниченными правами, а ядру ОС нужны привилегированные. Мост между ними — команда SVC: она синхронно вызывает исключение SVCall, и обработчик получает управление в привилегированном режиме. Номер нужного сервиса передаётся прямо в коде команды.

Обновлено Редакция GAW

SVC (supervisor call) — команда ядер Cortex-M, которая вызывает исключение SVCall. Её назначение Arm описывает так: в среде ОС приложения используют SVC, чтобы обратиться к функциям ядра и драйверам (DUI 0553B, разд. 2.3.2). В отличие от PendSV, исключение синхронное: оно возникает ровно на этой команде.

Параметры

ПараметрЗначение
Номер исключения11 (в CMSIS — IRQn = −5)
Векторсмещение 0x2C в таблице векторов
Приоритетполе PRI_11, биты 31:24 регистра SHPR2, 0xE000ED1C
Аргумент8 бит, 0–255, в коде команды
Кодировка16 бит: 0xDF и imm8 в младшем байте

Источники: DUI 0553B, табл. 2-16 и 4-22, разд. 3.12.10; DDI 0403E, разд. A7.7.178.

Как передать номер сервиса

Процессор аргумент #imm не использует — его разбирает обработчик. При входе в исключение ядро кладёт в стек кадр исключения, и в нём есть адрес возврата: адрес команды, следующей за SVC. Команда занимает два байта, а номер — её младший байт, поэтому обработчик читает байт по адресу «сохранённый PC − 2». Аргументы для сервиса передают в R0–R3: они тоже лежат в кадре, и обработчик может вернуть результат, записав его в сохранённый R0.

Когда SVC превращается в HardFault

SVCall должно быть обслужено немедленно. Если его приоритет не выше текущего уровня выполнения — например, SVC вызвана из обработчика прерывания с более высоким приоритетом или при PRIMASK = 1, — ядро эскалирует исключение в HardFault (DDI 0403E, разд. B1.5). Это частая ошибка при переносе кода: функцию RTOS, построенную на SVC, вызывают из критической секции с запрещёнными прерываниями.

Где применяют

  • Запуск планировщика. В обработчике SVC удобно переключить стек на PSP и перейти в режим потока — так можно стартовать первую задачу.
  • Вызов привилегированных функций. Регистры разрешения и ожидания прерываний NVIC доступны только привилегированному коду (DUI 0553B, табл. 4-2), а обработчик SVCall выполняется с привилегиями.
  • Защищённые сервисы. Номер в команде работает как номер системного вызова: одна точка входа, таблица функций внутри.

Устройство режимов и стеков Cortex-M разобрано в статье о ядре Cortex-M3, а настройка приоритетов исключений STM32 — в статье о прерываниях STM32.

Частые вопросы

Как обработчику узнать номер, указанный в SVC #n?

Процессор номер игнорирует, его достают программно. В стековом кадре лежит адрес возврата — адрес команды после SVC. Сама SVC 16-битная, номер — её младший байт (кодировка 0xDF imm8, DDI 0403E, разд. A7.7.178), поэтому номер читают как байт по адресу «сохранённый PC − 2». Какой стек смотреть, MSP или PSP, подсказывает бит 2 значения EXC_RETURN в LR.

Почему SVC внутри прерывания или при запрещённых прерываниях даёт HardFault?

SVCall — синхронное исключение: оно должно быть обслужено сразу. Если его приоритет не выше текущего уровня выполнения, обычное вытеснение невозможно, и ядро эскалирует его в HardFault. Arm приводит прямой пример: команда SVC при PRIMASK = 1 (DDI 0403E, разд. B1.5). Поэтому SVC вызывают из кода задач, а не из обработчиков с высоким приоритетом.

SVC и SWI — одно и то же?

Да. В старых версиях архитектуры Arm эта команда называлась SWI (software interrupt), ассемблер Armv7-M принимает старое написание как синоним (DDI 0403E, разд. A7.7.178).

Источники

  1. Arm. Cortex-M4 Devices Generic User Guide, ARM DUI 0553B (ID012616) — разд. 2.3.2: SVCall — исключение, которое вызывает команда SVC; в среде ОС приложения обращаются через SVC к функциям ядра и драйверам; табл. 2-16: номер 11, приоритет настраиваемый, смещение вектора 0x2C, активация синхронная; разд. 3.12.10: синтаксис SVC{cond} #imm, imm — 8-битное значение 0–255, процессор его игнорирует, обработчик может получить его через сохранённый в стеке PC; разд. 4.3.8, табл. 4-22: SHPR2 по адресу 0xE000ED1C, биты 31:24 PRI_11 — приоритет SVCall
  2. Arm. Armv7-M Architecture Reference Manual, ARM DDI 0403E.e (ID021621) — разд. A7.7.178: SVC — вызов системного супервизора, прежнее имя SWI; кодировка T1 — 16 бит 1101 1111 imm8, imm8 в младшем байте; разд. B1.5: SVCall всегда разрешено, приоритет настраиваемый; разд. B1.5, «Priority escalation»: если групповой приоритет ожидающего синхронного исключения, в том числе SVCall, не выше текущего, оно эскалируется в HardFault; пример — команда SVC при PRIMASK = 1

Нашли ошибку?