Calculate kernel size in pages dinamically
This commit is contained in:
@@ -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
|
||||||
|
@@ -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)
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user