Move kernel_main into the elna code

This commit is contained in:
2025-08-02 23:38:30 +02:00
parent badac1378d
commit ed4b26f445
4 changed files with 80 additions and 80 deletions

View File

@@ -4,6 +4,11 @@
.include "./arch/riscv/constants.s"
.section .data
.globl pmem_address
pmem_address: .word
.section .text
# a0 - First pointer.
@@ -245,9 +250,8 @@ memset:
# Parameters:
# a0 - Corresponding virtual address.
# a1 - Physical page address.
# a2 - Free memory page that can be used to create a leaf page table.
# a3 - Page table level. If a3 is 0 a superpage is allocated, otherwise a normal page.
# a4 - Flags.
# a2 - Page table level. If a2 is 0 a superpage is allocated, otherwise a normal page.
# a3 - Flags.
#
# If the function creates new page tables in a2, it advances a2 by the page size and
# returns it in a0.
@@ -268,7 +272,7 @@ pmem_map_at:
and t2, t2, t5 # VPN[i] * PTESIZE.
add t2, t0, t2 # a + VPN[i] * PTESIZE.
beqz a3, .Lpmem_map_at_leaf
beqz a2, .Lpmem_map_at_leaf
lw t3, (t2)
andi t6, t3, 0b1
@@ -281,27 +285,29 @@ pmem_map_at:
j .Lpmem_map_at_next
.Lpmem_map_at_create:
la a7, pmem_address
# 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, a2
lw t0, (a7)
srli t3, t0, 2
ori t3, t3, 0b1
sw t3, (t2)
li t6, PAGE_SIZE
add a2, a2, t6
add t0, t0, t6
sw t0, (a7)
.Lpmem_map_at_next:
# Calculate the next page table address for the next level.
addi t1, t1, -10
addi a3, a3, -1
addi a2, a2, -1
j .Lpmem_map_at_loop
.Lpmem_map_at_leaf:
srli t3, a1, 2 # Physical page number mapped to 12 bits of the page table entry.
ori a4, a4, 0b1
or t3, t3, a4 # Execute, write, read and valid.
ori a3, a3, 0b1
or t3, t3, a3 # Execute, write, read and valid.
sw t3, (t2)
mv a0, a2

View File

@@ -1 +1,4 @@
.equ PAGE_SIZE, 4096
.equ PAGE_READ, 0b0010
.equ PAGE_WRITE, 0b0100
.equ PAGE_EXECUTE, 0b1000

View File

