Map the kernel to the higher half
This commit is contained in:
2
Rakefile
2
Rakefile
@@ -385,5 +385,5 @@ task :default do |t|
|
||||
QEMU = 'qemu-system-riscv32'
|
||||
|
||||
system QEMU, '-machine', 'virt', '-bios', 'default', '-nographic', '-serial', 'mon:stdio', '--no-reboot',
|
||||
'-kernel', *t.prerequisites
|
||||
'-kernel', t.prerequisites.last, exception: true
|
||||
end
|
||||
|
@@ -3,35 +3,45 @@ OUTPUT_FORMAT("elf32-littleriscv")
|
||||
ENTRY(_entry)
|
||||
|
||||
PHDRS {
|
||||
boot PT_LOAD FLAGS(5);
|
||||
text PT_LOAD FLAGS(5);
|
||||
data PT_LOAD FLAGS(6);
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
.text 0x80200000 : {
|
||||
.text.boot 0x80200000 : {
|
||||
KEEP(*(.text.boot));
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
ASSERT(. - ADDR(.text.boot) == 0x1000, "error: stub larger than one page");
|
||||
} :boot
|
||||
|
||||
_kernel_offset = 0x3fdff000;
|
||||
|
||||
.text 0xc0000000 : AT(ADDR(.text) - _kernel_offset) {
|
||||
PROVIDE(__executable_start = . - _kernel_offset);
|
||||
*(.text .text.*);
|
||||
} :text
|
||||
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
PROVIDE(etext = .);
|
||||
PROVIDE(etext = . - _kernel_offset);
|
||||
|
||||
.rodata : ALIGN(16) {
|
||||
.rodata : AT(ADDR(.rodata) - _kernel_offset) ALIGN(16) {
|
||||
*(.rodata .rodata.*);
|
||||
}
|
||||
|
||||
.data : ALIGN(16) {
|
||||
*(.data .data.*);
|
||||
} :data
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
PROVIDE(_data = . - _kernel_offset);
|
||||
|
||||
.bss : ALIGN(16) {
|
||||
__bss = .;
|
||||
.data : AT(ADDR(.data) - _kernel_offset) ALIGN(16) {
|
||||
*(.data .data.*);
|
||||
}
|
||||
|
||||
.bss (NOLOAD) : {
|
||||
PROVIDE(__bss_start = . - _kernel_offset);
|
||||
*(.bss .bss.* .sbss .sbss.*);
|
||||
__bss_end = .;
|
||||
}
|
||||
|
||||
. = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
PROVIDE(end = .);
|
||||
PROVIDE(end = . - _kernel_offset);
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame)
|
||||
|
@@ -1,4 +1,4 @@
|
||||
.global _entry, __bss, __bss_end, __stack_top
|
||||
.global _entry
|
||||
|
||||
.section .rodata
|
||||
|
||||
@@ -7,163 +7,6 @@ panic_message: .asciz "\nPanic"
|
||||
|
||||
.section .text
|
||||
|
||||
# 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
|
||||
imem_map_at:
|
||||
csrr t0, satp
|
||||
slli t0, t0, 12 # Root table address.
|
||||
|
||||
li t4, 0xfffffc00
|
||||
li t5, 0xffc # 10 bit * PTESIZE mask.
|
||||
li t1, 20
|
||||
|
||||
.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.
|
||||
srl t2, a0, t1
|
||||
and t2, t2, t5 # VPN[i] * PTESIZE.
|
||||
add t2, t0, t2 # a + VPN[i] * PTESIZE.
|
||||
|
||||
beqz a2, .Limem_map_at_leaf
|
||||
|
||||
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)
|
||||
|
||||
.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_loop
|
||||
|
||||
.Limem_map_at_leaf:
|
||||
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
|
||||
imem_initialize:
|
||||
# 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)
|
||||
|
||||
srli t0, a1, 12
|
||||
csrw satp, t0
|
||||
|
||||
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)
|
||||
li t0, 4096
|
||||
add a1, a1, t0
|
||||
add a2, a1, t0
|
||||
li a3, 1
|
||||
li a4, 0b0110
|
||||
call imem_map_range
|
||||
|
||||
csrr t0, satp
|
||||
li t1, 0x80000000
|
||||
or t0, t0, t1
|
||||
|
||||
sfence.vma
|
||||
csrw satp, t0
|
||||
sfence.vma
|
||||
|
||||
# Epilogue.
|
||||
lw ra, 28(sp)
|
||||
lw s0, 24(sp)
|
||||
addi sp, sp, 32
|
||||
ret
|
||||
|
||||
.type kernel_main, @function
|
||||
kernel_main:
|
||||
# Prologue.
|
||||
@@ -182,9 +25,10 @@ kernel_main:
|
||||
lw a0, 16(sp)
|
||||
li t0, 0xffc00000
|
||||
and a0, a0, t0
|
||||
lw a1, 20(sp)
|
||||
li a2, 0
|
||||
li a3, 0b0010
|
||||
mv a1, a0
|
||||
lw a2, 20(sp)
|
||||
li a3, 0
|
||||
li a4, 0b0010
|
||||
call imem_map_at
|
||||
|
||||
lw a0, 16(sp)
|
||||
@@ -350,18 +194,207 @@ _entry:
|
||||
|
||||
mv s1, a1
|
||||
|
||||
la a0, .text.boot
|
||||
mv a1, sp
|
||||
mv a0, sp
|
||||
call imem_initialize
|
||||
|
||||
lw t0, (end)
|
||||
la t1, next_paddr
|
||||
sw t0, (t1)
|
||||
li s2, 0xc0000000
|
||||
li s3, 0x80201000
|
||||
li s4, 0x1000
|
||||
|
||||
la a0, __bss
|
||||
la a1, __bss_end
|
||||
.rept 12
|
||||
mv a0, s2
|
||||
mv a1, s3
|
||||
li t0, 8192
|
||||
add a2, sp, t0
|
||||
li a3, 1
|
||||
li a4, 0b1110
|
||||
call imem_map_at
|
||||
|
||||
add s2, s2, s4
|
||||
add s3, s3, s4
|
||||
.endr
|
||||
|
||||
la a0, __bss_start
|
||||
la a1, end
|
||||
call bzero
|
||||
|
||||
mv a0, sp
|
||||
mv a1, s1
|
||||
j kernel_main
|
||||
tail kernel_main
|
||||
|
||||
# Activates paging and creates root page table.
|
||||
# Allocates enough pages for the kernel and its stack.
|
||||
#
|
||||
# Parameters:
|
||||
# a0 - Page aligned address following the kernel (kernel end).
|
||||
.type imem_initialize, @function
|
||||
imem_initialize:
|
||||
# Prologue.
|
||||
addi sp, sp, -32
|
||||
sw ra, 28(sp)
|
||||
sw s0, 24(sp)
|
||||
addi s0, sp, 32
|
||||
|
||||
sw a0, 20(sp)
|
||||
|
||||
srli t0, a0, 12
|
||||
csrw satp, t0
|
||||
|
||||
la a0, .text.boot
|
||||
mv a1, a0
|
||||
lw a2, 20(sp)
|
||||
li t0, 4096
|
||||
add a2, a2, t0
|
||||
li a3, 1
|
||||
li a4, 0b1010
|
||||
call imem_map_at
|
||||
|
||||
la a0, __executable_start
|
||||
la a1, etext
|
||||
lw a2, 20(sp)
|
||||
li t0, 4096
|
||||
add a2, a2, t0
|
||||
li a3, 1
|
||||
li a4, 0b1010
|
||||
call imem_map_range
|
||||
|
||||
la a0, etext
|
||||
la a1, _data
|
||||
lw a2, 20(sp)
|
||||
li t0, 4096
|
||||
add a2, a2, t0
|
||||
li a3, 1
|
||||
li a4, 0b0010
|
||||
call imem_map_range
|
||||
|
||||
la a0, _data
|
||||
lw a1, 20(sp)
|
||||
li t0, 4096
|
||||
add a1, a1, t0
|
||||
add a1, a1, t0
|
||||
add a1, a1, t0
|
||||
add a2, a1, t0
|
||||
li a3, 1
|
||||
li a4, 0b0110
|
||||
call imem_map_range
|
||||
|
||||
csrr t0, satp
|
||||
li t1, 0x80000000
|
||||
or t0, t0, t1
|
||||
|
||||
sfence.vma
|
||||
csrw satp, t0
|
||||
sfence.vma
|
||||
|
||||
# Epilogue.
|
||||
lw ra, 28(sp)
|
||||
lw s0, 24(sp)
|
||||
addi sp, sp, 32
|
||||
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 a3 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
|
||||
|
||||
mv a1, a0
|
||||
lw a2, 16(sp)
|
||||
lw a3, 12(sp)
|
||||
lw a4, 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
|
||||
|
||||
# Maps a page of physical memory to the identical virtual memory.
|
||||
#
|
||||
# Parameters:
|
||||
# a0 - Physical page address.
|
||||
# a1 - Corresponding virtual 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.
|
||||
#
|
||||
# Returns virtual page address in a0.
|
||||
.type imem_map_at, @function
|
||||
imem_map_at:
|
||||
csrr t0, satp
|
||||
slli t0, t0, 12 # Root table address.
|
||||
|
||||
li t4, 0xfffffc00
|
||||
li t5, 0xffc # 10 bit * PTESIZE mask.
|
||||
li t1, 20
|
||||
|
||||
.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.
|
||||
srl t2, a0, t1
|
||||
and t2, t2, t5 # VPN[i] * PTESIZE.
|
||||
add t2, t0, t2 # a + VPN[i] * PTESIZE.
|
||||
|
||||
beqz a3, .Limem_map_at_leaf
|
||||
|
||||
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, a2
|
||||
srli t3, t0, 2
|
||||
ori t3, t3, 0b1
|
||||
sw t3, (t2)
|
||||
|
||||
.Limem_map_at_next:
|
||||
# Calculate the next page table address for the next level.
|
||||
addi t1, t1, -10
|
||||
addi a3, a3, -1
|
||||
|
||||
j .Limem_map_at_loop
|
||||
|
||||
.Limem_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.
|
||||
sw t3, (t2)
|
||||
|
||||
ret
|
||||
|
@@ -23,9 +23,6 @@ type
|
||||
nameoff: Word
|
||||
end;
|
||||
|
||||
var
|
||||
next_paddr*: Pointer;
|
||||
|
||||
proc write_c(value: Char); extern;
|
||||
proc write_s(value: String); extern;
|
||||
|
||||
@@ -33,15 +30,6 @@ proc separator*() -> Char;
|
||||
return ','
|
||||
end;
|
||||
|
||||
proc alloc_pages(n: Word) -> Pointer;
|
||||
var
|
||||
paddr: Pointer;
|
||||
begin
|
||||
next_paddr := next_paddr + n * PAGE_SIZE;
|
||||
|
||||
return paddr
|
||||
end;
|
||||
|
||||
(*
|
||||
Prints a number in the hexadecimal format writing the digits into the sink
|
||||
procedure. If the value is shorter than the padding, pads the output with
|
||||
|
Reference in New Issue
Block a user