Skip to content

Commit 8fec329

Browse files
committed
ЛР14,16. Исправление обработчика перехватов
При реализации обработчика намеренно не было реализовано сохранение необерегаемых регистров. Так было сделано в виду неправильной интерпретации EABI. При входе в низкоуровневый обработчик необходимо сохранять весь регистровый файл.
1 parent 6f74ab5 commit 8fec329

File tree

3 files changed

+221
-149
lines changed

3 files changed

+221
-149
lines changed

Labs/14. Programming/README.md

Lines changed: 64 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -360,22 +360,16 @@ _endless_loop:
360360
# качестве аргумента.
361361
# В основе кода лежит обработчик из репозитория urv-core:
362362
# https://github.com/twlostow/urv-core/blob/master/sw/common/irq.S
363-
# Из реализации убраны сохранения нереализованных CS-регистров. Кроме того,
364-
# судя по документу приведенному ниже, обычное ABI подразумевает такое же
365-
# сохранение контекста, что и при программном вызове (EABI подразумевает ещё
366-
# меньшее сохранение контекста), поэтому нет нужды сохранять весь регистровый
367-
# файл.
368-
# Документ:
369-
# https://github.com/riscv-non-isa/riscv-eabi-spec/blob/master/EABI.adoc
363+
# Из реализации убраны сохранения нереализованных CS-регистров.
370364
_int_handler:
371365
# Данная операция меняет местами регистры sp и mscratch.
372366
# В итоге указатель на стек прерываний оказывается в регистре sp, а вершина
373367
# программного стека оказывается в регистре mscratch.
374368
csrrw sp, mscratch, sp
375369
376370
# Далее мы поднимаемся по стеку прерываний и сохраняем все регистры.
377-
addi sp, sp, -80 # Указатель на стек должен быть выровнен до 16 байт, поэтому
378-
# поднимаемся вверх не на 76, а на 80.
371+
addi sp, sp, -144 # Указатель на стек должен быть выровнен до 16 байт, поэтому
372+
# поднимаемся вверх не на 136, а на 144.
379373
sw ra, 4(sp)
380374
# Мы хотим убедиться, что очередное прерывание не наложит стек прерываний на
381375
# программный стек, поэтому записываем в освободившийся регистр низ
@@ -387,32 +381,46 @@ _int_handler:
387381
la ra, _stack_ptr
388382
blt sp, ra, _endless_loop
389383
390-
sw t0,12(sp) # Мы перепрыгнули через смещение 8, поскольку там должен
384+
sw gp,12(sp) # Мы перепрыгнули через смещение 8, поскольку там должен
391385
# лежать регистр sp, который ранее сохранили в mscratch.
392386
# Мы запишем его на стек чуть позже.
393-
sw t1,16(sp)
394-
sw t2,20(sp)
395-
sw a0,24(sp)
396-
sw a1,28(sp)
397-
sw a2,32(sp)
398-
sw a3,36(sp)
399-
sw a4,40(sp)
400-
sw a5,44(sp)
401-
sw a6,48(sp)
402-
sw a7,52(sp)
403-
sw t3,56(sp)
404-
sw t4,60(sp)
405-
sw t5,64(sp)
406-
sw t6,68(sp)
387+
sw tp,16(sp)
388+
sw t0,20(sp)
389+
sw t1,24(sp)
390+
sw t2,28(sp)
391+
sw s0,32(sp)
392+
sw s1,36(sp)
393+
sw a0,40(sp)
394+
sw a1,44(sp)
395+
sw a2,48(sp)
396+
sw a3,52(sp)
397+
sw a4,56(sp)
398+
sw a5,60(sp)
399+
sw a6,64(sp)
400+
sw a7,68(sp)
401+
sw s2,72(sp)
402+
sw s3,76(sp)
403+
sw s4,80(sp)
404+
sw s5,84(sp)
405+
sw s6,88(sp)
406+
sw s7,92(sp)
407+
sw s8,96(sp)
408+
sw s9,100(sp)
409+
sw s10,104(sp)
410+
sw s11,108(sp)
411+
sw t3,112(sp)
412+
sw t4,116(sp)
413+
sw t5,120(sp)
414+
sw t6,124(sp)
407415
408416
# Кроме того, мы сохраняем состояние регистров прерываний на случай, если
409417
# произойдет ещё одно прерывание.
410418
csrr t0,mscratch
411419
csrr t1,mepc
412420
csrr a0,mcause
413421
sw t0,8(sp)
414-
sw t1,72(sp)
415-
sw a0,76(sp)
422+
sw t1,128(sp)
423+
sw a0,132(sp)
416424
417425
# Вызов высокоуровневого обработчика прерываний.
418426
# Для того чтобы программа скомпоновалась, где-то должна быть описана
@@ -426,28 +434,42 @@ _int_handler:
426434
# сохраним его в регистр a0, и будем восстанавливаться из него.
427435
mv a0,sp
428436
429-
lw t1,72(a0)
430-
addi sp,sp,80
437+
lw t1,128(a0)
438+
addi sp,sp,144
431439
csrw mscratch,sp
432440
csrw mepc,t1
433441
lw ra,4(a0)
434442
lw sp,8(a0)
435-
lw t0,12(a0)
436-
lw t1,16(a0)
437-
lw t2,20(a0)
438-
lw a1,28(a0) # Мы пропустили a0, потому что сейчас он используется в
443+
lw gp,12(a0)
444+
lw tp,16(a0)
445+
lw t0,20(a0)
446+
lw t1,24(a0)
447+
lw t2,28(a0)
448+
lw s0,32(a0)
449+
lw s1,36(a0)
450+
lw a1,44(a0) # Мы пропустили a0, потому что сейчас он используется в
439451
# качестве указателя на верхушку стека и не может быть
440452
# восстановлен.
441-
lw a2,32(a0)
442-
lw a3,36(a0)
443-
lw a4,40(a0)
444-
lw a5,44(a0)
445-
lw a6,48(a0)
446-
lw a7,52(a0)
447-
lw t3,56(a0)
448-
lw t4,60(a0)
449-
lw t5,64(a0)
450-
lw t6,68(a0)
453+
lw a2,48(a0)
454+
lw a3,52(a0)
455+
lw a4,56(a0)
456+
lw a5,60(a0)
457+
lw a6,64(a0)
458+
lw a7,68(a0)
459+
lw s2,72(a0)
460+
lw s3,76(a0)
461+
lw s4,80(a0)
462+
lw s5,84(a0)
463+
lw s6,88(a0)
464+
lw s7,92(a0)
465+
lw s8,96(a0)
466+
lw s9,100(a0)
467+
lw s10,104(a0)
468+
lw s11,108(a0)
469+
lw t3,112(a0)
470+
lw t4,116(a0)
471+
lw t5,120(a0)
472+
lw t6,124(a0)
451473
lw a0,40(a0)
452474
453475
# Выход из обработчика прерывания

