From a7f8049a8126b6fd1565bcde77700ffeca5d4317 Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Thu, 11 Mar 2021 15:59:21 +0200 Subject: Map kernel to 0xc000 rather than 0xc010 --- linker.ld | 13 ++++----- src/boot.S | 96 +++++++++++++++++++++++++++++--------------------------------- 2 files changed, 51 insertions(+), 58 deletions(-) diff --git a/linker.ld b/linker.ld index 9383b44..a9c6ec8 100644 --- a/linker.ld +++ b/linker.ld @@ -14,12 +14,11 @@ SECTIONS *(.multiboot.header) } - /* Begin putting sections at 1 MiB */ - /* TODO load sections at VADDR_BASE rather than at VADDR_BASE + 1M */ - . = VADDR_BASE + 1M; + /* Begin putting sections at 4 MiB */ + . = VADDR_BASE; _kernel_start = .; - .text ALIGN(4K) : AT(ADDR(.text) - VADDR_BASE) { + .text ALIGN(4K) : AT(ADDR(.text) - VADDR_BASE + 4M) { begin_text = .; *(.multiboot.text) *(.text*) @@ -27,14 +26,14 @@ SECTIONS } /* Read-only data. */ - .rodata ALIGN(4K) : AT(ADDR(.rodata) - VADDR_BASE) { + .rodata ALIGN(4K) : AT(ADDR(.rodata) - VADDR_BASE + 4M) { begin_rodata = .; *(.rodata*) end_rodata = .; } /* Read-write data (initialized) */ - .data ALIGN(4K) : AT(ADDR(.data) - VADDR_BASE) { + .data ALIGN(4K) : AT(ADDR(.data) - VADDR_BASE + 4M) { begin_constinit = .; *(.constinit) end_constinit = .; @@ -49,7 +48,7 @@ SECTIONS } /* Read-write data (uninitialized) and stack */ - .bss ALIGN(4K) : AT(ADDR(.bss) - VADDR_BASE) { + .bss ALIGN(4K) : AT(ADDR(.bss) - VADDR_BASE + 4M) { begin_bss = .; *(.pages) *(.bss) diff --git a/src/boot.S b/src/boot.S index 23c1e25..6588004 100644 --- a/src/boot.S +++ b/src/boot.S @@ -39,90 +39,84 @@ stack_top: .section .pages, "aw", @nobits .align 4096 boot_page_directory: - .skip 4096 + .skip 1024 * 4 boot_page_table1: - .skip 4096 + .skip 1024 * 4 /* The linker script specifies _start as the entry point to the kernel and the bootloader will jump to this position once the kernel has been loaded. -*/ + */ .section .multiboot.text, "ax" -.set VADDR_BASE, 0xc0000000 +.set VADDR_OFFSET, 0xc0000000 - 0x400000 .global _start .type _start, @function _start: cli # Physical address of boot_page_table1. - movl $(boot_page_table1 - VADDR_BASE), %edi - # First address to map is address 0. - movl $0, %esi + movl $(boot_page_table1 - VADDR_OFFSET), %edi + + # Only map the kernel. + mov $_kernel_start - VADDR_OFFSET, %esi # Map 1023 pages. The 1024th will be the VGA text buffer. movl $1023, %ecx -1: - # Only map the kernel. - cmpl $_kernel_start, %esi - jl 2f - cmpl $(_kernel_end - VADDR_BASE), %esi - jge 3f +l_page_init: + cmpl $(_kernel_end - VADDR_OFFSET), %esi + jge map_vga - # Map physical address as "present, writable". Note that this maps - # .text and .rodata as writable. Mind security and map them as non-writable. + /* TODO: Map physical address as "present, writable". Note that this maps .text and .rodata as writable. + Mind security and map them as non-writable. */ movl %esi, %edx orl $0x003, %edx movl %edx, (%edi) -2: # Size of page is 4096 bytes. addl $4096, %esi # Size of entries in boot_page_table1 is 4 bytes. addl $4, %edi # Loop to the next entry if we haven't finished. - loop 1b - -3: - # Map VGA video memory to 0xC03FF000 as "present, writable". - movl $(0x000B8000 | 0x003), boot_page_table1 - VADDR_BASE + 1023 * 4 - - # The page table is used at both page directory entry 0 (virtually from 0x0 - # to 0x3FFFFF) (thus identity mapping the kernel) and page directory entry - # 768 (virtually from VADDR_BASE to 0xC03FFFFF) (thus mapping it in the - # higher half). The kernel is identity mapped because enabling paging does - # not change the next instruction, which continues to be physical. The CPU - # would instead page fault if there was no identity mapping. - - # Map the page table to both virtual addresses 0x00000000 and VADDR_BASE. - movl $(boot_page_table1 - VADDR_BASE + 0x003), boot_page_directory - VADDR_BASE + 0 - movl $(boot_page_table1 - VADDR_BASE + 0x003), boot_page_directory - VADDR_BASE + 768 * 4 + loop l_page_init - # Set cr3 to the address of the boot_page_directory. - movl $(boot_page_directory - VADDR_BASE), %ecx - movl %ecx, %cr3 +map_vga: + # Map VGA video memory to 0xC03FF000 as "present, writable". + movl $(0x000B8000 | 0x003), boot_page_table1 - VADDR_OFFSET + 1023 * 4 - # Enable paging and the write-protect bit. - movl %cr0, %ecx - orl $0x80010000, %ecx - movl %ecx, %cr0 - - # Jump to higher half with an absolute jump. - lea (kinit), %ecx - jmp *%ecx +/* + Enabling paging does not change the next instruction, which continues to be physical. Therefore, map the kernel + to both its physical address and to the higher half. + Use the page table at: + - entry 1 starts 0x0040 0000 ends 0x007f ffff + - entry 768 starts 0xc000 0000 ends 0xc03f ffff + */ + movl $(boot_page_table1 - VADDR_OFFSET + 0x003), boot_page_directory - VADDR_OFFSET + 1 * 4 + movl $(boot_page_table1 - VADDR_OFFSET + 0x003), boot_page_directory - VADDR_OFFSET + 768 * 4 + + # Set cr3 to the address of the boot_page_directory. + movl $(boot_page_directory - VADDR_OFFSET), %ecx + movl %ecx, %cr3 + + # Enable paging and the write-protect bit. + movl %cr0, %ecx + orl $0x80010000, %ecx + movl %ecx, %cr0 + + # Jump to higher half with an absolute jump. + lea (kinit), %ecx + jmp *%ecx .section .text .extern kernel_constructors .extern kernel_main kinit: - # At this point, paging is fully set up and enabled. - - # Unmap the identity mapping as it is now unnecessary. - movl $0, boot_page_directory + 0 - - # Reload crc3 to force a TLB flush so the changes to take effect. - movl %cr3, %ecx - movl %ecx, %cr3 + # At this point, paging is fully set up and enabled. + # Unmap the identity mapping as it is now unnecessary. + movl $0, boot_page_directory + 1 * 4 + # Reload crc3 to force a TLB flush so the changes to take effect. + movl %cr3, %ecx + movl %ecx, %cr3 #mov $stack_bottom, %ebp mov $stack_top, %esp # point the stack pointer to the stack -- cgit v1.2.1