Compare commits

...

3 commits

Author SHA1 Message Date
Imbus
a1b9321a74 Zeroing all registers in kernel entry code 2024-08-07 11:26:45 +02:00
Imbus
ad34ff9b86 Removing redundant imports 2024-08-07 11:26:33 +02:00
Imbus
be6678c0e6 Helpful comments in assembly and linker script files 2024-08-07 11:26:07 +02:00
8 changed files with 124 additions and 43 deletions

View file

@ -1,21 +1,65 @@
# 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.
# For a quick reference on RISC-V assembly:
# https://risc-v.guru/instructions/
# 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
.global _entry
_entry:
# Clear all the registers.
li x1, 0x0
li x2, 0x0
li x3, 0x0
li x4, 0x0
li x5, 0x0
li x6, 0x0
li x7, 0x0
li x8, 0x0
li x9, 0x0
li x10, 0x0
li x11, 0x0
li x12, 0x0
li x13, 0x0
li x14, 0x0
li x15, 0x0
li x16, 0x0
li x17, 0x0
li x18, 0x0
li x19, 0x0
li x20, 0x0
li x21, 0x0
li x22, 0x0
li x23, 0x0
li x24, 0x0
li x25, 0x0
li x26, 0x0
li x27, 0x0
li x28, 0x0
li x29, 0x0
li x30, 0x0
li x31, 0x0
# set up a stack for C.
# stack0 is declared in start.c,
# with a 4096-byte stack per CPU.
# sp = stack0 + (hartid * 4096)
la sp, stack0
li a0, 1024*4
csrr a1, mhartid
addi a1, a1, 1
mul a0, a0, a1
add sp, sp, a0
li a0, 1024*4 # a0 = 4096
# Control and Status Register Read
csrr a1, mhartid # a1 = unique hart (core) id
addi a1, a1, 1 # a1 += 1
mul a0, a0, a1 # a0 *= a1, aka a0 = 4096 * (hartid + 1), the base of the stack for this hart
add sp, sp, a0 # sp += a0, stack pointer is now properly configured
# jump to start() in start.c
call start
# Infinite spin loop.
spin:
j spin

View file

@ -9,6 +9,11 @@ SECTIONS
*/
. = 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.*)
. = ALIGN(0x1000);
@ -19,6 +24,10 @@ SECTIONS
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 : {
. = ALIGN(16);
*(.srodata .srodata.*) /* do not need to distinguish this from .rodata */
@ -26,6 +35,10 @@ SECTIONS
*(.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 : {
. = ALIGN(16);
*(.sdata .sdata.*) /* do not need to distinguish this from .data */
@ -33,6 +46,12 @@ SECTIONS
*(.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 : {
. = ALIGN(16);
*(.sbss .sbss.*) /* do not need to distinguish this from .bss */
@ -40,5 +59,6 @@ SECTIONS
*(.bss .bss.*)
}
/* PROVIDE, see vm.c */
PROVIDE(end = .);
}

View file

@ -1,11 +1,15 @@
#
# interrupts and exceptions while in supervisor
# mode come here.
#
# the current stack is a kernel stack.
# push all registers, call kerneltrap().
# when kerneltrap() returns, restore registers, return.
#
# For a quick reference on RISC-V assembly:
# https://risc-v.guru/instructions/
# Kernel trap handling
#
# interrupts and exceptions while in supervisor
# mode come here.
#
# the current stack is a kernel stack.
# push all registers, call kerneltrap().
# when kerneltrap() returns, restore registers, return.
.globl kerneltrap
.globl kernelvec
.align 4
@ -53,7 +57,8 @@ kernelvec:
ld ra, 0(sp)
ld sp, 8(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 t1, 40(sp)
ld t2, 48(sp)
@ -87,9 +92,11 @@ kernelvec:
# return to whatever we were doing in the kernel.
sret
#
# machine-mode timer interrupt.
#
# machine-mode timer interrupt
#
# See: start.c for timervec declaration
# extern void timervec();
.globl timervec
.align 4
timervec:
@ -97,7 +104,7 @@ timervec:
# scratch[0,8,16] : register save area.
# scratch[24] : address of CLINT's MTIMECMP register.
# scratch[32] : desired interval between interrupts.
csrrw a0, mscratch, a0
sd a1, 0(a0)
sd a2, 8(a0)

View file

@ -2,7 +2,6 @@
#include "param.h"
#include "memlayout.h"
#include "riscv.h"
#include "defs.h"
void main();
void timerinit();

View file

@ -1,12 +1,18 @@
# For a quick reference on RISC-V assembly:
# https://risc-v.guru/instructions/
# Context switch
#
# void swtch(struct context *old, struct context *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
swtch:
# sd = Store Double (64 bits)
sd ra, 0(a0)
sd sp, 8(a0)
sd s0, 16(a0)
@ -22,6 +28,7 @@ swtch:
sd s10, 96(a0)
sd s11, 104(a0)
# ld = Load Double (64 bits)
ld ra, 0(a1)
ld sp, 8(a1)
ld s0, 16(a1)
@ -36,7 +43,7 @@ swtch:
ld s9, 88(a1)
ld s10, 96(a1)
ld s11, 104(a1)
ret

View file

@ -1,14 +1,17 @@
#
# low-level code to handle traps from user space into
# the kernel, and returns from kernel to user.
#
# the kernel maps the page holding this code
# 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.
#
# For a quick reference on RISC-V assembly:
# https://risc-v.guru/instructions/
# Trampoline code
#
# low-level code to handle traps from user space into
# the kernel, and returns from kernel to user.
#
# the kernel maps the page holding this code
# 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 "memlayout.h"
@ -18,7 +21,7 @@
trampoline:
.align 4
.globl uservec
uservec:
uservec:
#
# trap.c sets stvec to point here, so
# traps from user space start here,
@ -34,7 +37,7 @@ uservec:
# but it's mapped to the same virtual address
# (TRAPFRAME) in every process's user page table.
li a0, TRAPFRAME
# save the user registers in TRAPFRAME
sd ra, 40(a0)
sd sp, 48(a0)
@ -145,7 +148,7 @@ userret:
# restore user a0
ld a0, 112(a0)
# return to user mode and user pc.
# usertrapret() set up sstatus and sepc.
sret

View file

@ -1,3 +1,6 @@
# For a quick reference on RISC-V assembly:
# https://risc-v.guru/instructions/
# Initial process that execs /init.
# This code runs in user space.

View file

@ -1,5 +1,3 @@
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
int