riscv64: real trap entry with save/restore and SRET return

Punch list §25 item 0.2 complete.

Verified: riscv64 builds clean and boots to the ok> prompt with no regression;
dict_hash 0x3d4e1daf289da94f, unchanged from item 0.1's baseline. Disassembly
confirms the 320-byte frame, all 16 integer caller-saved registers, the FS
check, and SRET on exit; riscv64_trap_entry lands at 0x414fa8, 4-byte aligned
as stvec direct mode requires.

Not verified, and the item says so: neither new path was exercised. No timer is
armed until 0.3, so riscv64_interrupt_handler never ran, and no exception
occurred during boot, so the fatal path was not observed -- it is preserved
structurally, same branch to the same unchanged handler. This is why C2
rewrote the acceptance to no-regression rather than to having taken and
returned from a trap.

Register set is the LP64D psABI caller-saved list, not this document's summary:
integer ra/t0-t6/a0-a7 (16), FP ft0-ft11/fa0-fa7 (20) plus fcsr, and sepc +
sstatus. Callee-saved registers are the C handler's responsibility.

The FP half is conditional on sstatus.FS != Off, which the item did not
anticipate. Nothing in boot.S or kernel_entry.S programs FS, so its value is
whatever firmware leaves; touching an f-register with FS == Off raises an
illegal-instruction trap, and doing that inside the trap handler would be
unrecoverable. Omitting the FP save is not an option either -- the built
riscv64 image contains 530 FP instructions (fld, fmul.d, fcvt.lu.d among them),
confirming B2's finding against the binary rather than the build flags alone.
So the save is conditional, and sstatus is restored after the f-registers.

