Skip to content
This repository has been archived by the owner on Jan 12, 2025. It is now read-only.

Commit

Permalink
Merge pull request #39 from lvntky/feature/memory
Browse files Browse the repository at this point in the history
Feature/memory
  • Loading branch information
lvntky authored Nov 10, 2023
2 parents 49eb54d + 816c368 commit bb37a8c
Show file tree
Hide file tree
Showing 14 changed files with 308 additions and 135 deletions.
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ objects = ./build/loader.o \
./build/tss.o \
./build/timer.o \
./build/keyboard.o \
./build/paging_enable.o \
./build/paging.o \
./build/render_font.o \
./build/panic.o \
./build/render_image.o \
Expand Down Expand Up @@ -55,7 +57,10 @@ build/%.o: gui/%.c
i686-elf-gcc $(CFLAGS) -c -o $@ $<

# MEMORY
build/%.o: kernel/memory/%.c
build/%.o: kernel/memory/asm/%.asm
nasm -f elf32 -o $@ $<

build/%.o: kernel/memory/src/%.c
i686-elf-gcc $(CFLAGS) -c -o $@ $<

# LOADER ASM
Expand Down
136 changes: 81 additions & 55 deletions boot/loader.asm
Original file line number Diff line number Diff line change
@@ -1,57 +1,83 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Artillery OS GRUB BootLoader ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

[BITS 32]
extern kernel_main

global start
start:
mov esp, _sys_stack ; This points the stack to our new stack area
jmp stublet

; This part MUST be 4byte aligned, so we solve that issue using 'ALIGN 4'
ALIGN 4
mboot:
; Multiboot macros to make a few lines later more readable
MULTIBOOT_PAGE_ALIGN equ 1<<0
MULTIBOOT_MEMORY_INFO equ 1<<1
MULTIBOOT_AOUT_KLUDGE equ 1<<16
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
EXTERN code, bss, end

; This is the GRUB Multiboot header. A boot signature
dd MULTIBOOT_HEADER_MAGIC
dd MULTIBOOT_HEADER_FLAGS
dd MULTIBOOT_CHECKSUM
; AOUT kludge - must be physical addresses. Make a note of these:
; The linker script fills in the data for these ones!
dd mboot
dd code
dd bss
dd end
dd start

; This is an endless loop here. Make a note of this: Later on, we
; will insert an 'extern _main', followed by 'call _main', right
; before the 'jmp $'.
stublet:
call kernel_main
jmp $


; Shortly we will add code for loading the GDT right here!


; In just a few pages in this tutorial, we will add our Interrupt
; Service Routines (ISRs) right here!



; Here is the definition of our BSS section. Right now, we'll use
; it just to store the stack. Remember that a stack actually grows
; downwards, so we declare the size of the data before declaring
; the identifier '_sys_stack'
SECTION .bss
resb 8192 ; This reserves 8KBytes of memory here
_sys_stack:
global loader ; the entry point for the linker

extern kernel_main ; kmain is defined in kmain.c
extern end_of_kernel

; setting up the multiboot headers for GRUB
MODULEALIGN equ 1<<0 ; align loaded modules on page
; boundaries
MEMINFO equ 1<<1 ; provide memory map
FLAGS equ MODULEALIGN | MEMINFO ; the multiboot flag field
MAGIC equ 0x1BADB002 ; magic number for bootloader to
; find the header
CHECKSUM equ -(MAGIC + FLAGS) ; checksum required

; paging for the kernel
KERNEL_VIRTUAL_BASE equ 0xC0000000 ; we start at 3GB
KERNEL_PAGE_IDX equ (KERNEL_VIRTUAL_BASE >> 22) ; PDT index for 4MB PDE

; the page directory used to boot the kernel into the higher half
section .data
align 4096 ; align on 4kB blocks
boot_page_directory:
dd 00000000000000000000000010001011b ; identity mapped first 4MB
times (KERNEL_PAGE_IDX-1) dd 0 ; no pages here
dd 00000000000000000000000010001011b ; map 0xC0000000 to the first 4MB
times (1024-KERNEL_PAGE_IDX-1) dd 0 ; no more pages


