Calculate kernel size in pages dinamically

This commit is contained in:
2025-07-31 23:37:31 +02:00
parent d12bfbcd43
commit 3e50e74526
3 changed files with 136 additions and 34 deletions

View File

@@ -2,9 +2,6 @@
# v. 2.0. If a copy of the MPL was not distributed with this file, You can # v. 2.0. If a copy of the MPL was not distributed with this file, You can
# obtain one at https://mozilla.org/MPL/2.0/. # obtain one at https://mozilla.org/MPL/2.0/.
.global write_s, write_c
.global memcmp, memchr, memmem, memcpy, bzero
.section .text .section .text
# a0 - First pointer. # a0 - First pointer.
@@ -13,6 +10,7 @@
# #
# Returns 0 in a0 if memory regions are equal. # Returns 0 in a0 if memory regions are equal.
.type memcmp, @function .type memcmp, @function
.globl memcmp
memcmp: memcmp:
mv t0, a0 mv t0, a0
li a0, 0 li a0, 0
@@ -41,6 +39,7 @@ memcmp:
# a0 - String pointer. # a0 - String pointer.
# a1 - Length of the string. # a1 - Length of the string.
.type write_s, @function .type write_s, @function
.globl write_s
write_s: write_s:
# Prologue. # Prologue.
addi sp, sp, -32 addi sp, sp, -32
@@ -80,6 +79,7 @@ write_s:
# Arguments: # Arguments:
# a0 - Character. # a0 - Character.
.type write_c, @function .type write_c, @function
.globl write_c
write_c: write_c:
li a1, 0 li a1, 0
li a2, 0 li a2, 0
@@ -102,6 +102,7 @@ write_c:
# Sets a0 to the pointer to the found character or to null if the character # Sets a0 to the pointer to the found character or to null if the character
# doesn't occur in the memory block. # doesn't occur in the memory block.
.type memchr, @function .type memchr, @function
.globl memchr
memchr: memchr:
.Lmemchr_loop: .Lmemchr_loop:
beqz a2, .Lmemchr_nil # Exit if the length is 0. beqz a2, .Lmemchr_nil # Exit if the length is 0.
@@ -132,6 +133,7 @@ memchr:
# Sets a0 to the pointer to the beginning of the substring in memory or to 0 # Sets a0 to the pointer to the beginning of the substring in memory or to 0
# if the substring doesn't occur in the block. # if the substring doesn't occur in the block.
.type memmem, @function .type memmem, @function
.globl memmem
memmem: memmem:
# Prologue. # Prologue.
addi sp, sp, -24 addi sp, sp, -24
@@ -193,6 +195,7 @@ memmem:
# #
# Preserves a0. # Preserves a0.
.type memcpy, @function .type memcpy, @function
.globl memcpy
memcpy: memcpy:
mv t0, a0 mv t0, a0
@@ -200,30 +203,37 @@ memcpy:
beqz a2, .Lmemcpy_end beqz a2, .Lmemcpy_end
lbu t1, (a1) lbu t1, (a1)
sb t1, (a0) sb t1, (t0)
addi a0, a0, 1 addi t0, t0, 1
addi a1, a1, 1 addi a1, a1, 1
addi a2, a2, -1 addi a2, a2, -1
j .Lmemcpy_loop j .Lmemcpy_loop
.Lmemcpy_end: .Lmemcpy_end:
mv a0, t0
ret ret
# Zeroes a chank of memory. # Sets a memory region to the given byte value.
# #
# Parameters: # Parameters:
# a0 - Memory pointer. # a0 - Memory chunk to fill.
# a1 - Memory size. # a1 - Constant byte.
bzero: # a2 - Memory size.
.type memset, @function
.globl memset
memset:
mv t0, a0 mv t0, a0
.Lbzero_loop: .Lmemset_loop:
bgt t0, a1, .Lbzero_end beqz a2, .Lmemset_end
sb zero, (t0)
sb a1, (t0)
addi a2, a2, -1
addi t0, t0, 1 addi t0, t0, 1
.Lbzero_end: j .Lmemset_loop
.Lmemset_end:
ret ret

