GDT finally works

This commit is contained in:
2025-08-10 21:29:16 +02:00
parent f8f00cc608
commit 8ee1ea1292
36 changed files with 868 additions and 206 deletions

1
kernel/.gitignore vendored
View File

@ -1,2 +1,3 @@
*.o
mop2
*.iso

View File

@ -1,53 +1,36 @@
.PHONY: all clean
CC := x86_64-elf-gcc
LD := x86_64-elf-ld
ARCH ?= x86_64
override CFLAGS = -Wall \
-Wextra \
-ffreestanding \
-fno-stack-protector \
-fno-stack-check \
-fno-lto \
-fno-PIC \
-ffunction-sections \
-fdata-sections \
-m64 \
-march=x86-64 \
-mabi=sysv \
-mno-80387 \
-mno-mmx \
-mno-sse \
-mno-sse2 \
-mno-red-zone \
-mcmodel=kernel \
-I. \
CFLAGS := -ffreestanding -Wall -Wextra -g -fcommon
CFLAGS += -I. \
-I../limine \
-DPRINTF_INCLUDE_CONFIG_H=1
override LDFLAGS = \
-m elf_x86_64 \
-nostdlib \
-static \
-z max-page-size=0x1000 \
--gc-sections \
-T link.ld
LDFLAGS := -nostdlib -static -T arch/$(ARCH)/link.ld
override NASMFLAGS = \
-felf64 \
-Wall \
-F dwarf -g
include arch/$(ARCH)/$(ARCH).mk
include extconf/extra.mk
override SRCFILES := $(shell find -L . -type f 2>/dev/null | LC_ALL=C sort)
override CFILES := $(filter %.c,$(SRCFILES))
override ASFILES := $(filter %.asm,$(SRCFILES))
override OBJ := $(patsubst %.c,%.o,$(CFILES)) $(patsubst %.asm,%.o,$(ASFILES))
SRCFILES := $(wildcard *.c) \
$(wildcard printf/*.c) \
$(wildcard bitmap/*.c) \
$(wildcard pmm/*.c) \
$(wildcard bootinfo/*.c) \
$(wildcard hal/*.c) \
$(wildcard hal/$(ARCH)/*.c) \
$(wildcard hal/$(ARCH)/*.S) \
$(wildcard *.S)
CFILES := $(filter %.c,$(SRCFILES))
ASFILES := $(filter %.S,$(SRCFILES))
OBJ := $(patsubst %.c,%.o,$(CFILES)) $(patsubst %.S,%.o,$(ASFILES))
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
%.o: %.asm
nasm $(NASMFLAGS) $< -o $@
%.o: %.S
$(CC) $(CFLAGS) -c $< -o $@
all: mop2

85
kernel/ansi_colors.h Normal file
View File

@ -0,0 +1,85 @@
#ifndef ANSI_COLORS_H_
#define ANSI_COLORS_H_
/*
* This is free and unencumbered software released into the public domain.
*
* For more information, please refer to <https://unlicense.org>
*/
//Regular text
#define BLK "\e[0;30m"
#define RED "\e[0;31m"
#define GRN "\e[0;32m"
#define YEL "\e[0;33m"
#define BLU "\e[0;34m"
#define MAG "\e[0;35m"
#define CYN "\e[0;36m"
#define WHT "\e[0;37m"
//Regular bold text
#define BBLK "\e[1;30m"
#define BRED "\e[1;31m"
#define BGRN "\e[1;32m"
#define BYEL "\e[1;33m"
#define BBLU "\e[1;34m"
#define BMAG "\e[1;35m"
#define BCYN "\e[1;36m"
#define BWHT "\e[1;37m"
//Regular underline text
#define UBLK "\e[4;30m"
#define URED "\e[4;31m"
#define UGRN "\e[4;32m"
#define UYEL "\e[4;33m"
#define UBLU "\e[4;34m"
#define UMAG "\e[4;35m"
#define UCYN "\e[4;36m"
#define UWHT "\e[4;37m"
//Regular background
#define BLKB "\e[40m"
#define REDB "\e[41m"
#define GRNB "\e[42m"
#define YELB "\e[43m"
#define BLUB "\e[44m"
#define MAGB "\e[45m"
#define CYNB "\e[46m"
#define WHTB "\e[47m"
//High intensty background
#define BLKHB "\e[0;100m"
#define REDHB "\e[0;101m"
#define GRNHB "\e[0;102m"
#define YELHB "\e[0;103m"
#define BLUHB "\e[0;104m"
#define MAGHB "\e[0;105m"
#define CYNHB "\e[0;106m"
#define WHTHB "\e[0;107m"
//High intensty text
#define HBLK "\e[0;90m"
#define HRED "\e[0;91m"
#define HGRN "\e[0;92m"
#define HYEL "\e[0;93m"
#define HBLU "\e[0;94m"
#define HMAG "\e[0;95m"
#define HCYN "\e[0;96m"
#define HWHT "\e[0;97m"
//Bold high intensity text
#define BHBLK "\e[1;90m"
#define BHRED "\e[1;91m"
#define BHGRN "\e[1;92m"
#define BHYEL "\e[1;93m"
#define BHBLU "\e[1;94m"
#define BHMAG "\e[1;95m"
#define BHCYN "\e[1;96m"
#define BHWHT "\e[1;97m"
//Reset
#define reset "\e[0m"
#define CRESET "\e[0m"
#define COLOR_RESET "\e[0m"
#endif // ANSI_COLORS_H_

View File

@ -1,56 +1,57 @@
/* Tell the linker that we want an x86_64 ELF64 output file */
OUTPUT_FORMAT(elf64-x86-64)
OUTPUT_ARCH(i386:x86-64)
/* We want the symbol kmain to be our entry point */
/* We want the symbol _start to be our entry point */
ENTRY(kmain)
/* Define the program headers we want so the bootloader gives us the right */
/* MMU permissions; this also allows us to exert more control over the linking */
/* process. */
/* MMU permissions */
PHDRS
{
limine_requests PT_LOAD;
text PT_LOAD;
rodata PT_LOAD;
data PT_LOAD;
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
dynamic PT_DYNAMIC FLAGS((1 << 1) | (1 << 2)) ; /* Dynamic PHDR for relocations */
}
SECTIONS
{
/* We want to be placed in the topmost 2GiB of the address space, for optimisations */
/* We wanna be placed in the topmost 2GiB of the address space, for optimisations */
/* and because that is what the Limine spec mandates. */
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
/* that is the beginning of the region. */
. = 0xffffffff80000000;
/* Define a section to contain the Limine requests and assign it to its own PHDR */
.limine_requests : {
KEEP(*(.limine_requests_start))
KEEP(*(.limine_requests))
KEEP(*(.limine_requests_end))
} :limine_requests
/* Move to the next memory page for .text */
. = ALIGN(CONSTANT(MAXPAGESIZE));
kernel_start = .;
kernel_text_start = .;
.text : {
*(.text .text.*)
} :text
kernel_text_end = .;
/* Move to the next memory page for .rodata */
. = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE);
kernel_rodata_start = .;
.rodata : {
*(.rodata .rodata.*)
} :rodata
kernel_rodata_end = .;
/* Move to the next memory page for .data */
. = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE);
kernel_data_start = .;
.data : {
*(.data .data.*)
} :data
/* Dynamic section for relocations, both in its own PHDR and inside data PHDR */
.dynamic : {
*(.dynamic)
} :data :dynamic
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
/* unnecessary zeros will be written to the binary. */
/* If you need, for example, .init_array and .fini_array, those should be placed */
@ -59,10 +60,13 @@ SECTIONS
*(.bss .bss.*)
*(COMMON)
} :data
kernel_data_end = .;
/* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */
/* Discard .note.* and .eh_frame since they may cause issues on some hosts. */
/DISCARD/ : {
*(.eh_frame*)
*(.eh_frame)
*(.note .note.*)
}
kernel_end = .;
}

