General constness + [[gnu::packed]] everywhere

This commit is contained in:
apio 2022-12-05 16:13:38 +01:00
parent a63a8b32b5
commit 4f183958e3
Signed by: apio
GPG Key ID: B8A7D06E42258954
3 changed files with 90 additions and 63 deletions

View File

@ -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 // 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. // hexadecimal digits. For example, BCD 0x22 is 22 in decimal.
// https://gitlab.com/bztsrc/bootboot/-/blob/master/bootboot_spec_1st_ed.pdf, page 15. // 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); return ((num >> 4) * 10) + (num & 0xf);
} }
static u64 bootloader_time_to_unix(const u8 boottime[8]) 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]); const int year = bcd_number_to_decimal(boottime[0]) * 100 + bcd_number_to_decimal(boottime[1]);
int month = bcd_number_to_decimal(boottime[2]); const int month = bcd_number_to_decimal(boottime[2]);
int day = bcd_number_to_decimal(boottime[3]); const int day = bcd_number_to_decimal(boottime[3]);
int hour = bcd_number_to_decimal(boottime[4]); const int hour = bcd_number_to_decimal(boottime[4]);
int minute = bcd_number_to_decimal(boottime[5]); const int minute = bcd_number_to_decimal(boottime[5]);
int second = bcd_number_to_decimal(boottime[6]); 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". // "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. // 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(); kinfoln("Current time: %.2d/%.2d/%d %.2d:%.2d:%.2d UTC", day, month, year, hour, minute, second).release_value();

View File

@ -12,15 +12,19 @@ extern "C" void enable_sse();
extern "C" void enable_write_protect(); extern "C" void enable_write_protect();
extern "C" void enable_nx(); extern "C" void enable_nx();
// FIXME: Split this into separate files?
// GDT code and definitions // GDT code and definitions
struct GDTR struct [[gnu::packed]] GDTR
{ {
u16 size; u16 size;
u64 offset; u64 offset;
} __attribute__((packed)); };
struct GDTEntry static_assert(sizeof(GDTR) == 10UL);
struct [[gnu::packed]] GDTEntry
{ {
u16 limit0; u16 limit0;
u16 base0; u16 base0;
@ -28,15 +32,19 @@ struct GDTEntry
u8 access; u8 access;
u8 limit1_flags; u8 limit1_flags;
u8 base2; u8 base2;
} __attribute__((packed)); };
struct HighGDTEntry static_assert(sizeof(GDTEntry) == 8UL);
struct [[gnu::packed]] HighGDTEntry
{ {
u32 base_high; u32 base_high;
u32 reserved; u32 reserved;
} __attribute__((packed)); };
struct TSS static_assert(sizeof(HighGDTEntry) == 8UL);
struct [[gnu::packed]] TSS
{ {
u32 reserved0; u32 reserved0;
u64 rsp[3]; u64 rsp[3];
@ -45,9 +53,11 @@ struct TSS
u64 reserved2; u64 reserved2;
u16 reserved3; u16 reserved3;
u16 iomap_base; u16 iomap_base;
} __attribute__((packed)); };
struct GlobalDescriptorTable static_assert(sizeof(TSS) == 104UL);
struct [[gnu::packed]] alignas(4096) GlobalDescriptorTable
{ {
GDTEntry null; GDTEntry null;
GDTEntry kernel_code; GDTEntry kernel_code;
@ -56,7 +66,7 @@ struct GlobalDescriptorTable
GDTEntry user_data; GDTEntry user_data;
GDTEntry tss; GDTEntry tss;
HighGDTEntry tss2; HighGDTEntry tss2;
} __attribute__((packed)) __attribute((aligned(4096))); };
static TSS task_state_segment; static TSS task_state_segment;
@ -174,9 +184,11 @@ struct IDTEntry
u32 offset2; u32 offset2;
u32 ignore; u32 ignore;
void set_offset(u64 offset); void set_offset(u64 offset);
u64 get_offset(); u64 get_offset() const;
}; };
static_assert(sizeof(IDTEntry) == 16UL);
void IDTEntry::set_offset(u64 offset) void IDTEntry::set_offset(u64 offset)
{ {
offset0 = (u16)(offset & 0x000000000000ffff); offset0 = (u16)(offset & 0x000000000000ffff);
@ -184,7 +196,7 @@ void IDTEntry::set_offset(u64 offset)
offset2 = (u32)((offset & 0xffffffff00000000) >> 32); offset2 = (u32)((offset & 0xffffffff00000000) >> 32);
} }
u64 IDTEntry::get_offset() u64 IDTEntry::get_offset() const
{ {
u64 offset = 0; u64 offset = 0;
offset |= (u64)offset0; offset |= (u64)offset0;
@ -199,17 +211,19 @@ static IDTEntry idt[256];
#define IDT_TA_UserInterruptGate 0b11101110 #define IDT_TA_UserInterruptGate 0b11101110
#define IDT_TA_TrapGate 0b10001111 #define IDT_TA_TrapGate 0b10001111
struct IDTR struct [[gnu::packed]] IDTR
{ {
u16 limit; u16 limit;
u64 offset; u64 offset;
} __attribute__((packed)); };
static_assert(sizeof(IDTR) == 10UL);
static void idt_add_handler(short num, void* handler, u8 type_attr) static void idt_add_handler(short num, void* handler, u8 type_attr)
{ {
check(handler != nullptr); check(handler != nullptr);
expect(num < 256, "IDT can only hold up to 256 entries"); 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->selector = 0x08;
entry_for_handler->type_attr = type_attr; entry_for_handler->type_attr = type_attr;
entry_for_handler->set_offset((u64)handler); entry_for_handler->set_offset((u64)handler);

View File

@ -12,22 +12,30 @@ const u64 sign = 0177777UL << 48; // sign extension
struct [[gnu::packed]] PageTableEntry struct [[gnu::packed]] PageTableEntry
{ {
bool present : 1; union {
bool read_write : 1; struct [[gnu::packed]]
bool user : 1; {
bool write_through : 1; bool present : 1;
bool cache_disabled : 1; bool read_write : 1;
bool accessed : 1; bool user : 1;
bool ignore0 : 1; bool write_through : 1;
bool larger_pages : 1; bool cache_disabled : 1;
bool ignore1 : 1; bool accessed : 1;
u8 available : 3; bool ignore0 : 1;
u64 address : 48; bool larger_pages : 1;
u8 available2 : 3; bool ignore1 : 1;
bool no_execute : 1; u8 available : 3;
u64 address : 48;
u8 available2 : 3;
bool no_execute : 1;
};
u64 raw;
};
void set_address(u64 addr); void set_address(u64 addr);
u64 get_address(); u64 get_address() const;
void clear();
}; };
#pragma GCC push_options #pragma GCC push_options
@ -38,13 +46,18 @@ void PageTableEntry::set_address(u64 addr)
this->address = (addr >> 12); this->address = (addr >> 12);
} }
u64 PageTableEntry::get_address() u64 PageTableEntry::get_address() const
{ {
return (u64)this->address << 12; return (u64)this->address << 12;
} }
#pragma GCC pop_options #pragma GCC pop_options
void PageTableEntry::clear()
{
raw = 0;
}
struct alignas(PAGE_SIZE) PageDirectory struct alignas(PAGE_SIZE) PageDirectory
{ {
PageTableEntry entries[512]; PageTableEntry entries[512];
@ -56,13 +69,13 @@ static_assert(sizeof(PageDirectory) == PAGE_SIZE);
namespace MMU 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; return (PageDirectory*)l4;
} }
u64 l4_index(u64 addr) constexpr u64 l4_index(u64 addr)
{ {
return (addr >> 39) & 0777; return (addr >> 39) & 0777;
} }
@ -72,14 +85,14 @@ namespace MMU
return l4_table()->entries[l4_index(addr)]; return l4_table()->entries[l4_index(addr)];
} }
PageDirectory* l3_table(u64 addr) constexpr PageDirectory* l3_table(u64 addr)
{ {
u64 l4 = l4_index(addr); const u64 l4 = l4_index(addr);
u64 l3 = sign | (rindex << 39) | (rindex << 30) | (rindex << 21) | (l4 << 12); const u64 l3 = sign | (rindex << 39) | (rindex << 30) | (rindex << 21) | (l4 << 12);
return (PageDirectory*)l3; return (PageDirectory*)l3;
} }
u64 l3_index(u64 addr) constexpr u64 l3_index(u64 addr)
{ {
return (addr >> 30) & 0777; return (addr >> 30) & 0777;
} }
@ -89,15 +102,15 @@ namespace MMU
return l3_table(addr)->entries[l3_index(addr)]; return l3_table(addr)->entries[l3_index(addr)];
} }
PageDirectory* l2_table(u64 addr) constexpr PageDirectory* l2_table(u64 addr)
{ {
u64 l4 = l4_index(addr); const u64 l4 = l4_index(addr);
u64 l3 = l3_index(addr); const u64 l3 = l3_index(addr);
u64 l2 = sign | (rindex << 39) | (rindex << 30) | (l4 << 21) | (l3 << 12); const u64 l2 = sign | (rindex << 39) | (rindex << 30) | (l4 << 21) | (l3 << 12);
return (PageDirectory*)l2; return (PageDirectory*)l2;
} }
u64 l2_index(u64 addr) constexpr u64 l2_index(u64 addr)
{ {
return (addr >> 21) & 0777; return (addr >> 21) & 0777;
} }
@ -107,16 +120,16 @@ namespace MMU
return l2_table(addr)->entries[l2_index(addr)]; return l2_table(addr)->entries[l2_index(addr)];
} }
PageDirectory* l1_table(u64 addr) constexpr PageDirectory* l1_table(u64 addr)
{ {
u64 l4 = l4_index(addr); const u64 l4 = l4_index(addr);
u64 l3 = l3_index(addr); const u64 l3 = l3_index(addr);
u64 l2 = l2_index(addr); const u64 l2 = l2_index(addr);
u64 l1 = sign | (rindex << 39) | (l4 << 30) | (l3 << 21) | (l2 << 12); const u64 l1 = sign | (rindex << 39) | (l4 << 30) | (l3 << 21) | (l2 << 12);
return (PageDirectory*)l1; return (PageDirectory*)l1;
} }
u64 l1_index(u64 addr) constexpr u64 l1_index(u64 addr)
{ {
return (addr >> 12) & 0777; return (addr >> 12) & 0777;
} }
@ -148,7 +161,7 @@ namespace MMU
asm volatile("invlpg (%0)" : : "r"(page) : "memory"); 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; int result = Flags::None;
if (entry.read_write) result |= Flags::ReadWrite; if (entry.read_write) result |= Flags::ReadWrite;
@ -161,7 +174,7 @@ namespace MMU
Result<PageTableEntry*> find_entry(u64 virt) Result<PageTableEntry*> find_entry(u64 virt)
{ {
auto& l4 = l4_entry(virt); const auto& l4 = l4_entry(virt);
if (!l4.present) return err(EFAULT); if (!l4.present) return err(EFAULT);
auto& l3 = l3_entry(virt); auto& l3 = l3_entry(virt);
if (!l3.present) return err(EFAULT); if (!l3.present) return err(EFAULT);
@ -263,30 +276,30 @@ namespace MMU
{ {
auto& l1 = *TRY(find_entry(virt)); auto& l1 = *TRY(find_entry(virt));
if (!l1.present) return err(EFAULT); if (!l1.present) return err(EFAULT);
u64 address = l1.get_address(); const u64 address = l1.get_address();
memset(&l1, 0, sizeof(l1)); l1.clear();
flush_page(virt); flush_page(virt);
return address; return address;
} }
Result<u64> get_physical(u64 virt) Result<u64> get_physical(u64 virt)
{ {
auto& l1 = *TRY(find_entry(virt)); const auto& l1 = *TRY(find_entry(virt));
if (!l1.present) return err(EFAULT); if (!l1.present) return err(EFAULT);
return l1.get_address(); return l1.get_address();
} }
Result<int> get_flags(u64 virt) Result<int> get_flags(u64 virt)
{ {
auto& l1 = *TRY(find_entry(virt)); const auto& l1 = *TRY(find_entry(virt));
if (!l1.present) return err(EFAULT); if (!l1.present) return err(EFAULT);
return arch_flags_to_mmu(l1); return arch_flags_to_mmu(l1);
} }
void setup_initial_page_directory() void setup_initial_page_directory()
{ {
PageDirectory* dir = get_page_directory(); PageDirectory* const dir = get_page_directory();
u64 paddr = (u64)dir; const u64 paddr = (u64)dir;
PageTableEntry& recursive_entry = dir->entries[rindex]; PageTableEntry& recursive_entry = dir->entries[rindex];
recursive_entry.read_write = true; recursive_entry.read_write = true;
recursive_entry.present = true; recursive_entry.present = true;