xv6, line by line
kernel/kernelvec.S

kernel/kernelvec.S

RISC-V assembly · 64 lines · annotated 100% · kernel · upstream

About this file

The entry point for traps that happen while the kernel is running: a timer or device interrupt that arrives during a system call or in the scheduler’s idle loop, or (by mistake) an exception in kernel code. trapinithart points stvec here at boot, and usertrap points it here again each time a process enters the kernel.

It is much simpler than kernel/trampoline.S. The hart is already in the kernel, with the kernel page table, a valid kernel stack in sp and the hart ID in tp. So kernelvec only has to push the registers that a C function is allowed to destroy, call kerneltrap in kernel/trap.c, pop them, and return with sret to the interrupted kernel instruction.

Read before: kernel/trampoline.S, for contrast. Read next: kerneltrap.

1 #
2 # interrupts and exceptions while in supervisor
3 # mode come here.
4 #
5 # the current stack is a kernel stack.
6 # push registers, call kerneltrap().
7 # when kerneltrap() returns, restore registers, return.
8 #
11.align 4
13 # make room to save registers.
14 addi sp, sp, -256
16 # save caller-saved registers.
17 sd ra, 0(sp)
18 # sd sp, 8(sp)
19 sd gp, 16(sp)
20 # sd tp, 24(sp)
21 sd t0, 32(sp)
22 sd t1, 40(sp)
23 sd t2, 48(sp)
24 sd a0, 72(sp)
25 sd a1, 80(sp)
26 sd a2, 88(sp)
27 sd a3, 96(sp)
28 sd a4, 104(sp)
29 sd a5, 112(sp)
30 sd a6, 120(sp)
31 sd a7, 128(sp)
32 sd t3, 216(sp)
33 sd t4, 224(sp)
34 sd t5, 232(sp)
35 sd t6, 240(sp)
37 # call the C trap handler in trap.c
40 # restore registers.
41 ld ra, 0(sp)
42 # ld sp, 8(sp)
43 ld gp, 16(sp)
44 # not tp (contains hartid), in case we moved CPUs
45 ld t0, 32(sp)
46 ld t1, 40(sp)
47 ld t2, 48(sp)
48 ld a0, 72(sp)
49 ld a1, 80(sp)
50 ld a2, 88(sp)
51 ld a3, 96(sp)
52 ld a4, 104(sp)
53 ld a5, 112(sp)
54 ld a6, 120(sp)
55 ld a7, 128(sp)
56 ld t3, 216(sp)
57 ld t4, 224(sp)
58 ld t5, 232(sp)
59 ld t6, 240(sp)
61 addi sp, sp, 256
63 # return to whatever we were doing in the kernel.
64 sret