GDT finally works
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
disk.hdd
|
||||
/limine
|
||||
/iso_root
|
||||
*.iso
|
||||
|
55
Makefile
55
Makefile
@ -1,30 +1,41 @@
|
||||
.PHONY: all disk clean
|
||||
.PHONY: all clean prepare cleanall iso
|
||||
|
||||
disk:
|
||||
all:
|
||||
make -C kernel all
|
||||
|
||||
prepare:
|
||||
if [ ! -d limine ]; then \
|
||||
git clone https://github.com/limine-bootloader/limine.git --branch=v9.x-binary --depth=1; \
|
||||
make -C limine; \
|
||||
mkdir limine; \
|
||||
cd limine; \
|
||||
git init; \
|
||||
git remote add origin https://github.com/limine-bootloader/limine.git; \
|
||||
git fetch origin 9246bb78f446962aae5b0a291db4be32f9866ba6; \
|
||||
git reset --hard FETCH_HEAD; \
|
||||
make; \
|
||||
fi
|
||||
make -C kernel
|
||||
rm -f disk.hdd
|
||||
dd if=/dev/zero bs=1M count=0 seek=64 of=disk.hdd
|
||||
PATH=$$PATH:/usr/sbin:/sbin sgdisk disk.hdd -n 1:2048 -t 1:ef00 -m 1
|
||||
./limine/limine bios-install disk.hdd
|
||||
mformat -i disk.hdd@@1M
|
||||
mmd -i disk.hdd@@1M ::/EFI ::/EFI/BOOT ::/boot ::/boot/limine
|
||||
mcopy -i disk.hdd@@1M kernel/mop2 ::/boot
|
||||
mcopy -i disk.hdd@@1M limine.conf limine/limine-bios.sys ::/boot/limine
|
||||
mcopy -i disk.hdd@@1M limine/BOOTX64.EFI ::/EFI/BOOT
|
||||
|
||||
cleanall:
|
||||
make clean
|
||||
rm -rf limine
|
||||
|
||||
clean:
|
||||
rm -rf limine disk.hdd
|
||||
make -C kernel clean
|
||||
rm -f mop2.iso
|
||||
|
||||
all: disk
|
||||
|
||||
run:
|
||||
qemu-system-x86_64 \
|
||||
-d guest_errors \
|
||||
-serial stdio \
|
||||
-hda disk.hdd
|
||||
iso:
|
||||
rm -rf iso_root
|
||||
mkdir -p iso_root/boot
|
||||
cp -v kernel/mop2 iso_root/boot
|
||||
mkdir -p iso_root/boot/limine
|
||||
cp -v limine.conf limine/limine-bios.sys limine/limine-bios-cd.bin \
|
||||
limine/limine-uefi-cd.bin iso_root/boot/limine
|
||||
mkdir -p iso_root/EFI/BOOT
|
||||
cp -v limine/BOOTX64.EFI iso_root/EFI/BOOT
|
||||
cp -v limine/BOOTIA32.EFI iso_root/EFI/BOOT
|
||||
xorriso -as mkisofs -R -r -J -b boot/limine/limine-bios-cd.bin \
|
||||
-no-emul-boot -boot-load-size 4 -boot-info-table -hfsplus \
|
||||
-apm-block-size 2048 --efi-boot boot/limine/limine-uefi-cd.bin \
|
||||
-efi-boot-part --efi-boot-image --protective-msdos-label \
|
||||
iso_root -o mop2.iso
|
||||
./limine/limine bios-install mop2.iso
|
||||
|
||||
|
1
kernel/.gitignore
vendored
1
kernel/.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
*.o
|
||||
mop2
|
||||
*.iso
|
||||
|
@ -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
85
kernel/ansi_colors.h
Normal 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_
|
@ -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 = .;
|
||||
}
|
22
kernel/arch/x86_64/x86_64.mk
Normal file
22
kernel/arch/x86_64/x86_64.mk
Normal 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
14
kernel/banner.h
Normal 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
117
kernel/bitmap/bitmap.c
Normal 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
36
kernel/bitmap/bitmap.h
Normal 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_
|
82
kernel/bootinfo/bootinfo.c
Normal file
82
kernel/bootinfo/bootinfo.c
Normal 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;
|
||||
}
|
33
kernel/bootinfo/bootinfo.h
Normal file
33
kernel/bootinfo/bootinfo.h
Normal 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_
|
@ -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);
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
#ifndef COM1_H_
|
||||
#define COM1_H_
|
||||
|
||||
void com1_init(void);
|
||||
|
||||
#endif // COM1_H_
|
6
kernel/compiler/attr.h
Normal file
6
kernel/compiler/attr.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef COMPILER_ATTR_H_
|
||||
#define COMPILER_ATTR_H_
|
||||
|
||||
#define PACKED __attribute__((packed))
|
||||
|
||||
#endif // COMPILER_ATTR_H_
|
@ -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
1
kernel/extconf/extra.mk
Normal file
@ -0,0 +1 @@
|
||||
CFLAGS += -DKPRINTF_COLORS
|
19
kernel/hal/hal.h
Normal file
19
kernel/hal/hal.h
Normal 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
9
kernel/hal/util.c
Normal 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
6
kernel/hal/util.h
Normal 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
94
kernel/hal/x86_64/gdt.c
Normal 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
6
kernel/hal/x86_64/gdt.h
Normal 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
21
kernel/hal/x86_64/hal.c
Normal 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
9
kernel/hal/x86_64/intr.S
Normal file
@ -0,0 +1,9 @@
|
||||
.global hal_intr_enable
|
||||
hal_intr_enable:
|
||||
sti
|
||||
ret
|
||||
|
||||
.global hal_intr_disable
|
||||
hal_intr_disable:
|
||||
cli
|
||||
ret
|
50
kernel/hal/x86_64/serial.c
Normal file
50
kernel/hal/x86_64/serial.c
Normal 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);
|
||||
}
|
8
kernel/hal/x86_64/serial.h
Normal file
8
kernel/hal/x86_64/serial.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef HAL_SERIAL_H_
|
||||
#define HAL_SERIAL_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool serial_init(void);
|
||||
|
||||
#endif // HAL_SERIAL_H_
|
13
kernel/hal/x86_64/serial1.S
Normal file
13
kernel/hal/x86_64/serial1.S
Normal 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
|
@ -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();
|
||||
}
|
||||
|
@ -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
71
kernel/pmm/pmm.c
Normal 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
20
kernel/pmm/pmm.h
Normal 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_
|
@ -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
|
||||
|
@ -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
31
kernel/spinlock.h
Normal 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_
|
@ -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_
|
3
run/qemu-x86_64.sh
Executable file
3
run/qemu-x86_64.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
qemu-system-x86_64 -m 4g -cdrom mop2.iso -boot d -serial stdio $@
|
Reference in New Issue
Block a user