View File

@ -0,0 +1,22 @@
CC := x86_64-elf-gcc
LD := x86_64-elf-ld
CFLAGS += -m64 \
-fPIE \
-mno-80387 \
-mno-mmx \
-mno-sse \
-nostartfiles \
-nostdlib \
-mno-sse2 \
-mno-red-zone \
-fno-stack-protector \
-fno-stack-check \
-fno-lto
LDFLAGS += -m elf_x86_64 \
-pie \
--no-dynamic-linker \
-z text \
-z max-page-size=0x1000

14
kernel/banner.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef BANNER_H_
#define BANNER_H_
#define BANNER_TEXT \
"___ ___ _____ _____ ______ _ _ \n" \
"| \\/ | | _ / ___| | ___ \\ (_) | | \n" \
"| . . |_ _ | | | \\ `--. | |_/ / __ ___ _ ___ ___| |_ \n" \
"| |\\/| | | | | | | | |`--. \\ | __/ '__/ _ \\| |/ _ \\/ __| __|\n" \
"| | | | |_| | \\ \\_/ /\\__/ / | | | | | (_) | | __/ (__| |_ \n" \
"\\_| |_/\\__, | \\___/\\____/ \\_| |_| \\___/| |\\___|\\___|\\__|\n" \
" __/ | _/ | \n" \
" |___/ |__/ \n" \
#endif // BANNER_H_

