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
|
||||
// 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();
|
||||
|
@ -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);
|
||||
|
@ -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<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;
|
||||
|
Loading…
Reference in New Issue
Block a user