From ed4b26f445b8147ea4881693fe0c7b4e8398260a Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Sat, 2 Aug 2025 23:38:30 +0200 Subject: [PATCH] Move kernel_main into the elna code --- arch/riscv/common.s | 24 +++++--- arch/riscv/constants.s | 3 + arch/riscv/kernel.s | 121 +++++++++++++++++----------------------- source/device_tree.elna | 12 +++- 4 files changed, 80 insertions(+), 80 deletions(-) diff --git a/arch/riscv/common.s b/arch/riscv/common.s index c121f5c..6ae0c68 100644 --- a/arch/riscv/common.s +++ b/arch/riscv/common.s @@ -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 diff --git a/arch/riscv/constants.s b/arch/riscv/constants.s index 44ecb51..73974e2 100644 --- a/arch/riscv/constants.s +++ b/arch/riscv/constants.s @@ -1 +1,4 @@ .equ PAGE_SIZE, 4096 +.equ PAGE_READ, 0b0010 +.equ PAGE_WRITE, 0b0100 +.equ PAGE_EXECUTE, 0b1000 diff --git a/arch/riscv/kernel.s b/arch/riscv/kernel.s index d1a78e2..621e12c 100644 --- a/arch/riscv/kernel.s +++ b/arch/riscv/kernel.s @@ -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: diff --git a/source/device_tree.elna b/source/device_tree.elna index 8ff1a7e..583e797 100644 --- a/source/device_tree.elna +++ b/source/device_tree.elna @@ -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.