117
kernel/bitmap/bitmap.c Normal file
View File

@ -0,0 +1,117 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "bitmap.h"
#define DIV_ROUNDUP(num, div) ((num + div - 1) / div)
void *bitmap_toptr(BitMap *bm, size_t block) {
uint8_t *ptr = (uint8_t *)(bm->mem_start + (block * BITMAP_BLOCK_SIZE));
return (void *)ptr;
}
size_t bitmap_toblock(BitMap *bm, void *ptr) {
uint8_t *p = ptr;
return (size_t)(p - bm->mem_start) / BITMAP_BLOCK_SIZE;
}
size_t bitmap_toblock_roundup(BitMap *bm, void *ptr) {
uint8_t *p = ptr;
return (size_t)DIV_ROUNDUP((size_t)(p - bm->mem_start), BITMAP_BLOCK_SIZE);
}
size_t bitmap_calcsize(size_t total) {
size_t nblocks = DIV_ROUNDUP(total, BITMAP_BLOCK_SIZE);
size_t nbytes = DIV_ROUNDUP(nblocks, 8);
return nbytes;
}
bool bitmap_get(BitMap *bm, size_t block) {
size_t elem = block / BITMAP_BLOCKS_PER_BYTE;
size_t off = block % BITMAP_BLOCKS_PER_BYTE;
return (bm->map[elem] & (1 << off)) != 0;
}
void bitmap_set(BitMap *bm, size_t block, bool value) {
size_t elem = block / BITMAP_BLOCKS_PER_BYTE;
size_t off = block % BITMAP_BLOCKS_PER_BYTE;
if (value) {
bm->map[elem] |= (1 << off);
} else {
bm->map[elem] &= ~(1 << off);
}
}
void bitmap_markblocks(BitMap *bm, size_t start, size_t size, bool value) {
if (!value && start < bm->last_deep_frag) {
bm->last_deep_frag = start;
}
for (size_t i = start; i < start + size; i++) {
bitmap_set(bm, i, value);
}
bm->alloc_blocks += value ? size : -size;
}
void bitmap_markregion(BitMap *bm, void *baseptr, size_t size, bool is_used) {
size_t base, size1;
if (is_used) {
base = bitmap_toblock(bm, baseptr);
size1 = DIV_ROUNDUP(size, BITMAP_BLOCK_SIZE);
} else {
base = bitmap_toblock(bm, baseptr);
size1 = size / BITMAP_BLOCK_SIZE;
}
bitmap_markblocks(bm, base, size1, is_used);
}
size_t bitmap_freeregion(BitMap *bm, size_t blocks) {
size_t curregstart = bm->last_deep_frag;
size_t curregsize = 0;
for (size_t i = curregstart; i < bm->nblocks; i++) {
if (bitmap_get(bm, i)) {
curregsize = 0;
curregstart = i + 1;
} else {
if (blocks == 1) {
bm->last_deep_frag = curregstart + 1;
}
curregsize++;
if (curregsize >= blocks) {
return curregstart;
}
}
}
return BITMAP_INVALID_BLOCK;
}
void *bitmap_alloc(BitMap *bm, size_t blocks) {
if (!blocks) {
return NULL;
}
size_t pickedreg = bitmap_freeregion(bm, blocks);
if (pickedreg == BITMAP_INVALID_BLOCK) {
return NULL;
}
bitmap_markblocks(bm, pickedreg, blocks, 1);
return bitmap_toptr(bm, pickedreg);
}
void bitmap_free(BitMap *bm, void *base, size_t blocks) {
bitmap_markregion(bm, base, BITMAP_BLOCK_SIZE * blocks, 0);
}
size_t bitmap_allocpageframe(BitMap *bm) {
size_t pickedreg = bitmap_freeregion(bm, 1);
bitmap_markblocks(bm, pickedreg, 1, 1);
return (bm->mem_start + (pickedreg * BITMAP_BLOCK_SIZE));
}
void bitmap_freepageframe(BitMap *bm, void *addr) {
bitmap_markregion(bm, addr, BITMAP_BLOCK_SIZE * 1, 0);
}

