Оглавление
§ Работа с CSR
Эти инструкции необходимы для управления машинным статусом. Они нужны для организации прерываний, чтения и записи состояния процессора, и управления.
Код операции: 73h
-------+-31--------20-+-19---15-+-14---12-+-11--7-+-6------0-+-CSR--+
ECALL | 000000000000 | 00000 | 000 | 00000 | 111_0011 | 000h |
EBREAK | 000000000001 | 00000 | 000 | 00000 | 111_0011 | 001h |
MRET | 001100000010 | 00000 | 000 | 00000 | 111_0011 | 302h |
-------+--------------+---------+---------+-------+----------+------+
CSRRW | csr[11:0] | rs1 | 001 | rd | 111_0011 |
CSRRS | csr[11:0] | rs1 | 010 | rd | 111_0011 |
CSRRC | csr[11:0] | rs1 | 011 | rd | 111_0011 |
-------+--------------+---------+---------+-------+----------+
CSRRWI | csr[11:0] | uimm | 101 | rd | 111_0011 |
CSRRSI | csr[11:0] | uimm | 110 | rd | 111_0011 |
CSRRCI | csr[11:0] | uimm | 111 | rd | 111_0011 |
-------+--------------+---------+-funct3--+-------+----------+
csr[31:30] определяют права доступа. При значений 11 запись в регистр CSR невозможна
csr[29:28] задают уровень привилегии доступа к регистру: 00=User, 01=Supervisor (S-mode), 11=Machine (M-mode).
Режимы работы процессора:
- User: уровень пользовательских приложений
- Supervisor: промежуточный, для операционной системы
- Machine: максимально возможный системный доступ ко всем ресурсам
Описания инструкции:
- CSRRW:
regs[rd] = csr; csr = regs[rs1] – прочесть из регистра CSR в rd и записать rs1 в CSR (обмен)
- CSRRS:
regs[rd] = csr; csr |= regs[rs1] – прочесть предыдущее значение, а потом установить маску (OR) регистра CSR
- CSRRC:
regs[rd] = csr; csr &= ~regs[rs1] – прочесть предыдущее значение, и сбросить по маске (AND NOT) регистр CSR
- ECALL: Вызов прерывания по определенному CSR
- EBREAK: Вызывается прерывание mcause=3 для передачи отладчику
Команды CSRRWI, CSRRSI, CSRRCI работают аналогично, но используют константу размером 00..1Fh.
§ Прерывания
При помощи CSR возможно установить вектора прерывания и способ их обработки.
# mstatus (Machine Status): Регистр управления машинным состоянием.
[3] MIE: Если бит в регистре установлен, то прерывания уровня M-mode (машинный уровень) разрешены
[7] MPIE: Предыдущий бит, который был в MIE до вызова прерывания, чтобы потом его восстановить
[12:11] MPP: Уровень привилегии, на котором процессор находился до прерывания (00-U, 01-S, 11-M)
# mie (Machine Interrupt Enabled): Регистр, в котором находятся разрешения на прерывания
[3] (MSIE): Software – программные прерывания
[7] (MTIE): Timer – разрешение таймера
[11] (MEIE): External – разрешение внешних прерывания (UART, GPIO, PS2 и т.д.)
# mip (Machine Interrupt Pending): Ожидание машинного прерывания
# mepc (Machine Exception Program Counter): Адрес PC при машинном исключении
- Копирование адреса инструкции, на котором произошло исключение
- Переход на адрес обработчика, который был записан в
mtvec
- На команде
MRET происходит копирование mepc в регистр pc (программный счетчик)
# mtvec (Machine Trap-Vector Base Address): Базовый адрес таблицы прерываний
[31:2] – базовый адрес начала таблицы, где находятся прерывания, выровнен по 4 байта
[1:0] – если там 00 (direct) то вызывает только адрес, если 01 (vectored) то вычисляется по формуле base + 4*cause, где base – это заданное в старших битах значение адреса, а cause – номер причины (или номер прерывания), что делает таблицу похожей на обычные векторные прерывания
# mcause (Machine Cause): Номер причины прерывания после вызова
[31] (Interrupt): кем было инициировано прерывание, если =1 то это внешнее прерывание, =0 исключение или ecall
- Остальные биты: сама причина прерывания
Коды прерывания для внешних прерываний:
3 (m_software) Программное взаимодействие, для многоядерных систем
7 (m_timer) Машинный таймер, когда наступило время, записанное в CSR mtimecmp и mtime
11 (m_external) Внешнее прерывание от периферии, IRQ
Для базовых:
0 (misaligned) Переход по невыровненному адресу
2 (illegal) При выполнении неизвестной инструкции
8 (u-ecall) Выполнение ECALL в User-mode
9 (s-ecall) Выполнение ECALL в Supervisor-mode
11 (`m-ecall) Выполнение ECALL в Machine-mode
# mtime (Machine Time): 64-битный счетчик, постоянно инкрементируется. Так как счетчик 64 бит, то его значения находятся в в 2-х CSR. Обычный адрес 0x2000000
# mtimecmp (Machine Time Compare): Регистр (64 бит) для сравнения счетчика, который выставляет флаг MTIP в mip и вызывает прерывание, если прерывания разрешены. Срабатывает когда mtime >= mtimecmp. Обычный адрес 0x2000008.
# mcycle (Machine Cycles): Количество тактов, которые сделаны процессором.
§ Список CSR
MSTATUS | 0x300 | Статус процессора
MIE | 0x304 | Разрешение прерываний
MTVEC | 0x305 | Базовый адрес таблицы прерывания
MSCRATCH | 0x340 | Временный регистр для хранения стека обработчика
MEPC | 0x341 | Адрес инструкции, где произошло прерывание
MCAUSE | 0x343 | Причина исключения
MTVAL | 0x343 | Дополнительно, к примеру адрес при ошибке доступа
MIP | 0x344 | Флаги ожидающих прерываний
Пояснения насчет mscratch – сюда при вызове прерывания сохраняется предыдущий стек пользователя, и выталкивается стек, с которым работает ядро или ОС.