Labs/14. Programming/startup.S

Lines changed: 80 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -57,22 +57,16 @@ _endless_loop:
5757
# качестве аргумента.
5858
# В основе кода лежит обработчик из репозитория urv-core:
5959
# https://github.com/twlostow/urv-core/blob/master/sw/common/irq.S
60-
# Из реализации убраны сохранения нереализованных CS-регистров. Кроме того,
61-
# судя по документу приведенному ниже, обычное ABI подразумевает такое же
62-
# сохранение контекста, что и при программном вызове (EABI подразумевает еще
63-
# меньшее сохранение контекста), поэтому нет нужды сохранять весь регистровый
64-
# файл.
65-
# Документ:
66-
# https://github.com/riscv-non-isa/riscv-eabi-spec/blob/master/EABI.adoc
60+
# Из реализации убраны сохранения нереализованных CS-регистров.
6761
_int_handler:
6862
# Данная операция меняет местами регистры sp и mscratch.
6963
# В итоге указатель на стек прерываний оказывается в регистре sp, а вершина
7064
# программного стека оказывается в регистре mscratch.
71-
csrrw sp, mscratch,sp
65+
csrrw sp, mscratch, sp
7266

7367
# Далее мы поднимаемся по стеку прерываний и сохраняем все регистры.
74-
addi sp, sp, -80 # Указатель на стек должен быть выровнен до 16 байт, поэтому
75-
# поднимаемся вверх не на 76, а на 80.
68+
addi sp, sp, -144 # Указатель на стек должен быть выровнен до 16 байт, поэтому
69+
# поднимаемся вверх не на 136, а на 144.
7670
sw ra, 4(sp)
7771
# Мы хотим убедиться, что очередное прерывание не наложит стек прерываний на
7872
# программный стек, поэтому записываем в освободившийся регистр низ
@@ -84,32 +78,46 @@ _int_handler:
8478
la ra, _stack_ptr
8579
blt sp, ra, _endless_loop
8680

