Helpful comments in assembly and linker script files
This commit is contained in:
parent
7a3c98f2b4
commit
be6678c0e6
6 changed files with 81 additions and 35 deletions
|
@ -1,7 +1,13 @@
|
||||||
# qemu -kernel loads the kernel at 0x80000000
|
# For a quick reference on RISC-V assembly:
|
||||||
# and causes each hart (i.e. CPU) to jump there.
|
# https://risc-v.guru/instructions/
|
||||||
# kernel.ld causes the following code to
|
|
||||||
# be placed at 0x80000000.
|
# Kernel entry point
|
||||||
|
#
|
||||||
|
# qemu -kernel loads the kernel at 0x80000000
|
||||||
|
# and causes each hart (i.e. CPU) to jump there.
|
||||||
|
# kernel.ld causes the following code to
|
||||||
|
# be placed at 0x80000000.
|
||||||
|
|
||||||
.section .text
|
.section .text
|
||||||
.global _entry
|
.global _entry
|
||||||
_entry:
|
_entry:
|
||||||
|
|
|
@ -9,6 +9,11 @@ SECTIONS
|
||||||
*/
|
*/
|
||||||
. = 0x80000000;
|
. = 0x80000000;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This section contains the code. This is, the machine language instructions
|
||||||
|
* that will be executed by the processor. In here we will find symbols
|
||||||
|
* that reference the functions in your object file.
|
||||||
|
*/
|
||||||
.text : {
|
.text : {
|
||||||
*(.text .text.*)
|
*(.text .text.*)
|
||||||
. = ALIGN(0x1000);
|
. = ALIGN(0x1000);
|
||||||
|
@ -19,6 +24,10 @@ SECTIONS
|
||||||
PROVIDE(etext = .);
|
PROVIDE(etext = .);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This contains any data that is marked as read only.
|
||||||
|
* It is not unusual to find this data interleaved with the text section.
|
||||||
|
*/
|
||||||
.rodata : {
|
.rodata : {
|
||||||
. = ALIGN(16);
|
. = ALIGN(16);
|
||||||
*(.srodata .srodata.*) /* do not need to distinguish this from .rodata */
|
*(.srodata .srodata.*) /* do not need to distinguish this from .rodata */
|
||||||
|
@ -26,6 +35,10 @@ SECTIONS
|
||||||
*(.rodata .rodata.*)
|
*(.rodata .rodata.*)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This section contains initialized global and static variables.
|
||||||
|
* Any global object that has been explicitly initialized to a value different than zero.
|
||||||
|
*/
|
||||||
.data : {
|
.data : {
|
||||||
. = ALIGN(16);
|
. = ALIGN(16);
|
||||||
*(.sdata .sdata.*) /* do not need to distinguish this from .data */
|
*(.sdata .sdata.*) /* do not need to distinguish this from .data */
|
||||||
|
@ -33,6 +46,12 @@ SECTIONS
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Contains all uninitialized global and static var iables. These are usually
|
||||||
|
* zeroed out by the startup code before we reach the main function. However,
|
||||||
|
* In an embedded system we usually provide our own startup code, which means
|
||||||
|
* we need to remember to do this ourselves.
|
||||||
|
*/
|
||||||
.bss : {
|
.bss : {
|
||||||
. = ALIGN(16);
|
. = ALIGN(16);
|
||||||
*(.sbss .sbss.*) /* do not need to distinguish this from .bss */
|
*(.sbss .sbss.*) /* do not need to distinguish this from .bss */
|
||||||
|
@ -40,5 +59,6 @@ SECTIONS
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* PROVIDE, see vm.c */
|
||||||
PROVIDE(end = .);
|
PROVIDE(end = .);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
#
|
# For a quick reference on RISC-V assembly:
|
||||||
# interrupts and exceptions while in supervisor
|
# https://risc-v.guru/instructions/
|
||||||
# mode come here.
|
|
||||||
#
|
# Kernel trap handling
|
||||||
# the current stack is a kernel stack.
|
#
|
||||||
# push all registers, call kerneltrap().
|
# interrupts and exceptions while in supervisor
|
||||||
# when kerneltrap() returns, restore registers, return.
|
# mode come here.
|
||||||
#
|
#
|
||||||
|
# the current stack is a kernel stack.
|
||||||
|
# push all registers, call kerneltrap().
|
||||||
|
# when kerneltrap() returns, restore registers, return.
|
||||||
|
|
||||||
.globl kerneltrap
|
.globl kerneltrap
|
||||||
.globl kernelvec
|
.globl kernelvec
|
||||||
.align 4
|
.align 4
|
||||||
|
@ -53,7 +57,8 @@ kernelvec:
|
||||||
ld ra, 0(sp)
|
ld ra, 0(sp)
|
||||||
ld sp, 8(sp)
|
ld sp, 8(sp)
|
||||||
ld gp, 16(sp)
|
ld gp, 16(sp)
|
||||||
# not tp (contains hartid), in case we moved CPUs
|
# Skip tp (thread pointer aka x4) (contains hartid)
|
||||||
|
# in case we moved CPUs
|
||||||
ld t0, 32(sp)
|
ld t0, 32(sp)
|
||||||
ld t1, 40(sp)
|
ld t1, 40(sp)
|
||||||
ld t2, 48(sp)
|
ld t2, 48(sp)
|
||||||
|
@ -87,9 +92,11 @@ kernelvec:
|
||||||
# return to whatever we were doing in the kernel.
|
# return to whatever we were doing in the kernel.
|
||||||
sret
|
sret
|
||||||
|
|
||||||
#
|
# machine-mode timer interrupt
|
||||||
# machine-mode timer interrupt.
|
#
|
||||||
#
|
# See: start.c for timervec declaration
|
||||||
|
# extern void timervec();
|
||||||
|
|
||||||
.globl timervec
|
.globl timervec
|
||||||
.align 4
|
.align 4
|
||||||
timervec:
|
timervec:
|
||||||
|
@ -97,7 +104,7 @@ timervec:
|
||||||
# scratch[0,8,16] : register save area.
|
# scratch[0,8,16] : register save area.
|
||||||
# scratch[24] : address of CLINT's MTIMECMP register.
|
# scratch[24] : address of CLINT's MTIMECMP register.
|
||||||
# scratch[32] : desired interval between interrupts.
|
# scratch[32] : desired interval between interrupts.
|
||||||
|
|
||||||
csrrw a0, mscratch, a0
|
csrrw a0, mscratch, a0
|
||||||
sd a1, 0(a0)
|
sd a1, 0(a0)
|
||||||
sd a2, 8(a0)
|
sd a2, 8(a0)
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
|
# For a quick reference on RISC-V assembly:
|
||||||
|
# https://risc-v.guru/instructions/
|
||||||
|
|
||||||
# Context switch
|
# Context switch
|
||||||
#
|
#
|
||||||
# void swtch(struct context *old, struct context *new);
|
|
||||||
#
|
|
||||||
# Save current registers in old. Load from new.
|
# Save current registers in old. Load from new.
|
||||||
|
#
|
||||||
|
# See: defs.h for swtch declaration
|
||||||
|
# See: proc.h for struct context definition
|
||||||
|
#
|
||||||
|
# void swtch(struct context *old, struct context *new);
|
||||||
|
|
||||||
.globl swtch
|
.globl swtch
|
||||||
swtch:
|
swtch:
|
||||||
|
# sd = Store Double (64 bits)
|
||||||
sd ra, 0(a0)
|
sd ra, 0(a0)
|
||||||
sd sp, 8(a0)
|
sd sp, 8(a0)
|
||||||
sd s0, 16(a0)
|
sd s0, 16(a0)
|
||||||
|
@ -22,6 +28,7 @@ swtch:
|
||||||
sd s10, 96(a0)
|
sd s10, 96(a0)
|
||||||
sd s11, 104(a0)
|
sd s11, 104(a0)
|
||||||
|
|
||||||
|
# ld = Load Double (64 bits)
|
||||||
ld ra, 0(a1)
|
ld ra, 0(a1)
|
||||||
ld sp, 8(a1)
|
ld sp, 8(a1)
|
||||||
ld s0, 16(a1)
|
ld s0, 16(a1)
|
||||||
|
@ -36,7 +43,7 @@ swtch:
|
||||||
ld s9, 88(a1)
|
ld s9, 88(a1)
|
||||||
ld s10, 96(a1)
|
ld s10, 96(a1)
|
||||||
ld s11, 104(a1)
|
ld s11, 104(a1)
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
#
|
# For a quick reference on RISC-V assembly:
|
||||||
# low-level code to handle traps from user space into
|
# https://risc-v.guru/instructions/
|
||||||
# the kernel, and returns from kernel to user.
|
|
||||||
#
|
# Trampoline code
|
||||||
# the kernel maps the page holding this code
|
#
|
||||||
# at the same virtual address (TRAMPOLINE)
|
# low-level code to handle traps from user space into
|
||||||
# in user and kernel space so that it continues
|
# the kernel, and returns from kernel to user.
|
||||||
# to work when it switches page tables.
|
#
|
||||||
# kernel.ld causes this code to start at
|
# the kernel maps the page holding this code
|
||||||
# a page boundary.
|
# at the same virtual address (TRAMPOLINE)
|
||||||
#
|
# in user and kernel space so that it continues
|
||||||
|
# to work when it switches page tables.
|
||||||
|
# kernel.ld causes this code to start at
|
||||||
|
# a page boundary.
|
||||||
|
|
||||||
#include "riscv.h"
|
#include "riscv.h"
|
||||||
#include "memlayout.h"
|
#include "memlayout.h"
|
||||||
|
@ -18,7 +21,7 @@
|
||||||
trampoline:
|
trampoline:
|
||||||
.align 4
|
.align 4
|
||||||
.globl uservec
|
.globl uservec
|
||||||
uservec:
|
uservec:
|
||||||
#
|
#
|
||||||
# trap.c sets stvec to point here, so
|
# trap.c sets stvec to point here, so
|
||||||
# traps from user space start here,
|
# traps from user space start here,
|
||||||
|
@ -34,7 +37,7 @@ uservec:
|
||||||
# but it's mapped to the same virtual address
|
# but it's mapped to the same virtual address
|
||||||
# (TRAPFRAME) in every process's user page table.
|
# (TRAPFRAME) in every process's user page table.
|
||||||
li a0, TRAPFRAME
|
li a0, TRAPFRAME
|
||||||
|
|
||||||
# save the user registers in TRAPFRAME
|
# save the user registers in TRAPFRAME
|
||||||
sd ra, 40(a0)
|
sd ra, 40(a0)
|
||||||
sd sp, 48(a0)
|
sd sp, 48(a0)
|
||||||
|
@ -145,7 +148,7 @@ userret:
|
||||||
|
|
||||||
# restore user a0
|
# restore user a0
|
||||||
ld a0, 112(a0)
|
ld a0, 112(a0)
|
||||||
|
|
||||||
# return to user mode and user pc.
|
# return to user mode and user pc.
|
||||||
# usertrapret() set up sstatus and sepc.
|
# usertrapret() set up sstatus and sepc.
|
||||||
sret
|
sret
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
# For a quick reference on RISC-V assembly:
|
||||||
|
# https://risc-v.guru/instructions/
|
||||||
|
|
||||||
# Initial process that execs /init.
|
# Initial process that execs /init.
|
||||||
# This code runs in user space.
|
# This code runs in user space.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue