Compare commits
1 Commits
feature/mo
...
feature/pa
| Author | SHA1 | Date | |
|---|---|---|---|
| 6c32c430d0 |
25
boot/boot.S
25
boot/boot.S
@@ -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
|
||||
|
||||
@@ -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
10
include/myke/mem/vmm.h
Normal 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
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
24
kernel/mem/vmm.c
Normal 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) {
|
||||
}
|
||||
22
linker.ld
22
linker.ld
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user