Files
eugenios/arch/riscv/kernel.s

377 lines
5.8 KiB
ArmAsm

.global _entry, __bss, __bss_end, __stack_top
.section .rodata
panic_message: .asciz "\nPanic"
.equ PANIC_MESSAGE_SIZE, . - panic_message
.section .text
bzero:
la t0, __bss
la t1, __bss_end
.Lbzero_loop:
bgt t0, t1, .Lbzero_end
sw zero, (t0)
addi t0, t0, 4
.Lbzero_end:
ret
# Maps a page of physical memory to the identical virtual memory.
#
# Parameters:
# a0 - Physical page address.
# a1 - Free memory page that can be used to create a leaf page table.
# a2 - Page table level. If a2 is 0 a superpage is allocated, otherwise a normal page.
# a3 - Flags.
#
# Returns virtual page address in a0.
.type imem_map_at, @function
imem_map_at:
csrr t0, satp
slli t0, t0, 12 # Root table address.
li t4, 0xfffffc00
li t5, 0xffc # 10 bit * PTESIZE mask.
li t1, 20
.Limem_map_at_loop:
# Multiply VPN[i] by 4 and add to the start address of the page table.
# This gives the physical address of the page table entry.
srl t2, a0, t1
and t2, t2, t5 # VPN[i] * PTESIZE.
add t2, t0, t2 # a + VPN[i] * PTESIZE.
beqz a2, .Limem_map_at_leaf
lw t3, (t2)
andi t6, t3, 0b1
beqz t6, .Limem_map_at_create
and t0, t3, t4
slli t0, t0, 2
j .Limem_map_at_next
.Limem_map_at_create:
# Take a chunk of free memory and use it as the next page table.
# The beginning addres off the chunk is the base address (a) for the next level.
mv t0, a1
srli t3, t0, 2
ori t3, t3, 0b1
sw t3, (t2)
.Limem_map_at_next:
# Calculate the next page table address for the next level.
addi t1, t1, -10
addi a2, a2, -1
j .Limem_map_at_loop
.Limem_map_at_leaf:
srli t3, a0, 2 # Physical page number mapped to 12 bits of the page table entry.
ori a3, a3, 0b1
or t3, t3, a3 # Execute, write, read and valid.
sw t3, (t2)
ret
# Maps multiple pages of physical memory to the identical virtual memory.
#
# Parameters:
# a0 - Start address.
# a1 - End address.
# a2 - Start of the free memory that can be used to create leaf page tables.
# a3 - Page table level. If a2 is 0 a superpage is allocated, otherwise a normal page.
# a4 - Flags.
.type imem_map_range, @function
imem_map_range:
# Prologue.
addi sp, sp, -32
sw ra, 28(sp)
sw s0, 24(sp)
addi s0, sp, 32
sw s1, 20(sp)
sw a2, 16(sp)
sw a3, 12(sp)
sw a4, 8(sp)
mv s1, a1
.Limem_map_range_loop:
bge a0, s1, .Limem_map_range_end
lw a1, 16(sp)
lw a2, 12(sp)
lw a3, 8(sp)
call imem_map_at
li t0, 4096
add a0, a0, t0
j .Limem_map_range_loop
.Limem_map_range_end:
lw s1, 20(sp)
# Epilogue.
lw ra, 28(sp)
lw s0, 24(sp)
addi sp, sp, 32
ret
# Activates paging and creates root page table.
# Allocates enough pages for the kernel and its stack.
#
# Parameters:
# a0 - Start (base) address of the kernel.
# a1 - Page aligned address following the kernel (kernel end).
.type imem_initialize, @function
imem_initialize:
# Prologue.
addi sp, sp, -32
sw ra, 28(sp)
sw s0, 24(sp)
addi s0, sp, 32
sw a0, 20(sp)
sw a1, 16(sp)
srli t0, a1, 12
csrw satp, t0
la a0, .text.boot
la a1, etext
lw a2, 16(sp)
li t0, 4096
add a2, a2, t0
li a3, 1
li a4, 0b1010
call imem_map_range
la a0, etext
lw a1, 16(sp)
li t0, 4096
add a1, a1, t0
add a2, a1, t0
li a3, 1
li a4, 0b0110
call imem_map_range
csrr t0, satp
li t1, 0x80000000
or t0, t0, t1
sfence.vma
csrw satp, t0
sfence.vma
# Epilogue.
lw ra, 28(sp)
lw s0, 24(sp)
addi sp, sp, 32
ret
.type kernel_main, @function
kernel_main:
# Prologue.
addi sp, sp, -32
sw ra, 28(sp)
sw s0, 24(sp)
addi s0, sp, 32
sw a0, 20(sp)
sw a1, 16(sp)
la t0, kernel_entry
csrw stvec, t0
# Map flat device tree to the virtual memory.
lw a0, 16(sp)
li t0, 0xffc00000
and a0, a0, t0
lw a1, 20(sp)
li a2, 0
li a3, 0b0010
call imem_map_at
lw a0, 16(sp)
call device_tree
# Do nothing in a loop.
.Lkernel_main:
j .Lkernel_main
# Epilogue.
lw ra, 28(sp)
lw s0, 24(sp)
addi sp, sp, 32
ret
.balign 4
.type kernel_entry, @function
kernel_entry:
csrw sscratch, sp
addi sp, sp, -4 * 31
sw ra, 0(sp)
sw gp, 4(sp)
sw tp, 8(sp)
sw t0, 12(sp)
sw t1, 16(sp)
sw t2, 20(sp)
sw t3, 24(sp)
sw t4, 28(sp)
sw t5, 32(sp)
sw t6, 36(sp)
sw a0, 40(sp)
sw a1, 44(sp)
sw a2, 48(sp)
sw a3, 52(sp)
sw a4, 56(sp)
sw a5, 60(sp)
sw a6, 64(sp)
sw a7, 68(sp)
sw s0, 72(sp)
sw s1, 76(sp)
sw s2, 80(sp)
sw s3, 84(sp)
sw s4, 88(sp)
sw s5, 92(sp)
sw s6, 96(sp)
sw s7, 100(sp)
sw s8, 104(sp)
sw s9, 108(sp)
sw s10, 112(sp)
sw s11, 116(sp)
csrr a0, sscratch
sw a0, 120(sp)
mv a0, sp
call handle_trap
lw ra, 0(sp)
lw gp, 4(sp)
lw tp, 8(sp)
lw t0, 12(sp)
lw t1, 16(sp)
lw t2, 20(sp)
lw t3, 24(sp)
lw t4, 28(sp)
lw t5, 32(sp)
lw t6, 36(sp)
lw a0, 40(sp)
lw a1, 44(sp)
lw a2, 48(sp)
lw a3, 52(sp)
lw a4, 56(sp)
lw a5, 60(sp)
lw a6, 64(sp)
lw a7, 68(sp)
lw s0, 72(sp)
lw s1, 76(sp)
lw s2, 80(sp)
lw s3, 84(sp)
lw s4, 88(sp)
lw s5, 92(sp)
lw s6, 96(sp)
lw s7, 100(sp)
lw s8, 104(sp)
lw s9, 108(sp)
lw s10, 112(sp)
lw s11, 116(sp)
lw sp, 120(sp)
sret
.type handle_trap, @function
handle_trap:
# Prologue.
addi sp, sp, -32
sw ra, 28(sp)
sw s0, 24(sp)
addi s0, sp, 32
csrr t0, scause
csrr t1, stval
csrr t2, sepc
li a1, PANIC_MESSAGE_SIZE
la a0, panic_message
call write_s
li a0, ' '
call write_c
csrr a0, scause
la a1, write_c
call print_i
call separator
call write_c
csrr a0, stval
la a1, write_c
call print_i
call separator
call write_c
csrr a0, sepc
la a1, write_c
call print_i
call panic
# Epilogue.
lw ra, 28(sp)
lw s0, 24(sp)
addi sp, sp, 32
ret
.type panic, @function
panic:
# Prologue.
addi sp, sp, -32
sw ra, 28(sp)
sw s0, 24(sp)
addi s0, sp, 32
li a0, '\n'
call write_c
.Lpanic:
j .Lpanic
# Epilogue.
lw ra, 28(sp)
lw s0, 24(sp)
addi sp, sp, 32
ret
.section .text.boot
_entry:
# Set the stack pointer.
la t0, end
li t1, 64 * 1024
add sp, t0, t1
mv s1, a1
la a0, .text.boot
mv a1, sp
call imem_initialize
lw t0, (end)
la t1, next_paddr
sw t0, (t1)
call bzero
mv a0, sp
mv a1, s1
j kernel_main