@@ -31,14 +31,18 @@ _start:
mv a0, s2
mv a1, sp
call get_page_tables_size
mv a3, a0
mv a0, s2
mv a1, sp
mv a2, s4
mv a1, s2
mv a2, sp
mv a3, s4
jal imem_initialize
mv a0, s3
mv a1, s3
jal imem_mirror
# Save the address where the initial page tables end in a variable.
add a0, a0, s3
la t0, pmem_address
sw a0, (t0)
call set_up_trap_routine
add sp, sp, s4 # Move the stack to the virtual memory.
@@ -48,11 +52,10 @@ _start:
mv a1, sp
call imem_zero
mv a0, sp
mv a1, s1
mv a0, s1
lui t0, %hi(kernel_main)
jr t0, %lo(kernel_main)
lui t0, %hi(device_tree)
jr t0, %lo(device_tree)
# Given the start and end addresses of the kernel, calculates how
# much additional storage should be mapped to store the page tables.
@@ -74,6 +77,8 @@ _start:
# Returns the result in a0.
.type get_page_tables_size, @function
get_page_tables_size:
li t0, 0xffc00000
and a0, a0, t0
sub a0, a1, a0
srli a0, a0, 22
@@ -119,7 +124,11 @@ imem_zero:
# Copies the identity mappings to the higher half.
#
# Parameters:
# a0 - Start of the kernel virtual space.
# a0 - Size of additional page tables.
# a1 - Start of the kernel virtual space.
#
# Returns a pointer pointing to the end of the last page table
# with higher half mappings in a0.
.type imem_mirror, @function
imem_mirror:
csrr t0, satp
@@ -127,12 +136,14 @@ imem_mirror:
li t3, PAGE_SIZE
add t1, t0, t3 # Original page table.
add t2, t1, t3 # Copied page table.
add t2, t1, a0 # Copied page table.
li t5, 0xffffffcf
mv t3, t2
.Limem_mirror_copy:
lw t4, (t1)
and t4, t4, t5 # Clear "dirty" and "accessed" bits.
sw t4, (t3)
addi t3, t3, 4
@@ -140,11 +151,13 @@ imem_mirror:
blt t1, t2, .Limem_mirror_copy
# Persist the copied page table in the root page table.
srli t4, a0, 20 # VPN[1] * PTESIZE.
srli t4, a1, 20 # VPN[1] * PTESIZE.
add t4, t0, t4 # a + VPN[1] * PTESIZE.
srli t3, t2, 2
ori t3, t3, 0b1
sw t3, (t4)
srli t5, t2, 2
ori t5, t5, 0b1
sw t5, (t4)
mv a0, t3
ret
@@ -152,10 +165,12 @@ imem_mirror:
# Allocates enough pages for the kernel and its stack.
#
# Parameters:
# a0 - Physical start of the text section.
# a1 - Page aligned address following the kernel (kernel end).
# a2 - Offset from the physical to virtual memory.
# a3 - Size of additional page tables.
# a0 - Size of additional page tables.
# a1 - Physical start of the text section.
# a2 - Page aligned address following the kernel (kernel end).
# a3 - Offset from the physical to virtual memory.
#
# Returns the size of the created page tables (a0) in a0.
.type imem_initialize, @function
imem_initialize:
# Prologue.
@@ -164,55 +179,54 @@ imem_initialize:
sw s0, 24(sp)
addi s0, sp, 32
sw a0, 20(sp)
sw s1, 16(sp)
sw s2, 12(sp)
sw s3, 8(sp)
sw a0, 4(sp)
sw a1, 4(sp)
# Set s1 to the beginning of free memory (skipping root page table).
li s1, PAGE_SIZE
add s1, a1, s1
slli a3, a3, 1 # Multiply by two to account for the copy in virtual memory.
# s1 is a1 + PAGE, where PAGE is a free page reserved for future use,
# since the size of the root page table is already included in a3.
# s1 is used to avoid calculating a1 + PAGE_SIZE twice.
add a3, s1, a3
sw a3, 20(sp)
add s1, a2, s1
# Set boundaries between segments.
lui s2, %hi(etext)
sub s2, s2, a2
sub s2, s2, a3
lui s3, %hi(_data)
sub s3, s3, a2
sub s3, s3, a3
# Set the root page since it is used by mapping functions,
# but don't activate paging before the segments are property mapped.
srli t0, a1, 12
srli t0, a2, 12
csrw satp, t0
# Zero memory for page tables.
mv a0, a1
add a1, s1, a3
mv a0, a2
add a1, s1, a0
call imem_zero
# Executable section.
mv a0, s1
lw a1, 4(sp)
addi a2, s2, %lo(etext)
li a3, 0b1010 # Read and execute.
li a3, PAGE_READ | PAGE_EXECUTE
jal imem_map_range
# Read only section.
addi a1, s2, %lo(etext)
addi a2, s3, %lo(_data)
li a3, 0b0010 # Read.
li a3, PAGE_READ
jal imem_map_range
# Data section.
addi a1, s3, %lo(_data)
lw a2, 20(sp)
li a3, 0b0110 # Read and write.
slli a2, a2, 1 # Multiply by two to account for the copy in virtual memory.
# s1 is a2 + PAGE, where PAGE is a free page reserved for future use,
# since the size of the root page table is already included in a0.
# s1 is used to avoid calculating a2 + PAGE_SIZE twice.
add a2, s1, a2
li a3, PAGE_READ | PAGE_WRITE
jal imem_map_range
# Enable paging.
@@ -227,6 +241,7 @@ imem_initialize:
lw s3, 8(sp)
lw s2, 12(sp)
lw s1, 16(sp)
lw a0, 20(sp)
# Epilogue.
lw ra, 28(sp)
@@ -338,40 +353,6 @@ imem_map_at:
.section .text
.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)
# Map flat device tree to the virtual memory.
lw a0, 16(sp)
li t0, 0xffc00000
and a0, a0, t0
mv a1, a0
lw a2, 20(sp)
li a3, 0
li a4, 0b0010
call pmem_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 trap_routine, @function
trap_routine:

View File

@@ -25,6 +25,7 @@ type
proc write_c(value: Char); extern;
proc write_s(value: String); extern;
proc pmem_map_at(virtual: Pointer, physical: Pointer, level: Word, flags: Word); extern;
proc separator*() -> Char;
return ','
@@ -382,7 +383,12 @@ proc device_tree*(raw: Pointer);
var
raw_as_char: ^Char;
header: fdt_header;
raw_virtual: Pointer;
begin
(* Map flat device tree to the virtual memory. *)
raw_virtual := cast(cast(raw: Word) & 4290772992u: Pointer);
pmem_map_at(raw_virtual, raw_virtual, 0u, 2u);
raw_as_char := cast(raw: ^Char);
parse_header(raw_as_char, @header);
@@ -390,7 +396,11 @@ begin
write_c('\n');
find_memory(raw_as_char, @header);
reserve_memory(raw_as_char, @header)
reserve_memory(raw_as_char, @header);
(* Do nothing in a loop. *)
while true do
end
end;
end.