1 Commits

Author SHA1 Message Date
6c32c430d0 feat: start of paging setup 2022-05-14 17:01:10 +02:00
7 changed files with 224 additions and 112 deletions

View File

@@ -19,7 +19,7 @@ forced to be within the first 8 KiB of the kernel file.
.long CHECKSUM
#.include "gdt.S"
.section .data
.section .data.boot
gdt:
.quad 0x0000000000000000
.quad 0x00CF9A000000FFFF
@@ -42,7 +42,7 @@ System V ABI standard and de-facto extensions. The compiler will assume the
stack is properly aligned and failure to align the stack will result in
undefined behavior.
*/
.section .bss
.section .bss.boot
.align 16
stack_bottom:
.skip 16384 # 16 KiB
@@ -53,7 +53,7 @@ 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. It
doesn't make sense to return from this function as the bootloader is gone.
*/
.section .text
.section .text.boot
.global _start
.type _start, @function
_start:
@@ -103,6 +103,25 @@ _start:
continue_boot:
sti
// setting up paging
// id map first 4MB using PSE. With
movl $135, kernel_page_directory - 0xC0000000
movl $135, kernel_page_directory - 0xC0000000 + 3072
// load into cr3
movl $kernel_page_directory - 0xC0000000, %eax
movl %eax, %cr3
// enable PSE TODO validate if PSE is actually supported
movl %cr4, %eax
orl $0x10, %eax
movl %eax, %cr4
// enable paging
movl %cr0, %eax
orl $0x80000000, %eax
movl %eax, %cr0
nop
pushl 0
popl %eax
/*
Enter the high-level kernel. The ABI requires the stack is 16-byte
aligned at the time of the call instruction (which afterwards pushes

View File

@@ -5,4 +5,39 @@
#ifndef NEW_KERNEL_PAGING_H
#define NEW_KERNEL_PAGING_H
#define PAGING_MASK_4K 0xFFFFF000
#define PAGING_MASK_4M 0xFFC00000
#define DIRECTORY_PRESENT_BIT (0)
#define DIRECTORY_RW_BIT (1)
#define DIRECTORY_US_BIT (2)
#define DIRECTORY_WT_BIT (3)
#define DIRECTORY_CACHE_BIT (4)
#define DIRECTORY_ACCESSED_BIT (5)
#define DIRECTORY_PAGE_SIZE_BIT (7)
#define DIRECTORY_ADDR_MASK 0xFFFFF000
#define DIRECTORY_PRESENT_MASK (1 << DIRECTORY_PRESENT_BIT)
#define DIRECTORY_RW_MASK (1 << DIRECTORY_RW_BIT)
#define DIRECTORY_US_MASK (1 << DIRECTORY_US_BIT)
#define DIRECTORY_WT_MASK (1 << DIRECTORY_WT_BIT)
#define DIRECTORY_CACHE_MASK (1 << DIRECTORY_CACHE_BIT)
#define DIRECTORY_ACCESSED_MASK (1 << DIRECTORY_ACCESSED_BIT)
#define DIRECTORY_PAGE_SIZE_MASK (1 << DIRECTORY_PAGE_SIZE_BIT)
#define DIRECTORY_SIZE 1024
#define PAGING_MODE_4M (1 << 0)
#define PAGING_MODE_RW (1 << 1)
#define PAGING_MODE_US (1 << 2)
#define PAGING_RESULT_OK 0
#define PAGING_RESULT_INUSE 1
#define PAGING_RESULT_ALIGN 2
#define PAGING_RESULT_ERR 99
typedef uint32_t page_directory_entry;
typedef uint32_t page_table_entry;
#endif //NEW_KERNEL_PAGING_H

10
include/myke/mem/vmm.h Normal file
View File

@@ -0,0 +1,10 @@
//
// Created by rick on 17-10-21.
//
#ifndef NEW_KERNEL_VMM_H
#define NEW_KERNEL_VMM_H
void vmm_init(multiboot_info_t *multiboot_info);
#endif //NEW_KERNEL_VMM_H

View File

@@ -13,7 +13,7 @@
#include <myke/libk/kprint.h>
#include <myke/libk/libk.h>
#include <myke/libk/syscall.h>
#include <myke/mem/mem.h>
#include <myke/mem/vmm.h>
#include <myke/util/init.h>
#include <myke/tasks/task.h>
@@ -21,15 +21,6 @@ const int version_major = 0,
version_minor = 0,
version_patch = 1;
void init_mmap(multiboot_info_t *multiboot_info) {
if (multiboot_info->flags & (1 << 6)) {
mmap_init_multiboot((struct multiboot_mmap_entry *) multiboot_info->mmap_addr,
multiboot_info->mmap_length / sizeof(struct multiboot_mmap_entry));
} else {
k_panics("mmap invalid!\n");
}
}
void init_pci_system() {
pci_scan();
pci_init_drivers();
@@ -38,6 +29,9 @@ void init_pci_system() {
void att_noreturn att_used kmain(multiboot_info_t *multiboot_info, uint32_t mb_name) {
// early init
isr_install();
// initialize memory management
vmm_init(multiboot_info);
// initialize early modules (kprint etc.)
init_execute_all(INIT_STAGE_EARLY_BOOT_0);
@@ -48,8 +42,6 @@ void att_noreturn att_used kmain(multiboot_info_t *multiboot_info, uint32_t mb_n
store_bootloader_info(multiboot_info);
// initialize memory management
init_mmap(multiboot_info);
// safe multiboot info for later use
debug_store_info(multiboot_info);

View File

@@ -2,58 +2,80 @@
// Created by rick on 21-02-21.
//
#include <attributes.h>
#include <stdbool.h>
#include <sys/types.h>
#include <attributes.h>
#include <myke/mem/paging.h>
#include <sys/param.h>
#define TABLE_ADDR_MASK 0xFFFFF000
#define DIRECTORY_SIZE 1024
#define PAGING_DIR_INDEX(virt) ((virt) >> 22)
#define PAGING_TABLE_INDEX(virt) ((virt) >> 12 & 0x03FF)
const uint32_t x = TABLE_ADDR_MASK;
typedef struct {
union {
struct {
bool present: 1;
bool read_write: 1;
bool user_mode: 1;
bool write_through: 1;
bool cache_disabled: 1;
bool accessed: 1;
char ignored: 1;
bool page_size: 1;
bool global: 1; // ignored
uint8_t avail: 3;
} att_packed;
uint32_t addr;
};
} att_packed page_directory_entry;
#define KERNEL_OFFSET 0xC0000000
typedef struct {
union {
struct {
bool present: 1;
bool read_write: 1;
bool user_supervisor: 1;
bool write_through: 1;
bool cache_disabled: 1;
bool accessed: 1;
bool dirty: 1;
char ignored: 1;
bool global: 1;
uint8_t available: 3;
} att_packed;
uint32_t addr;
};
} att_packed page_table_entry;
// One page table, only 4M
#define PAGING_STATE_EARLY 0
#define PAGING_STATE_FULL 60
page_directory_entry page_directory[DIRECTORY_SIZE] att_aligned(4096);
page_directory_entry att_aligned(4096) kernel_page_directory[DIRECTORY_SIZE] = {0};
void page_pre_init() {
for (int i = 0; i < DIRECTORY_SIZE; ++i) {
page_directory[i].read_write = true;
page_directory[i].user_mode = false;
page_directory[i].present = false;
int paging_state = PAGING_STATE_EARLY;
void paging_load_directory(uintptr_t physical_address) {
asm volatile("mov %%eax, %%cr3" : : "a" (physical_address));
}
uintptr_t paging_get_current_directory_physical() {
uintptr_t directory_address;
asm volatile("mov %%cr3, %%eax" : "=a" (directory_address));
return directory_address;
}
page_directory_entry *paging_get_current() {
return kernel_page_directory;
}
int paging_map_4m(uintptr_t physical_address, uintptr_t virtual_address, int count, int mode) {
if (virtual_address & ~PAGING_MASK_4M || physical_address & PAGING_MASK_4M) {
// address not 4M aligned
return PAGING_RESULT_ALIGN;
}
page_directory_entry *dir = paging_get_current();
for (int i = 0; i < count; ++i) {
page_directory_entry current_val = dir[PAGING_DIR_INDEX(virtual_address) + i];
if (current_val & DIRECTORY_PRESENT_MASK) {
return PAGING_RESULT_INUSE;
}
}
page_directory_entry mask = DIRECTORY_PAGE_SIZE_MASK;
if (mode & PAGING_MODE_RW) {
mask |= DIRECTORY_RW_MASK;
}
if (mode & PAGING_MODE_US) {
mask |= DIRECTORY_US_MASK;
}
for (int i = 0; i < count; ++i) {
dir[PAGING_DIR_INDEX(virtual_address) + i] = physical_address & mask;
}
paging_load_directory((uintptr_t) dir);
return PAGING_RESULT_OK;
}
int paging_map_memory(uintptr_t physical_address, uintptr_t virtual_address, int count, int mode) {
if (mode & PAGING_MODE_4M) {
return paging_map_4m(physical_address, virtual_address, count, mode);
}
if (paging_state < PAGING_STATE_FULL) {
// can't allocate 4K pages yet
if ((virtual_address & ~PAGING_MASK_4M) != (physical_address & ~PAGING_MASK_4M)) {
return PAGING_RESULT_ERR; // not in same pos in 4M page
}
int table_index = PAGING_TABLE_INDEX(virtual_address);
int pages = DIV_ROUND_UP(table_index + count, 1024);
return paging_map_4m(physical_address & PAGING_MASK_4M,
virtual_address & PAGING_MASK_4M,
pages,
mode | PAGING_MODE_4M);
}
return PAGING_RESULT_ERR;
}

24
kernel/mem/vmm.c Normal file
View File

@@ -0,0 +1,24 @@
//
// Created by rick on 17-10-21.
//
#include <sys/types.h>
#include <myke/libk/libk.h>
#include <myke/mem/mem.h>
#include <myke/mem/vmm.h>
void vmm_init(multiboot_info_t *multiboot_info) {
if (!(multiboot_info->flags & MULTIBOOT_INFO_MEM_MAP)) {
k_panics("No MMAP info available");
}
mmap_init_multiboot((struct multiboot_mmap_entry *) multiboot_info->mmap_addr,
multiboot_info->mmap_length / sizeof(struct multiboot_mmap_entry));
}
void* vmm_map_physical(uintptr_t physical) {
}
void* vmm_unmap_physical(uintptr_t physical) {
}
void* vmm_unmap_virtual(uintptr_t virtual) {
}

View File

@@ -10,24 +10,34 @@ SECTIONS
loaded at by the bootloader. */
. = 1M;
_kernel_start = .;
.data.boot ALIGN(4K) : {
*(.multiboot)
*(.data.boot)
}
.text.boot ALIGN(4K) : {
*(.text.boot)
}
.bss.boot ALIGN(4K) : {
*(.bss.boot)
}
. += 0xC0000000;
/* First put the multiboot header, as it is required to be put very early
early in the image or the bootloader won't recognize the file format.
Next we'll put the .text section. */
.text BLOCK(4K) : ALIGN(4K)
.text ALIGN(4K) : AT(ADDR(.text)-0xC0000000)
{
*(.multiboot)
*(.text)
}
/* Read-only data. */
.rodata BLOCK(4K) : ALIGN(4K)
.rodata ALIGN(4K) : AT(ADDR(.rodata)-0xC0000000)
{
*(.rodata)
}
/* Read-write data (initialized) */
.data BLOCK(4K) : ALIGN(4K)
.data ALIGN(4K) : AT(ADDR(.data)-0xC0000000)
{
*(.data)
@@ -53,12 +63,12 @@ SECTIONS
}
/* Read-write data (uninitialized) and stack */
.bss BLOCK(4K) : ALIGN(4K)
.bss ALIGN(4K) : AT(ADDR(.bss)-0xC0000000)
{
*(COMMON)
*(.bss)
}
_kernel_end = .;
_kernel_end = . - 0xC0000000;
/DISCARD/ : {
*(.eh_frame);