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' |   QEMU = 'qemu-system-riscv32' | ||||||
|  |  | ||||||
|   system QEMU, '-machine', 'virt', '-bios', 'default', '-nographic', '-serial', 'mon:stdio', '--no-reboot', |   system QEMU, '-machine', 'virt', '-bios', 'default', '-nographic', '-serial', 'mon:stdio', '--no-reboot', | ||||||
|     '-kernel', *t.prerequisites |     '-kernel', t.prerequisites.last, exception: true | ||||||
| end | end | ||||||
|   | |||||||
| @@ -3,35 +3,45 @@ OUTPUT_FORMAT("elf32-littleriscv") | |||||||
| ENTRY(_entry) | ENTRY(_entry) | ||||||
|  |  | ||||||
| PHDRS { | PHDRS { | ||||||
|  | 	boot PT_LOAD FLAGS(5); | ||||||
| 	text PT_LOAD FLAGS(5); | 	text PT_LOAD FLAGS(5); | ||||||
| 	data PT_LOAD FLAGS(6); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| SECTIONS { | SECTIONS { | ||||||
| 	.text 0x80200000 : { | 	.text.boot 0x80200000 : { | ||||||
| 		KEEP(*(.text.boot)); | 		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 .text.*); | ||||||
| 	} :text | 	} :text | ||||||
|  |  | ||||||
| 	. = ALIGN(CONSTANT(MAXPAGESIZE)); | 	. = ALIGN(CONSTANT(MAXPAGESIZE)); | ||||||
| 	PROVIDE(etext = .); | 	PROVIDE(etext = . - _kernel_offset); | ||||||
|  |  | ||||||
| 	.rodata : ALIGN(16) { | 	.rodata : AT(ADDR(.rodata) - _kernel_offset) ALIGN(16) { | ||||||
| 		*(.rodata .rodata.*); | 		*(.rodata .rodata.*); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	.data : ALIGN(16) { | 	. = ALIGN(CONSTANT(MAXPAGESIZE)); | ||||||
| 		*(.data .data.*); | 	PROVIDE(_data = . - _kernel_offset); | ||||||
| 	} :data |  | ||||||
|  |  | ||||||
| 	.bss : ALIGN(16) { | 	.data : AT(ADDR(.data) - _kernel_offset) ALIGN(16) { | ||||||
| 		__bss = .; | 		*(.data .data.*); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	.bss (NOLOAD) : { | ||||||
|  | 		PROVIDE(__bss_start = . - _kernel_offset); | ||||||
| 		*(.bss .bss.* .sbss .sbss.*); | 		*(.bss .bss.* .sbss .sbss.*); | ||||||
| 		__bss_end = .; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	. = ALIGN(CONSTANT(MAXPAGESIZE)); | 	. = ALIGN(CONSTANT(MAXPAGESIZE)); | ||||||
| 	PROVIDE(end = .); | 	PROVIDE(end = . - _kernel_offset); | ||||||
|  |  | ||||||
| 	/DISCARD/ : { | 	/DISCARD/ : { | ||||||
| 		*(.eh_frame) | 		*(.eh_frame) | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| .global _entry, __bss, __bss_end, __stack_top | .global _entry | ||||||
|  |  | ||||||
| .section .rodata | .section .rodata | ||||||
|  |  | ||||||
| @@ -7,163 +7,6 @@ panic_message: .asciz "\nPanic" | |||||||
|  |  | ||||||
| .section .text | .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 | .type kernel_main, @function | ||||||
| kernel_main: | kernel_main: | ||||||
| 	# Prologue. | 	# Prologue. | ||||||
| @@ -182,9 +25,10 @@ kernel_main: | |||||||
| 	lw a0, 16(sp) | 	lw a0, 16(sp) | ||||||
| 	li t0, 0xffc00000 | 	li t0, 0xffc00000 | ||||||
| 	and a0, a0, t0 | 	and a0, a0, t0 | ||||||
| 	lw a1, 20(sp) | 	mv a1, a0 | ||||||
| 	li a2, 0 | 	lw a2, 20(sp) | ||||||
| 	li a3, 0b0010 | 	li a3, 0 | ||||||
|  | 	li a4, 0b0010 | ||||||
| 	call imem_map_at | 	call imem_map_at | ||||||
|  |  | ||||||
| 	lw a0, 16(sp) | 	lw a0, 16(sp) | ||||||
| @@ -350,18 +194,207 @@ _entry: | |||||||
|  |  | ||||||
| 	mv s1, a1 | 	mv s1, a1 | ||||||
|  |  | ||||||
| 	la a0, .text.boot | 	mv a0, sp | ||||||
| 	mv a1, sp |  | ||||||
| 	call imem_initialize | 	call imem_initialize | ||||||
|  |  | ||||||
| 	lw t0, (end) | 	li s2, 0xc0000000 | ||||||
| 	la t1, next_paddr | 	li s3, 0x80201000 | ||||||
| 	sw t0, (t1) | 	li s4, 0x1000 | ||||||
|  |  | ||||||
| 	la a0, __bss | .rept 12 | ||||||
| 	la a1, __bss_end | 	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 | 	call bzero | ||||||
|  |  | ||||||
| 	mv a0, sp | 	mv a0, sp | ||||||
| 	mv a1, s1 | 	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 |     nameoff: Word | ||||||
|   end; |   end; | ||||||
|  |  | ||||||
| var |  | ||||||
|   next_paddr*: Pointer; |  | ||||||
|  |  | ||||||
| proc write_c(value: Char); extern; | proc write_c(value: Char); extern; | ||||||
| proc write_s(value: String); extern; | proc write_s(value: String); extern; | ||||||
|  |  | ||||||
| @@ -33,15 +30,6 @@ proc separator*() -> Char; | |||||||
|   return ',' |   return ',' | ||||||
| end; | 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 |   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 |   procedure. If the value is shorter than the padding, pads the output with | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user