36
kernel/bitmap/bitmap.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef BITMAP_BITMAP_H_
#define BITMAP_BITMAP_H_
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
typedef struct {
uint8_t *map;
size_t nblocks;
size_t nbytes;
size_t alloc_blocks;
size_t last_deep_frag;
uintptr_t mem_start;
bool init;
} BitMap;
#define BITMAP_BLOCKS_PER_BYTE 8
#define BITMAP_BLOCK_SIZE 0x1000
#define BITMAP_INVALID_BLOCK ((size_t)-1)
void *bitmap_toptr(BitMap *bm, size_t block);
size_t bitmap_toblock(BitMap *bm, void *ptr);
size_t bitmap_toblock_roundup(BitMap *bm, void *ptr);
size_t bitmap_calcsize(size_t total);
bool bitmap_get(BitMap *bm, size_t block);
void bitmap_set(BitMap *bm, size_t block, bool value);
void bitmap_markblocks(BitMap *bm, size_t start, size_t size, bool value);
void bitmap_markregion(BitMap *bm, void *baseptr, size_t size, bool is_used);
size_t bitmap_freeregion(BitMap *bm, size_t blocks);
void *bitmap_alloc(BitMap *bm, size_t blocks);
void bitmap_free(BitMap *bm, void *base, size_t blocks);
size_t bitmap_allocpageframe(BitMap *bm);
void bitmap_freepageframe(BitMap *bm, void *addr);
#endif // BITMAP_BITMAP_H_

View File

@ -0,0 +1,82 @@
#include <stdint.h>
#include <stddef.h>
#include <limine.h>
#include "bootinfo.h"
#include "hal/hal.h"
BootInfo BOOT_INFO;
static volatile struct limine_paging_mode_request PAGING_REQ = {
.id = LIMINE_PAGING_MODE_REQUEST,
.revision = 0,
#if defined(__x86_64__)
.mode = LIMINE_PAGING_MODE_X86_64_4LVL,
#else
# error "Paging mode is unknown for this architecture"
#endif
};
static volatile struct limine_kernel_address_request KERN_ADDR_REQ = {
.id = LIMINE_KERNEL_ADDRESS_REQUEST, .revision = 0,
};
static volatile struct limine_hhdm_request HHDM_REQ = {
.id = LIMINE_HHDM_REQUEST, .revision = 0,
};
static volatile struct limine_memmap_request MEMMAP_REQ = {
.id = LIMINE_MEMMAP_REQUEST, .revision = 0,
};
static volatile struct limine_smp_request SMP_REQ = {
.id = LIMINE_SMP_REQUEST, .revision = 0,
};
static volatile struct limine_rsdp_request RSDP_REQ = {
.id = LIMINE_RSDP_REQUEST, .revision = 0,
};
void bootinfo_init(void) {
struct limine_paging_mode_response *pagingres = PAGING_REQ.response;
#if defined(__x86_64__)
if (pagingres->mode != LIMINE_PAGING_MODE_X86_64_4LVL) {
#endif
hal_hang();
}
struct limine_hhdm_response *hhdmres = HHDM_REQ.response;
BOOT_INFO.hhdm_off = hhdmres->offset;
struct limine_kernel_address_response *kernaddrres = KERN_ADDR_REQ.response;
BOOT_INFO.kern_virtbase = kernaddrres->virtual_base;
BOOT_INFO.kern_physbase = kernaddrres->physical_base;
struct limine_memmap_response *memmapres = MEMMAP_REQ.response;
BOOT_INFO.memmap_entries = memmapres->entries;
BOOT_INFO.memmap_entrycount = memmapres->entry_count;
BOOT_INFO.memmap_total = 0;
for (size_t i = 0; i < memmapres->entry_count; i++) {
struct limine_memmap_entry *entry = memmapres->entries[i];
if (entry->type != LIMINE_MEMMAP_RESERVED) {
BOOT_INFO.memmap_total += entry->length;
}
}
struct limine_smp_response *smpres = SMP_REQ.response;
BOOT_INFO.smp = smpres;
BOOT_INFO.smp_bspindex = (uint64_t)(-1);
for (size_t i = 0; i < smpres->cpu_count; i++) {
struct limine_smp_info *entry = smpres->cpus[i];
if (entry->lapic_id == smpres->bsp_lapic_id) {
BOOT_INFO.smp_bspindex = i;
}
}
if (BOOT_INFO.smp_bspindex == (uint64_t)-1) {
hal_hang();
}
struct limine_rsdp_response *rsdpres = RSDP_REQ.response;
BOOT_INFO.rsdp = (size_t)rsdpres->address - BOOT_INFO.hhdm_off;
}