87-
sw t0, 12(sp) # Мы перепрыгнули через смещение 8, поскольку там должен
88-
# лежать регистр sp, который ранее сохранили в mscratch.
89-
# Мы запишем его на стек чуть позже.
90-
sw t1, 16(sp)
91-
sw t2, 20(sp)
92-
sw a0, 24(sp)
93-
sw a1, 28(sp)
94-
sw a2, 32(sp)
95-
sw a3, 36(sp)
96-
sw a4, 40(sp)
97-
sw a5, 44(sp)
98-
sw a6, 48(sp)
99-
sw a7, 52(sp)
100-
sw t3, 56(sp)
101-
sw t4, 60(sp)
102-
sw t5, 64(sp)
103-
sw t6, 68(sp)
81+
sw gp,12(sp) # Мы перепрыгнули через смещение 8, поскольку там должен
82+
# лежать регистр sp, который ранее сохранили в mscratch.
83+
# Мы запишем его на стек чуть позже.
84+
sw tp,16(sp)
85+
sw t0,20(sp)
86+
sw t1,24(sp)
87+
sw t2,28(sp)
88+
sw s0,32(sp)
89+
sw s1,36(sp)
90+
sw a0,40(sp)
91+
sw a1,44(sp)
92+
sw a2,48(sp)
93+
sw a3,52(sp)
94+
sw a4,56(sp)
95+
sw a5,60(sp)
96+
sw a6,64(sp)
97+
sw a7,68(sp)
98+
sw s2,72(sp)
99+
sw s3,76(sp)
100+
sw s4,80(sp)
101+
sw s5,84(sp)
102+
sw s6,88(sp)
103+
sw s7,92(sp)
104+
sw s8,96(sp)
105+
sw s9,100(sp)
106+
sw s10,104(sp)
107+
sw s11,108(sp)
108+
sw t3,112(sp)
109+
sw t4,116(sp)
110+
sw t5,120(sp)
111+
sw t6,124(sp)
104112

105113
# Кроме того, мы сохраняем состояние регистров прерываний на случай, если
106-
# произойдет еще одно прерывание.
107-
csrr t0, mscratch
108-
csrr t1, mepc
109-
csrr a0, mcause
110-
sw t0, 8(sp)
111-
sw t1, 72(sp)
112-
sw a0, 76(sp)
114+
# произойдет ещё одно прерывание.
115+
csrr t0,mscratch
116+
csrr t1,mepc
117+
csrr a0,mcause
118+
sw t0,8(sp)
119+
sw t1,128(sp)
120+
sw a0,132(sp)
113121

114122
# Вызов высокоуровневого обработчика прерываний.
115123
# Для того чтобы программа скомпоновалась, где-то должна быть описана
@@ -119,33 +127,47 @@ _int_handler:
119127
# Восстановление контекста. В первую очередь мы хотим восстановить CS-регистры,
120128
# на случай, если происходило вложенное прерывание. Для этого, мы должны
121129
# вернуть исходное значение указателя стека прерываний. Однако его нынешнее
122-
# значение нам еще необходимо для восстановления контекста, поэтому мы
130+
# значение нам ещё необходимо для восстановления контекста, поэтому мы
123131
# сохраним его в регистр a0, и будем восстанавливаться из него.
124132
mv a0,sp
125133

126-
lw t1, 72(a0)
127-
addi sp, sp, 80
128-
csrw mscratch, sp
129-
csrw mepc, t1
130-
lw ra, 4(a0)
131-
lw sp, 8(a0)
132-
lw t0, 12(a0)
133-
lw t1, 16(a0)
134-
lw t2, 20(a0)
135-
lw a1, 28(a0) # Мы пропустили a0, потому что сейчас он используется в
136-
# качестве указателя на верхушку стека и не может быть
137-
# восстановлен.
138-
lw a2, 32(a0)
139-
lw a3, 36(a0)
140-
lw a4, 40(a0)
141-
lw a5, 44(a0)
142-
lw a6, 48(a0)
143-
lw a7, 52(a0)
144-
lw t3, 56(a0)
145-
lw t4, 60(a0)
146-
lw t5, 64(a0)
147-
lw t6, 68(a0)
148-
lw a0, 40(a0)
134+
lw t1,128(a0)
135+
addi sp,sp,144
136+
csrw mscratch,sp
137+
csrw mepc,t1
138+
lw ra,4(a0)
139+
lw sp,8(a0)
140+
lw gp,12(a0)
141+
lw tp,16(a0)
142+
lw t0,20(a0)
143+
lw t1,24(a0)
144+
lw t2,28(a0)
145+
lw s0,32(a0)
146+
lw s1,36(a0)
147+
lw a1,44(a0) # Мы пропустили a0, потому что сейчас он используется в
148+
# качестве указателя на верхушку стека и не может быть
149+
# восстановлен.
150+
lw a2,48(a0)
151+
lw a3,52(a0)
152+
lw a4,56(a0)
153+
lw a5,60(a0)
154+
lw a6,64(a0)
155+
lw a7,68(a0)
156+
lw s2,72(a0)
157+
lw s3,76(a0)
158+
lw s4,80(a0)
159+
lw s5,84(a0)
160+
lw s6,88(a0)
161+
lw s7,92(a0)
162+
lw s8,96(a0)
163+
lw s9,100(a0)
164+
lw s10,104(a0)
165+
lw s11,108(a0)
166+
lw t3,112(a0)
167+
lw t4,116(a0)
168+
lw t5,120(a0)
169+
lw t6,124(a0)
170+
lw a0,40(a0)
149171

150172
# Выход из обработчика прерывания
151173
mret

0 commit comments

Comments
 (0)