Dispatch: scause bit 63 routes to riscv64_interrupt_handler with scause in a0;
cause 5 (supervisor timer) calls heartbeat_tick(). Other causes are ignored
rather than fatal -- none are enabled to arrive. Everything else still falls
through to riscv64_exception_handler, unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Robert Allan James
2026-08-03 12:52:34 -04:00
co-authored by Claude Opus 5
parent c3e4fc282c
commit f3821ed686
6 changed files with 10674 additions and 7 deletions
+1 -1
View File
@@ -2019,7 +2019,7 @@ on until there is a tick on all three architectures (§16.1, §16.5).*
Artemis in the banner, and the three logs exist under `logs/`.
*Refs:* the surviving blocks are 2057, 2049, 2050. `mkcapsule --lint` before building.
- [ ] **0.2 — riscv64: real trap entry.**
- [x] **0.2 — riscv64: real trap entry.**
Replace the one-way `riscv64_trap_entry` in `arch/riscv64/isr.S` with save / dispatch /
restore / `sret`. Route `scause` bit 63 + cause 5 to the timer path; everything else keeps
falling through to the existing fatal handler.
+1 -1
View File
@@ -1,5 +1,5 @@
# Capsule Block Manifest — Auto-generated
<!-- Generated by mkcapsule --manifest 2026-08-03T16:45:12Z -->
<!-- Generated by mkcapsule --manifest 2026-08-03T16:51:19Z -->
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
<!-- Hand-written justifications and immutability notes live -->
<!-- in MANIFEST.md alongside this auto-generated index. -->
@@ -0,0 +1,59 @@
tick_number,elapsed_ns,tick_interval_ns,cache_hits_delta,bucket_hits_delta,word_executions_delta,hot_word_count,avg_word_heat_q48,window_width,actual_window_size,predicted_label_hits,jitter_bits,apic_ticks,time_trust_q48,variance_q48,vm_call_depth_max,hera_heat_q48,hermes_heat_q48,artemis_heat_q48
1,10000,10000,0,0,183,4,45,731,731,0,0,0,65536,0,0,65536,0,0
2,20000,10000,0,0,173,5,44,582,582,0,0,0,65536,0,0,65536,0,0
3,30000,10000,0,0,184,6,60,582,582,0,0,0,65536,0,0,65536,0,0
4,40000,10000,0,0,174,8,71,4096,0,0,0,0,65536,0,0,65536,0,0
5,50000,10000,0,0,150,9,78,582,582,0,0,0,65536,0,0,65536,0,0
6,60000,10000,0,0,159,11,73,4096,0,0,0,0,65536,0,0,65536,0,0
7,70000,10000,0,0,188,15,71,685,685,0,0,0,65536,0,0,65536,0,0
8,80000,10000,0,0,214,16,83,685,685,0,0,0,65536,0,0,65536,0,0
9,90000,10000,0,0,216,19,82,4096,0,0,0,0,65536,0,0,65536,0,0
10,100000,10000,0,0,222,21,84,567,567,0,0,0,65536,0,0,65536,0,0
11,110000,10000,0,0,207,23,86,731,731,0,0,0,65536,0,0,65536,0,0
12,120000,10000,0,0,189,26,83,4096,0,0,0,0,65536,0,0,65536,0,0
13,130000,10000,0,0,221,28,80,731,731,0,0,0,65536,0,0,65536,0,0
14,140000,10000,0,0,204,29,83,685,685,0,0,0,65536,0,0,65536,0,0
15,150000,10000,0,0,203,30,82,731,731,0,0,0,65536,0,0,65536,0,0
16,160000,10000,0,0,201,32,83,567,567,0,0,0,65536,0,0,65536,0,0
17,170000,10000,0,0,190,34,86,731,731,0,0,0,65536,0,0,65536,0,0
18,180000,10000,0,0,170,35,73,582,582,0,0,0,65536,0,0,65536,0,0
19,190000,10000,0,0,154,28,44,731,731,0,0,0,65536,0,0,65536,0,0
20,200000,10000,0,0,154,28,41,567,567,0,0,0,65536,0,0,65536,0,0
21,210000,10000,0,0,153,32,39,4096,0,0,0,0,65536,0,0,65536,0,0
22,220000,10000,0,0,167,35,42,582,582,0,0,0,65536,0,0,65536,0,0
23,230000,10000,0,0,176,37,41,685,685,0,0,0,65536,0,0,65536,0,0
24,240000,10000,0,0,175,37,39,731,731,0,0,0,65536,0,0,65536,0,0
25,250000,10000,0,0,196,38,37,731,731,0,0,0,65536,0,0,65536,0,0
26,260000,10000,0,0,192,41,37,4096,0,0,0,0,65536,0,0,65536,0,0
27,270000,10000,0,0,158,40,38,685,685,0,0,0,65536,0,0,65536,0,0
28,280000,10000,0,0,158,40,35,4096,0,0,0,0,65536,0,0,65536,0,0
29,290000,10000,0,0,164,41,37,4096,0,0,0,0,65536,0,0,65536,0,0
30,300000,10000,0,0,154,43,39,685,685,0,0,0,65536,0,0,65536,0,0
31,310000,10000,0,0,172,46,35,582,582,0,0,0,65536,0,0,65536,0,0
32,320000,10000,0,0,180,49,34,567,567,0,0,0,65536,0,0,65536,0,0
33,330000,10000,0,0,145,51,35,567,567,0,0,0,65536,0,0,65536,0,0
34,340000,10000,0,0,203,53,37,582,582,0,0,0,65536,0,0,65536,0,0
35,350000,10000,0,0,154,55,39,731,731,0,0,0,65536,0,0,65536,0,0
36,360000,10000,0,0,144,57,37,4096,0,0,0,0,65536,0,0,65536,0,0
37,370000,10000,0,0,144,57,35,4096,0,0,0,0,65536,0,0,65536,0,0
38,380000,10000,0,0,132,57,34,4096,0,0,0,0,65536,0,0,65536,0,0
39,390000,10000,0,0,180,57,32,4096,0,0,0,0,65536,0,0,65536,0,0
40,400000,10000,0,0,220,63,29,4096,0,0,0,0,65536,0,0,65536,0,0
41,410000,10000,0,0,215,64,28,4096,24,0,0,0,65536,0,0,65536,0,0
42,420000,10000,0,0,208,68,29,4096,24,0,0,0,65536,0,0,65536,0,0
43,430000,10000,0,0,177,72,27,4096,24,0,0,0,65536,0,0,65536,0,0
44,440000,10000,0,0,199,77,28,4096,24,0,0,0,65536,0,0,65536,0,0
45,450000,10000,0,0,223,82,26,4096,30,0,0,0,65536,0,0,65536,0,0
46,460000,10000,0,0,202,85,24,4096,67,0,0,0,65536,0,0,65536,0,0
47,470000,10000,0,0,218,91,25,4096,198,0,0,0,65536,0,0,65536,0,0
48,480000,10000,0,0,221,92,26,4096,350,0,0,0,65536,0,0,65536,0,0
49,490000,10000,0,0,225,97,26,4096,528,0,0,0,65536,0,0,65536,0,0
50,500000,10000,0,0,214,100,27,4096,694,0,0,0,65536,0,0,65536,0,0
51,510000,10000,0,0,227,102,28,4096,883,0,0,0,65536,0,0,65536,0,0
52,520000,10000,0,0,208,102,29,4096,1043,0,0,0,65536,0,0,65536,0,0
53,530000,10000,0,0,207,102,30,4096,1202,0,0,0,65536,0,0,65536,0,0
54,540000,10000,0,0,200,102,31,4096,1319,0,0,0,65536,0,0,65536,0,0
55,550000,10000,0,0,205,103,32,4096,1464,0,0,0,65536,0,0,65536,0,0
56,560000,10000,0,0,211,103,32,4096,1620,0,0,0,65536,0,0,65536,0,0
57,570000,10000,0,0,193,110,33,4096,1712,0,0,0,65536,0,0,65536,0,0
58,580000,10000,0,0,190,5,67,4096,1775,0,0,0,65536,0,0,65536,0,0
1 tick_number elapsed_ns tick_interval_ns cache_hits_delta bucket_hits_delta word_executions_delta hot_word_count avg_word_heat_q48 window_width actual_window_size predicted_label_hits jitter_bits apic_ticks time_trust_q48 variance_q48 vm_call_depth_max hera_heat_q48 hermes_heat_q48 artemis_heat_q48
2 1 10000 10000 0 0 183 4 45 731 731 0 0 0 65536 0 0 65536 0 0
3 2 20000 10000 0 0 173 5 44 582 582 0 0 0 65536 0 0 65536 0 0
4 3 30000 10000 0 0 184 6 60 582 582 0 0 0 65536 0 0 65536 0 0
5 4 40000 10000 0 0 174 8 71 4096 0 0 0 0 65536 0 0 65536 0 0
6 5 50000 10000 0 0 150 9 78 582 582 0 0 0 65536 0 0 65536 0 0
7 6 60000 10000 0 0 159 11 73 4096 0 0 0 0 65536 0 0 65536 0 0
8 7 70000 10000 0 0 188 15 71 685 685 0 0 0 65536 0 0 65536 0 0
9 8 80000 10000 0 0 214 16 83 685 685 0 0 0 65536 0 0 65536 0 0
10 9 90000 10000 0 0 216 19 82 4096 0 0 0 0 65536 0 0 65536 0 0
11 10 100000 10000 0 0 222 21 84 567 567 0 0 0 65536 0 0 65536 0 0
12 11 110000 10000 0 0 207 23 86 731 731 0 0 0 65536 0 0 65536 0 0
13 12 120000 10000 0 0 189 26 83 4096 0 0 0 0 65536 0 0 65536 0 0
14 13 130000 10000 0 0 221 28 80 731 731 0 0 0 65536 0 0 65536 0 0
15 14 140000 10000 0 0 204 29 83 685 685 0 0 0 65536 0 0 65536 0 0
16 15 150000 10000 0 0 203 30 82 731 731 0 0 0 65536 0 0 65536 0 0
17 16 160000 10000 0 0 201 32 83 567 567 0 0 0 65536 0 0 65536 0 0
18 17 170000 10000 0 0 190 34 86 731 731 0 0 0 65536 0 0 65536 0 0
19 18 180000 10000 0 0 170 35 73 582 582 0 0 0 65536 0 0 65536 0 0
20 19 190000 10000 0 0 154 28 44 731 731 0 0 0 65536 0 0 65536 0 0
21 20 200000 10000 0 0 154 28 41 567 567 0 0 0 65536 0 0 65536 0 0
22 21 210000 10000 0 0 153 32 39 4096 0 0 0 0 65536 0 0 65536 0 0
23 22 220000 10000 0 0 167 35 42 582 582 0 0 0 65536 0 0 65536 0 0
24 23 230000 10000 0 0 176 37 41 685 685 0 0 0 65536 0 0 65536 0 0
25 24 240000 10000 0 0 175 37 39 731 731 0 0 0 65536 0 0 65536 0 0
26 25 250000 10000 0 0 196 38 37 731 731 0 0 0 65536 0 0 65536 0 0
27 26 260000 10000 0 0 192 41 37 4096 0 0 0 0 65536 0 0 65536 0 0
28 27 270000 10000 0 0 158 40 38 685 685 0 0 0 65536 0 0 65536 0 0
29 28 280000 10000 0 0 158 40 35 4096 0 0 0 0 65536 0 0 65536 0 0
30 29 290000 10000 0 0 164 41 37 4096 0 0 0 0 65536 0 0 65536 0 0
31 30 300000 10000 0 0 154 43 39 685 685 0 0 0 65536 0 0 65536 0 0
32 31 310000 10000 0 0 172 46 35 582 582 0 0 0 65536 0 0 65536 0 0
33 32 320000 10000 0 0 180 49 34 567 567 0 0 0 65536 0 0 65536 0 0
34 33 330000 10000 0 0 145 51 35 567 567 0 0 0 65536 0 0 65536 0 0
35 34 340000 10000 0 0 203 53 37 582 582 0 0 0 65536 0 0 65536 0 0
36 35 350000 10000 0 0 154 55 39 731 731 0 0 0 65536 0 0 65536 0 0
37 36 360000 10000 0 0 144 57 37 4096 0 0 0 0 65536 0 0 65536 0 0
38 37 370000 10000 0 0 144 57 35 4096 0 0 0 0 65536 0 0 65536 0 0
39 38 380000 10000 0 0 132 57 34 4096 0 0 0 0 65536 0 0 65536 0 0
40 39 390000 10000 0 0 180 57 32 4096 0 0 0 0 65536 0 0 65536 0 0
41 40 400000 10000 0 0 220 63 29 4096 0 0 0 0 65536 0 0 65536 0 0
42 41 410000 10000 0 0 215 64 28 4096 24 0 0 0 65536 0 0 65536 0 0
43 42 420000 10000 0 0 208 68 29 4096 24 0 0 0 65536 0 0 65536 0 0
44 43 430000 10000 0 0 177 72 27 4096 24 0 0 0 65536 0 0 65536 0 0
45 44 440000 10000 0 0 199 77 28 4096 24 0 0 0 65536 0 0 65536 0 0
46 45 450000 10000 0 0 223 82 26 4096 30 0 0 0 65536 0 0 65536 0 0
47 46 460000 10000 0 0 202 85 24 4096 67 0 0 0 65536 0 0 65536 0 0
48 47 470000 10000 0 0 218 91 25 4096 198 0 0 0 65536 0 0 65536 0 0
49 48 480000 10000 0 0 221 92 26 4096 350 0 0 0 65536 0 0 65536 0 0
50 49 490000 10000 0 0 225 97 26 4096 528 0 0 0 65536 0 0 65536 0 0
51 50 500000 10000 0 0 214 100 27 4096 694 0 0 0 65536 0 0 65536 0 0
52 51 510000 10000 0 0 227 102 28 4096 883 0 0 0 65536 0 0 65536 0 0
53 52 520000 10000 0 0 208 102 29 4096 1043 0 0 0 65536 0 0 65536 0 0
54 53 530000 10000 0 0 207 102 30 4096 1202 0 0 0 65536 0 0 65536 0 0
55 54 540000 10000 0 0 200 102 31 4096 1319 0 0 0 65536 0 0 65536 0 0
56 55 550000 10000 0 0 205 103 32 4096 1464 0 0 0 65536 0 0 65536 0 0
57 56 560000 10000 0 0 211 103 32 4096 1620 0 0 0 65536 0 0 65536 0 0
58 57 570000 10000 0 0 193 110 33 4096 1712 0 0 0 65536 0 0 65536 0 0
59 58 580000 10000 0 0 190 5 67 4096 1775 0 0 0 65536 0 0 65536 0 0
File diff suppressed because it is too large Load Diff
+35
View File
@@ -11,11 +11,46 @@
#include <stdint.h>
#include "arch.h"
#include "console.h"
#include "starkernel/timer.h"
volatile const char *g_sk_fault_word = (void *)0;
extern void riscv64_install_vectors(void);
/* scause cause codes for supervisor-mode interrupts (RISC-V Privileged Spec
* §4.1.9, Table "Supervisor cause register values"). Only the timer is used;
* software (1) and external (9) interrupts are not enabled. */
#define SCAUSE_INTERRUPT_BIT (1ULL << 63)
#define SCAUSE_S_TIMER 5ULL
/**
* @brief Dispatch an asynchronous supervisor interrupt.
*
* Called from @c riscv64_trap_entry in @c isr.S when @c scause has bit 63 set.
* Unlike @c riscv64_exception_handler() this **returns** the trap entry
* restores the caller-saved register set and issues @c SRET.
*
* Supervisor timer (cause 5) is routed to @c heartbeat_tick(). No timer is
* armed yet: arming via the SBI TIME extension, enabling @c sie.STIE, and the
* mandatory per-tick re-arm are punch-list item 0.3. Until then this path is
* unreachable, which is why item 0.2 accepts on "boots with no regression"
* rather than on having observed an interrupt.
*
* Any other cause is ignored rather than fatal: an unexpected-but-harmless
* asynchronous interrupt should not take the kernel down, and none are
* currently enabled to arrive.
*
* @param scause Raw @c scause value, interrupt bit still set.
*/
void riscv64_interrupt_handler(uint64_t scause)
{
uint64_t cause = scause & ~SCAUSE_INTERRUPT_BIT;
if (cause == SCAUSE_S_TIMER) {
heartbeat_tick();
}
}
/**
* @brief Print a 64-bit value as "0xNNNNNNNNNNNNNNNN" to the kernel console.
*
+168 -5
View File
@@ -15,13 +15,176 @@
.hidden riscv64_trap_entry
.hidden riscv64_install_vectors
/* Direct-mode trap entry: stvec[1:0] = 0 means all traps branch here */
/* ---------------------------------------------------------------------------
* Trap frame layout (offsets from sp), 320 bytes, 16-byte aligned.
*
* Only the LP64D psABI's *caller-saved* registers are saved: a C handler
* preserves callee-saved registers itself, and the interrupted code already
* expects caller-saved registers to be clobbered across a call.
*
* integer caller-saved (16): ra, t0-t6, a0-a7
* FP caller-saved (20): ft0-ft11, fa0-fa7 + fcsr
* supervisor CSRs (2): sepc, sstatus
*
* The FP half is saved only when sstatus.FS != Off. Nothing in boot.S or
* kernel_entry.S programs FS, so its state is whatever firmware left; touching
* an f-register while FS == Off raises an illegal-instruction trap, which
* inside the trap handler would be unrecoverable. The kernel image does
* contain real FP code (fld/fmul.d/fcvt on the Q48.16 and statistics paths),
* so the save cannot simply be omitted -- it has to be conditional.
* ------------------------------------------------------------------------- */
.equ TF_RA, 0
.equ TF_T0, 8
.equ TF_T1, 16
.equ TF_T2, 24
.equ TF_T3, 32
.equ TF_T4, 40
.equ TF_T5, 48
.equ TF_T6, 56
.equ TF_A0, 64
.equ TF_A1, 72
.equ TF_A2, 80
.equ TF_A3, 88
.equ TF_A4, 96
.equ TF_A5, 104
.equ TF_A6, 112
.equ TF_A7, 120
.equ TF_SEPC, 128
.equ TF_SSTATUS,136
.equ TF_FCSR, 144
.equ TF_F0, 152 /* ft0-ft7 : 152 .. 208 */
.equ TF_FA0, 216 /* fa0-fa7 : 216 .. 272 */
.equ TF_FT8, 280 /* ft8-ft11 : 280 .. 304 */
.equ TF_SIZE, 320
/* sstatus.FS occupies bits [14:13]; 0 = Off */
.equ SSTATUS_FS_SHIFT, 13
.equ SSTATUS_FS_MASK, 3
/* Direct-mode trap entry: stvec[1:0] = 0 means all traps branch here.
* stvec requires 4-byte alignment. */
.balign 4
.global riscv64_trap_entry
riscv64_trap_entry:
call riscv64_exception_handler
/* Should not return; if it does, spin */
1: wfi
j 1b
addi sp, sp, -TF_SIZE
sd ra, TF_RA(sp)
sd t0, TF_T0(sp)
sd t1, TF_T1(sp)
sd t2, TF_T2(sp)
sd t3, TF_T3(sp)
sd t4, TF_T4(sp)
sd t5, TF_T5(sp)
sd t6, TF_T6(sp)
sd a0, TF_A0(sp)
sd a1, TF_A1(sp)
sd a2, TF_A2(sp)
sd a3, TF_A3(sp)
sd a4, TF_A4(sp)
sd a5, TF_A5(sp)
sd a6, TF_A6(sp)
sd a7, TF_A7(sp)
csrr t0, sepc
sd t0, TF_SEPC(sp)
csrr t0, sstatus
sd t0, TF_SSTATUS(sp)
/* Save FP only if FS != Off */
srli t1, t0, SSTATUS_FS_SHIFT
andi t1, t1, SSTATUS_FS_MASK
beqz t1, 1f
frcsr t2
sd t2, TF_FCSR(sp)
fsd ft0, TF_F0+0(sp)
fsd ft1, TF_F0+8(sp)
fsd ft2, TF_F0+16(sp)
fsd ft3, TF_F0+24(sp)
fsd ft4, TF_F0+32(sp)
fsd ft5, TF_F0+40(sp)
fsd ft6, TF_F0+48(sp)
fsd ft7, TF_F0+56(sp)
fsd fa0, TF_FA0+0(sp)
fsd fa1, TF_FA0+8(sp)
fsd fa2, TF_FA0+16(sp)
fsd fa3, TF_FA0+24(sp)
fsd fa4, TF_FA0+32(sp)
fsd fa5, TF_FA0+40(sp)
fsd fa6, TF_FA0+48(sp)
fsd fa7, TF_FA0+56(sp)
fsd ft8, TF_FT8+0(sp)
fsd ft9, TF_FT8+8(sp)
fsd ft10, TF_FT8+16(sp)
fsd ft11, TF_FT8+24(sp)
1:
/* scause bit 63 set => interrupt (negative when read as signed). */
csrr a0, scause
bltz a0, 2f
/* Synchronous exception: fatal, does not return. */
call riscv64_exception_handler
9: wfi
j 9b
2: /* Interrupt: a0 already holds scause for the C dispatcher. */
call riscv64_interrupt_handler
/* Restore. Reload the saved sstatus first -- it decides whether the FP
* half was written, and it must be restored *after* the f-registers so
* that FS is back to the interrupted context's value on exit. */
ld t0, TF_SSTATUS(sp)
srli t1, t0, SSTATUS_FS_SHIFT
andi t1, t1, SSTATUS_FS_MASK
beqz t1, 3f
ld t2, TF_FCSR(sp)
fscsr t2
fld ft0, TF_F0+0(sp)
fld ft1, TF_F0+8(sp)
fld ft2, TF_F0+16(sp)
fld ft3, TF_F0+24(sp)
fld ft4, TF_F0+32(sp)
fld ft5, TF_F0+40(sp)
fld ft6, TF_F0+48(sp)
fld ft7, TF_F0+56(sp)
fld fa0, TF_FA0+0(sp)
fld fa1, TF_FA0+8(sp)
fld fa2, TF_FA0+16(sp)
fld fa3, TF_FA0+24(sp)
fld fa4, TF_FA0+32(sp)
fld fa5, TF_FA0+40(sp)
fld fa6, TF_FA0+48(sp)
fld fa7, TF_FA0+56(sp)
fld ft8, TF_FT8+0(sp)
fld ft9, TF_FT8+8(sp)
fld ft10, TF_FT8+16(sp)
fld ft11, TF_FT8+24(sp)
3:
csrw sstatus, t0
ld t0, TF_SEPC(sp)
csrw sepc, t0
ld ra, TF_RA(sp)
ld t0, TF_T0(sp)
ld t1, TF_T1(sp)
ld t2, TF_T2(sp)
ld t3, TF_T3(sp)
ld t4, TF_T4(sp)
ld t5, TF_T5(sp)
ld t6, TF_T6(sp)
ld a0, TF_A0(sp)
ld a1, TF_A1(sp)
ld a2, TF_A2(sp)
ld a3, TF_A3(sp)
ld a4, TF_A4(sp)
ld a5, TF_A5(sp)
ld a6, TF_A6(sp)
ld a7, TF_A7(sp)
addi sp, sp, TF_SIZE
sret
.global riscv64_install_vectors
riscv64_install_vectors: