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
// 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();

View File

@ -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);

View File

@ -12,6 +12,9 @@ const u64 sign = 0177777UL << 48; // sign extension
struct [[gnu::packed]] PageTableEntry
{
union {
struct [[gnu::packed]]
{
bool present : 1;
bool read_write : 1;
bool user : 1;
@ -25,9 +28,14 @@ struct [[gnu::packed]] PageTableEntry
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<PageTableEntry*> 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<u64> 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<int> 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;