section .text
align 4
dd MAGIC
dd FLAGS
dd CHECKSUM

; the entry point, called by GRUB
loader:
mov ecx, (boot_page_directory-KERNEL_VIRTUAL_BASE)
and ecx, 0xFFFFF000 ; we only care about the upper 20 bits
or ecx, 0x08 ; PWT, enable page write through?
mov cr3, ecx ; load pdt

mov ecx, cr4 ; read current config from cr4
or ecx, 0x00000010 ; set bit enabling 4MB pages
mov cr4, ecx ; enable it by writing to cr4

mov ecx, cr0 ; read current config from cr0
or ecx, 0x80000000 ; the highest bit controls paging
mov cr0, ecx ; enable paging by writing config to cr0

lea ecx, [higher_half] ; store the address higher_half in ecx
jmp ecx ; now we jump into 0xC0100000

; code executing from here on uses the page table, and is accessed through
; the upper half, 0xC0100000
higher_half:
mov DWORD [boot_page_directory], 0 ; erase identity mapping of kernel
invlpg [0] ; and flush any tlb-references to it

mov esp, stack+STACKSIZE ; sets up the stack pointer
push end_of_kernel
push eax ; eax contains the MAGIC number
push ebx ; ebx contains the multiboot data
; structure
call kernel_main ; call the main function of the kernel

hang:
jmp hang ; loop forever

; reserve initial stack space
STACKSIZE equ 0x4000 ; 16kB

section .bss
align 4
stack:
resb STACKSIZE ; reserve memory for stack on
; doubleworded memory
7 changes: 7 additions & 0 deletions kernel/include/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#ifndef _COMMON_H_
#define _COMMON_H_

#define UNUSED_ARGUMENT(x) (void)x;
#define KERNEL_BASE_ADDR 0xC0000000

#endif
4 changes: 3 additions & 1 deletion kernel/include/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "multiboot_util.h"
#include "system.h"
#include "common.h"
#include "../libc/include/stdio.h"
#include "tty.h"
#include "qemu_debug.h"
Expand All @@ -15,9 +16,10 @@
#include "../driver/include/keyboard.h"
#include "../../gui/render_font.h"
#include "panic.h"
#include "../memory/include/paging.h"
#include "../../gui/render_image.h"
#include "options.h"

void kernel_main();
void kernel_main(uint32_t, uint32_t, uint32_t);

#endif
7 changes: 5 additions & 2 deletions kernel/include/multiboot_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@

#include <stdbool.h>
#include "multiboot.h"
#include "common.h"
#include "../libc/include/stdio.h"
#include "qemu_debug.h"
#include "panic.h"

void print_multiboot_magic(unsigned int);
bool is_multiboot_info_present(multiboot_info_t *);
void display_memory_info(multiboot_info_t *, uint32_t);
void check_mboot_bootloader_magic(uint32_t);
multiboot_info_t *remap_multiboot_info(uint32_t);

#endif
2 changes: 2 additions & 0 deletions kernel/include/qemu_debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#define DEBUG_OUTPUT "->"
#define REGISTER_OUTPUT "[REGISTER]"
#define EXCEPTION_OUTPUT "[EXCEPTION]"
#define MEMORY_OUTPUT "[MEMORY DUMP]"
#define PAGE_OUTPUT "[PAGE DUMP]"

void qemu_init_debug();
void qemu_write_string(char *format, ...);
Expand Down
3 changes: 2 additions & 1 deletion kernel/include/tty.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
#include "../libc/include/stdio.h"
#include "qemu_debug.h"
#include "config.h"
#include "common.h"
#include <stddef.h>
#include <stdint.h>

#define VIDEO_MEM_ADDRESS 0xB8000
#define VIDEO_MEM_ADDRESS 0xB8000 + KERNEL_BASE_ADDR
#define VGA_WIDTH 80
#define VGA_HEIGHT 25