View File

@ -0,0 +1,33 @@
#ifndef BOOTINFO_BOOTINFO_H_
#define BOOTINFO_BOOTINFO_H_
#include <stdint.h>
#include <stddef.h>
#include <limine.h>
extern uint64_t kernel_text_start, kernel_text_end,
kernel_rodata_start, kernel_rodata_end,
kernel_data_start, kernel_data_end,
kernel_start, kernel_end;
typedef struct {
// Higher Half Direct Map: https://github.com/dreamportdev/Osdev-Notes/blob/master/01_Build_Process/02_Boot_Protocols.md#limine-protocol
size_t hhdm_off;
size_t kern_virtbase;
size_t kern_physbase;
size_t rsdp;
size_t memmap_total;
uint64_t memmap_entrycount;
LIMINE_PTR(struct limine_memmap_entry **) memmap_entries;
LIMINE_PTR(struct limine_smp_response *) smp;
uint64_t smp_bspindex;
} BootInfo;
extern BootInfo BOOT_INFO;
#define IS_IN_HHDM(a) ((size_t)a >= BOOT_INFO.hhdm_off \
&& (size_t)a <= BOOT_INFO.hhdm_off + BOOT_INFO.memmap_total)
void bootinfo_init(void);
#endif // BOOTINFO_BOOTINFO_H_

View File

@ -1,32 +0,0 @@
#include <serial.h>
#include <com1.h>
#define COM1 0x3f8
void com1_init(void) {
serial_outb(COM1 + 1, 0x00); // no intr
serial_outb(COM1 + 3, 0x80); // enable DLAB
serial_outb(COM1 + 0, 0x01); // 115200 baudrate
serial_outb(COM1 + 1, 0x00);
serial_outb(COM1 + 3, 0x03); // 8N1
serial_outb(COM1 + 2, 0xc7); // fifo
serial_outb(COM1 + 4, 0x0b); // irqs enabled, rts/dsr set
}
int32 com1_is_ready(void) {
return serial_inb(COM1 + 5) & 0x20;
}
void com1_putch(char c) {
while (!com1_is_ready());
serial_outb(COM1, c);
}
void com1_puts(char *s) {
while (*s) com1_putch(*s++);
}
void putchar_(char c) {
com1_putch(c);
}

View File

@ -1,6 +0,0 @@
#ifndef COM1_H_
#define COM1_H_
void com1_init(void);
#endif // COM1_H_

6
kernel/compiler/attr.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef COMPILER_ATTR_H_
#define COMPILER_ATTR_H_
#define PACKED __attribute__((packed))
#endif // COMPILER_ATTR_H_

View File

@ -1,12 +0,0 @@
#ifndef ERRORS_H_
#define ERRORS_H_
#include <types.h>
#define E_OK 0
typedef int32 Error;
#define E_ISOK(e) ((e) == (E_OK))
#endif // ERRORS_H_

1
kernel/extconf/extra.mk Normal file
View File

@ -0,0 +1 @@
CFLAGS += -DKPRINTF_COLORS

19
kernel/hal/hal.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef KERNEL_HAL_HAL_H_
#define KERNEL_HAL_HAL_H_
#include <stdint.h>
#include "util.h"
__attribute__((noreturn)) void hal_hang(void);
void hal_init(void);
void hal_intr_disable(void);
void hal_intr_enable(void);
void hal_memset(void *mem, uint8_t v, uint32_t size);
#if defined(__x86_64__)
# define HAL_PAGE_SIZE 0x1000
#endif
#endif // KERNEL_HAL_HAL_H_

9
kernel/hal/util.c Normal file
View File

@ -0,0 +1,9 @@
#include <stdint.h>
#include "hal.h"
void hal_memset(void *mem, uint8_t v, uint32_t size) {
uint8_t *mem1 = mem;
for (uint32_t i = 0; i < size; i++) {
mem1[i] = v;
}
}

6
kernel/hal/util.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef HAL_UTIL_H_
#define HAL_UTIL_H_
#define HAL_MEMSET(m, v, n) hal_memset((void *)(m), (v), (n))
#endif // HAL_UTIL_H_

94
kernel/hal/x86_64/gdt.c Normal file
View File

