Skip to content

Commit

Permalink
smp: Implement multi core support
Browse files Browse the repository at this point in the history
  • Loading branch information
sysheap committed Jan 5, 2025
1 parent bf8786a commit 402df03
Show file tree
Hide file tree
Showing 39 changed files with 783 additions and 496 deletions.
2 changes: 1 addition & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ target = "riscv64gc-unknown-none-elf"
# rustflags = ["-Ctarget-feature=+relax"]

[target.riscv64gc-unknown-none-elf]
runner = "./qemu_wrapper.sh --gdb --net"
runner = "./qemu_wrapper.sh --gdb --net --smp"
5 changes: 2 additions & 3 deletions common/src/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,12 @@ impl<T> Mutex<T> {
if self.disarmed.load(Ordering::SeqCst) {
return MutexGuard { mutex: self };
}
if self
while self
.locked
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
.is_err()
{
panic!("Lock held twice of Mutex<{}>", core::any::type_name::<T>());
// core::hint::spin_loop();
core::hint::spin_loop();
}
MutexGuard { mutex: self }
}
Expand Down
Binary file modified doc/riscv-sbi.pdf
Binary file not shown.
4 changes: 2 additions & 2 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ debugf FUNC: build
tmux new-session -d '{{debugReleaseCommand}}' \; split-window -v 'gdb-multiarch $(pwd)/target/riscv64gc-unknown-none-elf/release/kernel -ex "target remote :1234" -ex "hbreak {{FUNC}}" -ex "c"'\; attach

disassm: build
riscv64-unknown-elf-objdump -d --demangle --disassembler-color=on visualize-jumps=extended-color target/riscv64gc-unknown-none-elf/release/kernel | less
riscv64-linux-gnu-objdump -d --demangle --disassembler-color=on visualize-jumps=extended-color target/riscv64gc-unknown-none-elf/release/kernel | less

addr2line ADDR:
riscv64-unknown-elf-addr2line -f -p -i -C -e target/riscv64gc-unknown-none-elf/release/kernel {{ADDR}}
riscv64-linux-gnu-addr2line -f -p -i -C -e target/riscv64gc-unknown-none-elf/release/kernel {{ADDR}}
11 changes: 0 additions & 11 deletions kernel/qemu.ld
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,6 @@ SECTIONS
*(.sbss .sbss.*) *(.bss .bss.*)
}

# This page will be an unmapped area to prevent stack overflows
# I know - it is not the most efficient way because we waste some actual
# memory here. It would be better to only have a guard page in virtual memory.
# However, this needs more redesigning about adress space layout
# so lets leave this here as quick fix
# The guard page ist not aligned such that it starts directly after bss
# and continues until the kernel_stack
stack_overflow_guard (NOLOAD) : ALIGN(4K) {
. = . + 1;
}

kernel_stack (NOLOAD) : ALIGN(4K) {
. = . + 512K;
}
Expand Down
41 changes: 34 additions & 7 deletions kernel/src/asm/boot.S
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,39 @@ bss_cleared:

call kernel_init

# Enable all interrupts
li t0, -1
csrw sie, t0
# We should never come here
j asm_panic_rust

# Enable global interrupts
li t0, 0b10
csrs sstatus, t0
.section .text
.global start_hart
.align 4
start_hart:
.option push
.option norelax
la gp, __global_pointer$
.option pop

# disable interrupts.
csrw sie, zero

# Load trap vector machine mode
la t0, supervisor_trap_table
addi t0, t0, 1 # Use vectored mode -> we know the address is 4 byte aligned
csrw stvec, t0

# a1 contains the cpu struct
csrw sscratch, a1

# Load kernel page tables such that we get the correct stack
ld t1, {KERNEL_PAGE_TABLES_SATP_OFFSET}(a1)
csrw satp, t1
sfence.vma zero, zero

# Set kernel stack pointer to 0xffffffffffffffff
li sp, 0
addi sp, sp, -64

call hart_init

j wfi_loop
# We should never come here
j asm_panic_rust
33 changes: 30 additions & 3 deletions kernel/src/asm/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,31 @@
use core::arch::global_asm;
use core::arch::{asm, global_asm};