View File

@@ -19,14 +19,14 @@ SECTIONS {
} :text } :text
. = ALIGN(CONSTANT(MAXPAGESIZE)); . = ALIGN(CONSTANT(MAXPAGESIZE));
PROVIDE(etext = . - _kernel_offset); PROVIDE(etext = .);
.rodata : AT(ADDR(.rodata) - _kernel_offset) ALIGN(16) { .rodata : AT(ADDR(.rodata) - _kernel_offset) ALIGN(16) {
*(.rodata .rodata.*); *(.rodata .rodata.*);
} }
. = ALIGN(CONSTANT(MAXPAGESIZE)); . = ALIGN(CONSTANT(MAXPAGESIZE));
PROVIDE(_data = . - _kernel_offset); PROVIDE(_data = .);
.data : AT(ADDR(.data) - _kernel_offset) ALIGN(16) { .data : AT(ADDR(.data) - _kernel_offset) ALIGN(16) {
*(.data .data.*); *(.data .data.*);
@@ -38,7 +38,7 @@ SECTIONS {
} }
. = ALIGN(CONSTANT(MAXPAGESIZE)); . = ALIGN(CONSTANT(MAXPAGESIZE));
PROVIDE(end = . - _kernel_offset); PROVIDE(end = .);
/DISCARD/ : { /DISCARD/ : {
*(.eh_frame) *(.eh_frame)

View File

@@ -1,3 +1,7 @@
# This Source Code Form is subject to the terms of the Mozilla Public License,
# v. 2.0. If a copy of the MPL was not distributed with this file, You can
# obtain one at https://mozilla.org/MPL/2.0/.
.section .rodata .section .rodata
panic_message: .asciz "\nPanic" panic_message: .asciz "\nPanic"
@@ -6,29 +10,41 @@ panic_message: .asciz "\nPanic"
.section .text.boot .section .text.boot
.type _start, @function .type _start, @function
.global _start .globl _start
_start: _start:
# Save the physical start of the text section.
# This must be the first instruction.
auipc s2, 0
mv s1, a1 # Save the device tree pointer. mv s1, a1 # Save the device tree pointer.
auipc s2, 0 # Save the physical start of the text section. # Virtual address of the start of the text section.
lui s3, %hi(_start)
addi s3, s3, %lo(_start)
sub s4, s3, s2 # Save the offset to the virtual memory address.
# Set the stack pointer. # Set the stack pointer.
lui sp, %hi(end) mv a0, s4
addi sp, sp, %lo(end) call set_up_stack
li t0, 64 * 1024
add sp, sp, t0
# Create identity mapping for the kernel and copy it to higher half.
mv a0, s2 mv a0, s2
mv a1, sp mv a1, sp
call get_page_tables_size
mv a3, a0
mv a0, s2
mv a1, sp
mv a2, s4
jal imem_initialize jal imem_initialize
mv a0, s3
jal imem_mirror jal imem_mirror
la a0, __bss_start call set_up_trap_routine
la a1, end add sp, sp, s4 # Move the stack to the virtual memory.
call bzero
lui t0, %hi(trap_routine) # Zero BSS and kernel stack.
addi t0, t0, %lo(trap_routine) lui a0, %hi(__bss_start)
csrw stvec, t0 addi a0, a0, %lo(__bss_start)
mv a1, sp
call imem_zero
mv a0, sp mv a0, sp
mv a1, s1 mv a1, s1
@@ -36,7 +52,74 @@ _start:
lui t0, %hi(kernel_main) lui t0, %hi(kernel_main)
jr t0, %lo(kernel_main) jr t0, %lo(kernel_main)
# Given the start and end addresses of the kernel, calculates how
# much additional storage should be mapped to store the page tables.
# The original formula for getting the number of required pages is:
# ((sp - start) / 4096 + 1 + 1023) / 1024.
#
# - sp is the stack pointer (kernel end).
# - The kernel size is divided by the page size. It is the kernel size in pages.
# - One additional page is added for the root page table.
# - 1023 is added so the next division is rounded up and not down.
#
# A simplified formula is used in the actual implementation.
#
# Parameters:
# a0 - Kernel start address.
# a1 - Kernel end address.
#
# Returns the result in a0.
.type get_page_tables_size, @function
get_page_tables_size:
sub a0, a1, a0
srli a0, a0, 22
addi a0, a0, 1
slli a0, a0, 12
ret
# Set an exception handler.
.type set_up_trap_routine, @function
set_up_trap_routine:
lui t0, %hi(trap_routine)
addi t0, t0, %lo(trap_routine)
csrw stvec, t0
ret
.type set_up_stack, @function
set_up_stack:
lui sp, %hi(end)
addi sp, sp, %lo(end)
sub sp, sp, a0
li t0, 64 * 1024
add sp, sp, t0
ret
# Zeroes a chunk of memory.
#
# Parameters:
# a0 - Memory start pointer.
# a1 - Memory end pointer.
.type imem_zero, @function
imem_zero:
mv t0, a0
.Limem_zero_loop:
bgeu t0, a1, .Limem_zero_end
sw zero, (t0)
addi t0, t0, 4
j .Limem_zero_loop
.Limem_zero_end:
ret
# Copies the identity mappings to the higher half. # Copies the identity mappings to the higher half.
#
# Parameters:
# a0 - Start of the kernel virtual space.
.type imem_mirror, @function .type imem_mirror, @function
imem_mirror: imem_mirror:
csrr t0, satp csrr t0, satp
@@ -57,8 +140,7 @@ imem_mirror:
blt t1, t2, .Limem_mirror_copy blt t1, t2, .Limem_mirror_copy
# Persist the copied page table in the root page table. # Persist the copied page table in the root page table.
lui t4, %hi(_start) srli t4, a0, 20 # VPN[1] * PTESIZE.
srli t4, t4, 20 # VPN[1] * PTESIZE.
add t4, t0, t4 # a + VPN[1] * PTESIZE. add t4, t0, t4 # a + VPN[1] * PTESIZE.
srli t3, t2, 2 srli t3, t2, 2
ori t3, t3, 0b1 ori t3, t3, 0b1
@@ -72,6 +154,8 @@ imem_mirror:
# Parameters: # Parameters:
# a0 - Physical start of the text section. # a0 - Physical start of the text section.
# a1 - Page aligned address following the kernel (kernel end). # a1 - Page aligned address following the kernel (kernel end).
# a2 - Offset from the physical to virtual memory.
# a3 - Size of additional page tables.
.type imem_initialize, @function .type imem_initialize, @function
imem_initialize: imem_initialize:
# Prologue. # Prologue.
@@ -80,16 +164,26 @@ imem_initialize:
sw s0, 24(sp) sw s0, 24(sp)
addi s0, sp, 32 addi s0, sp, 32
sw a1, 20(sp)
sw s1, 16(sp) sw s1, 16(sp)
sw s2, 12(sp) sw s2, 12(sp)
sw s3, 8(sp) sw s3, 8(sp)
# Set s1 to the beginning of free memory (skipping root page table).
li s1, 4096 li s1, 4096
add s1, a1, s1 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)
# Set boundaries between segments. # Set boundaries between segments.
lui s2, %hi(etext) lui s2, %hi(etext)
sub s2, s2, a2
lui s3, %hi(_data) lui s3, %hi(_data)
sub s3, s3, a2
# Set the root page since it is used by mapping functions, # Set the root page since it is used by mapping functions,
# but don't activate paging before the segments are property mapped. # but don't activate paging before the segments are property mapped.
@@ -115,8 +209,6 @@ imem_initialize:
# Data section. # Data section.
addi a0, s3, %lo(_data) addi a0, s3, %lo(_data)
lw a1, 20(sp) lw a1, 20(sp)
li t0, 4096 * 3
add a1, a1, t0
mv a2, s1 mv a2, s1
li a3, 1 li a3, 1
li a4, 0b0110 li a4, 0b0110