Compare commits
No commits in common. "5dbcb337266595a63e745c03981d4b62f5608b2a" and "5948d6c8e8b09cef1f4e21a298a8ff1abf17b364" have entirely different histories.
5dbcb33726
...
5948d6c8e8
9 changed files with 19 additions and 70 deletions
2
Makefile
2
Makefile
|
@ -27,7 +27,7 @@ CFLAGS += -fno-omit-frame-pointer # More reliable backtraces in GDB
|
||||||
|
|
||||||
all: kernel.elf
|
all: kernel.elf
|
||||||
|
|
||||||
kernel.elf: entry.o start.o lib/string.o lib/proc.o lib/spinlock.o lib/proc.o lib/uart.o lib/panic.o
|
kernel.elf: entry.o start.o lib/string.o lib/proc.o lib/spinlock.o lib/proc.o
|
||||||
@echo LD $@
|
@echo LD $@
|
||||||
@$(LD) $(LDFLAGS) -o $@ $^
|
@$(LD) $(LDFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
|
20
README.md
20
README.md
|
@ -6,23 +6,3 @@ For a quick reference on RISC-V assembly:
|
||||||
Toolchains:
|
Toolchains:
|
||||||
- https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack
|
- https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack
|
||||||
- https://github.com/xpack-dev-tools/qemu-riscv-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. |
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
#include <uart.h>
|
|
||||||
volatile int panicked;
|
|
||||||
|
|
||||||
void panic(char *s) {
|
|
||||||
panicked = 1;
|
|
||||||
uart_puts(s);
|
|
||||||
while (1);
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
#ifndef KERNEL_PANIC_H
|
|
||||||
#define KERNEL_PANIC_H
|
|
||||||
|
|
||||||
void panic(char *s);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -4,11 +4,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// #include <lib/stdio.h>
|
// #include <lib/stdio.h>
|
||||||
#include <panic.h>
|
|
||||||
#include <proc.h>
|
#include <proc.h>
|
||||||
#include <riscv.h>
|
#include <riscv.h>
|
||||||
#include <spinlock.h>
|
#include <spinlock.h>
|
||||||
|
|
||||||
|
// void panic(char *s) { for (;;); }
|
||||||
|
void panic(char *s) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The aquire() and release() functions control ownership of the lock.
|
* The aquire() and release() functions control ownership of the lock.
|
||||||
* To perform these operations, modern CPU's provide atomic instructions
|
* To perform these operations, modern CPU's provide atomic instructions
|
||||||
|
@ -58,8 +60,8 @@ void acquire(struct spinlock *lk) {
|
||||||
panic("acquire");
|
panic("acquire");
|
||||||
|
|
||||||
// Spin until aquired. See file header for details
|
// 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
|
__sync_synchronize(); // No loads/stores after this point
|
||||||
|
|
||||||
// Record info about lock acquisition for holding() and debugging.
|
// Record info about lock acquisition for holding() and debugging.
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
/* 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
10
lib/uart.h
|
@ -1,10 +0,0 @@
|
||||||
#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,9 +40,6 @@ static inline u64 r_tp() {
|
||||||
return x;
|
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.
|
* Read the value of the sstatus register.
|
||||||
* (Supervisor Status Register)
|
* (Supervisor Status Register)
|
||||||
|
|
23
start.c
23
start.c
|
@ -1,10 +1,18 @@
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <proc.h>
|
|
||||||
#include <riscv.h>
|
#include <riscv.h>
|
||||||
#include <spinlock.h>
|
#include <spinlock.h>
|
||||||
#include <string.h>
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include <uart.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++);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate one stack per CPU (hart).
|
* Allocate one stack per CPU (hart).
|
||||||
|
@ -20,13 +28,8 @@ volatile int greeted = 0;
|
||||||
|
|
||||||
/* This is where entry.S drops us of. All cores land here */
|
/* This is where entry.S drops us of. All cores land here */
|
||||||
void start() {
|
void start() {
|
||||||
u64 id = r_mhartid();
|
|
||||||
|
|
||||||
// Keep each CPU's hartid in its tp (thread pointer) register, for cpuid().
|
u64 a = r_mhartid();
|
||||||
// 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);
|
acquire(&sl);
|
||||||
|
|
||||||
|
@ -36,7 +39,7 @@ void start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
uart_puts("Hart number: ");
|
uart_puts("Hart number: ");
|
||||||
uart_putc(id + '0');
|
uart_putc(a + '0');
|
||||||
uart_putc('\n');
|
uart_putc('\n');
|
||||||
|
|
||||||
release(&sl);
|
release(&sl);
|
||||||
|
|
Loading…
Add table
Reference in a new issue