global_asm!(include_str!("boot.S"));
global_asm!(include_str!("trap.S"));
use crate::{cpu, sbi::extensions::timer_extension};

global_asm!(include_str!("boot.S"), KERNEL_PAGE_TABLES_SATP_OFFSET = const cpu::KERNEL_PAGE_TABLES_SATP_OFFSET);
global_asm!(include_str!("trap.S"), TRAP_FRAME_OFFSET = const cpu::TRAP_FRAME_OFFSET, KERNEL_PAGE_TABLES_SATP_OFFSET = const cpu::KERNEL_PAGE_TABLES_SATP_OFFSET);
global_asm!(include_str!("powersave.S"), EID = const timer_extension::EID, FID_SET_TIMER = const timer_extension::FID_SET_TIMER);
global_asm!(include_str!("panic.S"));

#[unsafe(no_mangle)]
pub fn asm_panic_rust() {
let ra: usize;
unsafe {
asm!("mv {}, ra", out(reg)ra);
}
panic!("Panic from asm code (ra={ra:#x})");
}

#[unsafe(no_mangle)]
#[naked]
pub extern "C" fn wfi_loop() -> ! {
unsafe {
core::arch::naked_asm!(
"
0:
wfi
j 0
"
)
}
}
14 changes: 14 additions & 0 deletions kernel/src/asm/panic.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.section .text
.global powersave
.align 4
asm_panic:
# Disable interrupts.
csrw sie, zero

# Load emergency stack
la sp, __stop_kernel_stack

# Jump to asm_panic_rust such that we still now
# where we came from via the ra register
j asm_panic_rust

31 changes: 31 additions & 0 deletions kernel/src/asm/powersave.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
.section .text
.global powersave
.align 4
powersave:
# Disable timer interrupt
li t0, (1 << 5)
csrc sie, t0

# Set next timer interrupt to -2
li a7, {EID}
li a6, {FID_SET_TIMER}

# arg
li a0, 0
# Somehow u64::MAX triggers timer interrupt indefinitely
# u64::MAX - 1 works as intended.
addi a0, a0, -2

ecall

# a0 should be 0 to indicate success
bne a0, x0, powersave_error

wfi
j powersave

powersave_error:
call asm_panic
powersave_error_sleep:
wfi
j powersave_error_sleep
29 changes: 23 additions & 6 deletions kernel/src/asm/trap.S
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
# Save all registers to the kernel trap frame
csrrw t6, sscratch, t6

# Add trap frame offset
addi t6, t6, {TRAP_FRAME_OFFSET}

# Save all registers
# In order to make things easier we also save x0 which is always zero
.set i, 0
Expand All @@ -39,6 +42,9 @@
csrr t6, sscratch
save_gp 31, t5

# Remove trap frame offset
addi t5, t5, -{TRAP_FRAME_OFFSET}

# Restore trap frame pointer
csrw sscratch, t5
.endm
Expand All @@ -47,6 +53,9 @@
# Restore all registers
csrr t6, sscratch

# Add trap frame offset
addi t6, t6, {TRAP_FRAME_OFFSET}

.set i,0
.rept 32
load_fp %i # We need to restore the floating point register first. Otherwise the last load_gp overwrites the address of the trap frame
Expand All @@ -63,15 +72,23 @@ asm_\func:

save_regs

# Load kernel stack frame
la sp, __stop_kernel_stack
# Load kernel page tables such that we get the correct stack
csrr t0, sscratch
ld t1, {KERNEL_PAGE_TABLES_SATP_OFFSET}(t0)
csrw satp, t1
sfence.vma zero, zero

# Set kernel stack pointer to 0xffffffffffffffff
li sp, 0
addi sp, sp, -64

csrr a0, scause
csrr a1, stval
csrr a2, sepc
csrr a3, sscratch
call \func

# Restore the process page table
call get_process_satp_value
csrw satp, a0
sfence.vma

restore_regs

sret
Expand Down
Loading

0 comments on commit 402df03

Please sign in to comment.