@ -0,0 +1,94 @@
#include <stdint.h>
#include <stddef.h>
#include "compiler/attr.h"
#include "hal/hal.h"
#define GDT_SIZE 5
typedef struct {
uint16_t limitlow;
uint16_t baselow;
uint8_t basemid;
uint8_t access;
uint8_t gran;
uint8_t basehigh;
} PACKED GdtEntry;
typedef struct {
uint16_t limit;
uint64_t base;
} PACKED GdtPtr;
typedef struct {
GdtEntry old[5];
GdtEntry tsslow;
GdtEntry tsshigh;
} PACKED ExtendedGdt;
typedef struct {
uint32_t resv0;
uint64_t rsp0;
uint64_t rsp1;
uint64_t rsp2;
uint64_t resv1;
uint64_t ist[7];
uint64_t resv2;
uint16_t resv3;
uint16_t iopb_off;
} PACKED Tss;
static Tss tss = {0};
static ExtendedGdt *curgdt = NULL;
#define KCODE 0x08
#define KDATA 0x10
#define UCODE 0x18
#define UDATA 0x20
#define TSS 0x28
#define GDT_PRESENT 0x80
#define GDT_TSS 0x89
static uint64_t gdt_curretbase(void) {
GdtPtr gdtr;
asm volatile("sgdt %0" : "=m"(gdtr));
return gdtr.base;
}
void gdt_setenty(GdtEntry *entry, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) {
entry->baselow = base & 0xffff;
entry->basemid = (base >> 16) & 0xff;
entry->basehigh = (base >> 24) & 0xff;
entry->limitlow = limit & 0xffff;
entry->gran = (limit >> 16) & 0x0f | (gran & 0xf0);
entry->access = access;
}
void gdt_init(void) {
uint64_t base = gdt_curretbase();
curgdt = (ExtendedGdt *)base;
HAL_MEMSET(&tss, 0, sizeof(tss));
tss.iopb_off = sizeof(tss);
uint64_t tss_base = (uint64_t)&tss;
uint32_t tss_limit = sizeof(tss) - 1;
gdt_setenty(&curgdt->tsslow, tss_base & 0xFFFFFFFF, tss_limit, GDT_PRESENT | GDT_TSS, 0x0);
GdtEntry *tsshigh = &curgdt->tsshigh;
tsshigh->baselow = (tss_base >> 32) & 0xffff;
tsshigh->basemid = (tss_base >> 48) & 0xff;
tsshigh->basehigh = (tss_base >> 56) & 0xff;
tsshigh->access = 0;
tsshigh->gran = 0;
tsshigh->limitlow = 0;
GdtPtr gdtr;
asm volatile("sgdt %0" : "=m"(gdtr));
gdtr.limit = sizeof(ExtendedGdt) - 1;
asm volatile("lgdt %0" :: "m"(gdtr));
asm volatile("ltr %0" :: "r"((uint16_t)0x28));
}

6
kernel/hal/x86_64/gdt.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef HAL_GDT_H_
#define HAL_GDT_H_
void gdt_init(void);
#endif // HAL_GDT_H_

21
kernel/hal/x86_64/hal.c Normal file
View File

@ -0,0 +1,21 @@
#include <stdint.h>
#include <stdbool.h>
#include "hal/hal.h"
#include "kprintf.h"
#include "serial.h"
#include "gdt.h"
void hal_init(void) {
if (!serial_init()) {
hal_hang(); // going further makes no sense
}
LOG("hal", "serial init\n");
gdt_init();
}
__attribute__((noreturn)) void hal_hang(void) {
for(;;) {
asm("hlt");
}
}

9
kernel/hal/x86_64/intr.S Normal file
View File

@ -0,0 +1,9 @@
.global hal_intr_enable
hal_intr_enable:
sti
ret
.global hal_intr_disable
hal_intr_disable:
cli
ret

View File

