build: # Build as default target
CXXFLAGS := -std=c++20 -fno-strict-aliasing -Wall -Wextra -Werror \
- -mgeneral-regs-only -fno-exceptions -fno-rtti -ffreestanding -O2 $(CXXFLAGS)
+ -mgeneral-regs-only -fno-exceptions -fno-rtti -ffreestanding -O2 \
+ -I libcpp $(CXXFLAGS)
LDFLAGS := $(CXXFLAGS) $(LDFLAGS)
TO_ISO := isodir/boot/grub/grub.cfg
$(TARGETS_TO_VAR): SUBDIR := $(SUBDIR)
$(TARGETS_TO_VAR): CXX := g++-system
-$(TARGETS_TO_VAR): CXXFLAGS := $(CXXFLAGS) -mcmodel=kernel -mno-red-zone\
--isystem $(INCLUDES) -isystem $(INCLUDES)/c++ -isystem $(INCLUDES)/c++/x86_64-unknown-linux-gnu
-# The previous line is a dirty hack. But not that much, because it doesn't allow me to include non-freestanding headers anyways
-$(TARGETS_TO_VAR): LDFLAGS := $(LDFLAGS) -z max-page-size=0x1000 -mno-red-zone -mcmodel=kernel
+$(TARGETS_TO_VAR): CXXFLAGS := $(CXXFLAGS) -mcmodel=kernel -mno-red-zone
+$(TARGETS_TO_VAR): LDFLAGS := $(LDFLAGS) -mno-red-zone -mcmodel=kernel -z max-page-size=0x1000
$(TARGETS_TO_VAR): LDLIBS := -nostdlib -lgcc
$(OUT_DIR)$(EXEC_NAME): kernel/linker.ld $(CRTI_OBJ) $(CRTBEGIN_OBJ) $(filter-out $(CRTI_OBJ) $(CRTN_OBJ),$(OBJS)) $(CRTEND_OBJ) $(CRTN_OBJ)
mkdir -p '$(@D)'
#include "elf64.hpp"
-void os::elf::load_elf(os::process& result, std::byte* start, std::size_t length, const paging::PML4T& original_PML4T) {
- os::assert(length >= sizeof(os::elf::header), "Elf file isn't big enough to contain a header: there is an error.");
+void os::elf::load_elf(os::process& result, amy::byte* start, amy::size length, const paging::PML4T& original_PML4T) {
+ os::assert(length >= 0 && (unsigned long long)(length) >= sizeof(os::elf::header), "Elf file isn't big enough to contain a header: there is an error.");
// TODO: Check that the elf file sections are all fully inside the file.
// Load test-module elf file:
os::assert(elf_header.type == 2, "Elf file not executable.");
os::assert(elf_header.arch == 0x3E, "Elf file not x86_64.");
- constexpr std::size_t stack_size = 16 * 0x1000 /* 64KiB */;
- std::byte* const stack = (std::byte*)0x0000'8000'0000'0000 - stack_size;
+ constexpr amy::size stack_size = 16 * 0x1000 /* 64KiB */;
+ amy::byte* const stack = (amy::byte*)0x0000'8000'0000'0000 - stack_size;
const auto page = os::paging::page_allocator.allocate(1);
os::assert(page.ptr != nullptr, "Not enough memory for elf file loading.");
result.PML4T = phys_ptr<paging::PML4T>(page.ptr.get_phys_addr());
- result.rip = std::uint64_t(elf_header.entry);
- result.rsp = std::uint64_t(stack + stack_size);
+ result.rip = amy::u64(elf_header.entry);
+ result.rsp = amy::u64(stack + stack_size);
result.rax = 0;
result.rbx = 0;
result.rcx = 0;
memset(result.PML4T->contents, 0, 256 * sizeof(os::paging::PML4E));
memcpy(result.PML4T->contents + 256, original_PML4T.contents + 256, 256 * sizeof(os::paging::PML4E));
- for (std::size_t i = 0; i < elf_header.entry_count_program_header_table; i++) {
+ for (amy::size i = 0; i < elf_header.entry_count_program_header_table; i++) {
const os::elf::program_header program_header = *(os::elf::program_header*)(
start + elf_header.program_header_table
+ i * elf_header.entry_size_program_header_table
continue;
}
os::print("Segment: loadable\n");
- os::assert(0x1000 <= std::uint64_t(program_header.p_vaddr)
- && std::uint64_t(program_header.p_vaddr + program_header.p_memsz) < 0x10'0000'0000,
+ os::assert(0x1000 <= amy::u64(program_header.p_vaddr)
+ && amy::u64(program_header.p_vaddr + program_header.p_memsz) < 0x10'0000'0000,
"Program segments must be contained between 0x1000 and 0x10'0000'0000 (i.e. 64GiB).");
// Allocate, map and initialise memory for segment (memory above program_header.p_filesz is already 0-initialised by the page allocator):
- std::size_t nb_pages = (std::uint64_t(program_header.p_vaddr) % 0x1000 + program_header.p_memsz + 0x1000 - 1) / 0x1000;
- for (std::size_t i = 0; i < nb_pages; i++) {
+ amy::size nb_pages = (amy::u64(program_header.p_vaddr) % 0x1000 + program_header.p_memsz + 0x1000 - 1) / 0x1000;
+ for (amy::size i = 0; i < nb_pages; i++) {
auto const alloc = os::paging::page_allocator.allocate(1);
os::assert(alloc.ptr != nullptr, "Failed to allocate enough memory for loading of elf binary.");
os::paging::map_page(*result.PML4T, (os::paging::page<0>*)(program_header.p_vaddr + i * 0x1000), alloc.ptr, {
#pragma once
-#include <cstdint>
+#include <types.hpp>
#include "lib/phys_ptr.hpp"
#include "ring3.hpp"
struct program_header;
struct header {
- std::uint8_t magic[4];
- std::uint8_t bitn;
- std::uint8_t endianness;
- std::uint8_t header_version;
- std::uint8_t abi;
- std::uint64_t : 64;
- std::uint16_t type;
- std::uint16_t arch;
- std::uint32_t elf_version;
+ amy::u8 magic[4];
+ amy::u8 bitn;
+ amy::u8 endianness;
+ amy::u8 header_version;
+ amy::u8 abi;
+ amy::u64 : 64;
+ amy::u16 type;
+ amy::u16 arch;
+ amy::u32 elf_version;
void* entry;
- std::uint64_t program_header_table;
- std::uint64_t section_header_table;
- std::uint32_t flags;
- std::uint16_t header_size;
- std::uint16_t entry_size_program_header_table;
- std::uint16_t entry_count_program_header_table;
- std::uint16_t entry_size_section_header_table;
- std::uint16_t entry_count_section_header_table;
- std::uint16_t index_section_names_section_header_table;
+ amy::u64 program_header_table;
+ amy::u64 section_header_table;
+ amy::u32 flags;
+ amy::u16 header_size;
+ amy::u16 entry_size_program_header_table;
+ amy::u16 entry_count_program_header_table;
+ amy::u16 entry_size_section_header_table;
+ amy::u16 entry_count_section_header_table;
+ amy::u16 index_section_names_section_header_table;
};
static_assert(sizeof(header) == 64);
struct program_header {
- std::uint32_t type;
- std::uint32_t flags;
- std::uint64_t p_offset;
- std::byte* p_vaddr;
- std::uint64_t : 64;
- std::uint64_t p_filesz;
- std::uint64_t p_memsz;
- std::uint64_t align;
+ amy::u32 type;
+ amy::u32 flags;
+ amy::u64 p_offset;
+ amy::byte* p_vaddr;
+ amy::u64 : 64;
+ amy::u64 p_filesz;
+ amy::u64 p_memsz;
+ amy::u64 align;
};
static_assert(sizeof(program_header) == 56);
- void load_elf(os::process& result, std::byte* start, std::size_t length, const paging::PML4T& original_PML4T);
+ void load_elf(os::process& result, amy::byte* start, amy::size length, const paging::PML4T& original_PML4T);
} } // namespace os::elf
asm volatile("lidt %0" : : "m"(idtr));
}
bool os::is_APIC_builtin() {
- std::uint32_t eax, ebx, ecx, edx;
+ amy::u32 eax, ebx, ecx, edx;
__cpuid(0x01, eax, ebx, ecx, edx);
return (edx & (1 << 9)) != 0;
}
outb(0xA1, 0xFF);
outb(0x21, 0xFF);
}
-void os::set_APIC_base(os::phys_ptr<volatile std::uint32_t> ptr) {
+void os::set_APIC_base(os::phys_ptr<volatile amy::u32> ptr) {
os::set_msr(0x1B, (ptr.get_phys_addr() & 0xFFFFFFFFFFFFF000) | 0x800);
}
-os::phys_ptr<volatile std::uint32_t> os::get_APIC_base() {
- return os::phys_ptr<volatile std::uint32_t>{os::get_msr(0x1B) & 0xFFFFFFFFFFFFF000};
+os::phys_ptr<volatile amy::u32> os::get_APIC_base() {
+ return os::phys_ptr<volatile amy::u32>{os::get_msr(0x1B) & 0xFFFFFFFFFFFFF000};
}
-std::uint32_t os::get_APIC_reg(std::ptrdiff_t offset) {
+amy::u32 os::get_APIC_reg(amy::dptr offset) {
return get_APIC_base()[offset / 4];
}
-void os::set_APIC_reg(std::ptrdiff_t offset, std::uint32_t v) {
+void os::set_APIC_reg(amy::dptr offset, amy::u32 v) {
get_APIC_base()[offset / 4] = v;
}
-extern "C" void set_APIC_reg_asm(std::ptrdiff_t offset, std::uint32_t v) {
+extern "C" void set_APIC_reg_asm(amy::dptr offset, amy::u32 v) {
os::set_APIC_reg(offset, v);
}
os::print("Interrupt: Device Not Available.\n");
while (true) { os::hlt(); }
}
-extern "C" void int_double_fault(std::uint32_t err_code) {
+extern "C" void int_double_fault(amy::u32 err_code) {
os::print("Interrupt: Double Fault.\n");
os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
os::print("Interrupt: Coprocessor Segment Overrun.\n");
while (true) { os::hlt(); }
}
-extern "C" void int_invalid_TSS(std::uint32_t err_code) {
+extern "C" void int_invalid_TSS(amy::u32 err_code) {
os::print("Interrupt: Invalid TSS.\n");
os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
}
-extern "C" void int_segment_not_present(std::uint32_t err_code) {
+extern "C" void int_segment_not_present(amy::u32 err_code) {
os::print("Interrupt: Segment Not Present.\n");
os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
}
-extern "C" void int_stack_segment_fault(std::uint32_t err_code) {
+extern "C" void int_stack_segment_fault(amy::u32 err_code) {
os::print("Interrupt: Stack-Segment Fault.\n");
os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
}
-extern "C" void int_general_protection_fault(std::uint32_t err_code) {
+extern "C" void int_general_protection_fault(amy::u32 err_code) {
os::print("Interrupt: General Protection Fault.\n");
os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
}
-extern "C" void int_page_fault(std::uint32_t err_code, std::uint64_t vaddr) {
+extern "C" void int_page_fault(amy::u32 err_code, amy::u64 vaddr) {
if (
(0xFFFF'C000'0000'0000 <= vaddr && vaddr < 0xFFFF'C000'1000'0000) // process/port info
) { // Kernel memory
os::print("Interrupt: x87 Floating-Point Exception.\n");
while (true) { os::hlt(); }
}
-extern "C" void int_alignment_check(std::uint32_t err_code) {
+extern "C" void int_alignment_check(amy::u32 err_code) {
os::print("Interrupt: Alignment Check.\n");
os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
os::print("Interrupt: Virtualization Exception.\n");
while (true) { os::hlt(); }
}
-extern "C" void int_control_protection_exception(std::uint32_t err_code) {
+extern "C" void int_control_protection_exception(amy::u32 err_code) {
os::print("Interrupt: Control Protection Exception.\n");
os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
os::print("Interrupt: Hypervisor Injection Exception.\n");
while (true) { os::hlt(); }
}
-extern "C" void int_VMM_communication_exception(std::uint32_t err_code) {
+extern "C" void int_VMM_communication_exception(amy::u32 err_code) {
os::print("Interrupt: VMM Communication Exception.\n");
os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
}
-extern "C" void int_security_exception(std::uint32_t err_code) {
+extern "C" void int_security_exception(amy::u32 err_code) {
os::print("Interrupt: Security Exception.\n");
os::print("Err code: {}.\n", err_code);
while (true) { os::hlt(); }
#pragma once
-#include <cstdint>
+#include <types.hpp>
#include "lib/phys_ptr.hpp"
#include "serial.hpp"
#include "utils.hpp"
namespace os {
struct ide {
- std::uint16_t offset_low;
- std::uint16_t kernel_cs;
- std::uint8_t ist_offset : 3;
- std::uint8_t reserved_1 : 5 = 0;
- std::uint8_t gate_type : 4;
- std::uint8_t bit_0 : 1 = 0;
- std::uint8_t dpl : 2;
- std::uint8_t present : 1;
- std::uint16_t offset_mid;
- std::uint32_t offset_high;
- std::uint32_t reserved_2 = 0;
+ amy::u16 offset_low;
+ amy::u16 kernel_cs;
+ amy::u8 ist_offset : 3;
+ amy::u8 reserved_1 : 5 = 0;
+ amy::u8 gate_type : 4;
+ amy::u8 bit_0 : 1 = 0;
+ amy::u8 dpl : 2;
+ amy::u8 present : 1;
+ amy::u16 offset_mid;
+ amy::u32 offset_high;
+ amy::u32 reserved_2 = 0;
};
static_assert(sizeof(ide) == 16);
-template <size_t interrupt_nb>
+template <amy::size interrupt_nb>
using idt __attribute__((aligned(0x1000))) = ide[interrupt_nb];
struct __attribute__((packed)) idtr {
- std::uint16_t size;
- std::uint64_t offset;
+ amy::u16 size;
+ amy::u64 offset;
};
void lidt(idtr idtr);
bool is_APIC_builtin();
void disable_PIC();
-void set_APIC_base(phys_ptr<volatile std::uint32_t> ptr);
-phys_ptr<volatile std::uint32_t> get_APIC_base();
-std::uint32_t get_APIC_reg(std::ptrdiff_t offset);
-void set_APIC_reg(std::ptrdiff_t offset, std::uint32_t v);
+void set_APIC_base(phys_ptr<volatile amy::u32> ptr);
+phys_ptr<volatile amy::u32> get_APIC_base();
+amy::u32 get_APIC_reg(amy::dptr offset);
+void set_APIC_reg(amy::dptr offset, amy::u32 v);
struct isr_info {
- std::uintptr_t addr;
+ amy::uptr addr;
enum class type_t { trap_gate = 0xF, interrupt_gate = 0xE };
type_t type : 4;
- std::uint8_t dpl: 2 = 0b00;
+ amy::u8 dpl: 2 = 0b00;
bool present : 1 = true;
};
template<typename... Ts>
void assert(bool cond, const char* format, const Ts&... vs);
-template<size_t interrupt_nb>
+template<amy::size interrupt_nb>
void enable_interrupts(const isr_info (&ISRs)[interrupt_nb], os::idt<interrupt_nb>& idt) {
os::assert(is_APIC_builtin(), "No builtin APIC.");
disable_PIC();
set_APIC_reg(0xF0, 0x1FF); // Enable APIC
- for (std::size_t i = 0; i < interrupt_nb; i++) {
+ for (amy::size i = 0; i < interrupt_nb; i++) {
idt[i] = {
- .offset_low = uint16_t(ISRs[i].addr & 0xFFFF),
+ .offset_low = amy::u16(ISRs[i].addr & 0xFFFF),
.kernel_cs = 0x10,
.ist_offset = 0,
- .gate_type = std::uint8_t(ISRs[i].type), // Trap gate.
+ .gate_type = amy::u8(ISRs[i].type), // Trap gate.
.dpl = ISRs[i].dpl,
- .present = std::uint8_t(ISRs[i].present ? 1 : 0),
- .offset_mid = uint16_t((ISRs[i].addr >> 16) & 0xFFFF),
- .offset_high = uint32_t((ISRs[i].addr >> 32) & 0xFFFFFFFF),
+ .present = amy::u8(ISRs[i].present ? 1 : 0),
+ .offset_mid = amy::u16((ISRs[i].addr >> 16) & 0xFFFF),
+ .offset_high = amy::u32((ISRs[i].addr >> 32) & 0xFFFFFFFF),
};
}
os::idtr idtr {
.size = sizeof(idt) - 1,
- .offset = reinterpret_cast<uintptr_t>(&idt[0]),
+ .offset = reinterpret_cast<amy::uptr>(&idt[0]),
};
lidt(idtr);
sti();
os::assert(os::cpu_has_msr(), "MSRs aren't supported.");
// Initialise kernel map.
- os::assert(std::size_t(&_kernel_phys_start) % 4096 == 0, "Kernel isn't page aligned !");
- os::assert(std::size_t(&_kernel_phys_rw_start) % 4096 == 0, "Kernel isn't page aligned !");
- os::assert(std::size_t(&_kernel_phys_end) % 4096 == 0, "Kernel isn't page aligned !");
- for (std::size_t i = std::size_t(&_kernel_phys_start); i < std::size_t(&_kernel_phys_rw_start); ) {
- if (i % (1024 * 1024 * 1024) == 0 && i + 1024 * 1024 * 1024 < std::size_t(&_kernel_phys_rw_start)) {
+ os::assert(amy::iptr(&_kernel_phys_start) % 4096 == 0, "Kernel isn't page aligned !");
+ os::assert(amy::iptr(&_kernel_phys_rw_start) % 4096 == 0, "Kernel isn't page aligned !");
+ os::assert(amy::iptr(&_kernel_phys_end) % 4096 == 0, "Kernel isn't page aligned !");
+ for (amy::size i = amy::iptr(&_kernel_phys_start); i < amy::iptr(&_kernel_phys_rw_start); ) {
+ if (i % (1024 * 1024 * 1024) == 0 && i + 1024 * 1024 * 1024 < amy::iptr(&_kernel_phys_rw_start)) {
os::paging::map_page<2, 3>(os::paging::global_PML4T, (os::paging::page<2>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr<os::paging::page<2>>(i),
{ .RW = false, .US = false, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = true, .AVL = 0, .NX = false });
i += 1024 * 1024 * 1024;
- } else if (i % (1024 * 1024 * 2) == 0 && i + 1024 * 1024 * 2 < std::size_t(&_kernel_phys_rw_start)) {
+ } else if (i % (1024 * 1024 * 2) == 0 && i + 1024 * 1024 * 2 < amy::iptr(&_kernel_phys_rw_start)) {
os::paging::map_page<1, 3>(os::paging::global_PML4T, (os::paging::page<1>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr<os::paging::page<1>>(i),
{ .RW = false, .US = false, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = true, .AVL = 0, .NX = false });
i += 1024 * 1024 * 2;
i += 1024 * 4;
}
}
- for (std::size_t i = std::size_t(&_kernel_phys_rw_start); i < std::size_t(&_kernel_phys_end); ) {
- if (i % (1024 * 1024 * 1024) == 0 && i + 1024 * 1024 * 1024 < std::size_t(&_kernel_phys_rw_start)) {
+ for (amy::size i = amy::iptr(&_kernel_phys_rw_start); i < amy::iptr(&_kernel_phys_end); ) {
+ if (i % (1024 * 1024 * 1024) == 0 && i + 1024 * 1024 * 1024 < amy::iptr(&_kernel_phys_rw_start)) {
os::paging::map_page<2, 3>(os::paging::global_PML4T, (os::paging::page<2>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr<os::paging::page<2>>(i),
{ .RW = true, .US = false, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = true, .AVL = 0, .NX = true });
i += 1024 * 1024 * 1024;
- } else if (i % (1024 * 1024 * 2) == 0 && i + 1024 * 1024 * 2 < std::size_t(&_kernel_phys_rw_start)) {
+ } else if (i % (1024 * 1024 * 2) == 0 && i + 1024 * 1024 * 2 < amy::iptr(&_kernel_phys_rw_start)) {
os::paging::map_page<1, 3>(os::paging::global_PML4T, (os::paging::page<1>*)(0xFFFF'FFFF'8000'0000 + i), os::phys_ptr<os::paging::page<1>>(i),
{ .RW = true, .US = false, .PWT = false, .PCD = false, .A = false, .D = false, .PAT = false, .G = true, .AVL = 0, .NX = true });
i += 1024 * 1024 * 2;
switch (it->type) {
case multiboot2::info::type_t::memory_map:
os::print("RAM:\n");
- for (std::size_t i = 0; i < multiboot2::memory_map_number_of_entries(it); i++) {
- std::size_t const s = multiboot2::memory_map_base_addr(it, i);
- std::size_t const e = s + multiboot2::memory_map_length(it, i);
+ for (amy::size i = 0; i < multiboot2::memory_map_number_of_entries(it); i++) {
+ amy::iptr const s = multiboot2::memory_map_base_addr(it, i);
+ amy::iptr const e = s + multiboot2::memory_map_length(it, i);
os::print("{} -> {} : {}\n", (void*)s, (void*)e, multiboot2::memory_map_type(it, i));
if (multiboot2::memory_map_type(it, i) != 1) {
continue;
}
os::assert(s % 0x1000 == 0, "Memory map unaligned on page boundaries.");
os::assert(e % 0x1000 == 0, "Memory map unaligned on page boundaries.");
- for (std::size_t j = s; j < e; ) {
+ for (amy::iptr j = s; j < e; ) {
if (j % (1024 * 1024 * 1024) == 0 && j + 1024 * 1024 * 1024 < e) {
os::paging::map_page<2, 3>(
os::paging::global_PML4T,
}
}
// /TODO
- os::paging::load_pml4t(os::phys_ptr<os::paging::PML4T>{std::uintptr_t(&os::paging::global_PML4T) - 0xFFFF'FFFF'8000'0000});
+ os::paging::load_pml4t(os::phys_ptr<os::paging::PML4T>{amy::uptr(&os::paging::global_PML4T) - 0xFFFF'FFFF'8000'0000});
{ // Enable interrupts really early so I don't have to manually manage memory... Will make better later, when I make utils.hpp/incrementing_int64_map better.
os::isr_info isr_info[32];
- for (size_t i = 0; i < sizeof(isr_info) / sizeof(isr_info[0]); i++) {
+ for (amy::size i = 0; (unsigned long long)(i) < sizeof(isr_info) / sizeof(isr_info[0]); i++) {
isr_info[i].type = os::isr_info::type_t::trap_gate;
}
asm ("movq $handler_0x00,%0" : "=ri"(isr_info[0x00].addr) : );
// TODO: Not an emergency, but adapt in case we need multiple PML4Es. (*NOT* the case right now.)
static_assert(sizeof(os::processes) <= 1024 * 1024 * 1024, "Error: processes array too big.");
{
- std::size_t const index = (std::uint64_t(&os::processes) >> (12 + 9 * 3)) & 0x1FF;
+ amy::size const index = (amy::size(&os::processes) >> (12 + 9 * 3)) & 0x1FF;
os::paging::global_PML4T.contents[index].paging_table_info({.RW = true, .US = false, .PWT = false, .PCD = false, .A = false, .AVL = 0, .NX = false});
const auto PDPT_alloc = os::paging::page_allocator.allocate(1);
os::memset((void*)PDPT_alloc.ptr, 0, 0x1000);
os::phys_ptr<os::paging::page<0>> start_address = nullptr;
os::phys_ptr<os::paging::page<0>> end_address = nullptr;
} available_ram[50];
- std::size_t available_ram_length = 0;
+ amy::size available_ram_length = 0;
bool module_specified = false;
for (auto it = multiboot2::next(info); it->type != multiboot2::info::type_t::end; it = multiboot2::next(it)) {
);
break;
case multiboot2::info::type_t::memory_map:
- for (std::size_t i = 0; i < multiboot2::memory_map_number_of_entries(it); i++) {
+ for (amy::size i = 0; i < multiboot2::memory_map_number_of_entries(it); i++) {
if (multiboot2::memory_map_type(it, i) != 1) {
continue;
}
os::print("{}->{}: {}\n", multiboot2::modules_mod_start(it), multiboot2::modules_mod_end(it), multiboot2::modules_string(it));
module_specified = true;
os::elf::load_elf(os::get_process(os::processes.create()),
- (std::byte*)multiboot2::modules_mod_start(it),
+ (amy::byte*)multiboot2::modules_mod_start(it),
multiboot2::modules_mod_end(it) - multiboot2::modules_mod_start(it),
os::paging::global_PML4T);
break;
os::assert(module_specified, "No modules specified in the multiboot. This is unsupported.");
// kernel_start and kernel_end are aligned to 4K by the linker script.
- const os::phys_ptr<os::paging::page<0>> kernel_s{std::size_t(&_kernel_phys_start)};
- const os::phys_ptr<os::paging::page<0>> kernel_e{std::size_t(&_kernel_phys_end)};
+ const os::phys_ptr<os::paging::page<0>> kernel_s{amy::uptr(&_kernel_phys_start)};
+ const os::phys_ptr<os::paging::page<0>> kernel_e{amy::uptr(&_kernel_phys_end)};
// Remove kernel from available RAM:
- for (std::size_t i = 0; i < available_ram_length; i++) {
+ for (amy::iptr i = 0; i < available_ram_length; i++) {
if (kernel_e < available_ram[i].start_address || available_ram[i].end_address < kernel_s) {
continue;
}
}
// Add available RAM to the page allocator (warning: overrides the multiboot info structure and the multiboot modules):
- for (std::size_t i = 0; i < available_ram_length; i++) {
+ for (amy::iptr i = 0; i < available_ram_length; i++) {
os::paging::page_allocator.deallocate({
.ptr = available_ram[i].start_address,
- .size = std::size_t(available_ram[i].end_address - available_ram[i].start_address + 1)
+ .size = amy::size(available_ram[i].end_address - available_ram[i].start_address + 1)
});
}
}
os::print("RAM END\n");
os::print("Loading ring 3 interrupts stack.\n");
- os::set_ring0_stack(TSS, std::uint64_t(&interrupt_stack_top));
+ os::set_ring0_stack(TSS, amy::size(&interrupt_stack_top));
os::print("Loading TSS.\n");
os::load_tss();
os::print("Enabling syscalls.\n");
#pragma once
#ifdef __cplusplus
-# include <cstdint>
+# include <types.hpp>
# include "phys_ptr.hpp"
namespace multiboot2 {
#endif // __cplusplus
#ifdef __cplusplus
- constexpr std::uint32_t magic = 0xE85250D6;
- constexpr std::uint32_t arch_i386_32bit = 0;
- constexpr std::uint32_t arch_mips_32bit = 4;
- constexpr std::uint32_t checksum(std::uint32_t arch, std::uint32_t length) { return -(magic + arch + length); }
+ constexpr amy::u32 magic = 0xE85250D6;
+ constexpr amy::u32 arch_i386_32bit = 0;
+ constexpr amy::u32 arch_mips_32bit = 4;
+ constexpr amy::u32 checksum(amy::u32 arch, amy::u32 length) { return -(magic + arch + length); }
#else
# define multiboot2_magic 0xE85250D6
# define multiboot2_arch_i386_32bit 0
#ifdef __cplusplus
struct __attribute__((packed)) info_start {
- std::uint32_t total_size;
- std::uint32_t reserved;
+ amy::u32 total_size;
+ amy::u32 reserved;
};
struct __attribute__((packed)) info {
- enum class type_t : std::uint32_t {
+ enum class type_t : amy::u32 {
end = 0,
basic_memory_info = 4,
bios_boot_device = 5,
image_load_base_physical_address = 21,
};
type_t type;
- std::uint32_t size;
- std::uint8_t rest[];
+ amy::u32 size;
+ amy::u8 rest[];
};
inline os::phys_ptr<const info> next(os::phys_ptr<const info_start> ptr) {
return os::phys_ptr<const info>((ptr.get_phys_addr() + ptr->size + 7) / 8 * 8); // + 7) / 8 * 8 is required for alignment.
}
- inline std::uint64_t framebuffer_addr(os::phys_ptr<const info> ptr) {
- return *reinterpret_cast<const std::uint64_t*>(&ptr->rest[0]);
+ inline amy::u64 framebuffer_addr(os::phys_ptr<const info> ptr) {
+ return *reinterpret_cast<const amy::u64*>(&ptr->rest[0]);
}
- inline std::uint32_t framebuffer_pitch(os::phys_ptr<const info> ptr) {
- return *reinterpret_cast<const std::uint32_t*>(&ptr->rest[8]);
+ inline amy::u32 framebuffer_pitch(os::phys_ptr<const info> ptr) {
+ return *reinterpret_cast<const amy::u32*>(&ptr->rest[8]);
}
- inline std::uint32_t framebuffer_width(os::phys_ptr<const info> ptr) {
- return *reinterpret_cast<const std::uint32_t*>(&ptr->rest[12]);
+ inline amy::u32 framebuffer_width(os::phys_ptr<const info> ptr) {
+ return *reinterpret_cast<const amy::u32*>(&ptr->rest[12]);
}
- inline std::uint32_t framebuffer_height(os::phys_ptr<const info> ptr) {
- return *reinterpret_cast<const std::uint32_t*>(&ptr->rest[16]);
+ inline amy::u32 framebuffer_height(os::phys_ptr<const info> ptr) {
+ return *reinterpret_cast<const amy::u32*>(&ptr->rest[16]);
}
- inline std::uint8_t framebuffer_bpp(os::phys_ptr<const info> ptr) {
- return *reinterpret_cast<const std::uint8_t*>(&ptr->rest[20]);
+ inline amy::u8 framebuffer_bpp(os::phys_ptr<const info> ptr) {
+ return *reinterpret_cast<const amy::u8*>(&ptr->rest[20]);
}
- inline std::uint8_t framebuffer_type(os::phys_ptr<const info> ptr) {
- return *reinterpret_cast<const std::uint8_t*>(&ptr->rest[21]);
+ inline amy::u8 framebuffer_type(os::phys_ptr<const info> ptr) {
+ return *reinterpret_cast<const amy::u8*>(&ptr->rest[21]);
}
- inline const std::uint8_t* color_info(os::phys_ptr<const info> ptr) {
- return reinterpret_cast<const std::uint8_t*>(&ptr->rest[24]);
+ inline const amy::u8* color_info(os::phys_ptr<const info> ptr) {
+ return reinterpret_cast<const amy::u8*>(&ptr->rest[24]);
}
- inline std::uint32_t memory_map_entry_size(os::phys_ptr<const info> ptr) {
- return *reinterpret_cast<const std::uint32_t*>(&ptr->rest[0]);
+ inline amy::u32 memory_map_entry_size(os::phys_ptr<const info> ptr) {
+ return *reinterpret_cast<const amy::u32*>(&ptr->rest[0]);
}
- inline std::uint32_t memory_map_entry_version(os::phys_ptr<const info> ptr) {
- return *reinterpret_cast<const std::uint32_t*>(&ptr->rest[4]);
+ inline amy::u32 memory_map_entry_version(os::phys_ptr<const info> ptr) {
+ return *reinterpret_cast<const amy::u32*>(&ptr->rest[4]);
}
- inline std::size_t memory_map_number_of_entries(os::phys_ptr<const info> ptr) {
+ inline amy::size memory_map_number_of_entries(os::phys_ptr<const info> ptr) {
return (ptr->size - 16) / memory_map_entry_size(ptr);
}
- inline std::uint64_t memory_map_base_addr(os::phys_ptr<const info> ptr, std::size_t index) {
- return *reinterpret_cast<const std::uint64_t*>(&ptr->rest[8 + memory_map_entry_size(ptr) * index + 0]);
+ inline amy::u64 memory_map_base_addr(os::phys_ptr<const info> ptr, amy::size index) {
+ return *reinterpret_cast<const amy::u64*>(&ptr->rest[8 + memory_map_entry_size(ptr) * index + 0]);
}
- inline std::uint64_t memory_map_length(os::phys_ptr<const info> ptr, std::size_t index) {
- return *reinterpret_cast<const std::uint64_t*>(&ptr->rest[8 + memory_map_entry_size(ptr) * index + 8]);
+ inline amy::u64 memory_map_length(os::phys_ptr<const info> ptr, amy::size index) {
+ return *reinterpret_cast<const amy::u64*>(&ptr->rest[8 + memory_map_entry_size(ptr) * index + 8]);
}
- inline std::uint32_t memory_map_type(os::phys_ptr<const info> ptr, std::size_t index) {
- return *reinterpret_cast<const std::uint32_t*>(&ptr->rest[8 + memory_map_entry_size(ptr) * index + 16]);
+ inline amy::u32 memory_map_type(os::phys_ptr<const info> ptr, amy::size index) {
+ return *reinterpret_cast<const amy::u32*>(&ptr->rest[8 + memory_map_entry_size(ptr) * index + 16]);
}
- inline os::phys_ptr<std::byte> modules_mod_start(os::phys_ptr<const info> ptr) {
- return os::phys_ptr<std::byte>{*reinterpret_cast<const std::uint32_t*>(&ptr->rest[0])};
+ inline os::phys_ptr<amy::byte> modules_mod_start(os::phys_ptr<const info> ptr) {
+ return os::phys_ptr<amy::byte>{*reinterpret_cast<const amy::u32*>(&ptr->rest[0])};
}
- inline os::phys_ptr<std::byte> modules_mod_end(os::phys_ptr<const info> ptr) {
- return os::phys_ptr<std::byte>{*reinterpret_cast<const std::uint32_t*>(&ptr->rest[4])};
+ inline os::phys_ptr<amy::byte> modules_mod_end(os::phys_ptr<const info> ptr) {
+ return os::phys_ptr<amy::byte>{*reinterpret_cast<const amy::u32*>(&ptr->rest[4])};
}
inline const char* modules_string(os::phys_ptr<const info> ptr) {
return reinterpret_cast<const char*>(&ptr->rest[8]);
#pragma once
-#include <cstddef>
-#include <compare>
+#include <types.hpp>
namespace os {
template <>
class phys_ptr<void> {
public:
- constexpr explicit phys_ptr(std::uintptr_t phys_addr): phys_addr(phys_addr) {}
- constexpr phys_ptr(std::nullptr_t): phys_addr(~0ull) {}
+ constexpr explicit phys_ptr(amy::uptr phys_addr): phys_addr(phys_addr) {}
+ constexpr phys_ptr(amy::nptr): phys_addr(~0ull) {}
inline void* operator->() const {
return get_virt_addr();
return get_virt_addr();
}
- constexpr std::uintptr_t get_phys_addr() const {
+ constexpr amy::uptr get_phys_addr() const {
return phys_addr;
}
- friend constexpr auto operator<=>(phys_ptr<void> a, phys_ptr<void> b) = default;
+ friend constexpr bool operator<(phys_ptr<void> a, phys_ptr<void> b) = default;
+ friend constexpr bool operator<=(phys_ptr<void> a, phys_ptr<void> b) = default;
+ friend constexpr bool operator>(phys_ptr<void> a, phys_ptr<void> b) = default;
+ friend constexpr bool operator>=(phys_ptr<void> a, phys_ptr<void> b) = default;
+ friend constexpr bool operator==(phys_ptr<void> a, phys_ptr<void> b) = default;
+ friend constexpr bool operator!=(phys_ptr<void> a, phys_ptr<void> b) = default;
private:
constexpr void* get_virt_addr() const {
return reinterpret_cast<void*>(phys_addr + 0xFFFF800000000000);
}
- std::uintptr_t phys_addr;
+ amy::uptr phys_addr;
};
template <typename T>
class phys_ptr {
public:
- constexpr explicit phys_ptr(std::uintptr_t phys_addr): phys_addr(phys_addr) {}
- constexpr phys_ptr(std::nullptr_t): phys_addr(~0ull) {}
+ constexpr explicit phys_ptr(amy::uptr phys_addr): phys_addr(phys_addr) {}
+ constexpr phys_ptr(amy::nptr): phys_addr(~0ull) {}
- T& operator[](std::size_t i) const {
+ T& operator[](amy::size i) const {
return get_virt_addr()[i];
}
T& operator*() const {
operator--();
return old;
}
- constexpr phys_ptr<T>& operator+=(std::ptrdiff_t offset) {
+ constexpr phys_ptr<T>& operator+=(amy::dptr offset) {
return *this = *this + offset;
}
- constexpr phys_ptr<T>& operator-=(std::ptrdiff_t offset) {
+ constexpr phys_ptr<T>& operator-=(amy::dptr offset) {
return *this = *this - offset;
}
- friend constexpr phys_ptr<T> operator+(phys_ptr<T> ptr, std::ptrdiff_t offset) {
+ friend constexpr phys_ptr<T> operator+(phys_ptr<T> ptr, amy::dptr offset) {
return phys_ptr<T>{ptr.phys_addr + offset * sizeof(T)};
}
- friend constexpr phys_ptr<T> operator+(std::ptrdiff_t offset, phys_ptr<T> ptr) {
+ friend constexpr phys_ptr<T> operator+(amy::dptr offset, phys_ptr<T> ptr) {
return ptr + offset;
}
- friend constexpr phys_ptr<T> operator-(phys_ptr<T> ptr, std::ptrdiff_t offset) {
+ friend constexpr phys_ptr<T> operator-(phys_ptr<T> ptr, amy::dptr offset) {
return phys_ptr<T>{ptr.phys_addr - offset * sizeof(T)};
}
- friend constexpr std::ptrdiff_t operator-(phys_ptr<T> a, phys_ptr<T> b) {
+ friend constexpr amy::dptr operator-(phys_ptr<T> a, phys_ptr<T> b) {
return (a.phys_addr - b.phys_addr) / sizeof(T);
}
- constexpr std::uintptr_t get_phys_addr() const {
+ constexpr amy::uptr get_phys_addr() const {
return phys_addr;
}
- friend constexpr auto operator<=>(phys_ptr<T> a, phys_ptr<T> b) = default;
+ friend constexpr bool operator<(phys_ptr<T> a, phys_ptr<T> b) {
+ return a.phys_addr < b.phys_addr;
+ }
+ friend constexpr bool operator<=(phys_ptr<T> a, phys_ptr<T> b) {
+ return a.phys_addr <= b.phys_addr;
+ }
+ friend constexpr bool operator>(phys_ptr<T> a, phys_ptr<T> b) {
+ return a.phys_addr > b.phys_addr;
+ }
+ friend constexpr bool operator>=(phys_ptr<T> a, phys_ptr<T> b) {
+ return a.phys_addr >= b.phys_addr;
+ }
+ friend constexpr bool operator==(phys_ptr<T> a, phys_ptr<T> b) {
+ return a.phys_addr == b.phys_addr;
+ }
+ friend constexpr bool operator!=(phys_ptr<T> a, phys_ptr<T> b) {
+ return a.phys_addr != b.phys_addr;
+ }
private:
constexpr T* get_virt_addr() const {
return reinterpret_cast<T*>(phys_addr + 0xFFFF800000000000);
}
- std::uintptr_t phys_addr;
+ amy::uptr phys_addr;
};
} // namespace os
}
}
-os::paging::page_allocator_t::block os::paging::page_allocator_t::allocate(std::uint64_t count) {
+os::paging::page_allocator_t::block os::paging::page_allocator_t::allocate(amy::size count) {
if (begin == nullptr) {
return { .ptr = nullptr, .size = count };
}
#pragma once
-#include <cstdint>
+#include <types.hpp>
#include "serial.hpp"
#include "utils.hpp"
#include "lib/phys_ptr.hpp"
namespace os { namespace paging {
-template <std::size_t depth> struct paging_entry;
-template <std::size_t depth> struct paging_table;
-template <std::size_t depth> struct page;
+template <amy::size depth> struct paging_entry;
+template <amy::size depth> struct paging_table;
+template <amy::size depth> struct page;
struct page_info {
bool RW;
bool D;
bool PAT;
bool G;
- std::uint16_t AVL; // Only 14 bits, actually.
+ amy::u16 AVL; // Only 14 bits, actually.
bool NX;
};
struct paging_table_info {
bool PWT;
bool PCD;
bool A;
- std::uint16_t AVL; // Really 16 bits !
+ amy::u16 AVL; // Really 16 bits !
bool NX;
};
-template <std::size_t depth> struct paging_entry {
- std::uint64_t data = 0;
+template <amy::size depth> struct paging_entry {
+ amy::u64 data = 0;
bool is_present() {
return (data & (1 << 0)) != 0;
}
os::phys_ptr<os::paging::page<depth>> page_ptr() {
os::assert(is_page(), "Cannot access page physical pointer for a non-page.");
- std::uintptr_t addr = data & (depth == 0 ? 0x0000'FFFF'FFFF'F000 : 0x0000'FFFF'FFFF'E000);
+ amy::uptr addr = data & (depth == 0 ? 0x0000'FFFF'FFFF'F000 : 0x0000'FFFF'FFFF'E000);
return os::phys_ptr<os::paging::page<depth>>(addr | ((addr & 0x0000'8000'0000'0000) != 0 ? 0xFFFF'8000'0000'0000 : 0));
}
void page_ptr(os::phys_ptr<os::paging::page<depth>> page) {
}
os::phys_ptr<os::paging::paging_table<depth - 1>> paging_table_ptr() {
os::assert(!is_page(), "Cannot access paging table physical pointer for a page.");
- std::uintptr_t addr = data & 0x0000'FFFF'FFFF'F000;
+ amy::uptr addr = data & 0x0000'FFFF'FFFF'F000;
return os::phys_ptr<os::paging::paging_table<depth - 1>>(addr | ((addr & 0x0000'8000'0000'0000) != 0 ? 0xFFFF'8000'0000'0000 : 0));
}
void paging_table_ptr(os::phys_ptr<os::paging::paging_table<depth - 1>> table) {
| (info.D ? (1ull << 6) : 0)
| (info.PAT ? (depth == 0 ? 1 << 7: 1 << 12) : 0)
| (info.G ? (1ull << 8) : 0)
- | (std::uint64_t(info.AVL & 0x7) << 9)
- | (std::uint64_t(info.AVL & 0x3FF8) << 49)
+ | (amy::u64(info.AVL & 0x7) << 9)
+ | (amy::u64(info.AVL & 0x3FF8) << 49)
| (info.NX ? (1ull << 63) : 0);
}
void paging_table_info(os::paging::paging_table_info info) {
| (info.PWT ? (1ull << 3) : 0)
| (info.PCD ? (1ull << 4) : 0)
| (info.A ? (1ull << 5) : 0)
- | (std::uint64_t(info.AVL & 0x1) << 6)
- | (std::uint64_t(info.AVL & 0x1E) << 7)
- | (std::uint64_t(info.AVL & 0xFFE0) << 47)
+ | (amy::u64(info.AVL & 0x1) << 6)
+ | (amy::u64(info.AVL & 0x1E) << 7)
+ | (amy::u64(info.AVL & 0xFFE0) << 47)
| (info.NX ? (1ull << 63) : 0);
}
};
-template <std::size_t depth> struct __attribute__((aligned(0x1000))) paging_table {
+template <amy::size depth> struct __attribute__((aligned(0x1000))) paging_table {
paging_entry<depth> contents[512];
};
// Alignment should be the same as size, but that's literally too big for the compiler.
-template <std::size_t depth> struct __attribute__((aligned(0x1000))) page {
- std::byte contents[0x1000ull << (9 * depth)];
+template <amy::size depth> struct __attribute__((aligned(0x1000))) page {
+ amy::byte contents[0x1000ull << (9 * depth)];
};
static_assert(sizeof(page<0>) == 0x1000);
extern PML4T global_PML4T;
-template <std::size_t depth, std::size_t paging_depth = 3>
+template <amy::size depth, amy::size paging_depth = 3>
void map_page(paging_table<paging_depth>& paging_table, page<depth> const* vaddr, phys_ptr<page<depth>> paddr, os::paging::page_info page_info);
-template <std::size_t depth>
-void on_all_pages(const paging_table<depth>& paging_table, auto f, std::size_t vaddr_offset = 0);
+template <amy::size depth>
+void on_all_pages(const paging_table<depth>& paging_table, auto f, amy::uptr vaddr_offset = 0);
void load_pml4t(phys_ptr<PML4T> PML4T);
public:
struct block {
phys_ptr<paging::page<0>> ptr = nullptr;
- std::uint64_t size;
+ amy::size size;
};
page_allocator_t();
void print_all() const;
- block allocate(std::uint64_t page_count);
+ block allocate(amy::size page_count);
void deallocate(block b);
private:
struct __attribute__((aligned(0x1000))) page {
phys_ptr<page> next;
- std::uint64_t size;
+ amy::size size;
};
static_assert(sizeof(page) == 0x1000);
static_assert(alignof(page) == 0x1000);
bool merge(phys_ptr<page> it);
};
-template <std::size_t depth, std::size_t paging_depth>
+template <amy::size depth, amy::size paging_depth>
void map_page(paging_table<paging_depth>& paging_table, page<depth> const* vaddr, phys_ptr<page<depth>> paddr, os::paging::page_info page_info) {
- std::size_t const index = (std::uint64_t(vaddr) >> (12 + 9 * paging_depth)) & 0x1FF;
+ amy::size const index = (amy::uptr(vaddr) >> (12 + 9 * paging_depth)) & 0x1FF;
if constexpr (depth == paging_depth) {
os::assert(!paging_table.contents[index].is_present(), "Virtual address 0x{} is already mapped.", vaddr);
paging_table.contents[index].page_info(page_info);
}
}
-template <std::size_t depth>
-void on_all_pages(const paging_table<depth>& paging_table, auto f, std::size_t vaddr_offset) {
- for (std::size_t i = 0; i < 512; i++) {
+template <amy::size depth>
+void on_all_pages(const paging_table<depth>& paging_table, auto f, amy::uptr vaddr_offset) {
+ for (amy::size i = 0; i < 512; i++) {
if (!is_present(paging_table.contents[i])) {
continue;
}
- std::size_t const new_offset = ([&]() {
- std::size_t const new_offset = vaddr_offset + (i << (12 + 9 * depth));
+ amy::uptr const new_offset = ([&]() {
+ amy::uptr const new_offset = vaddr_offset + (i << (12 + 9 * depth));
return new_offset | (new_offset >> 47 ? 0xFFFF'8000'0000'0000 : 0);
})();
if constexpr (depth == 3) {
#include "serial.hpp"
#include "paging.hpp"
-void os::run_first_process(std::int64_t pid) {
+void os::run_first_process(amy::i64 pid) {
current_pid = pid;
os::paging::load_pml4t(os::get_process(current_pid).PML4T);
- os::ftl_to_userspace((void*)os::get_process(current_pid).rip, (std::byte*)os::get_process(current_pid).rsp);
+ os::ftl_to_userspace((void*)os::get_process(current_pid).rip, (amy::byte*)os::get_process(current_pid).rsp);
}
-void os::set_ring0_stack(os::tss& tss, std::uint64_t stack) {
+void os::set_ring0_stack(os::tss& tss, amy::u64 stack) {
tss.rsp0 = stack;
}
// This is required to enable syscall/sysret on x86_64 intel.
os::set_msr(0xC0000080, os::get_msr(0xC0000080) | (1 << 0));
os::set_msr(0xC0000081,
- (std::uint64_t(24 - 8 + 0b11) << 48) + // sysret_cs_and_ss (e.g., userspace segments)
- (std::uint64_t( 8 - 8 + 0b00) << 32) + // syscall_cs_and_ss (e.g., kernelspace segments)
- std::uint64_t(0) // syscall_target_eip, only relevant to 32-bits so useless here
+ (amy::u64(24 - 8 + 0b11) << 48) + // sysret_cs_and_ss (e.g., userspace segments)
+ (amy::u64( 8 - 8 + 0b00) << 32) + // syscall_cs_and_ss (e.g., kernelspace segments)
+ amy::u64(0) // syscall_target_eip, only relevant to 32-bits so useless here
);
- os::set_msr(0xC0000082, std::uint64_t(&syscall_64bit_handler)); // RIP for 64-bit program
+ os::set_msr(0xC0000082, amy::u64(&syscall_64bit_handler)); // RIP for 64-bit program
os::set_msr(0xC0000083, 0); // RIP for 32-bit program, we ignore this one because the OS is only supposed to support programs running with 64 bits.
os::set_msr(0xC0000084, 0x00000000); // syscall flag mask, we don't want to change the flags for now.
}
os::paging::load_pml4t(os::processes.get(os::current_pid).PML4T);
}
-// extern "C" std::int64_t syscall_mount_kernel_device(std::int64_t wd, char device, char const* path, std::int64_t path_len, int mount_type) {
-extern "C" std::int64_t syscall_mount_kernel_device(std::int64_t, char, char const*, std::int64_t, int) {
+// extern "C" int os::syscall_mount_kernel_device(amy::fd wd, char device, char const* path, amy::size path_len, int mount_type);
+extern "C" int os::syscall_mount_kernel_device(amy::fd, char, char const*, amy::size, int) {
os::assert(false, "mount_kernel_device not implemented yet.");
__builtin_unreachable();
}
-// extern "C" std::int64_t syscall_open(std::int64_t wd, char const* path, std::int64_t path_len, int options) {
-extern "C" std::int64_t syscall_open(std::int64_t, char const*, std::int64_t, int) {
+// extern "C" amy::fd os::syscall_open(amy::fd wd, char const* path, amy::size path_len, int options);
+extern "C" amy::fd os::syscall_open(amy::fd, char const*, amy::size, int) {
os::assert(false, "open not implemented yet.");
__builtin_unreachable();
}
-extern "C" std::int64_t syscall_read(std::int64_t file, char* data, std::int64_t len) {
+extern "C" amy::size os::syscall_read(amy::fd file, char* data, amy::size len) {
os::assert(file == 0, "Read isn't really implemented for now.");
os::assert(len >= 0, "Read expects a positive size.");
if (len == 0) {
return 0;
}
- for (std::int64_t i = 0; i < len; i++) {
+ for (amy::size i = 0; i < len; i++) {
if (i == 0) {
data[i] = os::read_serial();
continue;
return len;
}
-// extern "C" std::int64_t syscall_close(std::int64_t file) {
-extern "C" std::int64_t syscall_close(std::int64_t) {
- os::assert(false, "Close isn't implemented for now.");
- __builtin_unreachable();
-}
-
-extern "C" std::int64_t syscall_write(std::int64_t file, char const* data, std::int64_t len) {
+extern "C" amy::size os::syscall_write(amy::fd file, char const* data, amy::size len) {
os::assert(file == 0, "Write isn't really implemented for now.");
os::assert(len >= 0, "Write expects a positive size.");
if (len == 0) {
return 0;
}
- for (std::int64_t i = 0; i < len; i++) {
+ for (amy::size i = 0; i < len; i++) {
if (os::serial_transmit_empty()) {
os::write_serial(data[i]);
} else {
return len;
}
+// extern "C" int syscall_close(amy::fd file);
+extern "C" int os::syscall_close(amy::fd) {
+ os::assert(false, "Close isn't implemented for now.");
+ __builtin_unreachable();
+}
+
extern "C" void os::syscall_rax_error_handler() {
os::assert(false, "Incorrect %rax for syscall.");
__builtin_unreachable();
}
os::incrementing_int64_map<os::process>& os::processes = *reinterpret_cast<os::incrementing_int64_map<os::process>*>(0xFFFF'C000'0000'0000);
-std::int64_t os::current_pid;
-os::process& os::get_process(std::int64_t pid) {
+amy::pid os::current_pid;
+os::process& os::get_process(amy::pid pid) {
return processes.get(pid);
}
#pragma once
-#include <cstdint>
-#include <cstddef>
+#include <types.hpp>
#include "lib/phys_ptr.hpp"
#include "paging.hpp"
namespace os {
struct __attribute__((packed)) tss {
- std::uint32_t reserved_1;
- std::uint64_t rsp0;
- std::uint64_t rsp1;
- std::uint64_t rsp2;
- std::uint64_t reserved_2;
- std::uint64_t ist1;
- std::uint64_t ist2;
- std::uint64_t ist3;
- std::uint64_t ist4;
- std::uint64_t ist5;
- std::uint64_t ist6;
- std::uint64_t ist7;
- char reserved_3[10];
- std::uint16_t iopb;
+ amy::u32 reserved_1;
+ amy::u64 rsp0;
+ amy::u64 rsp1;
+ amy::u64 rsp2;
+ amy::u64 reserved_2;
+ amy::u64 ist1;
+ amy::u64 ist2;
+ amy::u64 ist3;
+ amy::u64 ist4;
+ amy::u64 ist5;
+ amy::u64 ist6;
+ amy::u64 ist7;
+ amy::byte reserved_3[10];
+ amy::u16 iopb;
};
struct process;
-extern "C" void ftl_to_userspace(void* program, std::byte* stack);
-void run_first_process(std::int64_t pid);
+extern "C" void ftl_to_userspace(void* program, amy::byte* stack);
+void run_first_process(amy::i64 pid);
extern "C" void load_tss();
extern "C" void syscall_64bit_handler();
-extern "C" std::int64_t syscall_open(std::int64_t wd, char const* path, std::int64_t path_len, int options);
-extern "C" std::int64_t syscall_read(std::int64_t file, char* data, std::int64_t len);
-extern "C" std::int64_t syscall_write(std::int64_t file, char const* data, std::int64_t len);
-extern "C" std::int64_t syscall_fseek(std::int64_t file, std::int64_t offset, int from);
+extern "C" int syscall_mount_kernel_device(amy::fd wd, char device, char const* path, amy::size path_len, int mount_type);
+extern "C" amy::fd syscall_open(amy::fd wd, char const* path, amy::size path_len, int options);
+extern "C" amy::size syscall_read(amy::fd file, char* data, amy::size len);
+extern "C" amy::size syscall_write(amy::fd file, char const* data, amy::size len);
+extern "C" int syscall_close(amy::fd file);
extern "C" void syscall_rax_error_handler();
-void set_ring0_stack(tss& tss, std::uint64_t stack);
+void set_ring0_stack(tss& tss, amy::u64 stack);
void enable_syscalls();
struct port {
bool exists;
bool is_open;
- std::uint64_t other_pid;
- std::uint64_t other_port;
+ amy::u64 other_pid;
+ amy::u64 other_port;
};
struct process {
phys_ptr<paging::PML4T> PML4T = nullptr;
- std::uint64_t rax;
- std::uint64_t rbx;
- std::uint64_t rcx;
- std::uint64_t rdx;
- std::uint64_t rsp;
- std::uint64_t rbp;
- std::uint64_t rsi;
- std::uint64_t rdi;
- std::uint64_t r8;
- std::uint64_t r9;
- std::uint64_t r10;
- std::uint64_t r11;
- std::uint64_t r12;
- std::uint64_t r13;
- std::uint64_t r14;
- std::uint64_t r15;
- std::uint64_t rip;
+ amy::u64 rax;
+ amy::u64 rbx;
+ amy::u64 rcx;
+ amy::u64 rdx;
+ amy::u64 rsp;
+ amy::u64 rbp;
+ amy::u64 rsi;
+ amy::u64 rdi;
+ amy::u64 r8;
+ amy::u64 r9;
+ amy::u64 r10;
+ amy::u64 r11;
+ amy::u64 r12;
+ amy::u64 r13;
+ amy::u64 r14;
+ amy::u64 r15;
+ amy::u64 rip;
incrementing_int64_map<port> ports;
};
static_assert(0xFFFF'C000'0000'0000 + sizeof(incrementing_int64_map<process>) < 0xFFFF'FFFF'8000'0000);
extern incrementing_int64_map<process>& processes;
-extern "C" std::int64_t current_pid;
-extern "C" process& get_process(std::int64_t pid);
+extern "C" amy::pid current_pid;
+extern "C" process& get_process(amy::i64 pid);
} // namespace os
// You should have received a copy of the GNU General Public License along with this program. If
// not, see <https://www.gnu.org/licenses/>.
-#include <cstddef>
#include "utils.hpp"
#include "interrupts.hpp"
#include "serial.hpp"
bool os::serial_received() {
return (inb(serial_port + 5) & 0x01) != 0;
}
-std::uint8_t os::read_serial() {
+amy::u8 os::read_serial() {
while (!serial_received()) {}
return inb(serial_port + 0);
}
bool os::serial_transmit_empty() {
return (inb(serial_port + 5) & 0x20) != 0;
}
-void os::write_serial(std::uint8_t v) {
+void os::write_serial(amy::u8 v) {
while (!serial_transmit_empty()) {}
outb(serial_port + 0, v);
}
}
void os::print_formatted(const char* format, const char* val) {
os::assert(format[0] == '}', "Format string unsupported. TODO.");
- for (std::size_t i = 0; val[i] != '\0'; i++) {
+ for (amy::size i = 0; val[i] != '\0'; i++) {
os::printc(val[i]);
}
}
-void os::print_formatted(const char* format, std::uint64_t val) {
+void os::print_formatted(const char* format, amy::u64 val) {
os::assert(format[0] == '}', "Format string unsupported. TODO.");
char data[20];
char* curr = data + 19;
os::printc(*curr++);
}
}
-void os::print_formatted(const char* format, std::int64_t val) {
+void os::print_formatted(const char* format, amy::i64 val) {
os::assert(format[0] == '}', "Format string unsupported. TODO.");
if (val < 0) {
os::printc('-');
- os::print_formatted(format, std::uint64_t(-val));
+ os::print_formatted(format, amy::u64(-val));
} else {
os::printc(' ');
- os::print_formatted(format, std::uint64_t(val));
+ os::print_formatted(format, amy::u64(val));
}
}
void os::print_formatted(const char* format, phys_ptr<void> val) {
os::assert(format[0] == '}', "Format string unsupported. TODO.");
os::print("0x");
for (int i = 60; i >= 0; i -= 4) {
- const int v = (reinterpret_cast<std::uintptr_t>(val) >> i) & 0xF;
+ const int v = (reinterpret_cast<amy::uptr>(val) >> i) & 0xF;
os::printc(v < 10 ? v + '0' : v - 10 + 'a');
}
}
#pragma once
-#include <cstdint>
-
+#include "types.hpp"
#include "lib/phys_ptr.hpp"
namespace os {
template<typename... Ts>
void assert(bool cond, const char* format, const Ts&... vs);
-constexpr std::uint16_t serial_port{0x3F8};
+constexpr amy::u16 serial_port{0x3F8};
bool init_serial_port();
bool serial_received();
-std::uint8_t read_serial();
+amy::u8 read_serial();
bool serial_transmit_empty();
-void write_serial(std::uint8_t v);
+void write_serial(amy::u8 v);
void printc(char c);
void print_formatted(const char* format, const char* val);
-void print_formatted(const char* format, std::uint64_t val);
-void print_formatted(const char* format, std::int64_t val);
+void print_formatted(const char* format, amy::u64 val);
+void print_formatted(const char* format, amy::i64 val);
void print_formatted(const char* format, phys_ptr<void> val);
void print_formatted(const char* format, const void* val);
using T = T_;
};
template <typename T> using get_more_general_type_helper_t = get_more_general_type_helper<T>::T;
-template <> struct get_more_general_type_helper<std::uint8_t> { using T = std::uint64_t; };
-template <> struct get_more_general_type_helper<std::uint16_t> { using T = std::uint64_t; };
-template <> struct get_more_general_type_helper<std::uint32_t> { using T = std::uint64_t; };
-template <> struct get_more_general_type_helper<std::int8_t> { using T = std::int64_t; };
-template <> struct get_more_general_type_helper<std::int16_t> { using T = std::int64_t; };
-template <> struct get_more_general_type_helper<std::int32_t> { using T = std::int64_t; };
+template <> struct get_more_general_type_helper<amy::u8> { using T = amy::u64; };
+template <> struct get_more_general_type_helper<amy::u16> { using T = amy::u64; };
+template <> struct get_more_general_type_helper<amy::u32> { using T = amy::u64; };
+template <> struct get_more_general_type_helper<amy::i8> { using T = amy::i64; };
+template <> struct get_more_general_type_helper<amy::i16> { using T = amy::i64; };
+template <> struct get_more_general_type_helper<amy::i32> { using T = amy::i64; };
template <> struct get_more_general_type_helper<char*> { using T = const char*; };
template <> struct get_more_general_type_helper<const char*> { using T = const char*; };
template <typename T_> struct get_more_general_type_helper<phys_ptr<T_>> { using T = phys_ptr<void>; };
template <typename T_> struct get_more_general_type_helper<T_*> { using T = const void*; };
-template <std::size_t n> struct get_more_general_type_helper<char[n]> { using T = const char*; };
+template <amy::size n> struct get_more_general_type_helper<char[n]> { using T = const char*; };
struct print_nth_helper {
- std::size_t n;
+ amy::size n;
const char* format;
template <typename T> inline print_nth_helper operator%(const T& v) {
if (n == 0) {
print_formatted(format, v);
- return print_nth_helper{std::size_t(-1), format};
- } else {
- return print_nth_helper{n - 1, format};
}
+ return print_nth_helper{n - 1, format};
}
};
template<typename... Ts>
void print(const char* format, const Ts&... vs) {
- std::size_t arg_n = 0;
+ amy::size arg_n = 0;
bool arg_n_is_given = 0;
- for (std::size_t i = 0; format[i] != '\0'; i++) {
+ for (amy::size i = 0; format[i] != '\0'; i++) {
if (format[i] == '{') {
i++;
if (format[i] == '\0') {
printc('{');
continue;
} else {
- std::size_t format_spec_end = i;
+ amy::size format_spec_end = i;
while (format[format_spec_end] != '}') {
if (format[format_spec_end++] == '\0') {
os::assert(false, "Error in format string: unterminated '{{}'.");
}
}
- std::size_t n = arg_n;
+ amy::size n = arg_n;
if ('0' <= format[i] && format[i] <= '9') {
if (arg_n == 0) {
arg_n_is_given = true;
}
os::assert(arg_n_is_given, "Error in format string: either the arg_id is always given, or never.");
- std::size_t n_ = 0;
+ amy::size n_ = 0;
while ('0' <= format[i] && format[i] <= '9') {
n_ = n_ * 10 + (format[i++] - '0');
}
} else {
os::assert(format[i] == '}', "Error in format string: ':' required before format spec.");
}
- os::assert(n < sizeof...(vs), "Error in format string: not enough arguments.");
+ os::assert(n < amy::size(sizeof...(vs)), "Error in format string: not enough arguments.");
(print_nth_helper{n, &format[i]} % ... % get_more_general_type_helper_t<Ts>(vs));
i = format_spec_end;
arg_n++;
asm volatile("hlt" :);
}
-void os::outb(std::uint16_t port, std::uint8_t data) {
+void os::outb(amy::u16 port, amy::u8 data) {
asm volatile ("outb %1,%0" : : "dN"(port), "a"(data));
}
-std::uint8_t os::inb(std::uint16_t port) {
- std::uint8_t data;
+amy::u8 os::inb(amy::u16 port) {
+ amy::u8 data;
asm volatile ("inb %1,%0" : "=a"(data) : "dN"(port));
return data;
}
bool os::cpu_has_msr() {
- std::uint32_t eax, ebx, ecx, edx;
+ amy::u32 eax, ebx, ecx, edx;
__cpuid(0x01, eax, ebx, ecx, edx);
return (edx & (1 << 5)) != 0;
}
-std::uint64_t os::get_msr(std::uint32_t msr) {
- std::uint64_t lo, hi;
+amy::u64 os::get_msr(amy::u32 msr) {
+ amy::u64 lo, hi;
asm volatile ("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr));
return lo + (hi << 32);
}
-void os::set_msr(std::uint32_t msr, std::uint64_t v) {
- asm volatile ("wrmsr" : : "a"(v & 0xFFFFFFFF), "d"((v >> 32) & 0xFFFFFFFF), "c"(msr));
+void os::set_msr(amy::u32 msr, amy::u64 v) {
+ asm volatile ("wrmsr" : : "a"(v & 0xFFFF'FFFF), "d"((v >> 32) & 0xFFFF'FFFF), "c"(msr));
}
-extern "C" void* os::memset(void* dest, int c, size_t n) {
+extern "C" void* os::memset(void* dest, int c, amy::size n) {
+ os::assert(n >= 0, "Memset expects a positive size.");
while (n-- > 0) {
- reinterpret_cast<std::byte*>(dest)[n] = std::byte(c);
+ reinterpret_cast<amy::byte*>(dest)[n] = amy::byte(c);
}
return dest;
}
-extern "C" void* os::memcpy(void* dest, const void* src, size_t n) {
+extern "C" void* os::memcpy(void* dest, const void* src, amy::size n) {
+ os::assert(n >= 0, "Memcpy expects a positive size.");
while (n-- > 0) {
- reinterpret_cast<std::byte*>(dest)[n] = reinterpret_cast<const std::byte*>(src)[n];
+ reinterpret_cast<amy::byte*>(dest)[n] = reinterpret_cast<const amy::byte*>(src)[n];
}
return dest;
}
#pragma once
-#include <cstdint>
-#include <cstddef>
-#include <new>
+#include <types.hpp>
+#include <memory.hpp>
#include "serial.hpp"
namespace os {
void cli();
void sti();
void hlt();
-void outb(std::uint16_t port, std::uint8_t data);
-std::uint8_t inb(std::uint16_t port);
+void outb(amy::u16 port, amy::u8 data);
+amy::u8 inb(amy::u16 port);
bool cpu_has_msr();
-std::uint64_t get_msr(std::uint32_t msr);
-void set_msr(std::uint32_t msr, std::uint64_t v);
+amy::u64 get_msr(amy::u32 msr);
+void set_msr(amy::u32 msr, amy::u64 v);
template <typename T> T clamp(T min, T v, T max) {
return v < min ? min : max < v ? max : v;
}
-extern "C" void* memset(void* dest, int c, size_t n);
-extern "C" void* memcpy(void* dest, const void* src, size_t n);
+extern "C" void* memset(void* dest, int c, amy::size n);
+extern "C" void* memcpy(void* dest, const void* src, amy::size n);
template <typename T>
struct incrementing_int64_map {
incrementing_int64_map(const incrementing_int64_map& other) = delete;
incrementing_int64_map& operator=(const incrementing_int64_map& other) = delete;
~incrementing_int64_map() {
- for (std::int64_t i = 0; i < n; i++) {
+ for (amy::i64 i = 0; i < n; i++) {
if (present(i)) { remove(i); }
}
}
bool has_room() {
return n < max_n;
}
- bool present(std::int64_t index) {
+ bool present(amy::i64 index) {
return 0 <= index && index < n && elems[index].present;
}
- std::int64_t create() {
+ amy::i64 create() {
os::assert(has_room(), "Too many allocated elems in incrementing_int64_map.");
elems[n].present = true;
new(elems[n].buffer) T;
return n++;
}
- void remove(std::int64_t index) {
+ void remove(amy::i64 index) {
os::assert(present(index), "Tried removing non-existant element of incrementing_int64_map.");
get(index).~T();
elems[index].present = false;
}
- T& get(std::int64_t index) {
+ T& get(amy::i64 index) {
os::assert(present(index), "Tried getting non-existant element of incrementing_int64_map.");
- return *std::launder(reinterpret_cast<T*>(&elems[index].buffer[0]));
+ return *amy::launder(reinterpret_cast<T*>(&elems[index].buffer[0]));
}
- const T& get(std::int64_t index) const {
+ const T& get(amy::i64 index) const {
os::assert(present(index), "Tried getting non-existant element of incrementing_int64_map.");
- return *std::launder(reinterpret_cast<T*>(&elems[index].buffer[0]));
+ return *amy::launder(reinterpret_cast<T*>(&elems[index].buffer[0]));
}
private:
struct elem_t {
bool present;
- alignas(T) std::byte buffer[sizeof(T)];
+ alignas(T) amy::byte buffer[sizeof(T)];
};
- std::int64_t n = 0;
- static constexpr std::int64_t max_n = 4096;
+ amy::i64 n = 0;
+ static constexpr amy::i64 max_n = 4096;
elem_t elems[max_n];
};
--- /dev/null
+// Copyright 2023 Amélia COUTARD.
+//
+// This file from the program "voyage au centre des fichiers" is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with this program. If
+// not, see <https://www.gnu.org/licenses/>.
+
+#pragma once
+
+#include <types.hpp>
+
+// See the C++ documentation for documentation.
+
+// Placement new and delete (taken from glibcxx, should be fine copyright-wise):
+[[nodiscard]] inline void* operator new(unsigned long, void* p) noexcept {
+ return p;
+}
+[[nodiscard]] inline void* operator new[](unsigned long, void* p) noexcept {
+ return p;
+}
+inline void operator delete(void*, void*) noexcept {}
+inline void operator delete[](void*, void*) noexcept {}
+
+namespace amy {
+
+// Taken from glibcxx, should be fine copyright-wise:
+template <typename T>
+[[nodiscard]] constexpr T* launder(T* p) noexcept {
+ return __builtin_launder(p);
+}
+} // namespace amy
--- /dev/null
+// Copyright 2023 Amélia COUTARD.
+//
+// This file from the program "voyage au centre des fichiers" is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with this program. If
+// not, see <https://www.gnu.org/licenses/>.
+
+#pragma once
+
+#include <stdint.h>
+
+namespace amy {
+
+enum class byte : unsigned char {};
+using i8 = int8_t;
+using u8 = uint8_t;
+using i16 = int16_t;
+using u16 = uint16_t;
+using i32 = int32_t;
+using u32 = uint32_t;
+using i64 = int64_t;
+using u64 = uint64_t;
+
+using iptr = intptr_t;
+using uptr = uintptr_t;
+using dptr = __PTRDIFF_TYPE__;
+using nptr = decltype(nullptr);
+
+using size = i64;
+
+using pid = i64;
+using fd = i64;
+
+} // namespace amy
mov $4, %rax
syscall
ret
+
+.globl loop_de_loop
+loop_de_loop:
+1: jmp 1b
// You should have received a copy of the GNU General Public License along with this program. If
// not, see <https://www.gnu.org/licenses/>.
-#include <stddef.h>
-#include <stdint.h>
+#include <types.hpp>
+
+enum mount_type {
+ MOUNT_REPLACE = 0,
+ MOUNT_BEFORE = 1,
+ MOUNT_AFTER = 2,
+};
enum open_options {
MODE_READ = 0x1,
};
namespace sys {
-extern "C" int64_t mount_kernel_device(int64_t wd, char device, char const* path, int64_t path_len);
-extern "C" int64_t open(int64_t wd, char const* path, int64_t path_len, open_options options);
-extern "C" int64_t read(int64_t file, char* data, int64_t len);
-extern "C" int64_t write(int64_t file, char const* data, int64_t len);
-extern "C" int64_t close(int64_t file);
+extern "C" int mount_kernel_device(amy::fd wd, char device, char const* path, amy::size path_len, mount_type type);
+extern "C" amy::fd open(amy::fd wd, char const* path, amy::size path_len, open_options options);
+extern "C" amy::size read(amy::fd file, char* data, amy::size len);
+extern "C" amy::size write(amy::fd file, char const* data, amy::size len);
+extern "C" int close(amy::fd file);
} // namespace sys
-void loop_de_loop() {
- loop_de_loop();
-}
+extern "C" void loop_de_loop();
extern "C" void _start() {
- sys::mount_kernel_device(-1, 'I', "/", 1); // 'I' is the I/O device. /serial is the serial port /fb is the framebuffer
- const int64_t serial = sys::open(-1, "/serial", 7, MODE_WRITE);
+ sys::mount_kernel_device(-1, 'I', "/", 1, MOUNT_REPLACE); // 'I' is the I/O device. /serial is the serial port /fb is the framebuffer
+ const amy::fd serial = sys::open(-1, "/serial", 7, MODE_WRITE);
sys::write(serial, "Entrez votre nom: ", 18);
char data[32];
- int64_t read = 0;
- int64_t read_this_time;
+ amy::size read = 0;
+ amy::size read_this_time;
do {
read_this_time = sys::read(serial, data + read, 1);
if (read_this_time) {