Compare commits
No commits in common. "a1b9321a74b357a3e40a8061bd6f30f01628ae8b" and "7a3c98f2b433d59c0b661fc785bd18162741f3ae" have entirely different histories.
a1b9321a74
...
7a3c98f2b4
8 changed files with 43 additions and 124 deletions
|
@ -1,65 +1,21 @@
|
||||||
# For a quick reference on RISC-V assembly:
|
# qemu -kernel loads the kernel at 0x80000000
|
||||||
# https://risc-v.guru/instructions/
|
# and causes each hart (i.e. CPU) to jump there.
|
||||||
|
# kernel.ld causes the following code to
|
||||||
# Kernel entry point
|
# be placed at 0x80000000.
|
||||||
#
|
|
||||||
# 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:
|
||||||
# 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.
|
# set up a stack for C.
|
||||||
# stack0 is declared in start.c,
|
# stack0 is declared in start.c,
|
||||||
# with a 4096-byte stack per CPU.
|
# with a 4096-byte stack per CPU.
|
||||||
# sp = stack0 + (hartid * 4096)
|
# sp = stack0 + (hartid * 4096)
|
||||||
la sp, stack0
|
la sp, stack0
|
||||||
li a0, 1024*4 # a0 = 4096
|
li a0, 1024*4
|
||||||
|
csrr a1, mhartid
|
||||||
# Control and Status Register Read
|
addi a1, a1, 1
|
||||||
csrr a1, mhartid # a1 = unique hart (core) id
|
mul a0, a0, a1
|
||||||
addi a1, a1, 1 # a1 += 1
|
add sp, sp, a0
|
||||||
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
|
# jump to start() in start.c
|
||||||
call start
|
call start
|
||||||
|
|
||||||
# Infinite spin loop.
|
|
||||||
spin:
|
spin:
|
||||||
j spin
|
j spin
|
||||||
|
|
|
@ -9,11 +9,6 @@ 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);
|
||||||
|
@ -24,10 +19,6 @@ 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 */
|
||||||
|
@ -35,10 +26,6 @@ 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 */
|
||||||
|
@ -46,12 +33,6 @@ 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 */
|
||||||
|
@ -59,6 +40,5 @@ SECTIONS
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PROVIDE, see vm.c */
|
|
||||||
PROVIDE(end = .);
|
PROVIDE(end = .);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
# For a quick reference on RISC-V assembly:
|
#
|
||||||
# https://risc-v.guru/instructions/
|
# interrupts and exceptions while in supervisor
|
||||||
|
# mode come here.
|
||||||
# Kernel trap handling
|
#
|
||||||
#
|
# the current stack is a kernel stack.
|
||||||
# interrupts and exceptions while in supervisor
|
# push all registers, call kerneltrap().
|
||||||
# mode come here.
|
# when kerneltrap() returns, restore registers, return.
|
||||||
#
|
#
|
||||||
# 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
|
||||||
|
@ -57,8 +53,7 @@ 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)
|
||||||
# Skip tp (thread pointer aka x4) (contains hartid)
|
# not tp (contains hartid), in case we moved CPUs
|
||||||
# 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)
|
||||||
|
@ -92,11 +87,9 @@ 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:
|
||||||
|
@ -104,7 +97,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)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "memlayout.h"
|
#include "memlayout.h"
|
||||||
#include "riscv.h"
|
#include "riscv.h"
|
||||||
|
#include "defs.h"
|
||||||
|
|
||||||
void main();
|
void main();
|
||||||
void timerinit();
|
void timerinit();
|
||||||
|
|
|
@ -1,18 +1,12 @@
|
||||||
# For a quick reference on RISC-V assembly:
|
|
||||||
# https://risc-v.guru/instructions/
|
|
||||||
|
|
||||||
# Context switch
|
# Context switch
|
||||||
#
|
#
|
||||||
# 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);
|
# void swtch(struct context *old, struct context *new);
|
||||||
|
#
|
||||||
|
# Save current registers in old. Load from 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)
|
||||||
|
@ -28,7 +22,6 @@ 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)
|
||||||
|
@ -43,7 +36,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,17 +1,14 @@
|
||||||
# For a quick reference on RISC-V assembly:
|
#
|
||||||
# https://risc-v.guru/instructions/
|
# low-level code to handle traps from user space into
|
||||||
|
# the kernel, and returns from kernel to user.
|
||||||
# Trampoline code
|
#
|
||||||
#
|
# the kernel maps the page holding this code
|
||||||
# low-level code to handle traps from user space into
|
# at the same virtual address (TRAMPOLINE)
|
||||||
# the kernel, and returns from kernel to user.
|
# in user and kernel space so that it continues
|
||||||
#
|
# to work when it switches page tables.
|
||||||
# the kernel maps the page holding this code
|
# kernel.ld causes this code to start at
|
||||||
# at the same virtual address (TRAMPOLINE)
|
# a page boundary.
|
||||||
# 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"
|
||||||
|
@ -21,7 +18,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,
|
||||||
|
@ -37,7 +34,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)
|
||||||
|
@ -148,7 +145,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,6 +1,3 @@
|
||||||
# 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.
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include "kernel/types.h"
|
||||||
|
#include "kernel/stat.h"
|
||||||
#include "user/user.h"
|
#include "user/user.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
Loading…
Reference in a new issue