General constness + [[gnu::packed]] everywhere
This commit is contained in:
parent
a63a8b32b5
commit
4f183958e3
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user