Compare commits
6 commits
5948d6c8e8
...
5dbcb33726
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5dbcb33726 | ||
![]() |
58bface3c9 | ||
![]() |
93295eaeb8 | ||
![]() |
74fdd26759 | ||
![]() |
f48e74bebe | ||
![]() |
f1f480251c |
9 changed files with 70 additions and 19 deletions
2
Makefile
2
Makefile
|
@ -27,7 +27,7 @@ CFLAGS += -fno-omit-frame-pointer # More reliable backtraces in GDB
|
|||
|
||||
all: kernel.elf
|
||||
|
||||
kernel.elf: entry.o start.o lib/string.o lib/proc.o lib/spinlock.o lib/proc.o
|
||||
kernel.elf: entry.o start.o lib/string.o lib/proc.o lib/spinlock.o lib/proc.o lib/uart.o lib/panic.o
|
||||
@echo LD $@
|
||||
@$(LD) $(LDFLAGS) -o $@ $^
|
||||
|
||||
|
|
20
README.md
20
README.md
|
@ -6,3 +6,23 @@ For a quick reference on RISC-V assembly:
|
|||
Toolchains:
|
||||
- https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack
|
||||
- https://github.com/xpack-dev-tools/qemu-riscv-xpack/
|
||||
|
||||
---
|
||||
|
||||
| Register | Name | Privilege Level | Description |
|
||||
|-------------|----------------------------|------------------|-----------------------------------------------------------------------------|
|
||||
| `mstatus` | Machine Status Register | Machine | Holds global interrupt enable, previous privilege mode, etc. |
|
||||
| `mtvec` | Machine Trap-Vector Base | Machine | Holds the base address of the trap handler (exception/interrupt entry). |
|
||||
| `mepc` | Machine Exception PC | Machine | Stores the program counter at the time of the last trap. |
|
||||
| `mcause` | Machine Cause Register | Machine | Indicates the cause of the last trap (interrupt or exception). |
|
||||
| `satp` | Supervisor Address Translation and Protection | Supervisor | Controls page table base address and mode (e.g., Sv39, Sv48). |
|
||||
| `sstatus` | Supervisor Status Register | Supervisor | Like `mstatus`, but accessible from supervisor mode. |
|
||||
| `stvec` | Supervisor Trap-Vector Base| Supervisor | Like `mtvec`, but for supervisor mode traps. |
|
||||
| `sepc` | Supervisor Exception PC | Supervisor | Like `mepc`, but for supervisor mode. |
|
||||
| `scause` | Supervisor Cause Register | Supervisor | Like `mcause`, but for supervisor mode traps. |
|
||||
| `sscratch` | Supervisor Scratch | Supervisor | Can be used to store temporary state across traps in supervisor mode. |
|
||||
| `mscratch` | Machine Scratch | Machine | Like `sscratch`, but in machine mode. |
|
||||
| `mcycle` | Machine Cycle Counter | Machine | Counts the number of cycles executed. |
|
||||
| `mtime` | Machine Timer Register | Machine (via memory-mapped) | Used for timing and scheduling (not a CSR, but a memory-mapped register). |
|
||||
| `mip` | Machine Interrupt Pending | Machine | Indicates pending interrupts. |
|
||||
| `mie` | Machine Interrupt Enable | Machine | Controls which interrupts are enabled. |
|
||||
|
|
8
lib/panic.c
Normal file
8
lib/panic.c
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <uart.h>
|
||||
volatile int panicked;
|
||||
|
||||
void panic(char *s) {
|
||||
panicked = 1;
|
||||
uart_puts(s);
|
||||
while (1);
|
||||
}
|
6
lib/panic.h
Normal file
6
lib/panic.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#ifndef KERNEL_PANIC_H
|
||||
#define KERNEL_PANIC_H
|
||||
|
||||
void panic(char *s);
|
||||
|
||||
#endif
|
|
@ -4,13 +4,11 @@
|
|||
*/
|
||||
|
||||
// #include <lib/stdio.h>
|
||||
#include <panic.h>
|
||||
#include <proc.h>
|
||||
#include <riscv.h>
|
||||
#include <spinlock.h>
|
||||
|
||||
// void panic(char *s) { for (;;); }
|
||||
void panic(char *s) {}
|
||||
|
||||
/**
|
||||
* The aquire() and release() functions control ownership of the lock.
|
||||
* To perform these operations, modern CPU's provide atomic instructions
|
||||
|
@ -60,8 +58,8 @@ void acquire(struct spinlock *lk) {
|
|||
panic("acquire");
|
||||
|
||||
// Spin until aquired. See file header for details
|
||||
while (__sync_lock_test_and_set(&lk->locked, 1) != 0) {
|
||||
}
|
||||
while (__sync_lock_test_and_set(&lk->locked, 1) != 0);
|
||||
|
||||
__sync_synchronize(); // No loads/stores after this point
|
||||
|
||||
// Record info about lock acquisition for holding() and debugging.
|
||||
|
|
9
lib/uart.c
Normal file
9
lib/uart.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* QEMU memory maps a UART device here. */
|
||||
#define UART_BASE ((volatile char *)0x10000000)
|
||||
|
||||
void uart_putc(char c) { *UART_BASE = c; }
|
||||
|
||||
void uart_puts(const char *s) {
|
||||
while (*s) uart_putc(*s++);
|
||||
}
|
||||
|
10
lib/uart.h
Normal file
10
lib/uart.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef UART_KERNEL_H
|
||||
#define UART_KERNEL_H
|
||||
|
||||
/** Send a single character to the UART device */
|
||||
void uart_putc(char c);
|
||||
|
||||
/** Send a **NULL TERMINATED** string to the UART device */
|
||||
void uart_puts(const char *s);
|
||||
|
||||
#endif
|
3
riscv.h
3
riscv.h
|
@ -40,6 +40,9 @@ static inline u64 r_tp() {
|
|||
return x;
|
||||
}
|
||||
|
||||
/** Write thread pointer */
|
||||
static inline void w_tp(u64 x) { asm volatile("mv tp, %0" : : "r"(x)); }
|
||||
|
||||
/**
|
||||
* Read the value of the sstatus register.
|
||||
* (Supervisor Status Register)
|
||||
|
|
23
start.c
23
start.c
|
@ -1,18 +1,10 @@
|
|||
#include <config.h>
|
||||
#include <proc.h>
|
||||
#include <riscv.h>
|
||||
#include <spinlock.h>
|
||||
#include <string.h>
|
||||
#include <types.h>
|
||||
|
||||
/* QEMU memory maps a UART device here. */
|
||||
#define UART_BASE ((volatile char *)0x10000000)
|
||||
|
||||
/** Send a single character to the UART device */
|
||||
void uart_putc(char c) { *UART_BASE = c; }
|
||||
|
||||
/** Send a **NULL TERMINATED** string to the UART device */
|
||||
void uart_puts(const char *s) {
|
||||
while (*s) uart_putc(*s++);
|
||||
}
|
||||
#include <uart.h>
|
||||
|
||||
/**
|
||||
* Allocate one stack per CPU (hart).
|
||||
|
@ -28,8 +20,13 @@ volatile int greeted = 0;
|
|||
|
||||
/* This is where entry.S drops us of. All cores land here */
|
||||
void start() {
|
||||
u64 id = r_mhartid();
|
||||
|
||||
u64 a = r_mhartid();
|
||||
// Keep each CPU's hartid in its tp (thread pointer) register, for cpuid().
|
||||
// This can then be retrieved with r_wp or cpuid(). It is used to index the
|
||||
// cpus[] array in mycpu(), which in turn holds state for each individual
|
||||
// cpu (struct Cpu).
|
||||
w_tp(id);
|
||||
|
||||
acquire(&sl);
|
||||
|
||||
|
@ -39,7 +36,7 @@ void start() {
|
|||
}
|
||||
|
||||
uart_puts("Hart number: ");
|
||||
uart_putc(a + '0');
|
||||
uart_putc(id + '0');
|
||||
uart_putc('\n');
|
||||
|
||||
release(&sl);
|
||||
|
|
Loading…
Add table
Reference in a new issue