Expand Down
11 changes: 11 additions & 0 deletions kernel/memory/asm/paging_enable.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
global pdt_set

section .text:

pdt_set:
mov eax, [esp+4] ; loads the address of the pdt into eax
mov cr3, eax ; loads the PDT
mov eax, cr0 ; read current config from cr0
or eax, 0x80000000 ; the highest bit controls paging
mov cr0, eax ; enable paging by writing config to cr0
ret
60 changes: 17 additions & 43 deletions kernel/memory/include/paging.h
Original file line number Diff line number Diff line change
@@ -1,54 +1,28 @@
#ifndef _PAGING_H_
#define _PAGING_H_

#define PAGING_ENTRY_SIZE 1024
#define KERNEL_BASE_VIRT 0xC0000000

#define PHYS_TO_VIRT(addr) ((addr) + KERNEL_BASE_VIRT)
#define VIRT_TO_PHYS(addr) ((addr)-KERNEL_BASE_VIRT)

#define PAGE_DIRECTORY_INDEX(x) (((x) >> 22) & 0x3FF)
#define PAGE_TABLE_INDEX(x) (((x) >> 12) & 0x3FF)

#include <stdint.h>
#include <stdbool.h>
#include "../../include/qemu_debug.h"
#include "../../descriptor_tables/include/isr.h"
#include "../../libc/include/string.h"

typedef struct page_directory_entry {
uint8_t config;
uint8_t low_addr; /* only the highest 4 bits are used */
uint16_t high_addr;
} __attribute__((packed)) page_directory_entry_t;

typedef struct directory_entry {
uint32_t present : 1;
uint32_t rw : 1;
uint32_t user : 1;
uint32_t writethrough : 1;
uint32_t disable_cache : 1;
uint32_t accessed : 1;
uint32_t zero : 1;
uint32_t large_pages : 1;
uint32_t unused : 1;
uint32_t available : 3;
uint32_t frame : 20;
} __attribute__((packed)) directory_entry_t;
typedef struct page_table_entry {
uint8_t config;
uint8_t middle; /* only the highest 4 bits and the lowest bit are used */
uint16_t high_addr;
} __attribute__((packed)) page_table_entry_t;

typedef struct page {
uint32_t present : 1;
uint32_t rw : 1;
uint32_t user : 1;
uint32_t writethrough : 1;
uint32_t disable_cache : 1;
uint32_t accessed : 1;
uint32_t dirty : 1;
uint32_t zero : 1;
uint32_t global : 1;
uint32_t available : 3;
uint32_t frame : 20;
} __attribute__((packed)) page_t;
#define NUM_ENTRIES 1024
#define PDT_SIZE NUM_ENTRIES * sizeof(page_directory_entry_t)
#define PT_SIZE NUM_ENTRIES * sizeof(page_table_entry_t)

typedef struct page_table {
page_t entries[PAGING_ENTRY_SIZE];
} page_table_t;
#define VIRTUAL_TO_PDT_IDX(a) ((a >> 20) & 0x3FF)

typedef struct page_directory {
directory_entry_t entries[PAGING_ENTRY_SIZE];
} page_directory_t;
void paging_init(uint32_t);

#endif
26 changes: 26 additions & 0 deletions kernel/memory/memory.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Memory

## Memory Layout

Each process in the Artillery OS runs in its own memory sandbox. This sandbox is the virtual address space,
which in 32-bit mode is always a 4GB block of memory addresses. These virtual addresses are mapped to
physical memory by page tables, which are maintained by the operating system kernel and consulted by the processor.
Each process has its own set of page tables, but there is a catch. Once virtual addresses are enabled,
they apply to all software running in the machine, including the kernel itself. Thus a portion of the virtual
address space must be reserved to the kernel

* Artillery OS User/Kernel Memory Split

..................... -> 0xFFFFFFFF
. Kernel Space .
. (1GB) .
..................... -> 0xC0000000
. .
. .
. .
. User Space .
. Mode .
. (3GB) .
. .
. .
..................... 0x00000000
Loading

0 comments on commit bb37a8c

Please sign in to comment.