diff --git a/arch/riscv/common.s b/arch/riscv/common.s index 4108d16..8d9abba 100644 --- a/arch/riscv/common.s +++ b/arch/riscv/common.s @@ -3,7 +3,7 @@ # obtain one at https://mozilla.org/MPL/2.0/. .global write_s, write_c -.global memcmp, memchr, memmem, memcpy +.global memcmp, memchr, memmem, memcpy, bzero .section .text @@ -211,3 +211,19 @@ memcpy: .Lmemcpy_end: mv a0, t0 ret + +# Zeroes a chank of memory. +# +# Parameters: +# a0 - Memory pointer. +# a1 - Memory size. +bzero: + mv t0, a0 + +.Lbzero_loop: + bgt t0, a1, .Lbzero_end + sb zero, (t0) + addi t0, t0, 1 + +.Lbzero_end: + ret diff --git a/arch/riscv/kernel.ld b/arch/riscv/kernel.ld index 7f34b36..6525e1a 100644 --- a/arch/riscv/kernel.ld +++ b/arch/riscv/kernel.ld @@ -12,7 +12,9 @@ SECTIONS { KEEP(*(.text.boot)); *(.text .text.*); } :text - PROVIDE(estart = .); + + . = ALIGN(CONSTANT(MAXPAGESIZE)); + PROVIDE(etext = .); .rodata : ALIGN(16) { *(.rodata .rodata.*); @@ -30,4 +32,8 @@ SECTIONS { . = ALIGN(CONSTANT(MAXPAGESIZE)); PROVIDE(end = .); + + /DISCARD/ : { + *(.eh_frame) + } } diff --git a/arch/riscv/kernel.s b/arch/riscv/kernel.s index 8ee06d7..746d84d 100644 --- a/arch/riscv/kernel.s +++ b/arch/riscv/kernel.s @@ -7,24 +7,13 @@ panic_message: .asciz "\nPanic" .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 @@ -32,43 +21,101 @@ imem_map_at: csrr t0, satp slli t0, t0, 12 # Root table address. - li t1, 0xffc # 10 bit * PTESIZE mask. - srli t4, a0, 2 # Physical page number. + li t4, 0xfffffc00 + li t5, 0xffc # 10 bit * PTESIZE mask. + li t1, 20 - # Multiply VPN[1] by 4 and add to the start address of the page table. +.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. - srli t2, a0, 20 - and t2, t2, t1 # VPN[1] * PTESIZE. - add t2, t0, t2 # a + VPN[1] * PTESIZE. + srl t2, a0, t1 + and t2, t2, t5 # VPN[i] * PTESIZE. + add t2, t0, t2 # a + VPN[i] * PTESIZE. - beqz a2, .Limem_map_at_super + beqz a2, .Limem_map_at_leaf - srli t3, a1, 2 + 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) - srli t2, a0, 10 - and t2, t2, t1 # VPN[0] * PTESIZE. - add t2, a1, t2 # a + VPN[0] * PTESIZE. +.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_leaf - -.Limem_map_at_super: - # Calculate PPN[1] (10 most significant bits of the physical address - # and map it to 12 bits of the table page entry. - li t1, 0xfff00000 - and t4, t4, t1 + j .Limem_map_at_loop .Limem_map_at_leaf: - ori t4, t4, 0b1111 # Execute, write, read and valid. - sw t4, (t2) + 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 @@ -79,31 +126,30 @@ imem_initialize: sw s0, 24(sp) addi s0, sp, 32 - li t0, 64 * 1024 - add t0, a1, t0 - sw t0, 20(sp) + sw a0, 20(sp) sw a1, 16(sp) srli t0, a1, 12 csrw satp, t0 -.Limem_initialize_loop: - lw t0, 20(sp) + 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) - - bge a0, t0, .Limem_initialize_activate - li t0, 4096 add a1, a1, t0 - li a2, 1 - call imem_map_at + add a2, a1, t0 + li a3, 1 + li a4, 0b0110 + call imem_map_range - li t0, 4096 - add a0, a0, t0 - - j .Limem_initialize_loop - -.Limem_initialize_activate: csrr t0, satp li t1, 0x80000000 or t0, t0, t1 @@ -134,8 +180,11 @@ kernel_main: # 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) @@ -309,7 +358,10 @@ _entry: la t1, next_paddr sw t0, (t1) + la a0, __bss + la a1, __bss_end call bzero + mv a0, sp mv a1, s1 j kernel_main