diff --git a/kernel/src/arch/Timer.cpp b/kernel/src/arch/Timer.cpp index 75792e93..26515c99 100644 --- a/kernel/src/arch/Timer.cpp +++ b/kernel/src/arch/Timer.cpp @@ -32,19 +32,19 @@ static u64 broken_down_to_unix(u64 year, u64 yday, u64 hour, u64 min, u64 sec) // The bootloader encodes the date and time in Binary-Coded Decimal (BCD), which represents decimal digits using // hexadecimal digits. For example, BCD 0x22 is 22 in decimal. // https://gitlab.com/bztsrc/bootboot/-/blob/master/bootboot_spec_1st_ed.pdf, page 15. -static int bcd_number_to_decimal(int num) +static inline constexpr int bcd_number_to_decimal(int num) { return ((num >> 4) * 10) + (num & 0xf); } static u64 bootloader_time_to_unix(const u8 boottime[8]) { - int year = bcd_number_to_decimal(boottime[0]) * 100 + bcd_number_to_decimal(boottime[1]); - int month = bcd_number_to_decimal(boottime[2]); - int day = bcd_number_to_decimal(boottime[3]); - int hour = bcd_number_to_decimal(boottime[4]); - int minute = bcd_number_to_decimal(boottime[5]); - int second = bcd_number_to_decimal(boottime[6]); + const int year = bcd_number_to_decimal(boottime[0]) * 100 + bcd_number_to_decimal(boottime[1]); + const int month = bcd_number_to_decimal(boottime[2]); + const int day = bcd_number_to_decimal(boottime[3]); + const int hour = bcd_number_to_decimal(boottime[4]); + const int minute = bcd_number_to_decimal(boottime[5]); + const int second = bcd_number_to_decimal(boottime[6]); // "The last byte can store 1/100th second precision, but in lack of support on most platforms, it is 0x00". // Therefore, let's not rely on it. kinfoln("Current time: %.2d/%.2d/%d %.2d:%.2d:%.2d UTC", day, month, year, hour, minute, second).release_value(); diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 306117d5..73ffbafd 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -12,15 +12,19 @@ extern "C" void enable_sse(); extern "C" void enable_write_protect(); extern "C" void enable_nx(); +// FIXME: Split this into separate files? + // GDT code and definitions -struct GDTR +struct [[gnu::packed]] GDTR { u16 size; u64 offset; -} __attribute__((packed)); +}; -struct GDTEntry +static_assert(sizeof(GDTR) == 10UL); + +struct [[gnu::packed]] GDTEntry { u16 limit0; u16 base0; @@ -28,15 +32,19 @@ struct GDTEntry u8 access; u8 limit1_flags; u8 base2; -} __attribute__((packed)); +}; -struct HighGDTEntry +static_assert(sizeof(GDTEntry) == 8UL); + +struct [[gnu::packed]] HighGDTEntry { u32 base_high; u32 reserved; -} __attribute__((packed)); +}; -struct TSS +static_assert(sizeof(HighGDTEntry) == 8UL); + +struct [[gnu::packed]] TSS { u32 reserved0; u64 rsp[3]; @@ -45,9 +53,11 @@ struct TSS u64 reserved2; u16 reserved3; u16 iomap_base; -} __attribute__((packed)); +}; -struct GlobalDescriptorTable +static_assert(sizeof(TSS) == 104UL); + +struct [[gnu::packed]] alignas(4096) GlobalDescriptorTable { GDTEntry null; GDTEntry kernel_code; @@ -56,7 +66,7 @@ struct GlobalDescriptorTable GDTEntry user_data; GDTEntry tss; HighGDTEntry tss2; -} __attribute__((packed)) __attribute((aligned(4096))); +}; static TSS task_state_segment; @@ -174,9 +184,11 @@ struct IDTEntry u32 offset2; u32 ignore; void set_offset(u64 offset); - u64 get_offset(); + u64 get_offset() const; }; +static_assert(sizeof(IDTEntry) == 16UL); + void IDTEntry::set_offset(u64 offset) { offset0 = (u16)(offset & 0x000000000000ffff); @@ -184,7 +196,7 @@ void IDTEntry::set_offset(u64 offset) offset2 = (u32)((offset & 0xffffffff00000000) >> 32); } -u64 IDTEntry::get_offset() +u64 IDTEntry::get_offset() const { u64 offset = 0; offset |= (u64)offset0; @@ -199,17 +211,19 @@ static IDTEntry idt[256]; #define IDT_TA_UserInterruptGate 0b11101110 #define IDT_TA_TrapGate 0b10001111 -struct IDTR +struct [[gnu::packed]] IDTR { u16 limit; u64 offset; -} __attribute__((packed)); +}; + +static_assert(sizeof(IDTR) == 10UL); static void idt_add_handler(short num, void* handler, u8 type_attr) { check(handler != nullptr); expect(num < 256, "IDT can only hold up to 256 entries"); - IDTEntry* entry_for_handler = &idt[num]; + IDTEntry* const entry_for_handler = &idt[num]; entry_for_handler->selector = 0x08; entry_for_handler->type_attr = type_attr; entry_for_handler->set_offset((u64)handler); diff --git a/kernel/src/arch/x86_64/MMU.cpp b/kernel/src/arch/x86_64/MMU.cpp index 12cbd372..fa09ff14 100644 --- a/kernel/src/arch/x86_64/MMU.cpp +++ b/kernel/src/arch/x86_64/MMU.cpp @@ -12,22 +12,30 @@ const u64 sign = 0177777UL << 48; // sign extension struct [[gnu::packed]] PageTableEntry { - bool present : 1; - bool read_write : 1; - bool user : 1; - bool write_through : 1; - bool cache_disabled : 1; - bool accessed : 1; - bool ignore0 : 1; - bool larger_pages : 1; - bool ignore1 : 1; - u8 available : 3; - u64 address : 48; - u8 available2 : 3; - bool no_execute : 1; + union { + struct [[gnu::packed]] + { + bool present : 1; + bool read_write : 1; + bool user : 1; + bool write_through : 1; + bool cache_disabled : 1; + bool accessed : 1; + bool ignore0 : 1; + bool larger_pages : 1; + bool ignore1 : 1; + u8 available : 3; + u64 address : 48; + u8 available2 : 3; + bool no_execute : 1; + }; + u64 raw; + }; void set_address(u64 addr); - u64 get_address(); + u64 get_address() const; + + void clear(); }; #pragma GCC push_options @@ -38,13 +46,18 @@ void PageTableEntry::set_address(u64 addr) this->address = (addr >> 12); } -u64 PageTableEntry::get_address() +u64 PageTableEntry::get_address() const { return (u64)this->address << 12; } #pragma GCC pop_options +void PageTableEntry::clear() +{ + raw = 0; +} + struct alignas(PAGE_SIZE) PageDirectory { PageTableEntry entries[512]; @@ -56,13 +69,13 @@ static_assert(sizeof(PageDirectory) == PAGE_SIZE); namespace MMU { - PageDirectory* l4_table() + constexpr PageDirectory* l4_table() { - u64 l4 = sign | (rindex << 39) | (rindex << 30) | (rindex << 21) | (rindex << 12); + constexpr u64 l4 = sign | (rindex << 39) | (rindex << 30) | (rindex << 21) | (rindex << 12); return (PageDirectory*)l4; } - u64 l4_index(u64 addr) + constexpr u64 l4_index(u64 addr) { return (addr >> 39) & 0777; } @@ -72,14 +85,14 @@ namespace MMU return l4_table()->entries[l4_index(addr)]; } - PageDirectory* l3_table(u64 addr) + constexpr PageDirectory* l3_table(u64 addr) { - u64 l4 = l4_index(addr); - u64 l3 = sign | (rindex << 39) | (rindex << 30) | (rindex << 21) | (l4 << 12); + const u64 l4 = l4_index(addr); + const u64 l3 = sign | (rindex << 39) | (rindex << 30) | (rindex << 21) | (l4 << 12); return (PageDirectory*)l3; } - u64 l3_index(u64 addr) + constexpr u64 l3_index(u64 addr) { return (addr >> 30) & 0777; } @@ -89,15 +102,15 @@ namespace MMU return l3_table(addr)->entries[l3_index(addr)]; } - PageDirectory* l2_table(u64 addr) + constexpr PageDirectory* l2_table(u64 addr) { - u64 l4 = l4_index(addr); - u64 l3 = l3_index(addr); - u64 l2 = sign | (rindex << 39) | (rindex << 30) | (l4 << 21) | (l3 << 12); + const u64 l4 = l4_index(addr); + const u64 l3 = l3_index(addr); + const u64 l2 = sign | (rindex << 39) | (rindex << 30) | (l4 << 21) | (l3 << 12); return (PageDirectory*)l2; } - u64 l2_index(u64 addr) + constexpr u64 l2_index(u64 addr) { return (addr >> 21) & 0777; } @@ -107,16 +120,16 @@ namespace MMU return l2_table(addr)->entries[l2_index(addr)]; } - PageDirectory* l1_table(u64 addr) + constexpr PageDirectory* l1_table(u64 addr) { - u64 l4 = l4_index(addr); - u64 l3 = l3_index(addr); - u64 l2 = l2_index(addr); - u64 l1 = sign | (rindex << 39) | (l4 << 30) | (l3 << 21) | (l2 << 12); + const u64 l4 = l4_index(addr); + const u64 l3 = l3_index(addr); + const u64 l2 = l2_index(addr); + const u64 l1 = sign | (rindex << 39) | (l4 << 30) | (l3 << 21) | (l2 << 12); return (PageDirectory*)l1; } - u64 l1_index(u64 addr) + constexpr u64 l1_index(u64 addr) { return (addr >> 12) & 0777; } @@ -148,7 +161,7 @@ namespace MMU asm volatile("invlpg (%0)" : : "r"(page) : "memory"); } - int arch_flags_to_mmu(PageTableEntry& entry) + int arch_flags_to_mmu(const PageTableEntry& entry) { int result = Flags::None; if (entry.read_write) result |= Flags::ReadWrite; @@ -161,7 +174,7 @@ namespace MMU Result find_entry(u64 virt) { - auto& l4 = l4_entry(virt); + const auto& l4 = l4_entry(virt); if (!l4.present) return err(EFAULT); auto& l3 = l3_entry(virt); if (!l3.present) return err(EFAULT); @@ -263,30 +276,30 @@ namespace MMU { auto& l1 = *TRY(find_entry(virt)); if (!l1.present) return err(EFAULT); - u64 address = l1.get_address(); - memset(&l1, 0, sizeof(l1)); + const u64 address = l1.get_address(); + l1.clear(); flush_page(virt); return address; } Result get_physical(u64 virt) { - auto& l1 = *TRY(find_entry(virt)); + const auto& l1 = *TRY(find_entry(virt)); if (!l1.present) return err(EFAULT); return l1.get_address(); } Result get_flags(u64 virt) { - auto& l1 = *TRY(find_entry(virt)); + const auto& l1 = *TRY(find_entry(virt)); if (!l1.present) return err(EFAULT); return arch_flags_to_mmu(l1); } void setup_initial_page_directory() { - PageDirectory* dir = get_page_directory(); - u64 paddr = (u64)dir; + PageDirectory* const dir = get_page_directory(); + const u64 paddr = (u64)dir; PageTableEntry& recursive_entry = dir->entries[rindex]; recursive_entry.read_write = true; recursive_entry.present = true;