@ -0,0 +1,50 @@
#include <stdint.h>
#include <stdbool.h>
#define SERIAL_PORT 0x3f8
extern uint8_t serial_inb(uint16_t port);
extern void serial_outb(uint16_t port, uint8_t value);
static int serial_received(void) {
return serial_inb(SERIAL_PORT + 5) & 1;
}
static uint8_t serial_read(void) {
while (serial_received() == 0);
return serial_inb(SERIAL_PORT);
}
static int serial_trans_empty(void) {
return serial_inb(SERIAL_PORT + 5) & 0x20;
}
static void serial_write(uint8_t value) {
while (!serial_trans_empty());
serial_outb(SERIAL_PORT, value);
}
// REFERENCE: https://wiki.osdev.org/Serial_Ports
bool serial_init(void) {
serial_outb(SERIAL_PORT + 1, 0x00);
serial_outb(SERIAL_PORT + 3, 0x80);
serial_outb(SERIAL_PORT + 0, 0x03);
serial_outb(SERIAL_PORT + 1, 0x00);
serial_outb(SERIAL_PORT + 3, 0x03);
serial_outb(SERIAL_PORT + 2, 0xc7);
serial_outb(SERIAL_PORT + 4, 0x0b);
serial_outb(SERIAL_PORT + 4, 0x1e);
serial_outb(SERIAL_PORT + 0, 0xae);
if (serial_inb(SERIAL_PORT + 0) != 0xae) {
return false;
}
serial_outb(SERIAL_PORT + 4, 0x0f);
return true;
}
// For printf library
void putchar_(char c) {
serial_write(c);
}

View File

@ -0,0 +1,8 @@
#ifndef HAL_SERIAL_H_
#define HAL_SERIAL_H_
#include <stdbool.h>
bool serial_init(void);
#endif // HAL_SERIAL_H_

View File

@ -0,0 +1,13 @@
.global serial_outb
serial_outb:
mov %di, %dx
mov %sil, %al
out %al, %dx
ret
.global serial_inb
serial_inb:
mov %di, %dx
in %dx, %al
movzx %al, %rax
ret

View File

@ -1,42 +1,22 @@
#include <limine.h>
#include <com1.h>
#include <kprintf.h>
// Halt and catch fire function.
static void hcf(void) {
for (;;) {
asm ("hlt");
}
}
__attribute__((used, section(".limine_requests")))
static volatile LIMINE_BASE_REVISION(3);
__attribute__((used, section(".limine_requests_start")))
static volatile LIMINE_REQUESTS_START_MARKER;
__attribute__((used, section(".limine_requests_end")))
static volatile LIMINE_REQUESTS_END_MARKER;
__attribute__((used, section(".limine_requests")))
static volatile struct limine_memmap_request memmap_request = {
.id = LIMINE_MEMMAP_REQUEST,
.revision = 0,
};
void limine_init(void) {
if (LIMINE_BASE_REVISION_SUPPORTED == false) {
hcf();
}
}
#include "kprintf.h"
#include "banner.h"
#include "hal/hal.h"
#include "bootinfo/bootinfo.h"
#include "pmm/pmm.h"
static volatile LIMINE_BASE_REVISION(2);
void kmain(void) {
limine_init();
com1_init();
if (LIMINE_BASE_REVISION_SUPPORTED == false) {
hal_hang();
}
kprintf("Hello dupa!\n");
bootinfo_init();
pmm_init();
hal_init();
hcf();
kprintf(BANNER_TEXT "\n");
hal_hang();
}

View File

@ -10,4 +10,18 @@
#define kvsnprintf vsnprintf_
#define kvprintf vprintf_
#ifdef KPRINTF_COLORS
# include "ansi_colors.h"
# define LOG(component, fmt, ...) kprintf(CRESET "[" CYN component CRESET "]: " fmt, ##__VA_ARGS__)
#else
# define LOG(component, fmt, ...) kprintf("["component"]: "fmt, ##__VA_ARGS__)
#endif
#ifdef KPRINTF_COLORS
# include "ansi_colors.h"
# define ERR(component, fmt, ...) kprintf(CRESET "[" RED component CRESET "]: " fmt, ##__VA_ARGS__)
#else
# define ERR(component, fmt, ...) kprintf("["component"]: "fmt, ##__VA_ARGS__)
#endif
#endif // KPRINTF_H_

71
kernel/pmm/pmm.c Normal file
View File

@ -0,0 +1,71 @@
#include <stddef.h>
#include <limine.h>
#include "pmm.h"
#include "spinlock.h"
#include "kprintf.h"
#include "bitmap/bitmap.h"
#include "bootinfo/bootinfo.h"
#define _DIV_ROUNDUP(num, div) ((num + div - 1) / div)
PhysMem PHYS_MEM;
void pmm_init(void) {
PHYS_MEM.spinlock = SPINLOCK_INIT();
BitMap *bm = &PHYS_MEM.self;
bm->init = false;
bm->nblocks = _DIV_ROUNDUP(BOOT_INFO.memmap_total, BITMAP_BLOCK_SIZE);
bm->nbytes = _DIV_ROUNDUP(bm->nblocks, 8);
struct limine_memmap_entry *memmap_ent = NULL;
for (size_t i = 0; i < BOOT_INFO.memmap_entrycount; i++) {
struct limine_memmap_entry *entry = BOOT_INFO.memmap_entries[i];
if (entry->type != LIMINE_MEMMAP_USABLE || entry->length < bm->nbytes) {
continue;
}
memmap_ent = entry;
break;
}
if (!memmap_ent) {
ERR("hal/pmm", "required memory: {%lx}\n", bm->nbytes);
hal_hang();
}
size_t physbegin = memmap_ent->base;
bm->map = (uint8_t *)(physbegin + BOOT_INFO.hhdm_off);
HAL_MEMSET(bm->map, 0xff, bm->nbytes);
for (size_t i = 0; i < BOOT_INFO.memmap_entrycount; i++) {
struct limine_memmap_entry *entry = BOOT_INFO.memmap_entries[i];
// mark usable as 0 and unusable as 1
bitmap_markregion(bm, (void *)entry->base, entry->length, entry->type != LIMINE_MEMMAP_USABLE);
}
bitmap_markregion(bm, (void *)physbegin, bm->nbytes, 1);
bm->alloc_blocks = 0;
LOG("hal/pmm", "phys bitmap init 0x%lx, size = 0x%lx\n", physbegin, bm->nbytes);
bm->init = true;
}
void *pmm_alloc(size_t pages) {
SPINLOCK_ACQUIRE(&PHYS_MEM.spinlock);
uintptr_t phys = (uintptr_t)bitmap_alloc(&PHYS_MEM.self, pages);
SPINLOCK_RELEASE(&PHYS_MEM.spinlock);
if (!phys) {
ERR("hal/pmm", "phys memory ran out\n");
hal_hang();
}
return (void *)phys;
}
void pmm_free(uintptr_t ptr, size_t pages) {
SPINLOCK_ACQUIRE(&PHYS_MEM.spinlock);
bitmap_markregion(&PHYS_MEM.self, (void *)ptr, pages * BITMAP_BLOCK_SIZE, 0);
SPINLOCK_RELEASE(&PHYS_MEM.spinlock);
}

20
kernel/pmm/pmm.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef PMM_PMM_H_
#define PMM_PMM_H_
#include <stddef.h>
#include <stdint.h>
#include "spinlock.h"
#include "bitmap/bitmap.h"
typedef struct {
SpinLock spinlock;
BitMap self;
} PhysMem;
extern PhysMem PHYS_MEM;
void pmm_init(void);
void *pmm_alloc(size_t pages);
void pmm_free(uintptr_t ptr, size_t pages);
#endif // PMM_PMM_H_

View File

@ -1,14 +0,0 @@
global serial_outb
serial_outb:
mov dx, di
mov al, sil
out dx, al
ret
global serial_inb
serial_inb:
mov dx, di
in al, dx
movzx rax, al
ret

View File

@ -1,9 +0,0 @@
#ifndef SERIAL_H_
#define SERIAL_H_
#include <types.h>
void serial_outb(uint16 port, uint8 value);
uint8 serial_inb(uint16 port);
#endif // SERIAL_H_

31
kernel/spinlock.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef SPINLOCK_SPINLOCK_H_
#define SPINLOCK_SPINLOCK_H_
#include <stdatomic.h>
#include "hal/hal.h"
typedef atomic_bool SpinLock;
// Spin more efficiently - cpu dependant
#if defined(__x86_64__)
# define SPINLOCK_HINT() asm volatile("pause")
#else
# define SPINLOCK_HINT()
#endif
#define SPINLOCK_ACQUIRE(sl) \
do { \
bool __unlocked = false; \
while (!atomic_compare_exchange_weak((sl), &__unlocked, true)) { \
SPINLOCK_HINT(); \
} \
} while(0)
#define SPINLOCK_RELEASE(sl) \
do { \
atomic_store((sl), false); \
} while(0)
#define SPINLOCK_INIT() false
#endif // SPINLOCK_SPINLOCK_H_

View File

@ -1,15 +0,0 @@
#ifndef TYPES_H_
#define TYPES_H_
#define NULL ((void *)0)
typedef char int8;
typedef unsigned char uint8;
typedef short int16;
typedef unsigned short uint16;
typedef int int32;
typedef unsigned int uint32;
typedef long long int64;
typedef unsigned long long uint64;
#endif // TYPES_H_